@tradeport/sui-trading-sdk 0.5.3 → 0.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/.babel.config.js +3 -0
  2. package/.claude/settings.json +5 -0
  3. package/.claude/settings.local.json +5 -0
  4. package/.env.demo +5 -0
  5. package/.eslintrc.json +46 -0
  6. package/.prettierignore +4 -0
  7. package/.prettierrc.json +7 -0
  8. package/.vscode/launch.json +23 -0
  9. package/CHANGELOG.md +746 -0
  10. package/jest.config.js +12 -0
  11. package/package.json +66 -71
  12. package/src/SuiTradingClient.ts +442 -0
  13. package/src/apiClients/createKioskClient.ts +10 -0
  14. package/src/apiClients/createSuiClient.ts +5 -0
  15. package/src/apiClients/graphqlClient.ts +17 -0
  16. package/src/bigNumberConfig.ts +10 -0
  17. package/src/constants.ts +1052 -0
  18. package/src/graphql/createChainGQLQuery.ts +27 -0
  19. package/src/graphql/gqlChainRequest.ts +21 -0
  20. package/src/graphql/queries/fetchAccountKiosks.ts +12 -0
  21. package/src/graphql/queries/fetchActiveLockStateByNftId.ts +15 -0
  22. package/src/graphql/queries/fetchBidsById.ts +36 -0
  23. package/src/graphql/queries/fetchCollectionBidById.ts +21 -0
  24. package/src/graphql/queries/fetchCollectionBidsAtSamePrice.ts +29 -0
  25. package/src/graphql/queries/fetchCollectionChainState.ts +17 -0
  26. package/src/graphql/queries/fetchCollectionFloorListingForMarket.ts +28 -0
  27. package/src/graphql/queries/fetchCollectionFloorListings.ts +15 -0
  28. package/src/graphql/queries/fetchCollectionsById.ts +39 -0
  29. package/src/graphql/queries/fetchCommissionByListingId.ts +13 -0
  30. package/src/graphql/queries/fetchCryptoToUsdRate.ts +13 -0
  31. package/src/graphql/queries/fetchKiosksByOwner.ts +14 -0
  32. package/src/graphql/queries/fetchListingsById.ts +29 -0
  33. package/src/graphql/queries/fetchListingsByNftId.ts +23 -0
  34. package/src/graphql/queries/fetchLockById.ts +23 -0
  35. package/src/graphql/queries/fetchMultibidById.ts +34 -0
  36. package/src/graphql/queries/fetchNftCollectionChainState.ts +12 -0
  37. package/src/graphql/queries/fetchNftsById.ts +75 -0
  38. package/src/graphql/queries/fetchNftsByKioskId.ts +45 -0
  39. package/src/graphql/queries/fetchOwnerCapByKiosk.ts +10 -0
  40. package/src/graphql/queries/fetchPersonalCapByKiosk.ts +10 -0
  41. package/src/graphql/queries/fetchSharedObjectsByType.ts +12 -0
  42. package/src/graphql/queries/fetchTransferPoliciesByType.ts +12 -0
  43. package/src/graphql/queries/fetchWalletKiosks.ts +14 -0
  44. package/src/graphql/queries/getCommissionByListingId.ts +15 -0
  45. package/src/helpers/addOneDollarFee.ts +17 -0
  46. package/src/helpers/addThirdPartyTxFee.ts +17 -0
  47. package/src/helpers/calculatePremium.ts +9 -0
  48. package/src/helpers/calculateRoyaltyFee.ts +28 -0
  49. package/src/helpers/destroyZeroCoin.ts +14 -0
  50. package/src/helpers/getActiveLockStateByNftId.ts +15 -0
  51. package/src/helpers/getCollectionChainState.ts +31 -0
  52. package/src/helpers/getCollectionFloorPrice.ts +12 -0
  53. package/src/helpers/getLockById.ts +29 -0
  54. package/src/helpers/getMarketFeePrice.ts +82 -0
  55. package/src/helpers/getNftType.ts +38 -0
  56. package/src/helpers/getRoyaltyRuleModule.ts +7 -0
  57. package/src/helpers/getSharedObjects.ts +119 -0
  58. package/src/helpers/getSuiToUsdRate.ts +14 -0
  59. package/src/helpers/getTradeportBiddingContractBidAmount.ts +31 -0
  60. package/src/helpers/getTransferPolicyRuleNamesFromSuiObject.ts +24 -0
  61. package/src/helpers/hasPersonalKioskRule.ts +7 -0
  62. package/src/helpers/hasRoyaltyRule.ts +7 -0
  63. package/src/helpers/hasTransferPolicyRules.ts +6 -0
  64. package/src/helpers/isExpiredListing.ts +9 -0
  65. package/src/helpers/isNonKioskListing.ts +14 -0
  66. package/src/helpers/isSIngleBid.ts +13 -0
  67. package/src/helpers/kiosk/assertNftInSharedKiosk.ts +31 -0
  68. package/src/helpers/kiosk/getKioskCollectionRoyaltyFeeAmount.ts +71 -0
  69. package/src/helpers/kiosk/getKioskIdFromKioskTx.ts +29 -0
  70. package/src/helpers/kiosk/getKioskPlaceBidCoin.ts +59 -0
  71. package/src/helpers/kiosk/getNativeKioskTransferPolicies.ts +29 -0
  72. package/src/helpers/kiosk/getNativeKioskTransferPoliciesByNftType.ts +21 -0
  73. package/src/helpers/kiosk/getRulePackageId.ts +59 -0
  74. package/src/helpers/kiosk/getTransferPoliciesToResolve.ts +154 -0
  75. package/src/helpers/kiosk/isBluemoveKioskBid.ts +1 -0
  76. package/src/helpers/kiosk/isTradePortKioskBid.ts +4 -0
  77. package/src/helpers/kiosk/kioskListingBcs.ts +19 -0
  78. package/src/helpers/kiosk/kioskTxWrapper.ts +152 -0
  79. package/src/helpers/kiosk/lockNftInsideKioskIfNotLocked.ts +100 -0
  80. package/src/helpers/kiosk/preProcessSharedBulkBuyingData.ts +171 -0
  81. package/src/helpers/kiosk/resolveCustomTransferPolicyRules.ts +75 -0
  82. package/src/helpers/kiosk/resolveFloorPriceRule.ts +21 -0
  83. package/src/helpers/kiosk/resolveKioskLockRule.ts +47 -0
  84. package/src/helpers/kiosk/resolvePersonalKioskRule.ts +23 -0
  85. package/src/helpers/kiosk/resolveRoyaltyRule.ts +57 -0
  86. package/src/helpers/kiosk/resolveTableAllowlistRule.ts +34 -0
  87. package/src/helpers/kiosk/resolveTransferPolicies.ts +158 -0
  88. package/src/helpers/kiosk/sharedKioskState.type.ts +11 -0
  89. package/src/helpers/kiosk/takeAndBorrowNftFromKiosk.ts +50 -0
  90. package/src/helpers/kiosk/takeLockedNftFromKiosk.ts +73 -0
  91. package/src/helpers/kiosk/upgradeKioskRulesPackageId.ts +17 -0
  92. package/src/helpers/originByte/confirmOBTranfer.ts +33 -0
  93. package/src/helpers/originByte/createOBKiosk.ts +14 -0
  94. package/src/helpers/originByte/depositNftIntoOBKiosk.ts +16 -0
  95. package/src/helpers/originByte/getOBBidderKiosk.ts +12 -0
  96. package/src/helpers/originByte/getOBKiosk.ts +24 -0
  97. package/src/helpers/originByte/getOrCreateOBKiosk.ts +42 -0
  98. package/src/helpers/originByte/isOBKiosk.ts +13 -0
  99. package/src/helpers/originByte/isOriginByteBid.ts +30 -0
  100. package/src/helpers/originByte/isOriginByteCollection.ts +11 -0
  101. package/src/helpers/originByte/shareOriginByteKiosk.ts +14 -0
  102. package/src/helpers/rpc/getAcountBalance.ts +18 -0
  103. package/src/helpers/rpc/getObjectType.ts +25 -0
  104. package/src/helpers/splitCoins.ts +12 -0
  105. package/src/helpers/track.ts +20 -0
  106. package/src/helpers/validateMinFloorPrice.ts +22 -0
  107. package/src/index.ts +2 -0
  108. package/src/methods/acceptCollectionBid/acceptCollectionBid.ts +189 -0
  109. package/src/methods/acceptCollectionBid/addAcceptCollectionBIdTxs.ts +398 -0
  110. package/src/methods/acceptNftBids/acceptNftBids.ts +174 -0
  111. package/src/methods/acceptNftBids/addAcceptNftBidTxs.ts +438 -0
  112. package/src/methods/applyFtStrategy/applyFtStrategy.ts +55 -0
  113. package/src/methods/applyNftStrategy/applyNftStrategy.ts +90 -0
  114. package/src/methods/buyListings/addBuyListingTxs.ts +806 -0
  115. package/src/methods/buyListings/buyListings.ts +230 -0
  116. package/src/methods/cancelMultiBid/cancelMultiBid.ts +51 -0
  117. package/src/methods/cancelNftTransfers/addCancelNftTransfersTx.ts +20 -0
  118. package/src/methods/cancelNftTransfers/cancelNftTransfers.ts +118 -0
  119. package/src/methods/claimNfts/addClaimNftsTxs.ts +247 -0
  120. package/src/methods/claimNfts/claimNfts.ts +270 -0
  121. package/src/methods/createMultiBid/createMultiBid.ts +36 -0
  122. package/src/methods/listNfts/addListTxs.ts +210 -0
  123. package/src/methods/listNfts/addRelistTxs.ts +87 -0
  124. package/src/methods/listNfts/listNfts.ts +152 -0
  125. package/src/methods/migrateNftsFromUnsharedToSharedKiosks/migrateNftsFromUnsharedToSharedKiosks.ts +226 -0
  126. package/src/methods/placeCollectionBids/addPlaceCollectionBidTxs.ts +149 -0
  127. package/src/methods/placeCollectionBids/placeCollectionBids.ts +153 -0
  128. package/src/methods/placeNftBids/addPlaceNftBidTxs.ts +154 -0
  129. package/src/methods/placeNftBids/placeNftBids.ts +111 -0
  130. package/src/methods/relistNft/relistNft.ts +153 -0
  131. package/src/methods/removeCollectionBids/addRemoveCollectionBidsTxs.ts +132 -0
  132. package/src/methods/removeCollectionBids/removeCollectionBids.ts +117 -0
  133. package/src/methods/removeNftBids/addRemoveNftBidTxs.ts +122 -0
  134. package/src/methods/removeNftBids/removeNftBids.ts +116 -0
  135. package/src/methods/sponsorNftListing/addSponsorNftListingTx.ts +40 -0
  136. package/src/methods/sponsorNftListing/sponsorNftListing.ts +60 -0
  137. package/src/methods/transferNfts/addTransferNftTx.ts +220 -0
  138. package/src/methods/transferNfts/transferNfts.ts +216 -0
  139. package/src/methods/unlistListings/addUnlistListingTxs.ts +399 -0
  140. package/src/methods/unlistListings/unlistListings.ts +158 -0
  141. package/src/methods/updateMultiBid/updateMultiBid.ts +66 -0
  142. package/src/methods/withdrawProfitsFromKiosks/withdrawProfitsFromKiosks.ts +100 -0
  143. package/src/tests/SuiWallet.ts +83 -0
  144. package/src/utils/addHexPrefix.ts +7 -0
  145. package/src/utils/addLeadingZerosAfter0x.ts +9 -0
  146. package/src/utils/normalizeNftType.ts +7 -0
  147. package/src/utils/printTxBlockTxs.ts +11 -0
  148. package/src/utils/pureValues.ts +13 -0
  149. package/src/utils/toUint8Array.ts +12 -0
  150. package/tsconfig.json +16 -0
  151. package/dist/index.d.ts +0 -194
  152. package/dist/index.js +0 -7419
  153. package/dist/index.js.map +0 -1
@@ -0,0 +1,438 @@
1
+ import { type TransactionArgument } from '@mysten/sui/transactions';
2
+ import { normalizeSuiObjectId, SUI_CLOCK_OBJECT_ID } from '@mysten/sui/utils';
3
+ import {
4
+ BLUEMOVE_CREATOR_CONFIG_OBJECT,
5
+ BLUEMOVE_MARKET_CONFIG_OBJECT,
6
+ BLUEMOVE_OFFER_DATA_OBJECT,
7
+ BLUEMOVE_ROYALTY_COLLECTION_OBJECT,
8
+ TRADEPORT_BIDDING_STORE,
9
+ TRADEPORT_KIOSK_BIDDING_STORE,
10
+ TRADEPORT_MULTI_BID_PACKAGE,
11
+ TRADEPORT_MULTI_BID_STORE,
12
+ } from '../../constants';
13
+ import { gqlChainRequest } from '../../graphql/gqlChainRequest';
14
+ import { fetchMultibidChainIdById } from '../../graphql/queries/fetchMultibidById';
15
+ import { getRoyaltyRuleModule } from '../../helpers/getRoyaltyRuleModule';
16
+ import { getSharedObjects } from '../../helpers/getSharedObjects';
17
+ import { getTransferPolicyRuleNamesFromSuiObject } from '../../helpers/getTransferPolicyRuleNamesFromSuiObject';
18
+ import { hasPersonalKioskRule } from '../../helpers/hasPersonalKioskRule';
19
+ import { hasNativeKioskTransferPolicyRules } from '../../helpers/hasTransferPolicyRules';
20
+ import { isSingleBid } from '../../helpers/isSIngleBid';
21
+ import { assertNftInSharedKiosk } from '../../helpers/kiosk/assertNftInSharedKiosk';
22
+ import {
23
+ getNativeKioskTransferPolicies,
24
+ knownTransferPolicyRules,
25
+ } from '../../helpers/kiosk/getNativeKioskTransferPolicies';
26
+ import { getRulePackageId } from '../../helpers/kiosk/getRulePackageId';
27
+ import { isTradePortKioskBid } from '../../helpers/kiosk/isTradePortKioskBid';
28
+ import { kioskTxWrapper } from '../../helpers/kiosk/kioskTxWrapper';
29
+ import { lockNftInsideKioskIfNotLocked } from '../../helpers/kiosk/lockNftInsideKioskIfNotLocked';
30
+ import {
31
+ resolveCustomTransferPolicyRules,
32
+ customTransferPolicyRuleNames,
33
+ } from '../../helpers/kiosk/resolveCustomTransferPolicyRules';
34
+ import { resolveTransferPolicies } from '../../helpers/kiosk/resolveTransferPolicies';
35
+ import { confirmOBTranfer } from '../../helpers/originByte/confirmOBTranfer';
36
+ import { getOBBidderKiosk } from '../../helpers/originByte/getOBBidderKiosk';
37
+ import { isOriginByteBid } from '../../helpers/originByte/isOriginByteBid';
38
+ import { isOriginByteCollection } from '../../helpers/originByte/isOriginByteCollection';
39
+ import { getObjectType } from '../../helpers/rpc/getObjectType';
40
+ import { addLeadingZerosAfter0x } from '../../utils/addLeadingZerosAfter0x';
41
+ import { type AcceptNftBidTx } from './acceptNftBids';
42
+
43
+ export function addTradeportAcceptNftBidTx({
44
+ tx,
45
+ sharedObjects,
46
+ bidNonce,
47
+ nftTokenId,
48
+ nftType,
49
+ }: AcceptNftBidTx) {
50
+ const { collection, royaltyStrategy } = sharedObjects;
51
+
52
+ if (collection && royaltyStrategy) {
53
+ tx.moveCall({
54
+ target:
55
+ '0xb42dbb7413b79394e1a0175af6ae22b69a5c7cc5df259cd78072b6818217c027::biddings::ob_accept_bid',
56
+ arguments: [
57
+ tx.object(TRADEPORT_BIDDING_STORE),
58
+ tx.pure.address(bidNonce),
59
+ tx.object(nftTokenId),
60
+ tx.object(collection),
61
+ tx.object(royaltyStrategy),
62
+ ],
63
+ typeArguments: [nftType],
64
+ });
65
+ } else {
66
+ tx.moveCall({
67
+ target:
68
+ '0xb42dbb7413b79394e1a0175af6ae22b69a5c7cc5df259cd78072b6818217c027::biddings::accept_bid',
69
+ arguments: [
70
+ tx.object(TRADEPORT_BIDDING_STORE),
71
+ tx.pure.address(bidNonce),
72
+ tx.object(nftTokenId),
73
+ ],
74
+ typeArguments: [nftType],
75
+ });
76
+ }
77
+ }
78
+
79
+ export async function addTradeportKioskAcceptNftBidTx({
80
+ tx,
81
+ suiClient,
82
+ kioskClient,
83
+ transferPolicies,
84
+ seller,
85
+ kioskTx,
86
+ bidNonce,
87
+ nftTokenId,
88
+ nftType,
89
+ royaltyRulePackageId,
90
+ royaltyRuleModule,
91
+ bidAmount,
92
+ shouldSplitRoyaltyFromUserGasCoins,
93
+ beforeResolveKioskTransferRequest,
94
+ }: AcceptNftBidTx) {
95
+ const transferPolicyId = getNativeKioskTransferPolicies(transferPolicies)?.at(0)?.id;
96
+
97
+ await lockNftInsideKioskIfNotLocked({
98
+ tx,
99
+ kioskClient,
100
+ kioskTx,
101
+ nftTokenId,
102
+ nftType,
103
+ transferPolicyId,
104
+ });
105
+
106
+ if (beforeResolveKioskTransferRequest) {
107
+ const [feeCoin, transferRequest] = tx.moveCall({
108
+ target:
109
+ '0x475e98e9c436ec118909f3b9e241d86bcbbc2cf9fba05e99a934823fefb375b7::kiosk_biddings::accept_bid_with_price_lock',
110
+ arguments: [
111
+ tx.object(TRADEPORT_KIOSK_BIDDING_STORE),
112
+ tx.pure.address(bidNonce),
113
+ tx.object(kioskTx.kiosk),
114
+ tx.object(kioskTx.kioskCap),
115
+ tx.pure.address(nftTokenId),
116
+ ],
117
+ typeArguments: [nftType],
118
+ });
119
+
120
+ await beforeResolveKioskTransferRequest?.(feeCoin, transferRequest);
121
+
122
+ await resolveTransferPolicies({
123
+ tx,
124
+ transferPolicies,
125
+ suiClient,
126
+ walletAddress: seller,
127
+ kioskTx,
128
+ kioskClient,
129
+ nftType,
130
+ price: bidAmount?.toString(),
131
+ transferRequest,
132
+ coinToSplit: feeCoin,
133
+ shouldSkipKioskLocking: true,
134
+ });
135
+
136
+ tx.transferObjects([tx.object(feeCoin)], tx.pure.address(addLeadingZerosAfter0x(seller)));
137
+ } else {
138
+ const [feeCoin, transferRequest] = tx.moveCall({
139
+ target:
140
+ '0x475e98e9c436ec118909f3b9e241d86bcbbc2cf9fba05e99a934823fefb375b7::kiosk_biddings::accept_bid_with_purchase_cap',
141
+ arguments: [
142
+ tx.object(TRADEPORT_KIOSK_BIDDING_STORE),
143
+ tx.pure.address(bidNonce),
144
+ tx.object(kioskTx.kiosk),
145
+ tx.object(kioskTx.kioskCap),
146
+ tx.pure.address(nftTokenId),
147
+ ],
148
+ typeArguments: [nftType],
149
+ });
150
+
151
+ if (!shouldSplitRoyaltyFromUserGasCoins) {
152
+ tx.moveCall({
153
+ target: `${royaltyRulePackageId}::${royaltyRuleModule}::pay`,
154
+ typeArguments: [nftType],
155
+ arguments: [tx.object(transferPolicyId), transferRequest, feeCoin],
156
+ });
157
+ }
158
+
159
+ await resolveTransferPolicies({
160
+ tx,
161
+ transferPolicies,
162
+ suiClient,
163
+ walletAddress: seller,
164
+ kioskTx,
165
+ kioskClient,
166
+ nftType,
167
+ price: shouldSplitRoyaltyFromUserGasCoins ? bidAmount?.toString() : '0',
168
+ transferRequest,
169
+ shouldSkipKioskLocking: true,
170
+ shouldSkipResolvingRoyaltyRule: !shouldSplitRoyaltyFromUserGasCoins,
171
+ });
172
+
173
+ if (shouldSplitRoyaltyFromUserGasCoins) {
174
+ tx.transferObjects([tx.object(feeCoin)], tx.pure.address(addLeadingZerosAfter0x(seller)));
175
+ }
176
+ }
177
+ }
178
+
179
+ export async function addOriginByteAcceptNftBidTx({
180
+ tx,
181
+ suiClient,
182
+ sharedObjects,
183
+ sellerKiosk,
184
+ bidNonce,
185
+ nftTokenId,
186
+ nftType,
187
+ itemOwner,
188
+ }: AcceptNftBidTx) {
189
+ await assertNftInSharedKiosk({
190
+ kioskId: sellerKiosk,
191
+ walletAddress: itemOwner,
192
+ });
193
+
194
+ const receiverKiosk = await getOBBidderKiosk({ suiClient, bidNonce });
195
+
196
+ let transferRequest: TransactionArgument;
197
+ if (sellerKiosk) {
198
+ transferRequest = tx.moveCall({
199
+ target:
200
+ '0x8534e4cdfd28709c94330a9783c3d5fe6f5daba0bffb69102ce303c5b38aed5a::bidding::sell_nft_from_kiosk',
201
+ arguments: [
202
+ tx.object(bidNonce),
203
+ tx.object(sellerKiosk),
204
+ tx.object(receiverKiosk),
205
+ tx.pure.address(nftTokenId),
206
+ ],
207
+ typeArguments: [nftType, '0x2::sui::SUI'],
208
+ });
209
+ } else {
210
+ transferRequest = tx.moveCall({
211
+ target:
212
+ '0x8534e4cdfd28709c94330a9783c3d5fe6f5daba0bffb69102ce303c5b38aed5a::bidding::sell_nft',
213
+ arguments: [tx.object(bidNonce), tx.object(receiverKiosk), tx.object(nftTokenId)],
214
+ typeArguments: [nftType, '0x2::sui::SUI'],
215
+ });
216
+ }
217
+
218
+ confirmOBTranfer({ tx, sharedObjects, transferRequest, nftType });
219
+ }
220
+
221
+ export function addBluemoveAcceptNftBidTx({
222
+ tx,
223
+ nftTokenId,
224
+ nftType,
225
+ bidNonce,
226
+ isListedOnBluemove,
227
+ }: AcceptNftBidTx) {
228
+ if (isListedOnBluemove) {
229
+ tx.moveCall({
230
+ target:
231
+ '0xd5dd28cc24009752905689b2ba2bf90bfc8de4549b9123f93519bb8ba9bf9981::marketplace::delist',
232
+ arguments: [tx.object(BLUEMOVE_MARKET_CONFIG_OBJECT), tx.pure.address(nftTokenId)],
233
+ typeArguments: [nftType, nftType],
234
+ });
235
+ }
236
+
237
+ tx.moveCall({
238
+ target:
239
+ '0xd5dd28cc24009752905689b2ba2bf90bfc8de4549b9123f93519bb8ba9bf9981::offer_item::accept_offer_nft',
240
+ arguments: [
241
+ tx.object(BLUEMOVE_MARKET_CONFIG_OBJECT),
242
+ tx.object(BLUEMOVE_ROYALTY_COLLECTION_OBJECT),
243
+ tx.object(BLUEMOVE_CREATOR_CONFIG_OBJECT),
244
+ tx.object(BLUEMOVE_OFFER_DATA_OBJECT),
245
+ tx.pure.u64(bidNonce),
246
+ isListedOnBluemove
247
+ ? ({
248
+ kind: 'Result',
249
+ index: 0,
250
+ } as any)
251
+ : tx.object(nftTokenId),
252
+ ],
253
+ typeArguments: [nftType],
254
+ });
255
+ }
256
+
257
+ export async function addSingleBidAcceptNftBidTx(txData: AcceptNftBidTx) {
258
+ const { nftType, tx, bidNonce, multiBidId, nftTokenId, suiClient, sharedKioskState } = txData;
259
+ const transferPolicies = getNativeKioskTransferPolicies(txData?.transferPolicies);
260
+ const transferPolicy = transferPolicies?.find(
261
+ (policy: { rules: any[] }) => policy?.rules?.length > 0,
262
+ );
263
+ const { chain_id: multiBidChainId, cancelled_at } = multiBidId
264
+ ? ((
265
+ await gqlChainRequest({
266
+ chain: 'sui',
267
+ query: fetchMultibidChainIdById,
268
+ variables: { multiBidId },
269
+ })
270
+ )?.multi_bids?.[0] ?? {})
271
+ : {};
272
+
273
+ if (multiBidChainId && cancelled_at) {
274
+ throw new Error(`MultiBid ${multiBidId} already cancelled`);
275
+ }
276
+
277
+ if (transferPolicy) {
278
+ const allRules = await getTransferPolicyRuleNamesFromSuiObject({
279
+ suiClient,
280
+ transferPolicyId: transferPolicy.id,
281
+ });
282
+
283
+ const unsupportedRule = allRules.find((r) => {
284
+ const moduleName = r.split('::').at(1);
285
+ return (
286
+ !knownTransferPolicyRules.includes(moduleName) &&
287
+ !customTransferPolicyRuleNames.includes(moduleName)
288
+ );
289
+ });
290
+ if (unsupportedRule) {
291
+ throw new Error(
292
+ `Found unsupported transfer policy rule ${unsupportedRule} for ${transferPolicy.id} of ${nftType}`,
293
+ );
294
+ }
295
+
296
+ return kioskTxWrapper({
297
+ tx: txData?.tx,
298
+ kioskClient: txData?.kioskClient,
299
+ kioskOwner: txData?.seller,
300
+ kiosk: txData?.sellerKiosk,
301
+ sharedKioskState,
302
+ async runCommands(kioskTx) {
303
+ if (!txData?.sellerKiosk) {
304
+ kioskTx.place({
305
+ item: txData?.nftTokenId,
306
+ itemType: txData?.nftType,
307
+ });
308
+ }
309
+
310
+ const [transferRequest] = tx.moveCall({
311
+ target: `${TRADEPORT_MULTI_BID_PACKAGE}::tradeport_biddings::accept_bid_with_transfer_policy`,
312
+ typeArguments: [nftType],
313
+ arguments: [
314
+ tx.object(SUI_CLOCK_OBJECT_ID),
315
+ tx.object(TRADEPORT_MULTI_BID_STORE),
316
+ tx.pure.id(normalizeSuiObjectId(bidNonce)),
317
+ tx.pure.option('id', multiBidChainId),
318
+ tx.object(kioskTx.getKiosk() as any),
319
+ tx.object(kioskTx.getKioskCap() as any),
320
+ tx.pure.id(nftTokenId),
321
+ tx.object(transferPolicy.id),
322
+ ],
323
+ });
324
+ // The contract resolves itself to the standard transfer policy rules
325
+ // Resolve custom transfer policy rules (e.g. table_allowlist_rule)
326
+ const customRules = allRules
327
+ .filter((r) => customTransferPolicyRuleNames.includes(r.split('::').at(1)))
328
+ .map((rule) => ({
329
+ rule,
330
+ rulePackageId: rule.split('::')[0],
331
+ moduleName: rule.split('::')[1],
332
+ }));
333
+ if (customRules.length > 0) {
334
+ resolveCustomTransferPolicyRules({
335
+ tx,
336
+ rules: customRules,
337
+ transferRequest,
338
+ nftType,
339
+ policyId: transferPolicy.id,
340
+ });
341
+ }
342
+
343
+ tx.moveCall({
344
+ target: '0x2::transfer_policy::confirm_request',
345
+ arguments: [tx.object(transferPolicy.id), transferRequest],
346
+ typeArguments: [nftType],
347
+ });
348
+ },
349
+ });
350
+ }
351
+
352
+ if (txData.sellerKiosk) {
353
+ throw new Error(`Can't use NFT in kiosk without transfer policy`);
354
+ }
355
+
356
+ tx.moveCall({
357
+ target: `${TRADEPORT_MULTI_BID_PACKAGE}::tradeport_biddings::accept_bid_without_transfer_policy`,
358
+ typeArguments: [nftType],
359
+ arguments: [
360
+ tx.object(SUI_CLOCK_OBJECT_ID),
361
+ tx.object(TRADEPORT_MULTI_BID_STORE),
362
+ tx.pure.id(bidNonce),
363
+ tx.pure.option('id', multiBidChainId),
364
+ tx.object(nftTokenId),
365
+ ],
366
+ });
367
+ }
368
+
369
+ export async function addTradePortAcceptNftBidTxHandler(txData: AcceptNftBidTx) {
370
+ const bidType = await getObjectType({
371
+ suiClient: txData?.suiClient,
372
+ objectId: normalizeSuiObjectId(txData?.bidNonce),
373
+ });
374
+
375
+ if (isSingleBid(bidType)) {
376
+ await addSingleBidAcceptNftBidTx(txData);
377
+ return;
378
+ }
379
+
380
+ if (isOriginByteBid(bidType)) {
381
+ if (isOriginByteCollection(txData?.transferPolicies)) {
382
+ const sharedObjects = await getSharedObjects(txData?.nftType);
383
+ await addOriginByteAcceptNftBidTx({ ...txData, sharedObjects });
384
+
385
+ return;
386
+ }
387
+
388
+ throw new Error(
389
+ `You cannot accept an Origin Byte bid with a NFT outside of an Origin Byte kiosk. Nft Token Id: ${txData?.nftTokenId}`,
390
+ );
391
+ }
392
+
393
+ if (isTradePortKioskBid(bidType)) {
394
+ if (txData?.sellerKiosk) {
395
+ const royaltyRuleModule = getRoyaltyRuleModule(txData?.nftType);
396
+ const royaltyRulePackageId = await getRulePackageId({
397
+ transferPolicies: txData?.transferPolicies,
398
+ suiClient: txData?.suiClient,
399
+ nftType: txData?.nftType,
400
+ ruleType: 'royalty_rule',
401
+ kioskClient: txData?.kioskClient,
402
+ });
403
+
404
+ return kioskTxWrapper({
405
+ tx: txData?.tx,
406
+ kioskClient: txData?.kioskClient,
407
+ kioskOwner: txData?.itemOwner,
408
+ kiosk: txData?.sellerKiosk,
409
+ shouldConvertToPersonalKiosk: Boolean(hasPersonalKioskRule(txData?.transferPolicies)),
410
+ shouldAssertNftInSharedKiosk: true,
411
+ failIfNoKiosk: Boolean(txData?.sellerKiosk),
412
+ sharedKioskState: txData?.sharedKioskState,
413
+ async runCommands(kioskTx) {
414
+ if (hasNativeKioskTransferPolicyRules(txData?.transferPolicies) && !txData?.sellerKiosk) {
415
+ kioskTx.place({
416
+ item: txData?.nftTokenId,
417
+ itemType: txData?.nftType,
418
+ });
419
+ }
420
+
421
+ await addTradeportKioskAcceptNftBidTx({
422
+ ...txData,
423
+ kioskTx,
424
+ royaltyRulePackageId,
425
+ royaltyRuleModule,
426
+ });
427
+ },
428
+ });
429
+ }
430
+
431
+ throw new Error(
432
+ `You cannot accept an Native Kiosk Bid with a NFT outside of a native kiosk. Nft Token Id: ${txData?.nftTokenId}`,
433
+ );
434
+ }
435
+
436
+ const sharedObjects = await getSharedObjects(txData?.nftType);
437
+ addTradeportAcceptNftBidTx({ ...txData, sharedObjects });
438
+ }
@@ -0,0 +1,55 @@
1
+ import { Transaction } from '@mysten/sui/transactions';
2
+ import {
3
+ TRADEPORT_NFT_STRATEGY_PACKAGE_ID,
4
+ TRADEPORT_NFT_STRATEGY_MANAGER_ID,
5
+ TRADEPORT_POOL_REGISTRY_ID,
6
+ TRADEPORT_POOL_VERSIONED_ID,
7
+ } from '../../constants';
8
+ import { getCollectionChainState } from '../../helpers/getCollectionChainState';
9
+
10
+ export type ApplyFtStrategy = {
11
+ collectionId: string;
12
+ strategyFtType?: string;
13
+ tx?: Transaction;
14
+ collectionChainState?: Record<string, unknown>;
15
+ };
16
+
17
+ export async function applyFtStrategy({
18
+ collectionId,
19
+ strategyFtType,
20
+ tx: existingTx,
21
+ collectionChainState,
22
+ }: ApplyFtStrategy): Promise<Transaction> {
23
+ const tx = existingTx ?? new Transaction();
24
+ const chainState = collectionChainState ?? (await getCollectionChainState(collectionId));
25
+ const nftStrategies = (chainState?.nft_strategies ?? {}) as Record<
26
+ string,
27
+ Record<string, unknown>
28
+ >;
29
+ const nftStrategyKeys = Object.keys(nftStrategies);
30
+ const nftType = chainState?.nft_type as string;
31
+
32
+ if (nftStrategyKeys.length === 0) {
33
+ throw new Error('No NFT strategies found for collection');
34
+ }
35
+
36
+ strategyFtType = strategyFtType ?? nftStrategyKeys[0];
37
+
38
+ if (!nftStrategyKeys.includes(strategyFtType)) {
39
+ throw new Error(`Specified FT type ${strategyFtType} is not supported for this collection`);
40
+ }
41
+
42
+ tx.moveCall({
43
+ target: `${TRADEPORT_NFT_STRATEGY_PACKAGE_ID}::tradeport_nft_strategy::apply_ft_strategy`,
44
+ typeArguments: [nftType, strategyFtType],
45
+ arguments: [
46
+ tx.object(TRADEPORT_NFT_STRATEGY_MANAGER_ID),
47
+ tx.object((nftStrategies[strategyFtType] as { kiosk_id: string }).kiosk_id),
48
+ tx.object(TRADEPORT_POOL_REGISTRY_ID),
49
+ tx.object(TRADEPORT_POOL_VERSIONED_ID),
50
+ tx.object.clock(),
51
+ ],
52
+ });
53
+
54
+ return tx;
55
+ }
@@ -0,0 +1,90 @@
1
+ import { Transaction } from '@mysten/sui/transactions';
2
+ import {
3
+ TRADEPORT_NFT_STRATEGY_PACKAGE_ID,
4
+ TRADEPORT_NFT_STRATEGY_MANAGER_ID,
5
+ TRADEPORT_ORDERBOOK_STORE,
6
+ TRADEPORT_LISTINGS_STORE,
7
+ } from '../../constants';
8
+ import { gqlChainRequest } from '../../graphql/gqlChainRequest';
9
+ import { fetchCollectionFloorListingsForMarket } from '../../graphql/queries/fetchCollectionFloorListingForMarket';
10
+ import { getNativeKioskTransferPolicies } from '../../helpers/kiosk/getNativeKioskTransferPolicies';
11
+ import { RequestContext } from '../../SuiTradingClient';
12
+ import { getCollectionChainState } from '../../helpers/getCollectionChainState';
13
+
14
+ export type ApplyNftStrategy = {
15
+ collectionId: string;
16
+ strategyFtType?: string;
17
+ tx?: Transaction;
18
+ };
19
+
20
+ export async function applyTradeportNftStrategy({
21
+ collectionId,
22
+ strategyFtType,
23
+ tx: existingTx,
24
+ }: ApplyNftStrategy): Promise<Transaction> {
25
+ const tx = existingTx ?? new Transaction();
26
+ const chainState = await getCollectionChainState(collectionId);
27
+ const nftStrategies = (chainState?.nft_strategies ?? {}) as Record<
28
+ string,
29
+ Record<string, unknown>
30
+ >;
31
+ const nftStrategyKeys = Object.keys(nftStrategies);
32
+ if (nftStrategyKeys.length === 0) {
33
+ throw new Error('No NFT strategies found for collection');
34
+ }
35
+
36
+ strategyFtType = strategyFtType ?? nftStrategyKeys[0];
37
+
38
+ if (!nftStrategyKeys.includes(strategyFtType)) {
39
+ throw new Error(`Specified FT type ${strategyFtType} is not supported for this collection`);
40
+ }
41
+
42
+ const transferPolicy = getNativeKioskTransferPolicies(chainState?.transfer_policies ?? [])?.at(0);
43
+
44
+ if (!transferPolicy) {
45
+ throw new Error('No transfer policy found for collection');
46
+ }
47
+
48
+ const nftType = chainState?.nft_type as string;
49
+ let suiBalance = BigInt(
50
+ (nftStrategies[strategyFtType] as { sui_balance: string }).sui_balance ?? 0n,
51
+ );
52
+
53
+ const result = await gqlChainRequest({
54
+ chain: 'sui',
55
+ query: fetchCollectionFloorListingsForMarket,
56
+ variables: {
57
+ collectionId,
58
+ marketAddress: TRADEPORT_NFT_STRATEGY_MANAGER_ID,
59
+ totalPrice: suiBalance.toString(),
60
+ },
61
+ });
62
+ if ((result?.listings?.length ?? 0) === 0) {
63
+ throw new Error(
64
+ `No floor listing found for collection with price bellow or equal to ${suiBalance} MIST`,
65
+ );
66
+ }
67
+
68
+ for (const floorListing of result.listings) {
69
+ suiBalance -= BigInt(floorListing.price);
70
+ if (suiBalance < 0n) {
71
+ break;
72
+ }
73
+
74
+ tx.moveCall({
75
+ target: `${TRADEPORT_NFT_STRATEGY_PACKAGE_ID}::tradeport_nft_strategy::apply_tradeport_nft_strategy_confirm_request`,
76
+ typeArguments: [nftType, strategyFtType],
77
+ arguments: [
78
+ tx.object(TRADEPORT_NFT_STRATEGY_MANAGER_ID),
79
+ tx.object((nftStrategies[strategyFtType] as { kiosk_id: string }).kiosk_id),
80
+ tx.object(TRADEPORT_LISTINGS_STORE),
81
+ tx.object(TRADEPORT_ORDERBOOK_STORE),
82
+ tx.object(floorListing.nft.delegated_owner),
83
+ tx.object(floorListing.nft.token_id),
84
+ tx.object(transferPolicy.id),
85
+ ],
86
+ });
87
+ }
88
+
89
+ return tx;
90
+ }