@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.
- package/CHANGELOG.md +12 -0
- package/dist/index.d.mts +38 -2
- package/dist/index.d.ts +38 -2
- package/dist/index.js +409 -350
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +409 -350
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/SuiTradingClient.ts +23 -2
- package/src/constants.ts +11 -0
- package/src/graphql/queries/fetchBidsById.ts +1 -0
- package/src/graphql/queries/fetchCollectionBidById.ts +1 -0
- package/src/graphql/queries/fetchCollectionBidsAtSamePrice.ts +1 -0
- package/src/graphql/queries/fetchMultibidById.ts +10 -0
- package/src/helpers/isSIngleBid.ts +13 -0
- package/src/helpers/kiosk/getKioskTransferPolicies.ts +7 -0
- package/src/helpers/kiosk/kioskTxWrapper.ts +8 -5
- package/src/methods/acceptCollectionBid/acceptCollectionBid.ts +2 -0
- package/src/methods/acceptCollectionBid/addAcceptCollectionBIdTxs.ts +10 -1
- package/src/methods/acceptNftBids/acceptNftBids.ts +3 -0
- package/src/methods/acceptNftBids/addAcceptNftBidTxs.ts +94 -1
- package/src/methods/cancelMultiBid/cancelMultiBid.ts +35 -0
- package/src/methods/createMultiBid/createMultiBid.ts +35 -0
- package/src/methods/placeCollectionBids/placeCollectionBids.ts +26 -11
- package/src/methods/placeNftBids/addPlaceNftBidTxs.ts +100 -230
- package/src/methods/placeNftBids/placeNftBids.ts +21 -14
- package/src/methods/removeCollectionBids/addRemoveCollectionBidsTxs.ts +10 -1
- package/src/methods/removeNftBids/addRemoveNftBidTxs.ts +30 -0
- package/src/methods/removeNftBids/removeNftBids.ts +2 -0
- package/src/methods/updateMultiBid/updateMultiBid.ts +59 -0
- package/src/tests/SuiWallet.ts +1 -1
|
@@ -1,263 +1,133 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ORIGIN_BYTE_NFT_TYPES_MISSING_ORDERBOOK,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
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
|
|
24
|
+
const {
|
|
76
25
|
tx,
|
|
77
|
-
suiClient,
|
|
78
|
-
bidder,
|
|
79
26
|
nftType,
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
|
|
88
|
-
|
|
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
|
-
|
|
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
|
-
|
|
105
|
-
|
|
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
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
133
|
-
|
|
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
|
-
|
|
175
|
-
tx.pure.
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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
|
-
|
|
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
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
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
|
-
|
|
251
|
-
(res
|
|
124
|
+
bidFeeBps = BigInt(
|
|
125
|
+
(res?.data?.content as unknown as { fields: { fee_bps: string } })?.fields?.fee_bps ?? 0,
|
|
126
|
+
);
|
|
252
127
|
|
|
253
|
-
return
|
|
128
|
+
return bidFeeBps;
|
|
254
129
|
}
|
|
255
130
|
|
|
256
|
-
function
|
|
257
|
-
|
|
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
|
|
19
|
+
nftTokenId?: string;
|
|
23
20
|
nftType: string;
|
|
24
|
-
bidAmount:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
+
}
|
package/src/tests/SuiWallet.ts
CHANGED
|
@@ -28,7 +28,7 @@ export class SuiWallet {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
async simulateCall(tx: Transaction): Promise<any> {
|
|
31
|
-
tx.setSenderIfNotSet(
|
|
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,
|