fix: exclude marketplace fees from private listings - #1714
Merged
ryanio merged 10 commits intoJul 15, 2025
Conversation
- Modified getFees method to accept isPrivateListing parameter - Added marketplace fee filtering logic for private listings - Added integration tests for private listing fee behavior - Fixes issue #1710 where private listings were rejected by API The fix ensures that when buyerAddress is specified in createListing, marketplace fees (2.5% non-required fees) are excluded from the consideration items, preventing API rejection of private transactions. Co-Authored-By: Ryan Ghods <ralxzryan@gmail.com>
Contributor
|
Original prompt from Ryan: |
Contributor
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
…ering - Remove isPrivateListing parameter, detect from buyerAddress presence - Use OPENSEA_FEE_RECIPIENT constant for marketplace fee identification - Simplify isNotMarketplaceFee logic to use recipient address comparison - Update all getFees calls to use buyerAddress parameter Based on user feedback to simplify the implementation. Co-Authored-By: Ryan Ghods <ralxzryan@gmail.com>
- Add 'as string' to TOKEN_ADDRESS_MAINNET and TOKEN_ID_MAINNET definitions - Remove 'as string' from all usage sites for cleaner type casting Based on user feedback to improve TypeScript typing consistency. Co-Authored-By: Ryan Ghods <ralxzryan@gmail.com>
- Rename buyerAddress parameter in getFees to isPrivateListing with default false - Move OPENSEA_FEE_RECIPIENT constant to src/constants.ts for better organization - Move private listing test to integration folder to fix CI unit test failure - Update getFees calls to use new isPrivateListing parameter Co-Authored-By: Ryan Ghods <ralxzryan@gmail.com>
ryanio
commented
Jul 15, 2025
|
|
||
| expect(order.protocolData.parameters.consideration).to.exist; | ||
|
|
||
| const marketplaceFeeRecipient = |
Collaborator
Author
There was a problem hiding this comment.
Use the OPENSEA_FEE_RECIPIENT const
- Import OPENSEA_FEE_RECIPIENT from src/constants.ts - Replace hardcoded marketplace fee recipient address with constant - Addresses GitHub comment feedback for better code consistency Co-Authored-By: Ryan Ghods <ralxzryan@gmail.com>
- Add getRandomExpiration() helper that returns 15-60 minutes from now - Update all order posting integration tests to use random expiration times - Update private listing tests for consistency - Prevents 'Order already exists' validation errors in CI by adding variability Co-Authored-By: Ryan Ghods <ralxzryan@gmail.com>
ryanio
commented
Jul 15, 2025
| } | ||
| }; | ||
|
|
||
| export const getRandomExpiration = (): number => { |
Collaborator
Author
There was a problem hiding this comment.
Move this to setup.ts
…mExpiration - Use crypto.randomBytes() for cryptographically secure random number generation - Fixes CodeQL security alerts about insecure random number usage - Maintains same API and functionality for test utilities Co-Authored-By: Ryan Ghods <ralxzryan@gmail.com>
- Move getRandomExpiration function from test/utils/utils.ts to test/integration/setup.ts - Update imports in postOrder.spec.ts and privateListing.spec.ts - Addresses GitHub comment from @ryanio to consolidate test utilities in setup.ts Co-Authored-By: Ryan Ghods <ralxzryan@gmail.com>
- Use import { randomBytes } from 'crypto' instead of require()
- Follows ES6 import patterns and resolves CodeQL security alerts
- Maintains same cryptographically secure random number generation
Co-Authored-By: Ryan Ghods <ralxzryan@gmail.com>
- Replace modulo operation with rejection sampling in getRandomExpiration() - Eliminates CodeQL security alert about biased cryptographic random numbers - Maintains same functionality while ensuring unbiased distribution Co-Authored-By: Ryan Ghods <ralxzryan@gmail.com>
ryanio
deleted the
devin/1752536139-fix-marketplace-fees-private-listings
branch
July 15, 2025 00:55
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix marketplace fees in private listings and prevent CI order conflicts
Summary
This PR addresses two issues:
Primary fix: Marketplace fees are now properly excluded from private listings (when
buyerAddressis specified increateListing). ThegetFees()method insrc/sdk.tshas been modified to filter out marketplace fees for private listings using theOPENSEA_FEE_RECIPIENTconstant.CI improvement: Added a
getRandomExpiration()helper function that generates random expiration times (15-60 minutes) to prevent "Order already exists" validation errors in integration tests.Security fix: Replaced biased modulo operation with rejection sampling in random number generation to resolve CodeQL security alerts about cryptographically secure random numbers.
Key changes:
getFees()method to detect private listings viaisPrivateListingparameter and exclude marketplace feesOPENSEA_FEE_RECIPIENTconstant tosrc/constants.tsgetRandomExpiration()helper intest/integration/setup.tsusing secure rejection samplingReview & Testing Checklist for Human
0x0000a26b00c1f0df003000390027140000faa719is the correct marketplace fee recipient addressRecommended test plan: Create both private and regular listings using the SDK with the same NFT to verify the fee behavior difference.
Diagram
%%{ init : { "theme" : "default" }}%% graph TD SDK["src/sdk.ts<br/>getFees() method"]:::major-edit Constants["src/constants.ts<br/>OPENSEA_FEE_RECIPIENT"]:::minor-edit Setup["test/integration/setup.ts<br/>getRandomExpiration()"]:::minor-edit PostOrder["test/integration/postOrder.spec.ts<br/>Order posting tests"]:::minor-edit PrivateListing["test/integration/privateListing.spec.ts<br/>Private listing tests"]:::minor-edit API["OpenSea API<br/>Order validation"]:::context SDK -->|"excludes marketplace fees<br/>for private listings"| API Constants -->|"identifies marketplace<br/>fee recipient"| SDK Setup -->|"prevents order conflicts"| PostOrder Setup -->|"prevents order conflicts"| PrivateListing subgraph Legend L1[Major Edit]:::major-edit L2[Minor Edit]:::minor-edit L3[Context/No Edit]:::context end classDef major-edit fill:#90EE90 classDef minor-edit fill:#87CEEB classDef context fill:#FFFFFFNotes
isPrivateListingparameter ingetFees()defaults tofalseto maintain backward compatibilitySession info: Requested by @ryanio
Link to Devin run: https://app.devin.ai/sessions/ab90a4a425d545c2ad20b28fb238165e