Skip to content

Conversation

@ryanio
Copy link
Collaborator

@ryanio ryanio commented Nov 28, 2025

Summary

Fixes SDK crash when fulfilling zero-payment private listings (e.g., rewards claims).

Closes #1832 - This PR supersedes #1832 by properly supporting zero-payment private listings instead of just throwing an error.

Problem

The SDK crashes when fulfilling private listings with no payment consideration items:

  1. constructPrivateListingCounterOrder accesses paymentItems[0] without checking if the array is empty
  2. fulfillPrivateOrder accesses counterOrder.parameters.offer[0].startAmount which is undefined for zero-payment listings

Why #1832's approach was insufficient

PR #1832 proposed throwing an error when paymentItems is empty. However, investigation of the backend (os2-core) revealed that zero-payment private listings are valid and deliberately supported:

  • PrivateListingValidationRule.kt bypasses the pricePerItem <= 0 check for REWARDS_PRIVATE_LISTING_CLAIM_WALLET
  • SeaportListingValidationRules.kt bypasses the "must have 1-7 currency items" check for the same wallet
  • Seaport.kt:1563-1574 explicitly handles empty payment items by returning offer: emptyList()

The backend already handles this correctly - the SDK should too.

Solution

Mirror the backend behavior:

  1. Allow empty payment items - constructPrivateListingCounterOrder now returns a counter order with offer: [] for zero-payment listings instead of crashing

  2. Compute value from original order - Added computePrivateListingValue() that sums native currency consideration items from the original order, handling both standard and zero-payment cases

  3. Use computed value - fulfillPrivateOrder now uses computePrivateListingValue() instead of counterOrder.parameters.offer[0].startAmount

Changes

  • src/orders/privateListings.ts:

    • Added computePrivateListingValue() helper function
    • Updated constructPrivateListingCounterOrder() to handle empty payment items
  • src/sdk/fulfillment.ts:

    • Import and use computePrivateListingValue()
    • Calculate ETH value from original order instead of counter order

Testing

  • All existing tests pass
  • Lint passes
  • Type check passes

@ryanio ryanio force-pushed the fix/zero-payment-private-listings branch from 8fd170b to 0e55cb3 Compare November 28, 2025 19:55
Fixes SDK crash when fulfilling zero-payment private listings (e.g., rewards claims).

Problem:
- constructPrivateListingCounterOrder crashes when paymentItems is empty
- fulfillPrivateOrder crashes accessing counterOrder.parameters.offer[0]

Solution (mirrors backend behavior in os2-core Seaport.kt):
- Allow empty payment items in constructPrivateListingCounterOrder
- Return counter order with offer: [] for zero-payment listings
- Add computePrivateListingValue() to calculate ETH value from original order
- Use computed value instead of counter order's offer[0].startAmount

This enables fulfillment of zero-payment private listings used for rewards
claims via REWARDS_PRIVATE_LISTING_CLAIM_WALLET.

Closes #1832
@ryanio ryanio force-pushed the fix/zero-payment-private-listings branch from 0e55cb3 to 4b8636e Compare November 28, 2025 19:57
@ryanio ryanio merged commit 125b065 into main Nov 28, 2025
8 checks passed
@ryanio ryanio deleted the fix/zero-payment-private-listings branch November 28, 2025 20:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants