@tradeport/sui-trading-sdk 0.0.0

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 (103) hide show
  1. package/.babel.config.js +3 -0
  2. package/.env.demo +4 -0
  3. package/.eslintrc.json +46 -0
  4. package/.prettierignore +4 -0
  5. package/.prettierrc.json +7 -0
  6. package/README.md +1 -0
  7. package/dist/index.d.mts +90 -0
  8. package/dist/index.d.ts +90 -0
  9. package/dist/index.js +3760 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/index.mjs +3733 -0
  12. package/dist/index.mjs.map +1 -0
  13. package/jest.config.js +7 -0
  14. package/package.json +45 -0
  15. package/src/SuiTradingClient.ts +158 -0
  16. package/src/apiClients/graphqlClient.ts +5 -0
  17. package/src/apiClients/kioskClient.ts +10 -0
  18. package/src/apiClients/suiClient.ts +5 -0
  19. package/src/constants.ts +74 -0
  20. package/src/graphql/createChainGQLQuery.ts +25 -0
  21. package/src/graphql/gqlChainRequest.ts +20 -0
  22. package/src/graphql/queries/fetchAccountKiosks.ts +12 -0
  23. package/src/graphql/queries/fetchBidsById.ts +28 -0
  24. package/src/graphql/queries/fetchCollectionBidById.ts +20 -0
  25. package/src/graphql/queries/fetchCollectionBidsAtSamePrice.ts +28 -0
  26. package/src/graphql/queries/fetchCollectionsById.ts +30 -0
  27. package/src/graphql/queries/fetchCommissionByListingId.ts +13 -0
  28. package/src/graphql/queries/fetchCryptoToUsdRate.ts +13 -0
  29. package/src/graphql/queries/fetchKiosksByOwner.ts +13 -0
  30. package/src/graphql/queries/fetchListingsById.ts +24 -0
  31. package/src/graphql/queries/fetchListingsByNftId.ts +23 -0
  32. package/src/graphql/queries/fetchNftsById.ts +61 -0
  33. package/src/graphql/queries/fetchOwnerCapByKiosk.ts +10 -0
  34. package/src/graphql/queries/fetchPersonalCapByKiosk.ts +10 -0
  35. package/src/graphql/queries/fetchSharedObjectsByType.ts +12 -0
  36. package/src/graphql/queries/fetchTransferPoliciesByType.ts +12 -0
  37. package/src/graphql/queries/getCommissionByListingId.ts +15 -0
  38. package/src/helpers/addOneDollarFee.ts +17 -0
  39. package/src/helpers/addThirdPartyTxFee.ts +17 -0
  40. package/src/helpers/destroyZeroCoin.ts +14 -0
  41. package/src/helpers/getMarketFeePrice.ts +78 -0
  42. package/src/helpers/getNftTypeFromNft.ts +8 -0
  43. package/src/helpers/getSharedObjects.ts +113 -0
  44. package/src/helpers/getSuiToUsdRate.ts +17 -0
  45. package/src/helpers/getTradeportBiddingContractParsedBidAmount.ts +32 -0
  46. package/src/helpers/hasRoyaltyRule.ts +14 -0
  47. package/src/helpers/hasTransferPolicyRules.ts +21 -0
  48. package/src/helpers/isNonKioskListing.ts +7 -0
  49. package/src/helpers/kiosk/getRulePackageId.ts +26 -0
  50. package/src/helpers/kiosk/isBluemoveKioskBid.ts +1 -0
  51. package/src/helpers/kiosk/isTradePortKioskBid.ts +4 -0
  52. package/src/helpers/kiosk/kioskTxWrapper.ts +102 -0
  53. package/src/helpers/kiosk/resolveFloorPriceRule.ts +25 -0
  54. package/src/helpers/kiosk/resolveKioskLockRule.ts +49 -0
  55. package/src/helpers/kiosk/resolvePersonalKioskRule.ts +26 -0
  56. package/src/helpers/kiosk/resolveRoyaltyRule.ts +41 -0
  57. package/src/helpers/kiosk/resolveTransferPolicies.ts +150 -0
  58. package/src/helpers/originByte/confirmOBTranfer.ts +33 -0
  59. package/src/helpers/originByte/createOBKiosk.ts +14 -0
  60. package/src/helpers/originByte/depositNftIntoOBKiosk.ts +14 -0
  61. package/src/helpers/originByte/getOBBidderKiosk.ts +9 -0
  62. package/src/helpers/originByte/getOBKiosk.ts +24 -0
  63. package/src/helpers/originByte/getOrCreateOBKiosk.ts +37 -0
  64. package/src/helpers/originByte/isOBKiosk.ts +13 -0
  65. package/src/helpers/originByte/isOriginByteBid.ts +6 -0
  66. package/src/helpers/originByte/isOriginByteTx.ts +2 -0
  67. package/src/helpers/originByte/shareOriginByteKiosk.ts +14 -0
  68. package/src/helpers/rpc/getAcountBalance.ts +17 -0
  69. package/src/helpers/rpc/getObjectType.ts +10 -0
  70. package/src/helpers/splitCoins.ts +12 -0
  71. package/src/index.ts +3 -0
  72. package/src/methods/acceptCollectionBid/acceptCollectionBid.ts +119 -0
  73. package/src/methods/acceptCollectionBid/addAcceptCollectionBIdTxs.ts +359 -0
  74. package/src/methods/acceptNftBids/acceptNftBids.ts +100 -0
  75. package/src/methods/acceptNftBids/addAcceptNftBidTxs.ts +214 -0
  76. package/src/methods/buyListings/addBuyListingTxs.ts +503 -0
  77. package/src/methods/buyListings/buyListings.ts +143 -0
  78. package/src/methods/claimNfts/addClaimNftsTxs.ts +104 -0
  79. package/src/methods/claimNfts/claimNfts.ts +139 -0
  80. package/src/methods/listNfts/addListTxs.ts +186 -0
  81. package/src/methods/listNfts/addRelistTxs.ts +79 -0
  82. package/src/methods/listNfts/listNfts.ts +80 -0
  83. package/src/methods/placeCollectionBids/addPlaceCollectionBidTxs.ts +146 -0
  84. package/src/methods/placeCollectionBids/placeCollectionBids.ts +120 -0
  85. package/src/methods/placeNftBids/addPlaceNftBidTxs.ts +146 -0
  86. package/src/methods/placeNftBids/placeNftBids.ts +69 -0
  87. package/src/methods/relistNft/relistNft.ts +104 -0
  88. package/src/methods/removeCollectionBid/addRemoveCollectionBidTxs.ts +119 -0
  89. package/src/methods/removeCollectionBid/removeCollectionBid.ts +97 -0
  90. package/src/methods/removeNftBids/addRemoveNftBidTxs.ts +84 -0
  91. package/src/methods/removeNftBids/removeNftBids.ts +80 -0
  92. package/src/methods/transferNfts/addTransferNftTx.ts +78 -0
  93. package/src/methods/transferNfts/transferNfts.ts +107 -0
  94. package/src/methods/unlistListings/addUnlistListingTxs.ts +258 -0
  95. package/src/methods/unlistListings/unlistListings.ts +108 -0
  96. package/src/methods/withdrawKioskProfits/withdrawKioskProfits.ts +25 -0
  97. package/src/tests/SuiWallet.ts +49 -0
  98. package/src/utils/addHexPrefix.ts +7 -0
  99. package/src/utils/addLeadingZerosAfter0x.ts +2 -0
  100. package/src/utils/parseSUI.ts +1 -0
  101. package/src/utils/printTxBlockTxs.ts +5 -0
  102. package/src/utils/toUint8Array.ts +12 -0
  103. package/tsconfig.json +14 -0
@@ -0,0 +1,503 @@
1
+ import {
2
+ BLUEMOVE_CREATOR_CONFIG_OBJECT,
3
+ BLUEMOVE_KIOSK_MARKETPLACE_KIOSK_OBJECT,
4
+ BLUEMOVE_MARKET_CONFIG_OBJECT,
5
+ BLUEMOVE_ROYALTY_COLLECTION_OBJECT,
6
+ HYPERSPACE_MP_TRANSFER_POLICY_TYPE,
7
+ HYPERSPACE_TRANSFER_POLICY_TYPE,
8
+ KEEPSAKE_MARKETPLACE_KIOSK,
9
+ KEEPSAKE_MARKETPLACE_OBJECT,
10
+ SOUFFL3_EXTENSION_OBJECT,
11
+ SOUFFL3_GENERIC_BUY_METHOD_COLLECTIONS,
12
+ SOUFFL3_MARKETPLACE_OBJECT,
13
+ SOUFFL3_VERSION_OBJECT,
14
+ TOCEN_MARKETPLACE_OBJECT,
15
+ TRADEPORT_KIOSK_LISTING_STORE,
16
+ TRADEPORT_LISTING_STORE,
17
+ } from '../../constants';
18
+ import { getCommissionByNftContractId } from '../../graphql/queries/getCommissionByListingId';
19
+ import { destroyZeroCoin } from '../../helpers/destroyZeroCoin';
20
+ import { kioskTxWrapper } from '../../helpers/kiosk/kioskTxWrapper';
21
+ import { resolveTransferPolicies } from '../../helpers/kiosk/resolveTransferPolicies';
22
+ import { confirmOBTranfer } from '../../helpers/originByte/confirmOBTranfer';
23
+ import { getOrCreateOBKiosk } from '../../helpers/originByte/getOrCreateOBKiosk';
24
+ import { isOriginByteTx } from '../../helpers/originByte/isOriginByteTx';
25
+ import { shareOriginByteKiosk } from '../../helpers/originByte/shareOriginByteKiosk';
26
+ import { splitCoins } from '../../helpers/splitCoins';
27
+ import { addLeadingZerosAfter0x } from '../../utils/addLeadingZerosAfter0x';
28
+ import { type BuyTx, type TocenBuyTx } from './buyListings';
29
+
30
+ export function addTradePortBuyTx({ txBlock, nftType, listingNonce, price, sharedObjects }: BuyTx) {
31
+ const [coin] = splitCoins({ txBlock, amounts: [txBlock.pure(price)] });
32
+
33
+ if (!coin) throw new Error('Coin could not be split');
34
+
35
+ const { collection, royaltyStrategy } = sharedObjects;
36
+ if (collection && royaltyStrategy) {
37
+ txBlock.moveCall({
38
+ target:
39
+ '0xb42dbb7413b79394e1a0175af6ae22b69a5c7cc5df259cd78072b6818217c027::listings::ob_buy',
40
+ arguments: [
41
+ txBlock.object(TRADEPORT_LISTING_STORE),
42
+ txBlock.pure(listingNonce),
43
+ txBlock.object(coin),
44
+ txBlock.object(collection),
45
+ txBlock.object(royaltyStrategy),
46
+ ],
47
+ typeArguments: [nftType],
48
+ });
49
+ } else {
50
+ txBlock.moveCall({
51
+ target: '0xb42dbb7413b79394e1a0175af6ae22b69a5c7cc5df259cd78072b6818217c027::listings::buy',
52
+ arguments: [
53
+ txBlock.object(TRADEPORT_LISTING_STORE),
54
+ txBlock.pure(listingNonce),
55
+ txBlock.object(coin),
56
+ ],
57
+ typeArguments: [nftType],
58
+ });
59
+ }
60
+
61
+ destroyZeroCoin({ txBlock, coin });
62
+ }
63
+
64
+ export const addTradeportKioskBuyTx = async ({
65
+ txBlock,
66
+ kioskTx,
67
+ nftType,
68
+ nftTokenId,
69
+ price,
70
+ sellerKiosk,
71
+ }: BuyTx) => {
72
+ const [coin] = splitCoins({ txBlock, amounts: [txBlock.pure(price)] });
73
+
74
+ if (!coin) throw new Error('Coin could not be split');
75
+
76
+ const [kioskItem, transferRequest, kioskPrice] = txBlock.moveCall({
77
+ target:
78
+ '0x33a9e4a3089d911c2a2bf16157a1d6a4a8cbd9a2106a98ecbaefe6ed370d7a25::kiosk_listings::buy',
79
+ arguments: [
80
+ txBlock.object(TRADEPORT_KIOSK_LISTING_STORE),
81
+ txBlock.object(sellerKiosk),
82
+ txBlock.object(kioskTx.kiosk.value ?? kioskTx.kiosk),
83
+ txBlock.pure(nftTokenId),
84
+ txBlock.object(coin),
85
+ ],
86
+ typeArguments: [nftType],
87
+ });
88
+
89
+ await resolveTransferPolicies({
90
+ txBlock,
91
+ kioskTx,
92
+ nftType,
93
+ priceObjectArgument: kioskPrice,
94
+ kioskItem,
95
+ transferRequest,
96
+ });
97
+
98
+ destroyZeroCoin({ txBlock, coin });
99
+ };
100
+
101
+ export async function addOriginByteBuyTx({
102
+ txBlock,
103
+ sharedObjects,
104
+ buyer,
105
+ nftTokenId,
106
+ nftType,
107
+ listingNonce,
108
+ price,
109
+ }: BuyTx) {
110
+ const { orderbook } = sharedObjects;
111
+ const { kiosk: buyerKiosk, isNewKiosk: isNewBuyerKiosk } = await getOrCreateOBKiosk({
112
+ txBlock,
113
+ address: buyer,
114
+ });
115
+ const [coin] = splitCoins({ txBlock, amounts: [txBlock.pure(price)] });
116
+
117
+ if (!coin) throw new Error('Coin could not be split');
118
+
119
+ const transferRequest = txBlock.moveCall({
120
+ target:
121
+ '0x8534e4cdfd28709c94330a9783c3d5fe6f5daba0bffb69102ce303c5b38aed5a::orderbook::buy_nft',
122
+ arguments: [
123
+ txBlock.object(orderbook),
124
+ txBlock.object(listingNonce),
125
+ txBlock.object(buyerKiosk),
126
+ txBlock.pure(nftTokenId),
127
+ txBlock.pure(price),
128
+ txBlock.object(coin),
129
+ ],
130
+ typeArguments: [nftType, '0x2::sui::SUI'],
131
+ });
132
+
133
+ confirmOBTranfer({ txBlock, sharedObjects, transferRequest, nftType });
134
+
135
+ destroyZeroCoin({ txBlock, coin });
136
+
137
+ if (isNewBuyerKiosk) {
138
+ await shareOriginByteKiosk({ txBlock, kiosk: buyerKiosk });
139
+ }
140
+ }
141
+
142
+ export const addHyperspaceKioskBuyTx = async ({
143
+ txBlock,
144
+ kioskTx,
145
+ nftType,
146
+ nftTokenId,
147
+ price,
148
+ sellerKiosk,
149
+ }: BuyTx) => {
150
+ const [coin] = splitCoins({ txBlock, amounts: [txBlock.pure(price)] });
151
+
152
+ if (!coin) throw new Error('Coin could not be split');
153
+
154
+ const [kioskItem, transferRequest, hyperspaceTransferRequest, hyperspaceMpTransferRequest] =
155
+ txBlock.moveCall({
156
+ target:
157
+ '0x6ea97b03c441edd54ae89224bf9560e583ee66c37e6c246f5db35258e580ba94::hyperspace::purchase',
158
+ arguments: [txBlock.object(sellerKiosk), txBlock.pure(nftTokenId), txBlock.object(coin)],
159
+ typeArguments: [nftType, HYPERSPACE_MP_TRANSFER_POLICY_TYPE],
160
+ });
161
+
162
+ const customTransferPolicies = [
163
+ {
164
+ type: HYPERSPACE_TRANSFER_POLICY_TYPE,
165
+ transferRequest: hyperspaceTransferRequest,
166
+ },
167
+ {
168
+ type: HYPERSPACE_MP_TRANSFER_POLICY_TYPE,
169
+ transferRequest: hyperspaceMpTransferRequest,
170
+ },
171
+ ];
172
+
173
+ await resolveTransferPolicies({
174
+ txBlock,
175
+ kioskTx,
176
+ nftType,
177
+ price: price?.toString(),
178
+ kioskItem,
179
+ transferRequest,
180
+ customTransferPolicies,
181
+ });
182
+ };
183
+
184
+ export function addBluemoveBuyTx({ txBlock, nftTokenId, nftType, price }: BuyTx) {
185
+ const [coin] = splitCoins({ txBlock, amounts: [txBlock.pure(price)] });
186
+
187
+ if (!coin) throw new Error('Coin could not be split');
188
+
189
+ txBlock.moveCall({
190
+ target:
191
+ '0xd5dd28cc24009752905689b2ba2bf90bfc8de4549b9123f93519bb8ba9bf9981::marketplace::buy_and_take',
192
+ arguments: [
193
+ txBlock.object(BLUEMOVE_MARKET_CONFIG_OBJECT),
194
+ txBlock.object(BLUEMOVE_ROYALTY_COLLECTION_OBJECT),
195
+ txBlock.object(BLUEMOVE_CREATOR_CONFIG_OBJECT),
196
+ txBlock.pure(nftTokenId),
197
+ txBlock.object(coin),
198
+ txBlock.pure(price),
199
+ ],
200
+ typeArguments: [nftType, nftType],
201
+ });
202
+ }
203
+
204
+ export async function addBluemoveKioskBuyTx({
205
+ txBlock,
206
+ kioskTx,
207
+ sharedObjects,
208
+ nftTokenId,
209
+ nftType,
210
+ price,
211
+ sellerKiosk,
212
+ }: BuyTx) {
213
+ const { transferPolicy } = sharedObjects;
214
+
215
+ const [coin1, coin2] = splitCoins({
216
+ txBlock,
217
+ amounts: [txBlock.pure(price), txBlock.pure(price * 0.025)],
218
+ });
219
+
220
+ if (!coin1 || !coin2) throw new Error('Coin could not be split');
221
+
222
+ txBlock.mergeCoins(txBlock.object(coin1), [txBlock.object(coin2)]);
223
+
224
+ const [kioskItem, transferRequest] = txBlock.moveCall({
225
+ target:
226
+ '0xcc97b74ed95c8e8a3ed88050a898727dee37896da579fc400d482b64db6149ff::kiosk_trade::kiosk_buy_v2',
227
+ arguments: [
228
+ txBlock.object(BLUEMOVE_KIOSK_MARKETPLACE_KIOSK_OBJECT),
229
+ txBlock.object(sellerKiosk),
230
+ txBlock.object(transferPolicy),
231
+ txBlock.object(kioskTx.kiosk.value ?? kioskTx.kiosk),
232
+ txBlock.pure(nftTokenId),
233
+ txBlock.pure(price),
234
+ txBlock.object(coin1),
235
+ ],
236
+ typeArguments: [nftType],
237
+ });
238
+
239
+ await resolveTransferPolicies({
240
+ txBlock,
241
+ kioskTx,
242
+ nftType,
243
+ price: price?.toString(),
244
+ kioskItem,
245
+ transferRequest,
246
+ });
247
+ }
248
+
249
+ export function addSouffl3BuyTx({
250
+ txBlock,
251
+ sharedObjects,
252
+ nftType,
253
+ price,
254
+ listingNonce,
255
+ collectionId,
256
+ buyer,
257
+ }: BuyTx) {
258
+ const [coin] = splitCoins({ txBlock, amounts: [txBlock.pure(price)] });
259
+
260
+ const { transferPolicy } = sharedObjects;
261
+
262
+ if (transferPolicy && !SOUFFL3_GENERIC_BUY_METHOD_COLLECTIONS?.includes(collectionId)) {
263
+ const [coinToDestroy] = txBlock.moveCall({
264
+ target:
265
+ '0x30d90b5b67be77e6e06f02dae9f0f2fcdad16e38854316ae8a7b4f5b4971f5e0::Market::buy_with_sui_with_ext',
266
+ arguments: [
267
+ txBlock.object(SOUFFL3_VERSION_OBJECT),
268
+ txBlock.object(SOUFFL3_EXTENSION_OBJECT),
269
+ txBlock.object(transferPolicy),
270
+ txBlock.object(listingNonce),
271
+ txBlock.pure(price),
272
+ txBlock.object(SOUFFL3_MARKETPLACE_OBJECT),
273
+ txBlock.object(coin),
274
+ ],
275
+ typeArguments: [nftType],
276
+ });
277
+
278
+ destroyZeroCoin({ txBlock, coin: coinToDestroy });
279
+ } else {
280
+ const [coinToDestroy] = txBlock.moveCall({
281
+ target:
282
+ '0x30d90b5b67be77e6e06f02dae9f0f2fcdad16e38854316ae8a7b4f5b4971f5e0::Market::buy_generic_with_ext',
283
+ arguments: [
284
+ txBlock.object(SOUFFL3_VERSION_OBJECT),
285
+ txBlock.object(SOUFFL3_EXTENSION_OBJECT),
286
+ txBlock.object(listingNonce),
287
+ txBlock.pure(price),
288
+ txBlock.object(SOUFFL3_MARKETPLACE_OBJECT),
289
+ txBlock.object(coin),
290
+ ],
291
+ typeArguments: [nftType, '0x2::sui::SUI'],
292
+ });
293
+
294
+ destroyZeroCoin({ txBlock, coin: coinToDestroy });
295
+ }
296
+ }
297
+
298
+ export function addSomisBuyTx({ txBlock, sharedObjects, nftTokenId, nftType, price }: BuyTx) {
299
+ const [coin] = splitCoins({ txBlock, amounts: [txBlock.pure(price)] });
300
+
301
+ if (!coin) throw new Error('Coin could not be split');
302
+
303
+ txBlock.moveCall({
304
+ target:
305
+ '0xf0b0beb956e26bde50dbd6ac393026c4525aee3b194a9478f09748f7211b5a02::marketplace::buy_nft',
306
+ arguments: [
307
+ txBlock.object(sharedObjects?.marketplace),
308
+ txBlock.pure(nftTokenId),
309
+ txBlock.object(coin),
310
+ ],
311
+ typeArguments: [nftType, '0x2::sui::SUI'],
312
+ });
313
+ }
314
+
315
+ export function addKeepsakeBuyTx({
316
+ txBlock,
317
+ sharedObjects,
318
+ buyer,
319
+ nftTokenId,
320
+ nftType,
321
+ price,
322
+ royalty,
323
+ }: BuyTx) {
324
+ const { keepsakeRoyaltyStrategy, transferPolicy } = sharedObjects;
325
+
326
+ const [coin1, coin2] = splitCoins({
327
+ txBlock,
328
+ amounts: [
329
+ txBlock.pure(price),
330
+ txBlock.pure((price * Number(royalty)) / 100 + price * Number(royalty) * 0.00005),
331
+ ],
332
+ });
333
+
334
+ if (!coin1 || !coin2) throw new Error('Coin could not be split');
335
+
336
+ const [balance] = txBlock.moveCall({
337
+ target: '0x2::coin::into_balance',
338
+ arguments: [txBlock.object(coin2)],
339
+ typeArguments: ['0x2::sui::SUI'],
340
+ });
341
+
342
+ if (!balance) throw new Error('Coin into_balance failed');
343
+
344
+ const [transferRequest] = txBlock.moveCall({
345
+ target:
346
+ '0x02be8c4a1a3cea4d3255d870d367c87838a8cc2bfe4f216a6b67b153027087a7::keepsake_marketplace::buy',
347
+ arguments: [
348
+ txBlock.object(KEEPSAKE_MARKETPLACE_OBJECT),
349
+ txBlock.object(KEEPSAKE_MARKETPLACE_KIOSK),
350
+ txBlock.pure(nftTokenId),
351
+ txBlock.object(coin1),
352
+ ],
353
+ typeArguments: [nftType],
354
+ });
355
+
356
+ if (!transferRequest) throw new Error('Transfer request could not be created');
357
+
358
+ txBlock.moveCall({
359
+ target:
360
+ '0x02be8c4a1a3cea4d3255d870d367c87838a8cc2bfe4f216a6b67b153027087a7::keepsake_royalties::confirm_transfer_with_balance',
361
+ arguments: [
362
+ txBlock.object(keepsakeRoyaltyStrategy),
363
+ txBlock.object(transferRequest),
364
+ txBlock.object(balance),
365
+ ],
366
+ typeArguments: [nftType],
367
+ });
368
+
369
+ txBlock.moveCall({
370
+ target:
371
+ '0x02be8c4a1a3cea4d3255d870d367c87838a8cc2bfe4f216a6b67b153027087a7::transfer_policy::confirm_request',
372
+ arguments: [txBlock.object(transferPolicy), txBlock.object(transferRequest)],
373
+ typeArguments: [nftType],
374
+ });
375
+
376
+ const [balanceToTransfer] = txBlock.moveCall({
377
+ target: '0x2::coin::from_balance',
378
+ arguments: [txBlock.object(balance)],
379
+ typeArguments: ['0x2::sui::SUI'],
380
+ });
381
+
382
+ if (!balanceToTransfer) throw new Error('Coin from_balance failed');
383
+
384
+ txBlock.transferObjects(
385
+ [txBlock.object(balanceToTransfer)],
386
+ txBlock.pure(addLeadingZerosAfter0x(buyer)),
387
+ );
388
+ }
389
+
390
+ export const addTocenBuyTx = ({ txBlock, nftTokenIds, nftType, price }: TocenBuyTx) => {
391
+ const [coin] = splitCoins({ txBlock, amounts: [txBlock.pure(price)] });
392
+
393
+ if (!coin) throw new Error('Coin could not be split');
394
+
395
+ txBlock.moveCall({
396
+ target:
397
+ '0x3605d91c559e80cf8fdeabae9abaccb0bc38f96eac0b32bf47e95a9159a5277f::tocen_marketplace::buy_cart',
398
+ arguments: [
399
+ txBlock.pure(TOCEN_MARKETPLACE_OBJECT),
400
+ txBlock.pure(nftTokenIds),
401
+ txBlock.object(coin),
402
+ ],
403
+ typeArguments: [nftType],
404
+ });
405
+ };
406
+
407
+ export async function addTradePortBuyTxHandler(txData: BuyTx) {
408
+ if (txData?.listingNonce && isOriginByteTx(txData?.sharedObjects)) {
409
+ await addOriginByteBuyTx(txData);
410
+ return;
411
+ }
412
+
413
+ if (txData?.sellerKiosk) {
414
+ return kioskTxWrapper({
415
+ txBlock: txData?.txBlock,
416
+ kioskOwner: txData?.buyer,
417
+ kiosk: txData?.sellerKiosk,
418
+ shouldConvertToPersonalKiosk: true,
419
+ async tx(kioskTx) {
420
+ await addTradeportKioskBuyTx({
421
+ ...txData,
422
+ kioskTx,
423
+ });
424
+ },
425
+ });
426
+ }
427
+
428
+ addTradePortBuyTx(txData);
429
+ }
430
+
431
+ export async function addHyperspaceBuyTxHandler(txData: BuyTx) {
432
+ if (txData?.listingNonce && isOriginByteTx(txData?.sharedObjects)) {
433
+ await addOriginByteBuyTx(txData);
434
+ return;
435
+ }
436
+
437
+ return kioskTxWrapper({
438
+ txBlock: txData?.txBlock,
439
+ kioskOwner: txData?.buyer,
440
+ kiosk: txData?.sellerKiosk,
441
+ shouldConvertToPersonalKiosk: true,
442
+ async tx(kioskTx) {
443
+ await addHyperspaceKioskBuyTx({
444
+ ...txData,
445
+ kioskTx,
446
+ });
447
+ },
448
+ });
449
+ }
450
+
451
+ export async function addBluemoveBuyTxHandler(txData: BuyTx) {
452
+ if (txData?.listingNonce && isOriginByteTx(txData?.sharedObjects)) {
453
+ await addOriginByteBuyTx(txData);
454
+ return;
455
+ }
456
+
457
+ if (txData?.sellerKiosk) {
458
+ return kioskTxWrapper({
459
+ txBlock: txData?.txBlock,
460
+ kioskOwner: txData?.buyer,
461
+ kiosk: txData?.sellerKiosk,
462
+ shouldConvertToPersonalKiosk: true,
463
+ async tx(kioskTx) {
464
+ await addBluemoveKioskBuyTx({
465
+ ...txData,
466
+ kioskTx,
467
+ });
468
+ },
469
+ });
470
+ }
471
+
472
+ addBluemoveBuyTx(txData);
473
+ }
474
+
475
+ export async function addClutchyBuyTxHandler(txData: BuyTx) {
476
+ await addOriginByteBuyTx(txData);
477
+ }
478
+
479
+ export async function addSouffl3BuyTxHandler(txData: BuyTx) {
480
+ addSouffl3BuyTx(txData);
481
+ }
482
+
483
+ export async function addSomisBuyTxHandler(txData: BuyTx) {
484
+ if (txData?.sharedObjects?.marketplace) {
485
+ addSomisBuyTx(txData);
486
+ return;
487
+ }
488
+
489
+ return addOriginByteBuyTx(txData);
490
+ }
491
+
492
+ export async function addKeepsakeBuyTxHandler(txData: BuyTx) {
493
+ const commission = await getCommissionByNftContractId(txData?.nftContractId);
494
+
495
+ addKeepsakeBuyTx({
496
+ ...txData,
497
+ royalty: commission?.royalty,
498
+ });
499
+ }
500
+
501
+ export function addTocenBuyTxHandler(txData: TocenBuyTx) {
502
+ addTocenBuyTx(txData);
503
+ }
@@ -0,0 +1,143 @@
1
+ import { TransactionBlock } from '@mysten/sui.js/transactions';
2
+ import { gqlChainRequest } from '../../graphql/gqlChainRequest';
3
+ import { fetchListingsById } from '../../graphql/queries/fetchListingsById';
4
+ import { addThirdPartyTxFee } from '../../helpers/addThirdPartyTxFee';
5
+ import { getNftTypeFromNft } from '../../helpers/getNftTypeFromNft';
6
+ import { getSharedObjects } from '../../helpers/getSharedObjects';
7
+ import {
8
+ addBluemoveBuyTxHandler,
9
+ addClutchyBuyTxHandler,
10
+ addHyperspaceBuyTxHandler,
11
+ addKeepsakeBuyTxHandler,
12
+ addSomisBuyTxHandler,
13
+ addSouffl3BuyTxHandler,
14
+ addTocenBuyTxHandler,
15
+ addTradePortBuyTxHandler,
16
+ } from './addBuyListingTxs';
17
+
18
+ type BuyTxBase = {
19
+ txBlock: TransactionBlock;
20
+ sharedObjects: any;
21
+ kioskTx?: any;
22
+ buyer: string;
23
+ nftTokenId: string;
24
+ nftType: string;
25
+ listingId: string;
26
+ listingNonce: string;
27
+ price: number;
28
+ sellerKiosk: string;
29
+ collectionId: string;
30
+ nftContractId: string;
31
+ remainingAccountBalance?: number;
32
+ royalty?: number;
33
+ };
34
+
35
+ type NormalBuyTx = {
36
+ nftTokenIds?: never;
37
+ } & BuyTxBase;
38
+
39
+ export type TocenBuyTx = {
40
+ nftTokenIds: string[];
41
+ } & BuyTxBase;
42
+
43
+ export type BuyTx = NormalBuyTx | TocenBuyTx;
44
+
45
+ export type BuyListing = {
46
+ listingId: string;
47
+ walletAddress: string;
48
+ };
49
+
50
+ export type BuyListings = {
51
+ listingIds: string[];
52
+ walletAddress: string;
53
+ };
54
+
55
+ export const buyListings = async ({
56
+ listingIds,
57
+ walletAddress,
58
+ }: BuyListings): Promise<TransactionBlock> => {
59
+ const res = await gqlChainRequest({
60
+ chain: 'sui',
61
+ query: fetchListingsById,
62
+ variables: { listingIds },
63
+ });
64
+
65
+ if (res?.listings?.length === 0) {
66
+ throw new Error('No listings found');
67
+ }
68
+
69
+ const txBlock = new TransactionBlock();
70
+ const tocenTokenIds: string[] = [];
71
+ let tocenNftType = '';
72
+ let tocenTotalPrice = 0;
73
+
74
+ for (const listing of res.listings) {
75
+ if (!listing?.listed) {
76
+ throw new Error(`Listing ${listing?.id} is not listed`);
77
+ }
78
+
79
+ const sharedObjects = await getSharedObjects(
80
+ listing?.nft?.properties?.nft_type || listing?.nft?.contract?.properties?.nft_type,
81
+ );
82
+
83
+ const buyTxData: BuyTx = {
84
+ txBlock,
85
+ sharedObjects,
86
+ buyer: walletAddress,
87
+ nftTokenId: listing.nft?.token_id,
88
+ nftType: getNftTypeFromNft(listing?.nft),
89
+ listingId: listing?.id,
90
+ listingNonce: listing?.nonce,
91
+ price: listing?.price,
92
+ sellerKiosk: listing.nft?.chain_state?.kiosk_id,
93
+ collectionId: listing?.nft?.collection_id,
94
+ nftContractId: listing?.nft?.contract_id,
95
+ };
96
+
97
+ switch (listing?.market_name) {
98
+ case 'tradeport':
99
+ await addTradePortBuyTxHandler(buyTxData);
100
+ break;
101
+ case 'hyperspace':
102
+ await addHyperspaceBuyTxHandler(buyTxData);
103
+ break;
104
+ case 'bluemove':
105
+ await addBluemoveBuyTxHandler(buyTxData);
106
+ break;
107
+ case 'clutchy':
108
+ await addClutchyBuyTxHandler(buyTxData);
109
+ break;
110
+ case 'souffl3':
111
+ await addSouffl3BuyTxHandler(buyTxData);
112
+ break;
113
+ case 'somis':
114
+ await addSomisBuyTxHandler(buyTxData);
115
+ break;
116
+ case 'keepsake':
117
+ await addKeepsakeBuyTxHandler(buyTxData);
118
+ break;
119
+ case 'tocen':
120
+ tocenTokenIds.push(buyTxData?.nftTokenId);
121
+ tocenNftType = buyTxData?.nftType;
122
+ tocenTotalPrice += Number(listing.price);
123
+ break;
124
+ default:
125
+ throw new Error('Marketplace not supported');
126
+ }
127
+
128
+ if (listing?.market_name !== 'tradeport') {
129
+ await addThirdPartyTxFee(txBlock, listing?.price);
130
+ }
131
+ }
132
+
133
+ if (tocenTokenIds?.length > 0) {
134
+ addTocenBuyTxHandler({
135
+ txBlock,
136
+ nftType: tocenNftType,
137
+ nftTokenIds: tocenTokenIds,
138
+ price: tocenTotalPrice,
139
+ } as TocenBuyTx);
140
+ }
141
+
142
+ return new TransactionBlock(txBlock);
143
+ };