@tradeport/sui-trading-sdk 0.4.13 → 0.4.15

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tradeport/sui-trading-sdk",
3
3
  "license": "MIT",
4
- "version": "0.4.13",
4
+ "version": "0.4.15",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
@@ -0,0 +1,36 @@
1
+ import { type SuiClient } from '@mysten/sui/client';
2
+ import { normalizeStructTag, normalizeSuiObjectId } from '@mysten/sui/utils';
3
+
4
+ export const getTransferPolicyRuleNamesFromSuiObject = async ({
5
+ suiClient,
6
+ transferPolicyId,
7
+ }: {
8
+ suiClient: SuiClient;
9
+ transferPolicyId: string;
10
+ }) => {
11
+ const { data, error } = await suiClient.getObject({
12
+ id: normalizeSuiObjectId(transferPolicyId),
13
+ options: {
14
+ showContent: true,
15
+ },
16
+ });
17
+
18
+ if (error) {
19
+ throw new Error(`Error on getting SUI object ${transferPolicyId}: ${error.code}`);
20
+ }
21
+
22
+ const content = data.content as unknown as {
23
+ fields: {
24
+ rules: {
25
+ fields: {
26
+ contents: Array<{ fields: { name: string } }>;
27
+ };
28
+ };
29
+ };
30
+ };
31
+ const ruleNames = content.fields.rules.fields.contents.map((rule) =>
32
+ normalizeStructTag(rule.fields.name),
33
+ );
34
+
35
+ return ruleNames;
36
+ };
@@ -1,6 +1,4 @@
1
1
  import { getNativeKioskTransferPolicies } from './kiosk/getNativeKioskTransferPolicies';
2
2
 
3
- export const hasNativeKioskTransferPolicyRules = (transferPolicies: any): boolean => {
4
- const nativeKioskTransferPolicies = getNativeKioskTransferPolicies(transferPolicies);
5
- return nativeKioskTransferPolicies?.some((policy: any) => policy?.rules?.length > 0);
6
- };
3
+ export const hasNativeKioskTransferPolicyRules = (transferPolicies: any): boolean =>
4
+ getNativeKioskTransferPolicies(transferPolicies)?.length > 0;
@@ -1,25 +1,47 @@
1
1
  import { getNormalizedRuleType, type KioskClient } from '@mysten/kiosk';
2
+ import { type SuiClient } from '@mysten/sui/client';
2
3
  import { addHexPrefix } from '../../utils/addHexPrefix';
3
4
  import { normalizedNftType } from '../../utils/normalizeNftType';
5
+ import { getTransferPolicyRuleNamesFromSuiObject } from '../getTransferPolicyRuleNamesFromSuiObject';
6
+ import { getNativeKioskTransferPolicies } from './getNativeKioskTransferPolicies';
4
7
 
5
8
  type RuleType = 'kiosk_royalty_rule' | 'royalty_rule' | 'personal_kiosk_rule' | 'kiosk_lock_rule';
6
9
 
7
10
  export const getRulePackageId = async ({
11
+ transferPolicies,
8
12
  nftType,
9
13
  ruleType,
10
14
  kioskClient,
15
+ suiClient,
11
16
  }: {
17
+ transferPolicies: any[];
18
+ suiClient: SuiClient;
12
19
  nftType: string;
13
20
  ruleType: RuleType;
14
21
  kioskClient: KioskClient;
15
22
  }) => {
16
- const transferPolicies = await kioskClient.getTransferPolicies({
23
+ const transferPoliciesFromMystenSdk = await kioskClient.getTransferPolicies({
17
24
  type: normalizedNftType(nftType),
18
25
  });
19
26
 
20
- const rule = transferPolicies
21
- .flatMap((policy) => policy.rules)
22
- .filter((rule) => rule?.split('::')?.[1] === ruleType)?.[0];
27
+ let rule: string | undefined;
28
+
29
+ if (transferPoliciesFromMystenSdk.length > 0) {
30
+ rule = transferPoliciesFromMystenSdk
31
+ .flatMap((policy) => policy.rules)
32
+ .filter((rule) => rule?.split('::')?.[1] === ruleType)?.[0];
33
+ } else if (transferPolicies.length > 0) {
34
+ const transferPolicyId = getNativeKioskTransferPolicies(transferPolicies)?.at(0)?.id;
35
+
36
+ const ruleNames = await getTransferPolicyRuleNamesFromSuiObject({
37
+ suiClient,
38
+ transferPolicyId,
39
+ });
40
+
41
+ rule = ruleNames.filter((ruleName) => ruleName?.split('::')?.[1] === ruleType)?.[0];
42
+ } else {
43
+ throw new Error(`No transfer policy found for ${nftType}`);
44
+ }
23
45
 
24
46
  const ruleDefinition = kioskClient.rules.find(
25
47
  (x) => getNormalizedRuleType(x.rule) === getNormalizedRuleType(rule),
@@ -6,6 +6,11 @@ import {
6
6
  type TransactionObjectInput,
7
7
  } from '@mysten/sui/transactions';
8
8
  import { normalizedNftType } from '../../utils/normalizeNftType';
9
+ import { getTransferPolicyRuleNamesFromSuiObject } from '../getTransferPolicyRuleNamesFromSuiObject';
10
+ import {
11
+ getNativeKioskTransferPolicies,
12
+ knownTransferPolicyRules,
13
+ } from './getNativeKioskTransferPolicies';
9
14
  import { resolveFloorPriceRule } from './resolveFloorPriceRule';
10
15
  import { resolveKioskLockRule } from './resolveKioskLockRule';
11
16
  import { resolvePersonalKioskRule } from './resolvePersonalKioskRule';
@@ -20,6 +25,7 @@ export type Policy = {
20
25
 
21
26
  type Props = {
22
27
  tx: Transaction;
28
+ transferPolicies: any[];
23
29
  suiClient: SuiClient;
24
30
  walletAddress: string;
25
31
  kioskClient: KioskClient;
@@ -40,6 +46,7 @@ const originByteRuleModules = ['royalty_strategy_bps', 'transfer_allowlist'];
40
46
 
41
47
  export const resolveTransferPolicies = async ({
42
48
  tx,
49
+ transferPolicies,
43
50
  suiClient,
44
51
  walletAddress,
45
52
  kioskClient,
@@ -55,49 +62,56 @@ export const resolveTransferPolicies = async ({
55
62
  coinToSplit,
56
63
  beforeResolveKioskTransferRequest,
57
64
  }: Props) => {
58
- const transferPolicies = await kioskClient.getTransferPolicies({
65
+ const transferPoliciesFromMystenSdk = await kioskClient.getTransferPolicies({
59
66
  type: normalizedNftType(nftType),
60
67
  });
61
68
 
62
- if (
63
- transferPolicies.length === 0 &&
64
- (customTransferPolicies ?? []).every(
65
- (p: { transferRequest: TransactionArgument }) => p.transferRequest !== transferRequest,
66
- )
67
- ) {
68
- throw new Error(
69
- `Missing transfer policy of ${nftType}. No way to resolve the transfer request.`,
70
- );
71
- }
69
+ let policies: Policy[] = [];
72
70
 
73
- let policies: Policy[] =
74
- transferPolicies.length > 0
75
- ? [
76
- {
77
- data: transferPolicies?.filter(
78
- (policy) =>
79
- policy?.rules?.filter(
80
- (rule) =>
81
- rule?.includes('royalty_rule') ||
82
- rule?.includes('kiosk_lock_rule') ||
83
- rule?.includes('personal_kiosk_rule') ||
84
- rule?.includes('floor_price_rule'),
85
- )?.length > 0,
86
- )?.[0],
87
- transferRequest,
88
- isCustom: false,
89
- },
90
- ]
91
- : [];
92
-
93
- if (!policies?.[0]?.data && transferPolicies.length > 0) {
71
+ if (transferPoliciesFromMystenSdk.length > 0) {
94
72
  policies = [
95
73
  {
96
- data: transferPolicies?.[0],
74
+ data:
75
+ // Find first policy with relevant rules, or fall back to first policy
76
+ transferPoliciesFromMystenSdk.find((policy) =>
77
+ policy?.rules?.some((rule) =>
78
+ knownTransferPolicyRules.some((ruleType) => rule?.includes(ruleType)),
79
+ ),
80
+ ) ?? transferPoliciesFromMystenSdk[0],
97
81
  transferRequest,
98
82
  isCustom: false,
99
83
  },
100
84
  ];
85
+ } else if (transferPolicies.length > 0) {
86
+ const transferPolicyId = getNativeKioskTransferPolicies(transferPolicies)?.at(0)?.id;
87
+
88
+ if (transferPolicyId) {
89
+ const ruleNames = await getTransferPolicyRuleNamesFromSuiObject({
90
+ suiClient,
91
+ transferPolicyId,
92
+ });
93
+
94
+ if (ruleNames.length > 0) {
95
+ policies = [
96
+ {
97
+ data: {
98
+ id: transferPolicyId,
99
+ rules: ruleNames,
100
+ },
101
+ transferRequest,
102
+ isCustom: false,
103
+ },
104
+ ];
105
+ }
106
+ }
107
+ } else if (
108
+ (customTransferPolicies ?? []).every(
109
+ (p: { transferRequest: TransactionArgument }) => p.transferRequest !== transferRequest,
110
+ )
111
+ ) {
112
+ throw new Error(
113
+ `Missing transfer policy of ${nftType}. No way to resolve the transfer request.`,
114
+ );
101
115
  }
102
116
 
103
117
  if (customTransferPolicies) {
@@ -278,6 +278,8 @@ export async function addTradePortAcceptCollectionBidTxHandler(txData: AcceptCol
278
278
  if (isTradePortKioskBid(bidType)) {
279
279
  const royaltyRuleModule = getRoyaltyRuleModule(txData?.nftType);
280
280
  const royaltyRulePackageId = await getRulePackageId({
281
+ transferPolicies: txData?.transferPolicies,
282
+ suiClient: txData?.suiClient,
281
283
  nftType: txData?.nftType,
282
284
  ruleType: 'royalty_rule',
283
285
  kioskClient: txData?.kioskClient,
@@ -14,6 +14,7 @@ import { gqlChainRequest } from '../../graphql/gqlChainRequest';
14
14
  import { fetchMultibidChainIdById } from '../../graphql/queries/fetchMultibidById';
15
15
  import { getRoyaltyRuleModule } from '../../helpers/getRoyaltyRuleModule';
16
16
  import { getSharedObjects } from '../../helpers/getSharedObjects';
17
+ import { getTransferPolicyRuleNamesFromSuiObject } from '../../helpers/getTransferPolicyRuleNamesFromSuiObject';
17
18
  import { hasPersonalKioskRule } from '../../helpers/hasPersonalKioskRule';
18
19
  import { isSingleBid } from '../../helpers/isSIngleBid';
19
20
  import { assertNftInSharedKiosk } from '../../helpers/kiosk/assertNftInSharedKiosk';
@@ -115,6 +116,7 @@ export async function addTradeportKioskAcceptNftBidTx({
115
116
 
116
117
  await resolveTransferPolicies({
117
118
  tx,
119
+ transferPolicies,
118
120
  suiClient,
119
121
  walletAddress: seller,
120
122
  kioskTx,
@@ -151,6 +153,7 @@ export async function addTradeportKioskAcceptNftBidTx({
151
153
 
152
154
  await resolveTransferPolicies({
153
155
  tx,
156
+ transferPolicies,
154
157
  suiClient,
155
158
  walletAddress: seller,
156
159
  kioskTx,
@@ -247,7 +250,7 @@ export function addBluemoveAcceptNftBidTx({
247
250
  }
248
251
 
249
252
  export async function addSingleBidAcceptNftBidTx(txData: AcceptNftBidTx) {
250
- const { nftType, tx, bidNonce, multiBidId, kioskClient, nftTokenId } = txData;
253
+ const { nftType, tx, bidNonce, multiBidId, kioskClient, nftTokenId, suiClient } = txData;
251
254
  const transferPolicies = getNativeKioskTransferPolicies(txData?.transferPolicies);
252
255
  const transferPolicy = transferPolicies?.find(
253
256
  (policy: { rules: any[] }) => policy?.rules?.length > 0,
@@ -270,7 +273,15 @@ export async function addSingleBidAcceptNftBidTx(txData: AcceptNftBidTx) {
270
273
  const transferPolicies = await kioskClient.getTransferPolicies({
271
274
  type: normalizeStructTag(nftType),
272
275
  });
273
- const { rules: allRules } = transferPolicies.find((p) => p.id === transferPolicy.id);
276
+ let { rules: allRules } = transferPolicies.find((p) => p.id === transferPolicy.id);
277
+
278
+ if (allRules.length === 0) {
279
+ allRules = await getTransferPolicyRuleNamesFromSuiObject({
280
+ suiClient,
281
+ transferPolicyId: transferPolicy.id,
282
+ });
283
+ }
284
+
274
285
  const unsupportedRule = allRules.find(
275
286
  (r) => !knownTransferPolicyRules.includes(r.split('::').at(1)),
276
287
  );
@@ -353,6 +364,8 @@ export async function addTradePortAcceptNftBidTxHandler(txData: AcceptNftBidTx)
353
364
  if (txData?.sellerKiosk) {
354
365
  const royaltyRuleModule = getRoyaltyRuleModule(txData?.nftType);
355
366
  const royaltyRulePackageId = await getRulePackageId({
367
+ transferPolicies: txData?.transferPolicies,
368
+ suiClient: txData?.suiClient,
356
369
  nftType: txData?.nftType,
357
370
  ruleType: 'royalty_rule',
358
371
  kioskClient: txData?.kioskClient,
@@ -19,7 +19,9 @@ import {
19
19
  } from '../../constants';
20
20
  import { getCommissionByNftContractId } from '../../graphql/queries/getCommissionByListingId';
21
21
  import { destroyZeroCoin } from '../../helpers/destroyZeroCoin';
22
+ import { getSharedObjects } from '../../helpers/getSharedObjects';
22
23
  import { assertNftInSharedKiosk } from '../../helpers/kiosk/assertNftInSharedKiosk';
24
+ import { getNativeKioskTransferPolicies } from '../../helpers/kiosk/getNativeKioskTransferPolicies';
23
25
  import { kioskTxWrapper } from '../../helpers/kiosk/kioskTxWrapper';
24
26
  import { resolveTransferPolicies } from '../../helpers/kiosk/resolveTransferPolicies';
25
27
  import { confirmOBTranfer } from '../../helpers/originByte/confirmOBTranfer';
@@ -29,8 +31,6 @@ import { shareOriginByteKiosk } from '../../helpers/originByte/shareOriginByteKi
29
31
  import { splitCoins } from '../../helpers/splitCoins';
30
32
  import { addLeadingZerosAfter0x } from '../../utils/addLeadingZerosAfter0x';
31
33
  import { type BuyTx, type TocenBuyTx } from './buyListings';
32
- import { getSharedObjects } from '../../helpers/getSharedObjects';
33
- import { getNativeKioskTransferPolicies } from '../../helpers/kiosk/getNativeKioskTransferPolicies';
34
34
 
35
35
  export function addTradePortBuyTx({ tx, nftType, listingNonce, price, sharedObjects }: BuyTx) {
36
36
  const [coin] = splitCoins({ tx, amounts: [tx.pure.u64(price)] });
@@ -68,6 +68,7 @@ export function addTradePortBuyTx({ tx, nftType, listingNonce, price, sharedObje
68
68
 
69
69
  export const addTradeportKioskBuyTx = async ({
70
70
  tx,
71
+ transferPolicies,
71
72
  kioskTx,
72
73
  suiClient,
73
74
  kioskClient,
@@ -110,6 +111,7 @@ export const addTradeportKioskBuyTx = async ({
110
111
 
111
112
  await resolveTransferPolicies({
112
113
  tx,
114
+ transferPolicies,
113
115
  suiClient,
114
116
  walletAddress: seller,
115
117
  kioskTx,
@@ -172,6 +174,7 @@ export async function addOriginByteBuyTx({
172
174
 
173
175
  export const addHyperspaceKioskBuyTx = async ({
174
176
  tx,
177
+ transferPolicies,
175
178
  suiClient,
176
179
  kioskTx,
177
180
  kioskClient,
@@ -211,6 +214,7 @@ export const addHyperspaceKioskBuyTx = async ({
211
214
 
212
215
  await resolveTransferPolicies({
213
216
  tx,
217
+ transferPolicies,
214
218
  suiClient,
215
219
  walletAddress: seller,
216
220
  kioskTx,
@@ -286,6 +290,7 @@ export async function addBluemoveKioskBuyTx({
286
290
  await beforeResolveKioskTransferRequest?.(transferRequest);
287
291
  await resolveTransferPolicies({
288
292
  tx,
293
+ transferPolicies,
289
294
  suiClient,
290
295
  walletAddress: seller,
291
296
  kioskTx,
@@ -69,6 +69,7 @@ export const addClaimAcceptedBidNftTx = async ({
69
69
 
70
70
  await resolveTransferPolicies({
71
71
  tx,
72
+ transferPolicies,
72
73
  suiClient,
73
74
  walletAddress: claimer,
74
75
  kioskTx,
@@ -109,6 +110,7 @@ export const addClaimAcceptedBidNftWithPurchaseCapTx = async ({
109
110
 
110
111
  await resolveTransferPolicies({
111
112
  tx,
113
+ transferPolicies,
112
114
  suiClient,
113
115
  walletAddress: claimer,
114
116
  kioskTx,
@@ -148,6 +150,7 @@ export const addClaimTransferredNftTx = async ({
148
150
 
149
151
  await resolveTransferPolicies({
150
152
  tx,
153
+ transferPolicies,
151
154
  suiClient,
152
155
  walletAddress: claimer,
153
156
  kioskTx,
@@ -190,6 +193,7 @@ export const addClaimTransferredNftWithPurchaseCapTx = async ({
190
193
 
191
194
  await resolveTransferPolicies({
192
195
  tx,
196
+ transferPolicies,
193
197
  suiClient,
194
198
  walletAddress: claimer,
195
199
  kioskTx,
@@ -104,6 +104,7 @@ export async function exerciseLongLocks(
104
104
 
105
105
  await resolveTransferPolicies({
106
106
  tx,
107
+ transferPolicies,
107
108
  suiClient: context.suiClient,
108
109
  walletAddress,
109
110
  kioskTx,
@@ -177,6 +178,7 @@ export async function exerciseLongLocks(
177
178
 
178
179
  await resolveTransferPolicies({
179
180
  tx,
181
+ transferPolicies,
180
182
  suiClient: context.suiClient,
181
183
  walletAddress,
182
184
  kioskTx,
@@ -173,6 +173,7 @@ export async function exerciseShortLocks(
173
173
  });
174
174
  await resolveTransferPolicies({
175
175
  tx,
176
+ transferPolicies,
176
177
  suiClient: context.suiClient,
177
178
  walletAddress,
178
179
  kioskTx,
@@ -132,6 +132,8 @@ export async function addTradePortPlaceCollectionBidTxHandler(txData: PlaceColle
132
132
  if (hasRoyaltyRule(txData?.transferPolicies)) {
133
133
  const royaltyRuleModule = getRoyaltyRuleModule(txData?.nftType);
134
134
  const royaltyRulePackageId = await getRulePackageId({
135
+ transferPolicies: txData?.transferPolicies,
136
+ suiClient: txData?.suiClient,
135
137
  nftType: txData.nftType,
136
138
  ruleType: getRoyaltyRuleModule(txData?.collectionId),
137
139
  kioskClient: txData?.kioskClient,
@@ -2,18 +2,18 @@ import { type KioskClient } from '@mysten/kiosk';
2
2
  import { type SuiClient } from '@mysten/sui/client';
3
3
  import { type Transaction } from '@mysten/sui/transactions';
4
4
  import {
5
- TRADEPORT_KIOSK_TRANSFERS_STORE,
6
5
  MYSTEN_TRANFER_POLICY_RULES_PACKAGE_ID,
6
+ TRADEPORT_KIOSK_TRANSFERS_STORE,
7
7
  } from '../../constants';
8
8
  import { destroyZeroCoin } from '../../helpers/destroyZeroCoin';
9
9
  import { getNftType } from '../../helpers/getNftType';
10
+ import { getTransferPolicyRuleNamesFromSuiObject } from '../../helpers/getTransferPolicyRuleNamesFromSuiObject';
10
11
  import { assertNftInSharedKiosk } from '../../helpers/kiosk/assertNftInSharedKiosk';
12
+ import { getNativeKioskTransferPolicies } from '../../helpers/kiosk/getNativeKioskTransferPolicies';
11
13
  import { kioskTxWrapper } from '../../helpers/kiosk/kioskTxWrapper';
12
14
  import { getOBKiosk } from '../../helpers/originByte/getOBKiosk';
13
15
  import { addLeadingZerosAfter0x } from '../../utils/addLeadingZerosAfter0x';
14
16
  import { type TransferNftTx } from './transferNfts';
15
- import { getNativeKioskTransferPolicies } from '../../helpers/kiosk/getNativeKioskTransferPolicies';
16
- import { normalizeSuiObjectId, normalizeStructTag } from '@mysten/sui/utils';
17
17
 
18
18
  type CollectionChainState = {
19
19
  transfer_policies: TransferPolicy[];
@@ -200,29 +200,10 @@ export async function getTransferPolicyForDirectTransfer(
200
200
  );
201
201
 
202
202
  if (validateRules && candidatePolicy) {
203
- const { data, error } = await suiClient.getObject({
204
- id: normalizeSuiObjectId(candidatePolicy.id),
205
- options: {
206
- showContent: true,
207
- },
203
+ const ruleNames = await getTransferPolicyRuleNamesFromSuiObject({
204
+ suiClient,
205
+ transferPolicyId: candidatePolicy.id,
208
206
  });
209
-
210
- if (error) {
211
- throw new Error(`Error on getting SUI object ${candidatePolicy.id}: ${error.code}`);
212
- }
213
-
214
- const content = data.content as unknown as {
215
- fields: {
216
- rules: {
217
- fields: {
218
- contents: Array<{ fields: { name: string } }>;
219
- };
220
- };
221
- };
222
- };
223
- const ruleNames = content.fields.rules.fields.contents.map((rule) =>
224
- normalizeStructTag(rule.fields.name),
225
- );
226
207
  if (!ruleNames.every((name) => name.startsWith(MYSTEN_TRANFER_POLICY_RULES_PACKAGE_ID))) {
227
208
  return undefined;
228
209
  }
@@ -27,14 +27,20 @@ export class SuiWallet {
27
27
  return 1;
28
28
  }
29
29
 
30
- async simulateCall(tx: Transaction): Promise<any> {
31
- tx.setSenderIfNotSet(this.keypair.toSuiAddress());
32
- const rawTransaction = await tx.build({ client: this.suiClient });
33
- const result = await this.suiClient.dryRunTransactionBlock({
34
- transactionBlock: rawTransaction,
30
+ async simulateCall(tx: Transaction, sender?: string): Promise<any> {
31
+ const result = await this.suiClient.devInspectTransactionBlock({
32
+ transactionBlock: tx,
33
+ sender: sender ?? this.keypair.toSuiAddress(),
35
34
  });
36
- if (result.balanceChanges.length === 0) {
37
- throw new Error('No balance changes were found');
35
+
36
+ if (result?.effects?.status?.status === 'failure') {
37
+ throw new Error(
38
+ `Error on transaction simulation (from effect): ${result.effects.status.error}`,
39
+ ); // result.effects.status.error
40
+ }
41
+
42
+ if (result?.error) {
43
+ throw new Error(`Error on transaction simulation: ${result.error}`); // result.error
38
44
  }
39
45
 
40
46
  return result;