@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.
- package/.babel.config.js +3 -0
- package/.env.demo +4 -0
- package/.eslintrc.json +46 -0
- package/.prettierignore +4 -0
- package/.prettierrc.json +7 -0
- package/README.md +1 -0
- package/dist/index.d.mts +90 -0
- package/dist/index.d.ts +90 -0
- package/dist/index.js +3760 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +3733 -0
- package/dist/index.mjs.map +1 -0
- package/jest.config.js +7 -0
- package/package.json +45 -0
- package/src/SuiTradingClient.ts +158 -0
- package/src/apiClients/graphqlClient.ts +5 -0
- package/src/apiClients/kioskClient.ts +10 -0
- package/src/apiClients/suiClient.ts +5 -0
- package/src/constants.ts +74 -0
- package/src/graphql/createChainGQLQuery.ts +25 -0
- package/src/graphql/gqlChainRequest.ts +20 -0
- package/src/graphql/queries/fetchAccountKiosks.ts +12 -0
- package/src/graphql/queries/fetchBidsById.ts +28 -0
- package/src/graphql/queries/fetchCollectionBidById.ts +20 -0
- package/src/graphql/queries/fetchCollectionBidsAtSamePrice.ts +28 -0
- package/src/graphql/queries/fetchCollectionsById.ts +30 -0
- package/src/graphql/queries/fetchCommissionByListingId.ts +13 -0
- package/src/graphql/queries/fetchCryptoToUsdRate.ts +13 -0
- package/src/graphql/queries/fetchKiosksByOwner.ts +13 -0
- package/src/graphql/queries/fetchListingsById.ts +24 -0
- package/src/graphql/queries/fetchListingsByNftId.ts +23 -0
- package/src/graphql/queries/fetchNftsById.ts +61 -0
- package/src/graphql/queries/fetchOwnerCapByKiosk.ts +10 -0
- package/src/graphql/queries/fetchPersonalCapByKiosk.ts +10 -0
- package/src/graphql/queries/fetchSharedObjectsByType.ts +12 -0
- package/src/graphql/queries/fetchTransferPoliciesByType.ts +12 -0
- package/src/graphql/queries/getCommissionByListingId.ts +15 -0
- package/src/helpers/addOneDollarFee.ts +17 -0
- package/src/helpers/addThirdPartyTxFee.ts +17 -0
- package/src/helpers/destroyZeroCoin.ts +14 -0
- package/src/helpers/getMarketFeePrice.ts +78 -0
- package/src/helpers/getNftTypeFromNft.ts +8 -0
- package/src/helpers/getSharedObjects.ts +113 -0
- package/src/helpers/getSuiToUsdRate.ts +17 -0
- package/src/helpers/getTradeportBiddingContractParsedBidAmount.ts +32 -0
- package/src/helpers/hasRoyaltyRule.ts +14 -0
- package/src/helpers/hasTransferPolicyRules.ts +21 -0
- package/src/helpers/isNonKioskListing.ts +7 -0
- package/src/helpers/kiosk/getRulePackageId.ts +26 -0
- package/src/helpers/kiosk/isBluemoveKioskBid.ts +1 -0
- package/src/helpers/kiosk/isTradePortKioskBid.ts +4 -0
- package/src/helpers/kiosk/kioskTxWrapper.ts +102 -0
- package/src/helpers/kiosk/resolveFloorPriceRule.ts +25 -0
- package/src/helpers/kiosk/resolveKioskLockRule.ts +49 -0
- package/src/helpers/kiosk/resolvePersonalKioskRule.ts +26 -0
- package/src/helpers/kiosk/resolveRoyaltyRule.ts +41 -0
- package/src/helpers/kiosk/resolveTransferPolicies.ts +150 -0
- package/src/helpers/originByte/confirmOBTranfer.ts +33 -0
- package/src/helpers/originByte/createOBKiosk.ts +14 -0
- package/src/helpers/originByte/depositNftIntoOBKiosk.ts +14 -0
- package/src/helpers/originByte/getOBBidderKiosk.ts +9 -0
- package/src/helpers/originByte/getOBKiosk.ts +24 -0
- package/src/helpers/originByte/getOrCreateOBKiosk.ts +37 -0
- package/src/helpers/originByte/isOBKiosk.ts +13 -0
- package/src/helpers/originByte/isOriginByteBid.ts +6 -0
- package/src/helpers/originByte/isOriginByteTx.ts +2 -0
- package/src/helpers/originByte/shareOriginByteKiosk.ts +14 -0
- package/src/helpers/rpc/getAcountBalance.ts +17 -0
- package/src/helpers/rpc/getObjectType.ts +10 -0
- package/src/helpers/splitCoins.ts +12 -0
- package/src/index.ts +3 -0
- package/src/methods/acceptCollectionBid/acceptCollectionBid.ts +119 -0
- package/src/methods/acceptCollectionBid/addAcceptCollectionBIdTxs.ts +359 -0
- package/src/methods/acceptNftBids/acceptNftBids.ts +100 -0
- package/src/methods/acceptNftBids/addAcceptNftBidTxs.ts +214 -0
- package/src/methods/buyListings/addBuyListingTxs.ts +503 -0
- package/src/methods/buyListings/buyListings.ts +143 -0
- package/src/methods/claimNfts/addClaimNftsTxs.ts +104 -0
- package/src/methods/claimNfts/claimNfts.ts +139 -0
- package/src/methods/listNfts/addListTxs.ts +186 -0
- package/src/methods/listNfts/addRelistTxs.ts +79 -0
- package/src/methods/listNfts/listNfts.ts +80 -0
- package/src/methods/placeCollectionBids/addPlaceCollectionBidTxs.ts +146 -0
- package/src/methods/placeCollectionBids/placeCollectionBids.ts +120 -0
- package/src/methods/placeNftBids/addPlaceNftBidTxs.ts +146 -0
- package/src/methods/placeNftBids/placeNftBids.ts +69 -0
- package/src/methods/relistNft/relistNft.ts +104 -0
- package/src/methods/removeCollectionBid/addRemoveCollectionBidTxs.ts +119 -0
- package/src/methods/removeCollectionBid/removeCollectionBid.ts +97 -0
- package/src/methods/removeNftBids/addRemoveNftBidTxs.ts +84 -0
- package/src/methods/removeNftBids/removeNftBids.ts +80 -0
- package/src/methods/transferNfts/addTransferNftTx.ts +78 -0
- package/src/methods/transferNfts/transferNfts.ts +107 -0
- package/src/methods/unlistListings/addUnlistListingTxs.ts +258 -0
- package/src/methods/unlistListings/unlistListings.ts +108 -0
- package/src/methods/withdrawKioskProfits/withdrawKioskProfits.ts +25 -0
- package/src/tests/SuiWallet.ts +49 -0
- package/src/utils/addHexPrefix.ts +7 -0
- package/src/utils/addLeadingZerosAfter0x.ts +2 -0
- package/src/utils/parseSUI.ts +1 -0
- package/src/utils/printTxBlockTxs.ts +5 -0
- package/src/utils/toUint8Array.ts +12 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { TransactionBlock } from '@mysten/sui.js/transactions';
|
|
2
|
+
import { gqlChainRequest } from '../../graphql/gqlChainRequest';
|
|
3
|
+
import { fetchCollectionBidById } from '../../graphql/queries/fetchCollectionBidById';
|
|
4
|
+
import { fetchCollectionsByIdWithOneNft } from '../../graphql/queries/fetchCollectionsById';
|
|
5
|
+
import { getNftTypeFromNft } from '../../helpers/getNftTypeFromNft';
|
|
6
|
+
import { getSharedObjects } from '../../helpers/getSharedObjects';
|
|
7
|
+
import {
|
|
8
|
+
addBluemoveRemoveCollectionBidTxHandler,
|
|
9
|
+
addClutchyRemoveCollectionBidTxHandler,
|
|
10
|
+
addTradePortRemoveCollectionBidTxHandler,
|
|
11
|
+
} from './addRemoveCollectionBidTxs';
|
|
12
|
+
|
|
13
|
+
export type RemoveCollectionBidTx = {
|
|
14
|
+
txBlock: TransactionBlock;
|
|
15
|
+
sharedObjects: any;
|
|
16
|
+
bidNonce: string;
|
|
17
|
+
bidder: string;
|
|
18
|
+
nftType: string;
|
|
19
|
+
nftTokenId: string;
|
|
20
|
+
bidAmount: number;
|
|
21
|
+
sellerKiosk: string;
|
|
22
|
+
bidMarketName: string;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type RemoveCollectionBid = {
|
|
26
|
+
bidId: string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const removeCollectionBid = async ({
|
|
30
|
+
bidId,
|
|
31
|
+
}: RemoveCollectionBid): Promise<TransactionBlock> => {
|
|
32
|
+
const res = await gqlChainRequest({
|
|
33
|
+
chain: 'sui',
|
|
34
|
+
query: fetchCollectionBidById,
|
|
35
|
+
variables: { bidId },
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
if (res?.bids?.length === 0) {
|
|
39
|
+
throw new Error('No bids found');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const txBlock = new TransactionBlock();
|
|
43
|
+
|
|
44
|
+
for (const bid of res.bids) {
|
|
45
|
+
let nftType;
|
|
46
|
+
if (
|
|
47
|
+
[
|
|
48
|
+
'fa58ae52-b18d-4179-a2d4-c2471ede5f14', // S-Card
|
|
49
|
+
'ca37bbb2-4398-46cb-b467-8a834d2d2612', // S-Card mint ticket
|
|
50
|
+
'c8e19183-3a9e-4312-939f-c63a1416e344', // Panzerdogs
|
|
51
|
+
'819eabe2-1565-4c3a-a9f6-1b5fca48e09a', // Panzerdog Tanks
|
|
52
|
+
]?.includes(bid?.collection_id)
|
|
53
|
+
) {
|
|
54
|
+
const collectionWithOneNftRes = await gqlChainRequest({
|
|
55
|
+
chain: 'sui',
|
|
56
|
+
query: fetchCollectionsByIdWithOneNft,
|
|
57
|
+
variables: { collectionIds: [bid?.collection_id] },
|
|
58
|
+
});
|
|
59
|
+
nftType = getNftTypeFromNft(collectionWithOneNftRes?.collections?.[0]?.nfts?.[0]);
|
|
60
|
+
} else if (bid?.collection_id === '07231735-96de-4710-8e11-52c61a482578') {
|
|
61
|
+
nftType =
|
|
62
|
+
'0x034c162f6b594cb5a1805264dd01ca5d80ce3eca6522e6ee37fd9ebfb9d3ddca::factory::PrimeMachin';
|
|
63
|
+
} else {
|
|
64
|
+
nftType = bid?.contract?.properties?.nft_type;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const sharedObjects = await getSharedObjects(nftType);
|
|
68
|
+
|
|
69
|
+
const txData: RemoveCollectionBidTx = {
|
|
70
|
+
txBlock,
|
|
71
|
+
sharedObjects,
|
|
72
|
+
bidNonce: bid?.nonce,
|
|
73
|
+
bidder: bid?.bidder,
|
|
74
|
+
nftType,
|
|
75
|
+
nftTokenId: bid?.nft?.token_id,
|
|
76
|
+
bidAmount: bid?.price,
|
|
77
|
+
sellerKiosk: bid?.nft?.chain_state?.kiosk_id,
|
|
78
|
+
bidMarketName: bid?.market_contract?.name,
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
switch (txData.bidMarketName) {
|
|
82
|
+
case 'tradeport':
|
|
83
|
+
await addTradePortRemoveCollectionBidTxHandler(txData);
|
|
84
|
+
break;
|
|
85
|
+
case 'bluemove':
|
|
86
|
+
await addBluemoveRemoveCollectionBidTxHandler(txData);
|
|
87
|
+
break;
|
|
88
|
+
case 'clutchy':
|
|
89
|
+
await addClutchyRemoveCollectionBidTxHandler(txData);
|
|
90
|
+
break;
|
|
91
|
+
default:
|
|
92
|
+
throw new Error('Marketplace not supported');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return new TransactionBlock(txBlock);
|
|
97
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BLUEMOVE_OFFER_DATA_OBJECT,
|
|
3
|
+
TOCEN_MARKETPLACE_OBJECT,
|
|
4
|
+
TRADEPORT_BIDDING_STORE,
|
|
5
|
+
TRADEPORT_KIOSK_BIDDING_STORE,
|
|
6
|
+
} from '../../constants';
|
|
7
|
+
import { isTradePortKioskBid } from '../../helpers/kiosk/isTradePortKioskBid';
|
|
8
|
+
import { isOriginByteBid } from '../../helpers/originByte/isOriginByteBid';
|
|
9
|
+
import { getObjectType } from '../../helpers/rpc/getObjectType';
|
|
10
|
+
import { type RemoveNftBidTx } from './removeNftBids';
|
|
11
|
+
|
|
12
|
+
export function addTradeportRemoveNftBidTx({ txBlock, bidNonce, nftType }: RemoveNftBidTx) {
|
|
13
|
+
txBlock.moveCall({
|
|
14
|
+
target:
|
|
15
|
+
'0xb42dbb7413b79394e1a0175af6ae22b69a5c7cc5df259cd78072b6818217c027::biddings::cancel_bid',
|
|
16
|
+
arguments: [txBlock.object(TRADEPORT_BIDDING_STORE), txBlock.pure(bidNonce)],
|
|
17
|
+
typeArguments: [nftType],
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function addTradeportKioskRemoveNftBidTx({ txBlock, bidNonce, nftType }: RemoveNftBidTx) {
|
|
22
|
+
txBlock.moveCall({
|
|
23
|
+
target:
|
|
24
|
+
'0x33a9e4a3089d911c2a2bf16157a1d6a4a8cbd9a2106a98ecbaefe6ed370d7a25::kiosk_biddings::cancel_bid',
|
|
25
|
+
arguments: [txBlock.object(TRADEPORT_KIOSK_BIDDING_STORE), txBlock.pure(bidNonce)],
|
|
26
|
+
typeArguments: [nftType],
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function addOriginByteRemoveNftBidTx({ txBlock, bidNonce }: RemoveNftBidTx) {
|
|
31
|
+
txBlock.moveCall({
|
|
32
|
+
target:
|
|
33
|
+
'0x8534e4cdfd28709c94330a9783c3d5fe6f5daba0bffb69102ce303c5b38aed5a::bidding::close_bid',
|
|
34
|
+
arguments: [txBlock.pure(bidNonce)],
|
|
35
|
+
typeArguments: ['0x2::sui::SUI'],
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function addBluemoveRemoveNftBidTx({
|
|
40
|
+
txBlock,
|
|
41
|
+
bidNonce,
|
|
42
|
+
nftTokenId,
|
|
43
|
+
nftType,
|
|
44
|
+
}: RemoveNftBidTx) {
|
|
45
|
+
txBlock.moveCall({
|
|
46
|
+
target:
|
|
47
|
+
'0xd5dd28cc24009752905689b2ba2bf90bfc8de4549b9123f93519bb8ba9bf9981::offer_item::cancel_offer_nft',
|
|
48
|
+
arguments: [
|
|
49
|
+
txBlock.object(BLUEMOVE_OFFER_DATA_OBJECT),
|
|
50
|
+
txBlock.pure(nftTokenId),
|
|
51
|
+
txBlock.pure(bidNonce),
|
|
52
|
+
],
|
|
53
|
+
typeArguments: [nftType],
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function addTocenRemoveNftBidTx({ txBlock, nftTokenId, bidAmount }: RemoveNftBidTx) {
|
|
58
|
+
txBlock.moveCall({
|
|
59
|
+
target:
|
|
60
|
+
'0x3605d91c559e80cf8fdeabae9abaccb0bc38f96eac0b32bf47e95a9159a5277f::tocen_marketplace::cancel_offer',
|
|
61
|
+
arguments: [
|
|
62
|
+
txBlock.pure(TOCEN_MARKETPLACE_OBJECT),
|
|
63
|
+
txBlock.pure(nftTokenId),
|
|
64
|
+
txBlock.pure(bidAmount),
|
|
65
|
+
],
|
|
66
|
+
typeArguments: [],
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export async function addTradePortRemoveNftBidTxHandler(txData: RemoveNftBidTx) {
|
|
71
|
+
const bidType = await getObjectType(txData?.bidNonce);
|
|
72
|
+
|
|
73
|
+
if (isOriginByteBid(bidType)) {
|
|
74
|
+
addOriginByteRemoveNftBidTx(txData);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (isTradePortKioskBid(bidType)) {
|
|
79
|
+
addTradeportKioskRemoveNftBidTx(txData);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
addTradeportRemoveNftBidTx(txData);
|
|
84
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { TransactionBlock } from '@mysten/sui.js/transactions';
|
|
2
|
+
import { gqlChainRequest } from '../../graphql/gqlChainRequest';
|
|
3
|
+
import { fetchBidsById } from '../../graphql/queries/fetchBidsById';
|
|
4
|
+
import { getNftTypeFromNft } from '../../helpers/getNftTypeFromNft';
|
|
5
|
+
import { getSharedObjects } from '../../helpers/getSharedObjects';
|
|
6
|
+
import {
|
|
7
|
+
addBluemoveRemoveNftBidTx,
|
|
8
|
+
addOriginByteRemoveNftBidTx,
|
|
9
|
+
addTocenRemoveNftBidTx,
|
|
10
|
+
addTradePortRemoveNftBidTxHandler,
|
|
11
|
+
} from './addRemoveNftBidTxs';
|
|
12
|
+
|
|
13
|
+
export type RemoveNftBidTx = {
|
|
14
|
+
txBlock: TransactionBlock;
|
|
15
|
+
sharedObjects: any;
|
|
16
|
+
bidNonce: string;
|
|
17
|
+
nftType: string;
|
|
18
|
+
nftTokenId: string;
|
|
19
|
+
bidAmount: number;
|
|
20
|
+
sellerKiosk: string;
|
|
21
|
+
bidMarketName: string;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type RemoveNftBid = {
|
|
25
|
+
bidId: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type RemoveNftBids = {
|
|
29
|
+
bidIds: string[];
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const removeNftBids = async ({ bidIds }: RemoveNftBids): Promise<TransactionBlock> => {
|
|
33
|
+
const res = await gqlChainRequest({
|
|
34
|
+
chain: 'sui',
|
|
35
|
+
query: fetchBidsById,
|
|
36
|
+
variables: { bidIds },
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (res?.bids?.length === 0) {
|
|
40
|
+
throw new Error('No bids found');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const txBlock = new TransactionBlock();
|
|
44
|
+
|
|
45
|
+
for (const bid of res.bids) {
|
|
46
|
+
const sharedObjects = await getSharedObjects(
|
|
47
|
+
bid?.nft?.properties?.nft_type || bid?.nft?.contract?.properties?.nft_type,
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const txData: RemoveNftBidTx = {
|
|
51
|
+
txBlock,
|
|
52
|
+
sharedObjects,
|
|
53
|
+
bidNonce: bid?.nonce,
|
|
54
|
+
nftType: getNftTypeFromNft(bid?.nft),
|
|
55
|
+
nftTokenId: bid?.nft?.token_id,
|
|
56
|
+
bidAmount: bid?.price,
|
|
57
|
+
sellerKiosk: bid?.nft?.chain_state?.kiosk_id,
|
|
58
|
+
bidMarketName: bid?.market_contract?.name,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
switch (txData.bidMarketName) {
|
|
62
|
+
case 'tradeport':
|
|
63
|
+
await addTradePortRemoveNftBidTxHandler(txData);
|
|
64
|
+
break;
|
|
65
|
+
case 'clutchy':
|
|
66
|
+
addOriginByteRemoveNftBidTx(txData);
|
|
67
|
+
break;
|
|
68
|
+
case 'bluemove':
|
|
69
|
+
addBluemoveRemoveNftBidTx(txData);
|
|
70
|
+
break;
|
|
71
|
+
case 'tocen':
|
|
72
|
+
addTocenRemoveNftBidTx(txData);
|
|
73
|
+
break;
|
|
74
|
+
default:
|
|
75
|
+
throw new Error('Marketplace not supported');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return new TransactionBlock(txBlock);
|
|
80
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TRADEPORT_KIOSK_TRANSFERS_ESCROW_KIOSK,
|
|
3
|
+
TRADEPORT_KIOSK_TRANSFERS_STORE,
|
|
4
|
+
} from '../../constants';
|
|
5
|
+
import { resolveTransferPolicies } from '../../helpers/kiosk/resolveTransferPolicies';
|
|
6
|
+
import { getOBKiosk } from '../../helpers/originByte/getOBKiosk';
|
|
7
|
+
import { addLeadingZerosAfter0x } from '../../utils/addLeadingZerosAfter0x';
|
|
8
|
+
import { type TransferNftTx } from './transferNfts';
|
|
9
|
+
|
|
10
|
+
export async function addOriginByteTransferNftTx({
|
|
11
|
+
txBlock,
|
|
12
|
+
nftTokenId,
|
|
13
|
+
nftType,
|
|
14
|
+
recipientAddress,
|
|
15
|
+
senderKiosk,
|
|
16
|
+
}: TransferNftTx) {
|
|
17
|
+
const recipientOBKiosk = await getOBKiosk(recipientAddress);
|
|
18
|
+
|
|
19
|
+
if (recipientOBKiosk) {
|
|
20
|
+
txBlock.moveCall({
|
|
21
|
+
target:
|
|
22
|
+
'0x2678c98fe23173eebea384509464eb81b1f3035a57419cb46d025000c337451a::ob_kiosk::p2p_transfer',
|
|
23
|
+
arguments: [
|
|
24
|
+
txBlock.object(senderKiosk),
|
|
25
|
+
txBlock.object(recipientOBKiosk),
|
|
26
|
+
txBlock.pure(nftTokenId),
|
|
27
|
+
],
|
|
28
|
+
typeArguments: [nftType],
|
|
29
|
+
});
|
|
30
|
+
} else {
|
|
31
|
+
txBlock.moveCall({
|
|
32
|
+
target:
|
|
33
|
+
'0x2678c98fe23173eebea384509464eb81b1f3035a57419cb46d025000c337451a::ob_kiosk::p2p_transfer_and_create_target_kiosk',
|
|
34
|
+
arguments: [
|
|
35
|
+
txBlock.object(senderKiosk),
|
|
36
|
+
txBlock.pure(addLeadingZerosAfter0x(recipientAddress)),
|
|
37
|
+
txBlock.pure(nftTokenId),
|
|
38
|
+
],
|
|
39
|
+
typeArguments: [nftType],
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function addTradeportKioskTransferTx({
|
|
45
|
+
txBlock,
|
|
46
|
+
sharedObjects,
|
|
47
|
+
kioskTx,
|
|
48
|
+
nftTokenId,
|
|
49
|
+
nftType,
|
|
50
|
+
recipientAddress,
|
|
51
|
+
}: TransferNftTx) {
|
|
52
|
+
const { transferPolicy } = sharedObjects;
|
|
53
|
+
|
|
54
|
+
const [transferRequest] = txBlock.moveCall({
|
|
55
|
+
target:
|
|
56
|
+
'0x78eae99d1a7edae714b5de107f4b44ccbdf5f9ca6919498d9b024ef378dc13f7::kiosk_transfers::transfer',
|
|
57
|
+
arguments: [
|
|
58
|
+
txBlock.object(TRADEPORT_KIOSK_TRANSFERS_STORE),
|
|
59
|
+
txBlock.object(TRADEPORT_KIOSK_TRANSFERS_ESCROW_KIOSK),
|
|
60
|
+
txBlock.object(kioskTx.kiosk.value ?? kioskTx.kiosk),
|
|
61
|
+
txBlock.object(kioskTx.kioskCap.value ?? kioskTx.kioskCap),
|
|
62
|
+
txBlock.pure(nftTokenId),
|
|
63
|
+
txBlock.pure(addLeadingZerosAfter0x(recipientAddress)),
|
|
64
|
+
txBlock.object(transferPolicy),
|
|
65
|
+
],
|
|
66
|
+
typeArguments: [nftType],
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
await resolveTransferPolicies({
|
|
70
|
+
txBlock,
|
|
71
|
+
kioskTx,
|
|
72
|
+
nftType,
|
|
73
|
+
price: '0',
|
|
74
|
+
transferRequest,
|
|
75
|
+
kioskToLockRuleProve: TRADEPORT_KIOSK_TRANSFERS_ESCROW_KIOSK,
|
|
76
|
+
shouldSkipKioskLocking: true,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { TransactionBlock } from '@mysten/sui.js/transactions';
|
|
2
|
+
import { gqlChainRequest } from '../../graphql/gqlChainRequest';
|
|
3
|
+
import { fetchNftsById } from '../../graphql/queries/fetchNftsById';
|
|
4
|
+
import { addOneDollarFee } from '../../helpers/addOneDollarFee';
|
|
5
|
+
import { getNftTypeFromNft } from '../../helpers/getNftTypeFromNft';
|
|
6
|
+
import { getSharedObjects } from '../../helpers/getSharedObjects';
|
|
7
|
+
import { kioskTxWrapper } from '../../helpers/kiosk/kioskTxWrapper';
|
|
8
|
+
import { isOBKiosk } from '../../helpers/originByte/isOBKiosk';
|
|
9
|
+
import { getAccountBalance } from '../../helpers/rpc/getAcountBalance';
|
|
10
|
+
import { addLeadingZerosAfter0x } from '../../utils/addLeadingZerosAfter0x';
|
|
11
|
+
import { addOriginByteTransferNftTx, addTradeportKioskTransferTx } from './addTransferNftTx';
|
|
12
|
+
|
|
13
|
+
export type TransferNftTx = {
|
|
14
|
+
txBlock: TransactionBlock;
|
|
15
|
+
nftType: string;
|
|
16
|
+
nftTokenId: string;
|
|
17
|
+
senderKiosk: string;
|
|
18
|
+
senderAddress: string;
|
|
19
|
+
recipientAddress: string;
|
|
20
|
+
sharedObjects?: any;
|
|
21
|
+
kioskTx?: any;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type TransferNfts = {
|
|
25
|
+
nftIds: string[];
|
|
26
|
+
recipientAddress: string;
|
|
27
|
+
walletAddress: string;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const transferNfts = async ({
|
|
31
|
+
nftIds,
|
|
32
|
+
recipientAddress,
|
|
33
|
+
walletAddress,
|
|
34
|
+
}: TransferNfts): Promise<TransactionBlock> => {
|
|
35
|
+
if (addLeadingZerosAfter0x(recipientAddress) === addLeadingZerosAfter0x(walletAddress)) {
|
|
36
|
+
throw new Error('Cannot transfer to self');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const recipientAddressBalance = await getAccountBalance({ owner: recipientAddress });
|
|
40
|
+
// Recipient address needs to have a balance to be a valid address
|
|
41
|
+
if (!recipientAddressBalance || !recipientAddress?.includes('0x')) {
|
|
42
|
+
throw new Error('Invalid recipient address');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const res = await gqlChainRequest({
|
|
46
|
+
chain: 'sui',
|
|
47
|
+
query: fetchNftsById,
|
|
48
|
+
variables: { nftIds },
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
if (res?.nfts?.length === 0) {
|
|
52
|
+
throw new Error('No nfts found');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const txBlock = new TransactionBlock();
|
|
56
|
+
|
|
57
|
+
for (const nft of res.nfts) {
|
|
58
|
+
if (nft?.listed) {
|
|
59
|
+
throw new Error('Cannot transfer a listed NFT');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const sharedObjects = await getSharedObjects(getNftTypeFromNft(nft));
|
|
63
|
+
|
|
64
|
+
const txData: TransferNftTx = {
|
|
65
|
+
txBlock,
|
|
66
|
+
nftType: getNftTypeFromNft(nft),
|
|
67
|
+
nftTokenId: nft?.token_id,
|
|
68
|
+
senderKiosk: nft?.chain_state?.kiosk_id,
|
|
69
|
+
senderAddress: walletAddress,
|
|
70
|
+
recipientAddress,
|
|
71
|
+
sharedObjects,
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// If NFT is not inside kiosk, transfer the NFT directly
|
|
75
|
+
if (!txData.senderKiosk) {
|
|
76
|
+
txBlock.transferObjects(
|
|
77
|
+
[txBlock.object(txData.nftTokenId)],
|
|
78
|
+
txBlock.pure(addLeadingZerosAfter0x(recipientAddress)),
|
|
79
|
+
);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const isSenderKioskOriginByte = await isOBKiosk(txData.senderAddress, txData.senderKiosk);
|
|
84
|
+
|
|
85
|
+
// If NFT is inside ob kiosk
|
|
86
|
+
if (isSenderKioskOriginByte) {
|
|
87
|
+
await addOriginByteTransferNftTx(txData);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// If NFT is inside native kiosk
|
|
92
|
+
await kioskTxWrapper({
|
|
93
|
+
txBlock: txData?.txBlock,
|
|
94
|
+
kioskOwner: txData?.senderAddress,
|
|
95
|
+
kiosk: txData?.senderKiosk,
|
|
96
|
+
async tx(kioskTx) {
|
|
97
|
+
await addTradeportKioskTransferTx({ ...txData, kioskTx });
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (res?.nfts?.length > 1) {
|
|
103
|
+
await addOneDollarFee(txBlock);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return new TransactionBlock(txBlock);
|
|
107
|
+
};
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BLUEMOVE_KIOSK_MARKETPLACE_KIOSK_OBJECT,
|
|
3
|
+
BLUEMOVE_MARKET_CONFIG_OBJECT,
|
|
4
|
+
HYPERSPACE_MP_TRANSFER_POLICY_TYPE,
|
|
5
|
+
KEEPSAKE_MARKETPLACE_KIOSK,
|
|
6
|
+
KEEPSAKE_MARKETPLACE_OBJECT,
|
|
7
|
+
SOUFFL3_VERSION_OBJECT,
|
|
8
|
+
TOCEN_MARKETPLACE_OBJECT,
|
|
9
|
+
TRADEPORT_KIOSK_LISTING_STORE,
|
|
10
|
+
TRADEPORT_LISTING_STORE,
|
|
11
|
+
} from '../../constants';
|
|
12
|
+
import { isNonKioskListing } from '../../helpers/isNonKioskListing';
|
|
13
|
+
import { kioskTxWrapper } from '../../helpers/kiosk/kioskTxWrapper';
|
|
14
|
+
import { isOriginByteTx } from '../../helpers/originByte/isOriginByteTx';
|
|
15
|
+
import { splitCoins } from '../../helpers/splitCoins';
|
|
16
|
+
import { type UnlistListingTx } from './unlistListings';
|
|
17
|
+
|
|
18
|
+
export function addTradePortUnlistTx({ txBlock, listingNonce, nftType }: UnlistListingTx) {
|
|
19
|
+
txBlock.moveCall({
|
|
20
|
+
target: '0xb42dbb7413b79394e1a0175af6ae22b69a5c7cc5df259cd78072b6818217c027::listings::unlist',
|
|
21
|
+
arguments: [txBlock.object(TRADEPORT_LISTING_STORE), txBlock.pure(listingNonce)],
|
|
22
|
+
typeArguments: [nftType],
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function addTradePortKioskUnlistTx({
|
|
27
|
+
txBlock,
|
|
28
|
+
kioskTx,
|
|
29
|
+
nftTokenId,
|
|
30
|
+
nftType,
|
|
31
|
+
}: UnlistListingTx) {
|
|
32
|
+
txBlock.moveCall({
|
|
33
|
+
target:
|
|
34
|
+
'0x33a9e4a3089d911c2a2bf16157a1d6a4a8cbd9a2106a98ecbaefe6ed370d7a25::kiosk_listings::unlist',
|
|
35
|
+
arguments: [
|
|
36
|
+
txBlock.object(TRADEPORT_KIOSK_LISTING_STORE),
|
|
37
|
+
txBlock.object(kioskTx.kiosk.value ?? kioskTx.kiosk),
|
|
38
|
+
txBlock.object(kioskTx.kioskCap.value ?? kioskTx.kioskCap),
|
|
39
|
+
txBlock.pure(nftTokenId),
|
|
40
|
+
],
|
|
41
|
+
typeArguments: [nftType],
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function addOriginByteUnlistTx({
|
|
46
|
+
txBlock,
|
|
47
|
+
sharedObjects,
|
|
48
|
+
listingNonce,
|
|
49
|
+
price,
|
|
50
|
+
nftTokenId,
|
|
51
|
+
nftType,
|
|
52
|
+
}: UnlistListingTx) {
|
|
53
|
+
const { orderbook } = sharedObjects;
|
|
54
|
+
|
|
55
|
+
txBlock.moveCall({
|
|
56
|
+
target:
|
|
57
|
+
'0x8534e4cdfd28709c94330a9783c3d5fe6f5daba0bffb69102ce303c5b38aed5a::orderbook::cancel_ask',
|
|
58
|
+
arguments: [
|
|
59
|
+
txBlock.object(orderbook),
|
|
60
|
+
txBlock.object(listingNonce),
|
|
61
|
+
txBlock.pure(price),
|
|
62
|
+
txBlock.pure(nftTokenId),
|
|
63
|
+
],
|
|
64
|
+
typeArguments: [nftType, '0x2::sui::SUI'],
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function addSouffl3UnlistTx({ txBlock, listingNonce, nftType }: UnlistListingTx) {
|
|
69
|
+
txBlock.moveCall({
|
|
70
|
+
target:
|
|
71
|
+
'0x30d90b5b67be77e6e06f02dae9f0f2fcdad16e38854316ae8a7b4f5b4971f5e0::Market::delist_generic',
|
|
72
|
+
arguments: [txBlock.object(SOUFFL3_VERSION_OBJECT), txBlock.pure(listingNonce)],
|
|
73
|
+
typeArguments: [nftType, '0x2::sui::SUI'],
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function addBluemoveUnlistTx({ txBlock, nftTokenId, nftType }: UnlistListingTx) {
|
|
78
|
+
txBlock.moveCall({
|
|
79
|
+
target:
|
|
80
|
+
'0xd5dd28cc24009752905689b2ba2bf90bfc8de4549b9123f93519bb8ba9bf9981::marketplace::delist_and_take',
|
|
81
|
+
arguments: [txBlock.object(BLUEMOVE_MARKET_CONFIG_OBJECT), txBlock.pure(nftTokenId)],
|
|
82
|
+
typeArguments: [nftType, nftType],
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export async function addBluemoveKioskUnlistTx({
|
|
87
|
+
txBlock,
|
|
88
|
+
kioskTx,
|
|
89
|
+
nftTokenId,
|
|
90
|
+
nftType,
|
|
91
|
+
}: UnlistListingTx) {
|
|
92
|
+
txBlock.moveCall({
|
|
93
|
+
target:
|
|
94
|
+
'0x2949e130ca4dabfe6448173758468a3e45ea3f070e3264f112b51c023f3ecf9f::kiosk_trade::kiosk_delist',
|
|
95
|
+
arguments: [
|
|
96
|
+
txBlock.object(BLUEMOVE_KIOSK_MARKETPLACE_KIOSK_OBJECT),
|
|
97
|
+
txBlock.object(kioskTx.kiosk.value ?? kioskTx.kiosk),
|
|
98
|
+
txBlock.pure(nftTokenId),
|
|
99
|
+
],
|
|
100
|
+
typeArguments: [nftType],
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function addKeepsakeUnlistTx({ txBlock, nftTokenId, nftType }: UnlistListingTx) {
|
|
105
|
+
txBlock.moveCall({
|
|
106
|
+
target:
|
|
107
|
+
'0x2be8c4a1a3cea4d3255d870d367c87838a8cc2bfe4f216a6b67b153027087a7::keepsake_marketplace::delist_and_take',
|
|
108
|
+
arguments: [
|
|
109
|
+
txBlock.object(KEEPSAKE_MARKETPLACE_OBJECT),
|
|
110
|
+
txBlock.object(KEEPSAKE_MARKETPLACE_KIOSK),
|
|
111
|
+
txBlock.pure(nftTokenId),
|
|
112
|
+
],
|
|
113
|
+
typeArguments: [nftType],
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export async function addHyperspaceKioskUnlistTx({
|
|
118
|
+
txBlock,
|
|
119
|
+
kioskTx,
|
|
120
|
+
nftTokenId,
|
|
121
|
+
nftType,
|
|
122
|
+
}: UnlistListingTx) {
|
|
123
|
+
const [coin] = splitCoins({ txBlock, amounts: [txBlock.pure(1)] });
|
|
124
|
+
|
|
125
|
+
txBlock.moveCall({
|
|
126
|
+
target:
|
|
127
|
+
'0x6ea97b03c441edd54ae89224bf9560e583ee66c37e6c246f5db35258e580ba94::hyperspace::delist',
|
|
128
|
+
arguments: [
|
|
129
|
+
txBlock.object(kioskTx.kiosk.value ?? kioskTx.kiosk),
|
|
130
|
+
txBlock.object(kioskTx.kioskCap.value ?? kioskTx.kioskCap),
|
|
131
|
+
txBlock.pure(nftTokenId),
|
|
132
|
+
],
|
|
133
|
+
typeArguments: [nftType, HYPERSPACE_MP_TRANSFER_POLICY_TYPE],
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
txBlock.transferObjects([txBlock.object(coin)], txBlock.pure(nftTokenId));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function addTocenUnlistTx({ txBlock, nftTokenId, nftType }: UnlistListingTx) {
|
|
140
|
+
txBlock.moveCall({
|
|
141
|
+
target:
|
|
142
|
+
'0x3605d91c559e80cf8fdeabae9abaccb0bc38f96eac0b32bf47e95a9159a5277f::tocen_marketplace::delist_and_take',
|
|
143
|
+
arguments: [txBlock.pure(TOCEN_MARKETPLACE_OBJECT), txBlock.pure(nftTokenId)],
|
|
144
|
+
typeArguments: [nftType],
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function addSomisUnlistTx({
|
|
149
|
+
txBlock,
|
|
150
|
+
sharedObjects,
|
|
151
|
+
nftTokenId,
|
|
152
|
+
nftType,
|
|
153
|
+
price,
|
|
154
|
+
}: UnlistListingTx) {
|
|
155
|
+
const { marketplace } = sharedObjects;
|
|
156
|
+
|
|
157
|
+
txBlock.moveCall({
|
|
158
|
+
target:
|
|
159
|
+
'0xf0b0beb956e26bde50dbd6ac393026c4525aee3b194a9478f09748f7211b5a02::marketplace::cancel_ask',
|
|
160
|
+
arguments: [txBlock.pure(marketplace), txBlock.pure(nftTokenId), txBlock.pure(price)],
|
|
161
|
+
typeArguments: [nftType, '0x2::sui::SUI'],
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export async function addTradePortUnlistTxHandler(txData: UnlistListingTx) {
|
|
166
|
+
if (txData?.listingNonce && isOriginByteTx(txData?.sharedObjects)) {
|
|
167
|
+
addOriginByteUnlistTx(txData);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (txData?.listingNonce && (await isNonKioskListing(txData?.listingNonce))) {
|
|
172
|
+
addTradePortUnlistTx(txData);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (txData?.sellerKiosk) {
|
|
177
|
+
return kioskTxWrapper({
|
|
178
|
+
txBlock: txData?.txBlock,
|
|
179
|
+
kioskOwner: txData?.seller,
|
|
180
|
+
kiosk: txData?.sellerKiosk,
|
|
181
|
+
async tx(kioskTx) {
|
|
182
|
+
await addTradePortKioskUnlistTx({
|
|
183
|
+
...txData,
|
|
184
|
+
kioskTx,
|
|
185
|
+
});
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
addTradePortUnlistTx(txData);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export async function addHyperspaceUnlistTxHandler(txData: UnlistListingTx) {
|
|
194
|
+
if (txData?.listingNonce && isOriginByteTx(txData?.sharedObjects)) {
|
|
195
|
+
addOriginByteUnlistTx(txData);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return kioskTxWrapper({
|
|
200
|
+
txBlock: txData?.txBlock,
|
|
201
|
+
kioskOwner: txData?.seller,
|
|
202
|
+
kiosk: txData?.sellerKiosk,
|
|
203
|
+
async tx(kioskTx) {
|
|
204
|
+
await addHyperspaceKioskUnlistTx({
|
|
205
|
+
...txData,
|
|
206
|
+
kioskTx,
|
|
207
|
+
});
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export async function addBluemoveUnlistTxHandler(txData: UnlistListingTx) {
|
|
213
|
+
if (txData?.listingNonce && isOriginByteTx(txData?.sharedObjects)) {
|
|
214
|
+
addOriginByteUnlistTx(txData);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (txData?.sellerKiosk) {
|
|
219
|
+
return kioskTxWrapper({
|
|
220
|
+
txBlock: txData?.txBlock,
|
|
221
|
+
kioskOwner: txData?.seller,
|
|
222
|
+
kiosk: txData?.sellerKiosk,
|
|
223
|
+
async tx(kioskTx) {
|
|
224
|
+
await addBluemoveKioskUnlistTx({
|
|
225
|
+
...txData,
|
|
226
|
+
kioskTx,
|
|
227
|
+
});
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
addBluemoveUnlistTx(txData);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export async function addClutchyUnlistTxHandler(txData: UnlistListingTx) {
|
|
236
|
+
addOriginByteUnlistTx(txData);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export async function addSouffl3UnlistTxHandler(txData: UnlistListingTx) {
|
|
240
|
+
addSouffl3UnlistTx(txData);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export async function addSomisUnlistTxHandler(txData: UnlistListingTx) {
|
|
244
|
+
if (txData?.sharedObjects?.marketplace) {
|
|
245
|
+
addSomisUnlistTx(txData);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
addOriginByteUnlistTx(txData);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export async function addKeepsakeUnlistTxHandler(txData: UnlistListingTx) {
|
|
253
|
+
addKeepsakeUnlistTx(txData);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export function addTocenUnlistTxHandler(txData: UnlistListingTx) {
|
|
257
|
+
addTocenUnlistTx(txData);
|
|
258
|
+
}
|