@tradeport/sui-trading-sdk 0.4.39 → 0.4.41
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/dist/index.d.mts +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +534 -134
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +518 -125
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -2
- package/src/SuiTradingClient.ts +15 -0
- package/src/bigNumberConfig.ts +10 -0
- package/src/constants.ts +17 -1
- package/src/graphql/queries/fetchNftCollectionChainState.ts +12 -0
- package/src/helpers/calculateRoyaltyFee.ts +12 -7
- package/src/helpers/isExpiredListing.ts +9 -0
- package/src/helpers/kiosk/preProcessSharedBulkBuyingData.ts +9 -8
- package/src/helpers/swap.ts +197 -0
- package/src/helpers/validateMinFloorPrice.ts +22 -0
- package/src/methods/buyListings/addBuyListingTxs.ts +111 -5
- package/src/methods/buyLocks/buyLocks.ts +2 -2
- package/src/methods/createLongLocks/createLongLocks.ts +2 -2
- package/src/methods/createShortLocks/createShortLocks.ts +3 -3
- package/src/methods/listNfts/addListTxs.ts +17 -37
- package/src/methods/listNfts/addRelistTxs.ts +26 -17
- package/src/methods/listNfts/listNfts.ts +27 -16
- package/src/methods/placeNftBids/addPlaceNftBidTxs.ts +1 -1
- package/src/methods/relistNft/relistNft.ts +19 -28
- package/src/methods/sponsorNftListing/addSponsorNftListingTx.ts +71 -0
- package/src/methods/sponsorNftListing/sponsorNftListing.ts +62 -0
- package/src/methods/unlistListings/addUnlistListingTxs.ts +68 -5
- package/src/methods/unlistListings/unlistListings.ts +2 -6
- package/src/tests/SuiWallet.ts +4 -1
- package/src/utils/printTxBlockTxs.ts +7 -1
- package/src/utils/pureValues.ts +13 -0
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ORIGIN_BYTE_NFT_TYPES_MISSING_ORDERBOOK,
|
|
3
3
|
TRADEPORT_BENEFICIARY_ADDRESS,
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
TRADEPORT_LISTINGS_PACKAGE,
|
|
5
|
+
TRADEPORT_LISTINGS_STORE,
|
|
6
6
|
} from '../../constants';
|
|
7
7
|
import { getMarketFeePrice } from '../../helpers/getMarketFeePrice';
|
|
8
8
|
import { getSharedObjects } from '../../helpers/getSharedObjects';
|
|
9
9
|
import { hasNativeKioskTransferPolicyRules } from '../../helpers/hasTransferPolicyRules';
|
|
10
10
|
import { assertNftInSharedKiosk } from '../../helpers/kiosk/assertNftInSharedKiosk';
|
|
11
|
-
import { getNativeKioskTransferPolicies } from '../../helpers/kiosk/getNativeKioskTransferPolicies';
|
|
12
11
|
import { kioskTxWrapper } from '../../helpers/kiosk/kioskTxWrapper';
|
|
13
12
|
import { takeAndBorrowNftFromKiosk } from '../../helpers/kiosk/takeAndBorrowNftFromKiosk';
|
|
14
13
|
import { depositItemIntoOBKiosk } from '../../helpers/originByte/depositNftIntoOBKiosk';
|
|
@@ -16,6 +15,7 @@ import { getOrCreateOBKiosk } from '../../helpers/originByte/getOrCreateOBKiosk'
|
|
|
16
15
|
import { isOriginByteCollection } from '../../helpers/originByte/isOriginByteCollection';
|
|
17
16
|
import { shareOriginByteKiosk } from '../../helpers/originByte/shareOriginByteKiosk';
|
|
18
17
|
import { normalizedNftType } from '../../utils/normalizeNftType';
|
|
18
|
+
import { validateMinFloorPrice } from '../../helpers/validateMinFloorPrice';
|
|
19
19
|
import { type ListNftTx } from './listNfts';
|
|
20
20
|
|
|
21
21
|
export async function addOriginByteListTx({
|
|
@@ -79,66 +79,44 @@ export function addTradePortListTx({
|
|
|
79
79
|
nftTokenId,
|
|
80
80
|
borrowedItem,
|
|
81
81
|
nftType,
|
|
82
|
-
collectionId,
|
|
83
82
|
listPrice,
|
|
84
83
|
}: ListNftTx) {
|
|
85
|
-
const marketFeePrice = getMarketFeePrice({ price: listPrice, collectionId });
|
|
86
|
-
|
|
87
84
|
tx.moveCall({
|
|
88
|
-
target:
|
|
85
|
+
target: `${TRADEPORT_LISTINGS_PACKAGE}::tradeport_listings::create_listing_without_transfer_policy`,
|
|
89
86
|
arguments: [
|
|
90
|
-
tx.object(
|
|
87
|
+
tx.object(TRADEPORT_LISTINGS_STORE),
|
|
91
88
|
borrowedItem ? tx.object(borrowedItem) : tx.object(nftTokenId),
|
|
92
89
|
tx.pure.u64(listPrice),
|
|
93
|
-
tx.pure.u64(marketFeePrice),
|
|
94
|
-
tx.pure.address(TRADEPORT_BENEFICIARY_ADDRESS),
|
|
95
90
|
],
|
|
96
91
|
typeArguments: [nftType],
|
|
97
92
|
});
|
|
98
93
|
}
|
|
99
94
|
|
|
100
|
-
export async function
|
|
95
|
+
export async function addKioskTradePortListTx({
|
|
101
96
|
tx,
|
|
102
97
|
kioskTx,
|
|
103
98
|
transferPolicies,
|
|
104
99
|
nftTokenId,
|
|
105
100
|
nftType,
|
|
106
|
-
collectionId,
|
|
107
101
|
listPrice,
|
|
108
102
|
}: ListNftTx) {
|
|
109
|
-
|
|
110
|
-
const minFloorPrice = transferPolicy?.rules?.filter(
|
|
111
|
-
(rule: any) => rule?.type === 'floor_price_rule',
|
|
112
|
-
)?.[0]?.floor_price;
|
|
113
|
-
|
|
114
|
-
if (minFloorPrice) {
|
|
115
|
-
if (listPrice < minFloorPrice) {
|
|
116
|
-
const formattedMinFloorPrice = Number(minFloorPrice) / 1000000000;
|
|
117
|
-
throw new Error(
|
|
118
|
-
`NFT Transfer Policy has a miminum floor price rule. Item cannot be listed for less than ${formattedMinFloorPrice} SUI`,
|
|
119
|
-
);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const marketFeePrice = getMarketFeePrice({ price: listPrice, collectionId });
|
|
103
|
+
validateMinFloorPrice({ transferPolicies, listPrice });
|
|
124
104
|
|
|
125
105
|
tx.moveCall({
|
|
126
|
-
target:
|
|
127
|
-
'0x475e98e9c436ec118909f3b9e241d86bcbbc2cf9fba05e99a934823fefb375b7::kiosk_listings::list',
|
|
106
|
+
target: `${TRADEPORT_LISTINGS_PACKAGE}::tradeport_listings::create_listing_with_transfer_policy`,
|
|
128
107
|
arguments: [
|
|
129
|
-
tx.object(
|
|
108
|
+
tx.object(TRADEPORT_LISTINGS_STORE),
|
|
130
109
|
tx.object(kioskTx.kiosk.value ?? kioskTx.kiosk),
|
|
131
110
|
tx.object(kioskTx.kioskCap.value ?? kioskTx.kioskCap),
|
|
132
|
-
tx.pure.
|
|
133
|
-
tx.pure.u64(listPrice
|
|
134
|
-
tx.pure.u64(marketFeePrice),
|
|
135
|
-
tx.pure.address(TRADEPORT_BENEFICIARY_ADDRESS),
|
|
111
|
+
tx.pure.id(nftTokenId),
|
|
112
|
+
tx.pure.u64(listPrice),
|
|
136
113
|
],
|
|
137
114
|
typeArguments: [nftType],
|
|
138
115
|
});
|
|
139
116
|
}
|
|
140
117
|
|
|
141
118
|
export async function addTradePortListTxHandler(txData: ListNftTx) {
|
|
119
|
+
// If NFT is an Origin Byte collection, create an Origin Byte listing
|
|
142
120
|
if (
|
|
143
121
|
isOriginByteCollection(txData?.transferPolicies) &&
|
|
144
122
|
!ORIGIN_BYTE_NFT_TYPES_MISSING_ORDERBOOK?.includes(normalizedNftType(txData?.nftType))
|
|
@@ -181,6 +159,7 @@ export async function addTradePortListTxHandler(txData: ListNftTx) {
|
|
|
181
159
|
});
|
|
182
160
|
}
|
|
183
161
|
|
|
162
|
+
// If NFT is in a kiosk, create a kiosk listing
|
|
184
163
|
if (txData?.sellerKiosk) {
|
|
185
164
|
return kioskTxWrapper({
|
|
186
165
|
tx: txData?.tx,
|
|
@@ -191,7 +170,7 @@ export async function addTradePortListTxHandler(txData: ListNftTx) {
|
|
|
191
170
|
sharedKioskState: txData?.sharedKioskState,
|
|
192
171
|
shouldUseSharedKioskTx: false,
|
|
193
172
|
async runCommands(kioskTx) {
|
|
194
|
-
await
|
|
173
|
+
await addKioskTradePortListTx({
|
|
195
174
|
...txData,
|
|
196
175
|
kioskTx,
|
|
197
176
|
});
|
|
@@ -199,7 +178,7 @@ export async function addTradePortListTxHandler(txData: ListNftTx) {
|
|
|
199
178
|
});
|
|
200
179
|
}
|
|
201
180
|
|
|
202
|
-
// If NFT not in a kiosk, but nft type has a transfer policy rule, create kiosk and place NFT in kiosk first
|
|
181
|
+
// If NFT is not in a kiosk, but nft type has a transfer policy rule, create kiosk and place NFT in kiosk first
|
|
203
182
|
if (!txData?.sellerKiosk && hasNativeKioskTransferPolicyRules(txData?.transferPolicies)) {
|
|
204
183
|
return kioskTxWrapper({
|
|
205
184
|
tx: txData?.tx,
|
|
@@ -213,7 +192,7 @@ export async function addTradePortListTxHandler(txData: ListNftTx) {
|
|
|
213
192
|
item: txData?.nftTokenId,
|
|
214
193
|
itemType: txData?.nftType,
|
|
215
194
|
});
|
|
216
|
-
await
|
|
195
|
+
await addKioskTradePortListTx({
|
|
217
196
|
...txData,
|
|
218
197
|
kioskTx,
|
|
219
198
|
});
|
|
@@ -221,5 +200,6 @@ export async function addTradePortListTxHandler(txData: ListNftTx) {
|
|
|
221
200
|
});
|
|
222
201
|
}
|
|
223
202
|
|
|
203
|
+
// Fallback to non-kiosk listing
|
|
224
204
|
addTradePortListTx(txData);
|
|
225
205
|
}
|
|
@@ -3,10 +3,9 @@ import { type Transaction, type TransactionObjectArgument } from '@mysten/sui/tr
|
|
|
3
3
|
import {
|
|
4
4
|
BLUEMOVE_MARKET_CONFIG_OBJECT,
|
|
5
5
|
TOCEN_MARKETPLACE_OBJECT,
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
TRADEPORT_LISTINGS_PACKAGE,
|
|
7
|
+
TRADEPORT_LISTINGS_STORE,
|
|
8
8
|
} from '../../constants';
|
|
9
|
-
import { getMarketFeePrice } from '../../helpers/getMarketFeePrice';
|
|
10
9
|
import { addTradePortListTx } from './addListTxs';
|
|
11
10
|
import { type SuiClient } from '@mysten/sui/client';
|
|
12
11
|
|
|
@@ -26,30 +25,40 @@ export type RelistNftTx = {
|
|
|
26
25
|
sellerKiosk: string;
|
|
27
26
|
};
|
|
28
27
|
|
|
29
|
-
export function addTradePortRelistTx({
|
|
28
|
+
export function addTradePortRelistTx({ tx, nftTokenId, nftType, listPrice }: RelistNftTx) {
|
|
29
|
+
tx.moveCall({
|
|
30
|
+
target: `${TRADEPORT_LISTINGS_PACKAGE}::tradeport_listings::relist_listing_without_transfer_policy`,
|
|
31
|
+
arguments: [
|
|
32
|
+
tx.object(TRADEPORT_LISTINGS_STORE),
|
|
33
|
+
tx.pure.id(nftTokenId),
|
|
34
|
+
tx.pure.u64(listPrice),
|
|
35
|
+
],
|
|
36
|
+
typeArguments: [nftType],
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function addKioskTradePortRelistTx({
|
|
30
41
|
tx,
|
|
42
|
+
kioskTx,
|
|
43
|
+
nftTokenId,
|
|
31
44
|
nftType,
|
|
32
|
-
collectionId,
|
|
33
|
-
listingNonce,
|
|
34
45
|
listPrice,
|
|
35
46
|
}: RelistNftTx) {
|
|
36
|
-
const marketFeePrice = getMarketFeePrice({ price: listPrice, collectionId });
|
|
37
|
-
|
|
38
47
|
tx.moveCall({
|
|
39
|
-
target:
|
|
48
|
+
target: `${TRADEPORT_LISTINGS_PACKAGE}::tradeport_listings::relist_listing_with_transfer_policy`,
|
|
40
49
|
arguments: [
|
|
41
|
-
tx.object(
|
|
42
|
-
tx.
|
|
50
|
+
tx.object(TRADEPORT_LISTINGS_STORE),
|
|
51
|
+
tx.object(kioskTx.kiosk.value ?? kioskTx.kiosk),
|
|
52
|
+
tx.object(kioskTx.kioskCap.value ?? kioskTx.kioskCap),
|
|
53
|
+
tx.pure.id(nftTokenId),
|
|
43
54
|
tx.pure.u64(listPrice),
|
|
44
|
-
tx.pure.u64(marketFeePrice),
|
|
45
|
-
tx.pure.address(TRADEPORT_BENEFICIARY_ADDRESS),
|
|
46
55
|
],
|
|
47
56
|
typeArguments: [nftType],
|
|
48
57
|
});
|
|
49
58
|
}
|
|
50
59
|
|
|
51
60
|
export function addBlueMoveRelistTx(txData: RelistNftTx) {
|
|
52
|
-
const { tx, nftTokenId, nftType, listPrice
|
|
61
|
+
const { tx, nftTokenId, nftType, listPrice } = txData;
|
|
53
62
|
|
|
54
63
|
const borrowedItem = tx.moveCall({
|
|
55
64
|
target:
|
|
@@ -58,11 +67,11 @@ export function addBlueMoveRelistTx(txData: RelistNftTx) {
|
|
|
58
67
|
typeArguments: [nftType, nftType],
|
|
59
68
|
}) as TransactionObjectArgument;
|
|
60
69
|
|
|
61
|
-
addTradePortListTx({ ...txData, listPrice, borrowedItem
|
|
70
|
+
addTradePortListTx({ ...txData, listPrice, borrowedItem });
|
|
62
71
|
}
|
|
63
72
|
|
|
64
73
|
export function addTocenRelistTx(txData: RelistNftTx) {
|
|
65
|
-
const { tx, nftTokenId, nftType, listPrice
|
|
74
|
+
const { tx, nftTokenId, nftType, listPrice } = txData;
|
|
66
75
|
|
|
67
76
|
const borrowedItem = tx.moveCall({
|
|
68
77
|
target:
|
|
@@ -71,5 +80,5 @@ export function addTocenRelistTx(txData: RelistNftTx) {
|
|
|
71
80
|
typeArguments: [nftType],
|
|
72
81
|
}) as any;
|
|
73
82
|
|
|
74
|
-
addTradePortListTx({ ...txData, listPrice, borrowedItem
|
|
83
|
+
addTradePortListTx({ ...txData, listPrice, borrowedItem });
|
|
75
84
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { type KioskClient } from '@mysten/kiosk';
|
|
2
2
|
import { type SuiClient } from '@mysten/sui/client';
|
|
3
3
|
import { Transaction, type TransactionObjectInput } from '@mysten/sui/transactions';
|
|
4
|
-
import { normalizeSuiAddress } from '@mysten/sui/utils';
|
|
5
4
|
import { type RequestContext } from '../../SuiTradingClient';
|
|
6
5
|
import {
|
|
7
6
|
DELOREAN_TOKEN_IDS_TO_DISABLE,
|
|
@@ -13,6 +12,10 @@ import { getNftType } from '../../helpers/getNftType';
|
|
|
13
12
|
import { type SharedKioskState } from '../../helpers/kiosk/sharedKioskState.type';
|
|
14
13
|
import { relistNft } from '../relistNft/relistNft';
|
|
15
14
|
import { addTradePortListTxHandler } from './addListTxs';
|
|
15
|
+
import { isOriginByteCollection } from '../../helpers/originByte/isOriginByteCollection';
|
|
16
|
+
import { addSponsorListingTx } from '../sponsorNftListing/addSponsorNftListingTx';
|
|
17
|
+
import { type SponsorNftListingOptions } from '../sponsorNftListing/sponsorNftListing';
|
|
18
|
+
import { isExpiredListing } from '../../helpers/isExpiredListing';
|
|
16
19
|
|
|
17
20
|
export type ListNftTx = {
|
|
18
21
|
tx: Transaction;
|
|
@@ -31,16 +34,11 @@ export type ListNftTx = {
|
|
|
31
34
|
sharedKioskState?: SharedKioskState;
|
|
32
35
|
};
|
|
33
36
|
|
|
34
|
-
export type ListNft = {
|
|
35
|
-
nftId: string;
|
|
36
|
-
listPriceInMist: number;
|
|
37
|
-
walletAddress: string;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
37
|
export type ListNfts = {
|
|
41
38
|
nfts: Array<{
|
|
42
39
|
id: string;
|
|
43
40
|
listPriceInMist: number;
|
|
41
|
+
sponsorOptions?: SponsorNftListingOptions;
|
|
44
42
|
}>;
|
|
45
43
|
walletAddress: string;
|
|
46
44
|
};
|
|
@@ -67,6 +65,8 @@ export const listNfts = async (
|
|
|
67
65
|
};
|
|
68
66
|
|
|
69
67
|
for (const nft of res.nfts) {
|
|
68
|
+
const inputNft = nfts?.find((n) => n.id === nft?.id);
|
|
69
|
+
|
|
70
70
|
if (DELOREAN_TOKEN_IDS_TO_DISABLE?.includes(nft?.token_id)) {
|
|
71
71
|
throw new Error(DELOREAN_TOKEN_IDS_TO_DISABLE_MESSAGE);
|
|
72
72
|
}
|
|
@@ -79,14 +79,14 @@ export const listNfts = async (
|
|
|
79
79
|
|
|
80
80
|
const transferPolicies = nft?.collection?.chain_state?.transfer_policies;
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
if (inputNft?.sponsorOptions?.shouldSponsor && isOriginByteCollection(transferPolicies)) {
|
|
83
|
+
throw new Error(`You cannot sponsor an Origin Byte NFT. Nft Token Id: ${nft?.token_id}`);
|
|
84
|
+
}
|
|
85
|
+
|
|
83
86
|
if (
|
|
84
87
|
nft?.listed ||
|
|
85
|
-
nft.listings.some(
|
|
86
|
-
(listing
|
|
87
|
-
listing.nonce &&
|
|
88
|
-
listing.seller &&
|
|
89
|
-
normalizeSuiAddress(listing.seller) === normalizeSuiAddress(walletAddress),
|
|
88
|
+
nft.listings.some((listing: { nonce?: string; seller?: string }) =>
|
|
89
|
+
isExpiredListing(listing, walletAddress),
|
|
90
90
|
)
|
|
91
91
|
) {
|
|
92
92
|
await relistNft({
|
|
@@ -96,7 +96,7 @@ export const listNfts = async (
|
|
|
96
96
|
sharedKioskState,
|
|
97
97
|
transferPolicies,
|
|
98
98
|
nft,
|
|
99
|
-
listPrice:
|
|
99
|
+
listPrice: inputNft?.listPriceInMist,
|
|
100
100
|
walletAddress,
|
|
101
101
|
});
|
|
102
102
|
} else {
|
|
@@ -110,18 +110,29 @@ export const listNfts = async (
|
|
|
110
110
|
collectionId: nft?.collection_id,
|
|
111
111
|
nftTokenId: nft?.token_id,
|
|
112
112
|
nftType,
|
|
113
|
-
listPrice:
|
|
113
|
+
listPrice: inputNft?.listPriceInMist,
|
|
114
114
|
sellerKiosk: nft?.chain_state?.kiosk_id,
|
|
115
115
|
};
|
|
116
116
|
|
|
117
117
|
await addTradePortListTxHandler(listTxData);
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
if (inputNft?.sponsorOptions?.shouldSponsor) {
|
|
121
|
+
await addSponsorListingTx({
|
|
122
|
+
tx,
|
|
123
|
+
suiClient: context.suiClient,
|
|
124
|
+
nftTokenId: nft?.token_id,
|
|
125
|
+
nftType,
|
|
126
|
+
walletAddress,
|
|
127
|
+
sponsorOptions: inputNft?.sponsorOptions,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
120
131
|
nftsForTracking.push({
|
|
121
132
|
walletAddress,
|
|
122
133
|
nftType,
|
|
123
134
|
collectionId: nft?.collection_id,
|
|
124
|
-
listPrice:
|
|
135
|
+
listPrice: inputNft?.listPriceInMist,
|
|
125
136
|
isRelist: nft?.listed,
|
|
126
137
|
marketRelistedFrom: nft?.listings?.[0]?.market_name,
|
|
127
138
|
});
|
|
@@ -105,7 +105,7 @@ export async function addTradePortPlaceNftBidTxHandler(txData: PlaceNftBidTx) {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
const [coin] = tx.splitCoins(coinToSplit ? coinToSplit : tx.gas, [
|
|
108
|
-
|
|
108
|
+
multiBidChainId ? 0n : price + fee + royalty,
|
|
109
109
|
]);
|
|
110
110
|
tx.moveCall({
|
|
111
111
|
target: `${TRADEPORT_MULTI_BID_PACKAGE}::tradeport_biddings::create_bid_with${transferPolicy ? '' : 'out'}_transfer_policy`,
|
|
@@ -3,21 +3,20 @@ import { type SuiClient } from '@mysten/sui/client';
|
|
|
3
3
|
import { type Transaction } from '@mysten/sui/transactions';
|
|
4
4
|
import { ORIGIN_BYTE_NFT_TYPES_MISSING_ORDERBOOK } from '../../constants';
|
|
5
5
|
import { getNftType } from '../../helpers/getNftType';
|
|
6
|
-
import { isNonKioskListing } from '../../helpers/isNonKioskListing';
|
|
7
6
|
import { kioskTxWrapper } from '../../helpers/kiosk/kioskTxWrapper';
|
|
8
7
|
import { isOriginByteCollection } from '../../helpers/originByte/isOriginByteCollection';
|
|
9
8
|
import { normalizedNftType } from '../../utils/normalizeNftType';
|
|
10
|
-
import {
|
|
9
|
+
import { addTradePortListTxHandler } from '../listNfts/addListTxs';
|
|
11
10
|
import {
|
|
12
11
|
addBlueMoveRelistTx,
|
|
13
12
|
addTocenRelistTx,
|
|
14
13
|
addTradePortRelistTx,
|
|
14
|
+
addKioskTradePortRelistTx,
|
|
15
15
|
} from '../listNfts/addRelistTxs';
|
|
16
16
|
import {
|
|
17
17
|
addBluemoveUnlistTxHandler,
|
|
18
18
|
addClutchyUnlistTxHandler,
|
|
19
19
|
addHyperspaceUnlistTxHandler,
|
|
20
|
-
addTradePortKioskUnlistTx,
|
|
21
20
|
addTradePortUnlistTxHandler,
|
|
22
21
|
} from '../unlistListings/addUnlistListingTxs';
|
|
23
22
|
import { type UnlistListingTx } from '../unlistListings/unlistListings';
|
|
@@ -73,30 +72,24 @@ export async function relistNft({
|
|
|
73
72
|
switch (firstListedOrExpiredListing.market_name) {
|
|
74
73
|
case 'tradeport':
|
|
75
74
|
if (
|
|
76
|
-
(!isOriginByteCollection(txData?.transferPolicies) ||
|
|
77
|
-
ORIGIN_BYTE_NFT_TYPES_MISSING_ORDERBOOK?.includes(normalizedNftType(txData?.nftType))) &&
|
|
78
75
|
txData?.listingNonce &&
|
|
79
|
-
(
|
|
80
|
-
|
|
81
|
-
listingNonce: txData?.listingNonce,
|
|
82
|
-
}))
|
|
76
|
+
isOriginByteCollection(txData?.transferPolicies) &&
|
|
77
|
+
!ORIGIN_BYTE_NFT_TYPES_MISSING_ORDERBOOK?.includes(normalizedNftType(txData?.nftType))
|
|
83
78
|
) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
await addTradePortUnlistTxHandler(txData);
|
|
92
|
-
await addTradePortListTxHandler({
|
|
93
|
-
...txData,
|
|
94
|
-
listPrice,
|
|
95
|
-
});
|
|
79
|
+
await addTradePortUnlistTxHandler(txData);
|
|
80
|
+
await addTradePortListTxHandler({
|
|
81
|
+
...txData,
|
|
82
|
+
listPrice,
|
|
83
|
+
});
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
96
86
|
|
|
97
|
-
|
|
98
|
-
}
|
|
87
|
+
if (txData?.listingNonce?.startsWith('0::')) {
|
|
88
|
+
addTradePortRelistTx({ ...txData, listPrice });
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
99
91
|
|
|
92
|
+
if (txData?.listingNonce?.startsWith('1::')) {
|
|
100
93
|
return kioskTxWrapper({
|
|
101
94
|
tx: txData?.tx,
|
|
102
95
|
kioskClient: txData?.kioskClient,
|
|
@@ -106,11 +99,7 @@ export async function relistNft({
|
|
|
106
99
|
sharedKioskState: txData?.sharedKioskState,
|
|
107
100
|
shouldUseSharedKioskTx: false,
|
|
108
101
|
async runCommands(kioskTx) {
|
|
109
|
-
await
|
|
110
|
-
...txData,
|
|
111
|
-
kioskTx,
|
|
112
|
-
});
|
|
113
|
-
await addTradePortKioskListTx({
|
|
102
|
+
await addKioskTradePortRelistTx({
|
|
114
103
|
...txData,
|
|
115
104
|
kioskTx,
|
|
116
105
|
listPrice,
|
|
@@ -119,6 +108,8 @@ export async function relistNft({
|
|
|
119
108
|
});
|
|
120
109
|
}
|
|
121
110
|
|
|
111
|
+
await addTradePortUnlistTxHandler({ ...txData, isPartOfRelist: true });
|
|
112
|
+
await addTradePortListTxHandler({ ...txData, listPrice });
|
|
122
113
|
break;
|
|
123
114
|
case 'hyperspace':
|
|
124
115
|
await addHyperspaceUnlistTxHandler(txData);
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { Transaction } from '@mysten/sui/transactions';
|
|
2
|
+
import {
|
|
3
|
+
calculateSwapInputAmountWithSlippage,
|
|
4
|
+
createSwapTransaction,
|
|
5
|
+
transferBackExtraSwappedCoin,
|
|
6
|
+
} from '../../helpers/swap';
|
|
7
|
+
import { TRADEPORT_SPONSOR_USDC_FEE_AMOUNT_PER_PERIOD, USDC_COIN_TYPE } from '../../constants';
|
|
8
|
+
import type { SuiClient } from '@mysten/sui/client';
|
|
9
|
+
import { SUI_CLOCK_OBJECT_ID } from '@mysten/sui.js/utils';
|
|
10
|
+
import { TRADEPORT_LISTINGS_PACKAGE, TRADEPORT_LISTINGS_STORE } from '../../constants';
|
|
11
|
+
import { type SponsorNftListingOptions } from './sponsorNftListing';
|
|
12
|
+
import BigNumber from '../../bigNumberConfig';
|
|
13
|
+
|
|
14
|
+
export const addSponsorListingTx = async ({
|
|
15
|
+
tx,
|
|
16
|
+
nftTokenId,
|
|
17
|
+
nftType,
|
|
18
|
+
suiClient,
|
|
19
|
+
walletAddress,
|
|
20
|
+
sponsorOptions,
|
|
21
|
+
}: {
|
|
22
|
+
tx: Transaction;
|
|
23
|
+
nftTokenId: string;
|
|
24
|
+
nftType: string;
|
|
25
|
+
suiClient: SuiClient;
|
|
26
|
+
walletAddress: string;
|
|
27
|
+
sponsorOptions: SponsorNftListingOptions;
|
|
28
|
+
}) => {
|
|
29
|
+
const coinInAmount = await calculateSwapInputAmountWithSlippage({
|
|
30
|
+
coinInType: sponsorOptions?.coinInType,
|
|
31
|
+
coinOutType: USDC_COIN_TYPE,
|
|
32
|
+
coinOutAmount: new BigNumber(TRADEPORT_SPONSOR_USDC_FEE_AMOUNT_PER_PERIOD)
|
|
33
|
+
?.times(sponsorOptions?.numOfPeriods)
|
|
34
|
+
.toString(),
|
|
35
|
+
slippage: sponsorOptions?.slippage,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const { coinOut } = await createSwapTransaction({
|
|
39
|
+
suiClient,
|
|
40
|
+
walletAddress,
|
|
41
|
+
options: {
|
|
42
|
+
transaction: tx,
|
|
43
|
+
coinInType: sponsorOptions?.coinInType,
|
|
44
|
+
coinInAmount,
|
|
45
|
+
coinOutType: USDC_COIN_TYPE,
|
|
46
|
+
slippage: sponsorOptions?.slippage,
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const [sponsorFeeCoin] = tx.splitCoins(coinOut, [
|
|
51
|
+
tx.pure.u64(
|
|
52
|
+
new BigNumber(TRADEPORT_SPONSOR_USDC_FEE_AMOUNT_PER_PERIOD)
|
|
53
|
+
?.times(sponsorOptions?.numOfPeriods)
|
|
54
|
+
.toString(),
|
|
55
|
+
),
|
|
56
|
+
]);
|
|
57
|
+
|
|
58
|
+
tx.moveCall({
|
|
59
|
+
target: `${TRADEPORT_LISTINGS_PACKAGE}::tradeport_listings::add_sponsored_listing`,
|
|
60
|
+
arguments: [
|
|
61
|
+
tx.object(TRADEPORT_LISTINGS_STORE),
|
|
62
|
+
tx.object(SUI_CLOCK_OBJECT_ID),
|
|
63
|
+
tx.pure.id(nftTokenId),
|
|
64
|
+
tx.pure.u64(sponsorOptions?.numOfPeriods),
|
|
65
|
+
tx.object(sponsorFeeCoin),
|
|
66
|
+
],
|
|
67
|
+
typeArguments: [nftType],
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
transferBackExtraSwappedCoin(tx, coinOut, walletAddress);
|
|
71
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Transaction } from '@mysten/sui/transactions';
|
|
2
|
+
import { gqlChainRequest } from '../../graphql/gqlChainRequest';
|
|
3
|
+
import { fetchNftCollectionChainState } from '../../graphql/queries/fetchNftCollectionChainState';
|
|
4
|
+
import { isOriginByteCollection } from '../../helpers/originByte/isOriginByteCollection';
|
|
5
|
+
import type { RequestContext } from '../../SuiTradingClient';
|
|
6
|
+
import { addSponsorListingTx } from './addSponsorNftListingTx';
|
|
7
|
+
import { getNftType } from '../../helpers/getNftType';
|
|
8
|
+
|
|
9
|
+
export type SponsorNftListingOptions = {
|
|
10
|
+
shouldSponsor?: boolean;
|
|
11
|
+
numOfPeriods?: number;
|
|
12
|
+
slippage?: number;
|
|
13
|
+
coinInType?: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type SponsorNftListing = {
|
|
17
|
+
nftTokenId: string;
|
|
18
|
+
walletAddress: string;
|
|
19
|
+
options: SponsorNftListingOptions;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const sponsorNftListing = async (
|
|
23
|
+
{ nftTokenId, walletAddress, options }: SponsorNftListing,
|
|
24
|
+
context: RequestContext,
|
|
25
|
+
): Promise<Transaction> => {
|
|
26
|
+
const res = await gqlChainRequest({
|
|
27
|
+
chain: 'sui',
|
|
28
|
+
query: fetchNftCollectionChainState,
|
|
29
|
+
variables: { nftTokenId },
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
if (res?.nfts?.length === 0) {
|
|
33
|
+
throw new Error(`No nft found with token id ${nftTokenId}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const nft = res?.nfts?.[0];
|
|
37
|
+
|
|
38
|
+
const nftType = getNftType({
|
|
39
|
+
collectionId: nft?.collection?.id,
|
|
40
|
+
collectionChainState: nft?.collection?.chain_state,
|
|
41
|
+
nft,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const transferPolicies = nft?.collection?.chain_state?.transfer_policies;
|
|
45
|
+
|
|
46
|
+
if (isOriginByteCollection(transferPolicies)) {
|
|
47
|
+
throw new Error(`You cannot sponsor an Origin Byte NFT. Nft Token Id: ${nftTokenId}`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const tx = new Transaction();
|
|
51
|
+
|
|
52
|
+
await addSponsorListingTx({
|
|
53
|
+
tx,
|
|
54
|
+
suiClient: context.suiClient,
|
|
55
|
+
nftTokenId,
|
|
56
|
+
nftType,
|
|
57
|
+
walletAddress,
|
|
58
|
+
sponsorOptions: options,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return Transaction.from(tx);
|
|
62
|
+
};
|