@tradeport/sui-trading-sdk 0.3.8 → 0.4.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 (31) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/index.d.mts +38 -2
  3. package/dist/index.d.ts +38 -2
  4. package/dist/index.js +409 -350
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +409 -350
  7. package/dist/index.mjs.map +1 -1
  8. package/package.json +1 -1
  9. package/src/SuiTradingClient.ts +23 -2
  10. package/src/constants.ts +11 -0
  11. package/src/graphql/queries/fetchBidsById.ts +1 -0
  12. package/src/graphql/queries/fetchCollectionBidById.ts +1 -0
  13. package/src/graphql/queries/fetchCollectionBidsAtSamePrice.ts +1 -0
  14. package/src/graphql/queries/fetchMultibidById.ts +10 -0
  15. package/src/helpers/isSIngleBid.ts +13 -0
  16. package/src/helpers/kiosk/getKioskTransferPolicies.ts +7 -0
  17. package/src/helpers/kiosk/kioskTxWrapper.ts +8 -5
  18. package/src/methods/acceptCollectionBid/acceptCollectionBid.ts +2 -0
  19. package/src/methods/acceptCollectionBid/addAcceptCollectionBIdTxs.ts +10 -1
  20. package/src/methods/acceptNftBids/acceptNftBids.ts +3 -0
  21. package/src/methods/acceptNftBids/addAcceptNftBidTxs.ts +94 -1
  22. package/src/methods/cancelMultiBid/cancelMultiBid.ts +35 -0
  23. package/src/methods/createMultiBid/createMultiBid.ts +35 -0
  24. package/src/methods/placeCollectionBids/placeCollectionBids.ts +26 -11
  25. package/src/methods/placeNftBids/addPlaceNftBidTxs.ts +100 -230
  26. package/src/methods/placeNftBids/placeNftBids.ts +21 -14
  27. package/src/methods/removeCollectionBids/addRemoveCollectionBidsTxs.ts +10 -1
  28. package/src/methods/removeNftBids/addRemoveNftBidTxs.ts +30 -0
  29. package/src/methods/removeNftBids/removeNftBids.ts +2 -0
  30. package/src/methods/updateMultiBid/updateMultiBid.ts +59 -0
  31. package/src/tests/SuiWallet.ts +1 -1
@@ -1,263 +1,133 @@
1
1
  import {
2
2
  ORIGIN_BYTE_NFT_TYPES_MISSING_ORDERBOOK,
3
- TRADEPORT_BENEFICIARY_ADDRESS,
4
- TRADEPORT_BIDDING_STORE,
5
- TRADEPORT_KIOSK_BIDDING_STORE,
3
+ TRADEPORT_MULTI_BID_PACKAGE,
4
+ TRADEPORT_MULTI_BID_STORE,
5
+ DYNAMIC_COLLECTION_IDS,
6
6
  } from '../../constants';
7
- import { destroyZeroCoin } from '../../helpers/destroyZeroCoin';
8
- import { getMarketFeePrice } from '../../helpers/getMarketFeePrice';
9
- import { getRoyaltyRuleModule } from '../../helpers/getRoyaltyRuleModule';
10
- import { getTradeportBiddingContractBidAmount } from '../../helpers/getTradeportBiddingContractBidAmount';
11
- import { hasTransferPolicyRules } from '../../helpers/hasTransferPolicyRules';
12
- import { getKioskPlaceBidCoin } from '../../helpers/kiosk/getKioskPlaceBidCoin';
13
7
  import { getKioskTransferPolicies } from '../../helpers/kiosk/getKioskTransferPolicies';
14
- import { getRulePackageId } from '../../helpers/kiosk/getRulePackageId';
15
- import { getOrCreateOBKiosk } from '../../helpers/originByte/getOrCreateOBKiosk';
16
- import { isOriginByteTx } from '../../helpers/originByte/isOriginByteTx';
17
- import { splitCoins } from '../../helpers/splitCoins';
18
8
  import { normalizedNftType } from '../../utils/normalizeNftType';
19
9
  import { type PlaceNftBidTx } from './placeNftBids';
10
+ import { type SuiClient } from '@mysten/sui/client';
11
+ import { gqlChainRequest } from '../../graphql/gqlChainRequest';
12
+ import { fetchMultibidChainIdById } from '../../graphql/queries/fetchMultibidById';
13
+ import { fromHex, normalizeSuiObjectId } from '@mysten/sui/utils';
14
+ import { isOriginByteTx } from '../../helpers/originByte/isOriginByteTx';
20
15
 
21
- function addTradePortPlaceNftBidTx({
22
- tx,
23
- collectionId,
24
- nftTokenId,
25
- nftType,
26
- bidAmount,
27
- }: PlaceNftBidTx) {
28
- const amountToBid = getTradeportBiddingContractBidAmount({ bidAmount, collectionId });
29
- const marketFeePrice = getMarketFeePrice({ price: amountToBid, collectionId });
30
-
31
- const [coin] = splitCoins({ tx, amounts: [tx.pure.u64(amountToBid + marketFeePrice)] });
32
-
33
- tx.moveCall({
34
- target: '0x398aae1ad267d989dcc99ba449b0a30101a6b851ec1284ccddab5937df66bfcf::biddings::bid',
35
- arguments: [
36
- tx.object(TRADEPORT_BIDDING_STORE),
37
- tx.pure.address(nftTokenId),
38
- tx.pure.u64(amountToBid),
39
- tx.object(coin),
40
- tx.pure.u64(marketFeePrice),
41
- tx.pure.address(TRADEPORT_BENEFICIARY_ADDRESS),
42
- ],
43
- typeArguments: [nftType],
44
- });
45
-
46
- destroyZeroCoin({ tx, coin });
47
- }
48
-
49
- type KumoBidAttributes = {
50
- accessory?: string;
51
- background?: string;
52
- eyes?: string;
53
- fur_colour?: string;
54
- mouth?: string;
55
- tail?: string;
56
- one_of_one?: string;
57
- };
58
-
59
- async function addTradePortKioskPlaceNftBidTx({
60
- tx,
61
- suiClient,
62
- bidder,
63
- collectionId,
64
- nftTokenId,
65
- nftType,
66
- bidAmount,
67
- royaltyRulePackageId,
68
- royaltyRuleModule,
69
- }: PlaceNftBidTx) {
70
- const transferPolicyId = await getKioskTransferPolicies(nftType).then(
71
- (policies) => policies?.[0]?.id,
72
- );
73
- const marketFeePrice = getMarketFeePrice({ price: bidAmount, collectionId });
16
+ export async function addTradePortPlaceNftBidTxHandler(txData: PlaceNftBidTx) {
17
+ if (
18
+ isOriginByteTx(txData?.sharedObjects) &&
19
+ !ORIGIN_BYTE_NFT_TYPES_MISSING_ORDERBOOK?.includes(normalizedNftType(txData?.nftType))
20
+ ) {
21
+ throw new Error('OriginByte bidding not supported currently');
22
+ }
74
23
 
75
- const coin = await getKioskPlaceBidCoin({
24
+ const {
76
25
  tx,
77
- suiClient,
78
- bidder,
79
26
  nftType,
80
- bidAmount,
81
- marketFeePrice,
82
- royaltyRulePackageId,
83
- royaltyRuleModule,
84
- transferPolicyId,
85
- });
27
+ multiBidId,
28
+ multiBidChainId: existingMultiBidChainId,
29
+ nftTokenId,
30
+ collectionId,
31
+ bcsHex,
32
+ expireAt,
33
+ } = txData;
34
+ let bcs: Uint8Array | undefined;
35
+ if (nftTokenId && isDynamicCollection(collectionId)) {
36
+ if (!bcsHex) {
37
+ throw new Error(`No BCS found for token ${nftTokenId}`);
38
+ }
86
39
 
87
- tx.moveCall({
88
- target:
89
- '0x475e98e9c436ec118909f3b9e241d86bcbbc2cf9fba05e99a934823fefb375b7::kiosk_biddings::bid',
90
- arguments: [
91
- tx.object(TRADEPORT_KIOSK_BIDDING_STORE),
92
- tx.pure.address(nftTokenId),
93
- tx.pure.u64(bidAmount),
94
- tx.object(coin),
95
- tx.pure.u64(marketFeePrice),
96
- tx.pure.address(TRADEPORT_BENEFICIARY_ADDRESS),
97
- ],
98
- typeArguments: [nftType],
99
- });
40
+ bcs = fromHex(bcsHex);
41
+ }
100
42
 
101
- destroyZeroCoin({ tx, coin });
102
- }
43
+ let multiBidChainId;
44
+ if (existingMultiBidChainId) {
45
+ multiBidChainId = existingMultiBidChainId;
46
+ } else {
47
+ const { chain_id: chainId, cancelled_at } = multiBidId
48
+ ? ((
49
+ await gqlChainRequest({
50
+ chain: 'sui',
51
+ query: fetchMultibidChainIdById,
52
+ variables: { multiBidId },
53
+ })
54
+ )?.multi_bids?.[0] ?? {})
55
+ : {};
56
+
57
+ if (chainId && cancelled_at) {
58
+ throw new Error(`MultiBid ${chainId} already cancelled`);
59
+ }
103
60
 
104
- async function addKumoTradePortKioskPlaceNftBidTx({
105
- tx,
106
- suiClient,
107
- bidder,
108
- collectionId,
109
- nftTokenId,
110
- nftType,
111
- bidAmount,
112
- royaltyRulePackageId,
113
- royaltyRuleModule,
114
- }: PlaceNftBidTx) {
115
- const transferPolicyId = await getKioskTransferPolicies(nftType).then(
116
- (policies) => policies?.[0]?.id,
117
- );
118
- const marketFeePrice = getMarketFeePrice({ price: bidAmount, collectionId });
61
+ multiBidChainId = chainId;
62
+ }
119
63
 
120
- const coin = await getKioskPlaceBidCoin({
121
- tx,
122
- suiClient,
123
- bidder,
124
- nftType,
125
- bidAmount,
126
- marketFeePrice,
127
- royaltyRulePackageId,
128
- royaltyRuleModule,
129
- transferPolicyId,
130
- });
64
+ const transferPolicies = await getKioskTransferPolicies(nftType);
65
+ const transferPolicy = transferPolicies?.find(
66
+ (policy: { rules: any[] }) => policy?.rules?.length > 0,
67
+ );
68
+ const price = BigInt(txData?.bidAmount ?? 0n);
69
+ const fee = (BigInt(txData?.bidAmount ?? 0) * (await getBidFeeBps(txData?.suiClient))) / 10_000n;
70
+ let royalty = 0n;
71
+ const royaltyRule = (transferPolicy?.rules ?? []).find((r: { type: string }) =>
72
+ r.type.endsWith('royalty_rule'),
73
+ );
131
74
 
132
- const kumoAttributes = await fetchKumoNftAttributes(suiClient, nftTokenId);
133
- const normalizedAttributes = normalizeKumoAttributes(kumoAttributes);
75
+ if (royaltyRule) {
76
+ const { amount_bp, min_amount } = royaltyRule;
77
+ royalty = BigInt((price * BigInt(amount_bp)) / 10_000n);
78
+ if (royalty < BigInt(min_amount ?? 0n)) {
79
+ royalty = BigInt(min_amount ?? 0n);
80
+ }
81
+ }
134
82
 
83
+ const [coin] = tx.splitCoins(tx.gas, [multiBidChainId ? 0n : price + fee + royalty]);
135
84
  tx.moveCall({
136
- target:
137
- '0x475e98e9c436ec118909f3b9e241d86bcbbc2cf9fba05e99a934823fefb375b7::kiosk_biddings::kumo_bid',
138
- arguments: [
139
- tx.object(TRADEPORT_KIOSK_BIDDING_STORE),
140
- tx.pure.address(nftTokenId),
141
- tx.pure.u64(bidAmount),
142
- tx.object(coin),
143
- tx.pure.u64(marketFeePrice),
144
- tx.pure.address(TRADEPORT_BENEFICIARY_ADDRESS),
145
- ...Object.values(normalizedAttributes).map((attr) => tx.pure.option('string', attr)),
146
- ],
85
+ target: `${TRADEPORT_MULTI_BID_PACKAGE}::tradeport_biddings::create_bid_with${transferPolicy ? '' : 'out'}_transfer_policy`,
147
86
  typeArguments: [nftType],
148
- });
149
-
150
- destroyZeroCoin({ tx, coin });
151
- }
152
-
153
- async function addOriginBytePlaceNftBidTx({
154
- tx,
155
- nftTokenId,
156
- collectionId,
157
- bidAmount,
158
- bidder,
159
- }: PlaceNftBidTx) {
160
- const { kiosk: bidderKiosk, isNewKiosk: isNewBidderKiosk } = await getOrCreateOBKiosk({
161
- tx,
162
- address: bidder,
163
- createMethod: 'create_for_sender',
164
- });
165
-
166
- const marketFeePrice = getMarketFeePrice({ price: bidAmount, collectionId });
167
-
168
- const [coin] = splitCoins({ tx, amounts: [tx.pure.u64(bidAmount + marketFeePrice)] });
169
-
170
- tx.moveCall({
171
- target:
172
- '0x8534e4cdfd28709c94330a9783c3d5fe6f5daba0bffb69102ce303c5b38aed5a::bidding::create_bid_with_commission',
173
87
  arguments: [
174
- isNewBidderKiosk ? tx.object(bidderKiosk) : tx.pure.address(bidderKiosk),
175
- tx.pure.address(nftTokenId),
176
- tx.pure.u64(bidAmount),
177
- tx.pure.address(TRADEPORT_BENEFICIARY_ADDRESS),
178
- tx.pure.u64(marketFeePrice),
88
+ tx.object(TRADEPORT_MULTI_BID_STORE),
89
+ tx.pure.u64(nftTokenId ? 1 : 0),
90
+ multiBidChainId
91
+ ? typeof multiBidChainId === 'string'
92
+ ? tx.pure.option('id', normalizeSuiObjectId(multiBidChainId))
93
+ : tx.moveCall({
94
+ target: '0x1::option::some',
95
+ typeArguments: ['0x2::object::ID'],
96
+ arguments: [multiBidChainId],
97
+ })
98
+ : undefined,
99
+ tx.pure.option('id', nftTokenId ? normalizeSuiObjectId(nftTokenId) : undefined),
100
+ tx.pure.option('vector<u8>', bcs ? [...bcs] : undefined),
101
+ tx.pure.option('u64', expireAt?.getTime()),
102
+ tx.pure.u64(price),
103
+ ...(transferPolicy ? [tx.object(transferPolicy.id)] : []),
179
104
  tx.object(coin),
180
105
  ],
181
- typeArguments: ['0x2::sui::SUI'],
182
106
  });
183
-
184
- destroyZeroCoin({ tx, coin });
185
107
  }
186
108
 
187
- export async function addTradePortPlaceNftBidTxHandler(txData: PlaceNftBidTx) {
188
- if (
189
- isOriginByteTx(txData?.sharedObjects) &&
190
- !ORIGIN_BYTE_NFT_TYPES_MISSING_ORDERBOOK?.includes(normalizedNftType(txData?.nftType))
191
- ) {
192
- throw new Error('OriginByte bidding not supported currently');
193
-
194
- // await addOriginBytePlaceNftBidTx(txData);
195
- // return;
196
- }
197
-
198
- if ((await hasTransferPolicyRules(txData?.nftType)) && txData?.sellerKiosk) {
199
- const royaltyRuleModule = getRoyaltyRuleModule(txData?.nftType);
200
- const royaltyRulePackageId = await getRulePackageId({
201
- nftType: txData?.nftType,
202
- ruleType: royaltyRuleModule,
203
- kioskClient: txData?.kioskClient,
204
- });
109
+ let bidFeeBps: bigint | undefined;
205
110
 
206
- if (txData?.collectionId === '67aca668-31b0-4713-91cf-079d392b041a') {
207
- await addKumoTradePortKioskPlaceNftBidTx({
208
- ...txData,
209
- royaltyRulePackageId,
210
- royaltyRuleModule,
211
- });
212
- return;
213
- }
214
-
215
- await addTradePortKioskPlaceNftBidTx({ ...txData, royaltyRulePackageId, royaltyRuleModule });
216
- return;
111
+ export async function getBidFeeBps(suiClient: SuiClient) {
112
+ if (bidFeeBps !== undefined) {
113
+ return bidFeeBps;
217
114
  }
218
115
 
219
- addTradePortPlaceNftBidTx(txData);
220
- }
221
-
222
- async function fetchKumoNftAttributes(
223
- suiClient: any,
224
- nftTokenId: string,
225
- ): Promise<KumoBidAttributes> {
226
- if (!nftTokenId) {
227
- throw new Error('NFT Token ID is required to fetch Kumo attributes');
228
- }
229
-
230
- let res;
231
- try {
232
- res = await suiClient.getObject({
233
- id: nftTokenId,
234
- options: { showContent: true },
235
- });
236
- } catch (error) {
237
- throw new Error(
238
- `Failed to fetch Kumo token object data: ${error instanceof Error ? error.message : 'Unknown error'}`,
239
- );
240
- }
241
-
242
- if (!res.data) {
243
- throw new Error(`NFT object data not found: ${nftTokenId}`);
244
- }
245
-
246
- if (res.data?.content?.dataType !== 'moveObject') {
247
- throw new Error('Invalid NFT Token ID - not a move object');
116
+ const res = await suiClient.getObject({
117
+ id: TRADEPORT_MULTI_BID_STORE,
118
+ options: { showContent: true },
119
+ });
120
+ if (res.error) {
121
+ throw new Error(`Error on getting SUI object ${TRADEPORT_MULTI_BID_STORE}: ${res.error.code}`);
248
122
  }
249
123
 
250
- const { accessory, background, eyes, fur_colour, mouth, tail, one_of_one } =
251
- (res.data?.content?.fields as KumoBidAttributes) || {};
124
+ bidFeeBps = BigInt(
125
+ (res?.data?.content as unknown as { fields: { fee_bps: string } })?.fields?.fee_bps ?? 0,
126
+ );
252
127
 
253
- return { accessory, background, eyes, fur_colour, mouth, tail, one_of_one };
128
+ return bidFeeBps;
254
129
  }
255
130
 
256
- function normalizeKumoAttributes(attributes: KumoBidAttributes) {
257
- const normalizeAttribute = (attr: string | undefined) =>
258
- !attr || attr === 'Default' || attr === 'None' ? null : attr;
259
-
260
- return Object.fromEntries(
261
- Object.entries(attributes).map(([key, value]) => [key, normalizeAttribute(value)]),
262
- );
131
+ export function isDynamicCollection(collectionId: string): boolean {
132
+ return DYNAMIC_COLLECTION_IDS.includes(collectionId);
263
133
  }
@@ -1,4 +1,3 @@
1
- import type { KioskClient } from '@mysten/kiosk';
2
1
  import { type SuiClient } from '@mysten/sui/client';
3
2
  import { Transaction } from '@mysten/sui/transactions';
4
3
  import { type RequestContext } from '../../SuiTradingClient';
@@ -15,22 +14,25 @@ import {
15
14
  export type PlaceNftBidTx = {
16
15
  tx: Transaction;
17
16
  suiClient: SuiClient;
18
- kioskClient: KioskClient;
19
- sharedObjects: any;
20
17
  bidder: string;
21
18
  collectionId: string;
22
- nftTokenId: string;
19
+ nftTokenId?: string;
23
20
  nftType: string;
24
- bidAmount: number;
25
- sellerKiosk: string;
26
- royaltyRulePackageId?: string;
27
- royaltyRuleModule?: string;
21
+ bidAmount: bigint;
22
+ multiBidId?: string;
23
+ multiBidChainId?: any;
24
+ expireAt?: Date;
25
+ sharedObjects?: any;
26
+ bcsHex?: string;
28
27
  };
29
28
 
30
29
  export type PlaceNftBid = {
31
30
  nftId: string;
32
31
  bidAmountInMist: number;
33
32
  walletAddress: string;
33
+ multiBidId?: string;
34
+ multiBidChainId?: any;
35
+ tx?: Transaction;
34
36
  };
35
37
 
36
38
  export type PlaceNftBids = {
@@ -39,12 +41,17 @@ export type PlaceNftBids = {
39
41
  bidAmountInMist: number;
40
42
  }>;
41
43
  walletAddress: string;
44
+ multiBidId?: string;
45
+ multiBidChainId?: any;
46
+ expireAt?: Date;
47
+ tx?: Transaction;
42
48
  };
43
49
 
44
50
  export const placeNftBids = async (
45
- { nfts, walletAddress }: PlaceNftBids,
51
+ { nfts, walletAddress, multiBidId, multiBidChainId, expireAt, tx: existingTx }: PlaceNftBids,
46
52
  context: RequestContext,
47
53
  ): Promise<Transaction> => {
54
+ const tx = existingTx ?? new Transaction();
48
55
  const res = await gqlChainRequest({
49
56
  chain: 'sui',
50
57
  query: fetchNftsById,
@@ -56,8 +63,6 @@ export const placeNftBids = async (
56
63
  }
57
64
 
58
65
  const nftsForTracking = [];
59
- const tx = new Transaction();
60
-
61
66
  for (const nft of res.nfts) {
62
67
  if (DELOREAN_TOKEN_IDS_TO_DISABLE?.includes(nft?.token_id)) {
63
68
  throw new Error(DELOREAN_TOKEN_IDS_TO_DISABLE_MESSAGE);
@@ -74,14 +79,16 @@ export const placeNftBids = async (
74
79
  const txData: PlaceNftBidTx = {
75
80
  tx,
76
81
  suiClient: context.suiClient,
77
- kioskClient: context.kioskClient,
78
82
  sharedObjects,
79
83
  bidder: walletAddress,
80
84
  collectionId: nft?.collection_id,
81
85
  nftTokenId: nft?.token_id,
82
86
  nftType,
83
- bidAmount: nfts?.find((n) => n.id === nft?.id)?.bidAmountInMist,
84
- sellerKiosk: nft?.chain_state?.kiosk_id,
87
+ bidAmount: BigInt(nfts?.find((n) => n.id === nft?.id)?.bidAmountInMist ?? 0n),
88
+ bcsHex: nft.chain_state?.bcs?.bcsHex,
89
+ multiBidId,
90
+ multiBidChainId,
91
+ expireAt,
85
92
  };
86
93
 
87
94
  await addTradePortPlaceNftBidTxHandler(txData);
@@ -4,12 +4,16 @@ import {
4
4
  TRADEPORT_BIDDING_STORE,
5
5
  } from '../../constants';
6
6
  import { getSharedObjects } from '../../helpers/getSharedObjects';
7
+ import { isSingleBid } from '../../helpers/isSIngleBid';
7
8
  import { isBluemoveKioskBid } from '../../helpers/kiosk/isBluemoveKioskBid';
8
9
  import { isTradePortKioskBid } from '../../helpers/kiosk/isTradePortKioskBid';
9
10
  import { isOriginByteBid } from '../../helpers/originByte/isOriginByteBid';
10
11
  import { getObjectType } from '../../helpers/rpc/getObjectType';
11
12
  import { addLeadingZerosAfter0x } from '../../utils/addLeadingZerosAfter0x';
12
- import { addTradeportKioskRemoveNftBidTx } from '../removeNftBids/addRemoveNftBidTxs';
13
+ import {
14
+ addSingleBidRemoveNftBidTx,
15
+ addTradeportKioskRemoveNftBidTx,
16
+ } from '../removeNftBids/addRemoveNftBidTxs';
13
17
  import { type RemoveCollectionBidTx } from './removeCollectionBids';
14
18
 
15
19
  export function addTradeportRemoveCollectionBidTx({
@@ -99,6 +103,11 @@ export async function addTradePortRemoveCollectionBidTxHandler(txData: RemoveCol
99
103
  export async function addBluemoveRemoveCollectionBidTxHandler(txData: RemoveCollectionBidTx) {
100
104
  const bidType = await getObjectType({ suiClient: txData?.suiClient, objectId: txData?.bidNonce });
101
105
 
106
+ if (isSingleBid(bidType)) {
107
+ await addSingleBidRemoveNftBidTx(txData);
108
+ return;
109
+ }
110
+
102
111
  if (isOriginByteBid(bidType)) {
103
112
  const sharedObjects = await getSharedObjects(txData?.nftType);
104
113
  addOriginByteRemoveCollectionBidTx({ ...txData, sharedObjects });
@@ -3,7 +3,12 @@ import {
3
3
  TOCEN_MARKETPLACE_OBJECT,
4
4
  TRADEPORT_BIDDING_STORE,
5
5
  TRADEPORT_KIOSK_BIDDING_STORE,
6
+ TRADEPORT_MULTI_BID_PACKAGE,
7
+ TRADEPORT_MULTI_BID_STORE,
6
8
  } from '../../constants';
9
+ import { gqlChainRequest } from '../../graphql/gqlChainRequest';
10
+ import { fetchMultibidChainIdById } from '../../graphql/queries/fetchMultibidById';
11
+ import { isSingleBid } from '../../helpers/isSIngleBid';
7
12
  import { isTradePortKioskBid } from '../../helpers/kiosk/isTradePortKioskBid';
8
13
  import { isOriginByteBid } from '../../helpers/originByte/isOriginByteBid';
9
14
  import { getObjectType } from '../../helpers/rpc/getObjectType';
@@ -62,9 +67,34 @@ export function addTocenRemoveNftBidTx({ tx, nftTokenId, bidAmount }: RemoveNftB
62
67
  });
63
68
  }
64
69
 
70
+ export async function addSingleBidRemoveNftBidTx({ tx, bidNonce, multiBidId }: RemoveNftBidTx) {
71
+ const multiBidChainId = multiBidId
72
+ ? (
73
+ await gqlChainRequest({
74
+ chain: 'sui',
75
+ query: fetchMultibidChainIdById,
76
+ variables: { multiBidId },
77
+ })
78
+ )?.multi_bids?.[0]?.chain_id
79
+ : undefined;
80
+ tx.moveCall({
81
+ target: `${TRADEPORT_MULTI_BID_PACKAGE}::tradeport_biddings::cancel_bid`,
82
+ arguments: [
83
+ tx.object(TRADEPORT_MULTI_BID_STORE),
84
+ tx.pure.id(bidNonce),
85
+ tx.pure.option('id', multiBidChainId),
86
+ ],
87
+ });
88
+ }
89
+
65
90
  export async function addTradePortRemoveNftBidTxHandler(txData: RemoveNftBidTx) {
66
91
  const bidType = await getObjectType({ suiClient: txData?.suiClient, objectId: txData?.bidNonce });
67
92
 
93
+ if (isSingleBid(bidType)) {
94
+ await addSingleBidRemoveNftBidTx(txData);
95
+ return;
96
+ }
97
+
68
98
  if (isOriginByteBid(bidType)) {
69
99
  addOriginByteRemoveNftBidTx(txData);
70
100
  return;
@@ -25,6 +25,7 @@ export type RemoveNftBidTx = {
25
25
  bidAmount: number;
26
26
  sellerKiosk: string;
27
27
  bidMarketName: string;
28
+ multiBidId?: string;
28
29
  };
29
30
 
30
31
  export type RemoveNftBid = {
@@ -73,6 +74,7 @@ export const removeNftBids = async (
73
74
  bidAmount: bid?.price,
74
75
  sellerKiosk: bid?.nft?.chain_state?.kiosk_id,
75
76
  bidMarketName: bid?.market_contract?.name,
77
+ multiBidId: bid?.multi_bid_id,
76
78
  };
77
79
 
78
80
  switch (txData.bidMarketName) {
@@ -0,0 +1,59 @@
1
+ import { Transaction } from '@mysten/sui/transactions';
2
+ import { TRADEPORT_MULTI_BID_PACKAGE, TRADEPORT_MULTI_BID_STORE } from '../../constants';
3
+ import { fetchMultibidChainIdById } from '../../graphql/queries/fetchMultibidById';
4
+ import { gqlChainRequest } from '../../graphql/gqlChainRequest';
5
+
6
+ export interface UpdateMultiBid {
7
+ walletAddress: string;
8
+ multiBidId?: string;
9
+ name?: string;
10
+ amount?: bigint;
11
+ amountToWithdraw?: bigint;
12
+ tx?: Transaction;
13
+ multiBidChainId?: any;
14
+ }
15
+
16
+ export async function updateMultiBid({
17
+ multiBidId,
18
+ name,
19
+ amount,
20
+ amountToWithdraw,
21
+ tx: existingTx,
22
+ multiBidChainId,
23
+ }: UpdateMultiBid): Promise<Transaction> {
24
+ const tx = existingTx ?? new Transaction();
25
+
26
+ if (!multiBidChainId) {
27
+ const { chain_id: chainId, cancelled_at } =
28
+ (
29
+ await gqlChainRequest({
30
+ chain: 'sui',
31
+ query: fetchMultibidChainIdById,
32
+ variables: { multiBidId },
33
+ })
34
+ )?.multi_bids?.[0] ?? {};
35
+ if (!chainId) {
36
+ throw new Error(`MultiBid ${multiBidId} not found`);
37
+ }
38
+
39
+ if (cancelled_at) {
40
+ throw new Error(`MultiBid ${multiBidId} already cancelled`);
41
+ }
42
+
43
+ multiBidChainId = chainId;
44
+ }
45
+
46
+ const [coin] = tx.splitCoins(tx.gas, [amount ?? 0n]);
47
+ tx.moveCall({
48
+ target: `${TRADEPORT_MULTI_BID_PACKAGE}::tradeport_biddings::update_multi_bid`,
49
+ arguments: [
50
+ tx.object(TRADEPORT_MULTI_BID_STORE),
51
+ typeof multiBidChainId === 'string' ? tx.pure.id(multiBidChainId) : multiBidChainId,
52
+ tx.pure.option('string', name),
53
+ coin,
54
+ tx.pure.option('u64', amountToWithdraw),
55
+ ],
56
+ });
57
+
58
+ return tx;
59
+ }
@@ -28,7 +28,7 @@ export class SuiWallet {
28
28
  }
29
29
 
30
30
  async simulateCall(tx: Transaction): Promise<any> {
31
- tx.setSenderIfNotSet('0x7cb678cc0446b986bab45d612a25946b2a63763d2252b1e554d1763eb788f660');
31
+ tx.setSenderIfNotSet(this.keypair.toSuiAddress());
32
32
  const rawTransaction = await tx.build({ client: this.suiClient });
33
33
  const result = await this.suiClient.dryRunTransactionBlock({
34
34
  transactionBlock: rawTransaction,