@mysten/kiosk 0.3.0 → 0.3.2

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
@@ -2,7 +2,7 @@
2
2
  "name": "@mysten/kiosk",
3
3
  "author": "Mysten Labs <build@mystenlabs.com>",
4
4
  "description": "Sui Kiosk library",
5
- "version": "0.3.0",
5
+ "version": "0.3.2",
6
6
  "license": "Apache-2.0",
7
7
  "main": "./dist/index.js",
8
8
  "module": "./dist/index.mjs",
@@ -24,27 +24,23 @@
24
24
  }
25
25
  },
26
26
  "dependencies": {
27
- "@mysten/sui.js": "0.35.1"
27
+ "@mysten/sui.js": "0.37.0"
28
28
  },
29
29
  "devDependencies": {
30
- "eslint": "^8.38.0",
31
- "prettier": "^2.8.7",
32
30
  "tsup": "^6.7.0",
33
31
  "typescript": "^5.0.4"
34
32
  },
35
- "prettier": {
36
- "printWidth": 80,
37
- "semi": true,
38
- "singleQuote": true,
39
- "trailingComma": "all"
40
- },
41
33
  "scripts": {
42
34
  "build": "pnpm build:types && pnpm build:tsup",
43
35
  "build:tsup": "tsup ./src/index.ts --format esm,cjs --sourcemap",
44
36
  "build:types": "tsc --build",
45
37
  "test": "echo \"Error: no test specified\"",
46
- "lint": "eslint --max-warnings=0 ./src/**/**",
47
- "prettier:fix": "prettier --write .",
48
- "pre-commit": "pnpm prettier:fix && pnpm lint && pnpm build"
38
+ "pre-commit": "pnpm prettier:fix && pnpm lint && pnpm build",
39
+ "prettier:check": "prettier -c --ignore-unknown .",
40
+ "prettier:fix": "prettier -w --ignore-unknown .",
41
+ "eslint:check": "eslint --max-warnings=0 .",
42
+ "eslint:fix": "pnpm run eslint:check --fix",
43
+ "lint": "pnpm run eslint:check && pnpm run prettier:check",
44
+ "lint:fix": "pnpm run eslint:fix && pnpm run prettier:fix"
49
45
  }
50
46
  }
package/src/bcs.ts CHANGED
@@ -3,38 +3,38 @@
3
3
 
4
4
  import { bcs } from '@mysten/sui.js';
5
5
  import {
6
- KIOSK_PURCHASE_CAP,
7
- KIOSK_TYPE,
8
- TRANSFER_POLICY_CREATED_EVENT,
9
- TRANSFER_POLICY_TYPE,
6
+ KIOSK_PURCHASE_CAP,
7
+ KIOSK_TYPE,
8
+ TRANSFER_POLICY_CREATED_EVENT,
9
+ TRANSFER_POLICY_TYPE,
10
10
  } from './types';
11
11
 
12
12
  // Register the `Kiosk` struct for faster queries.
13
13
  bcs.registerStructType(KIOSK_TYPE, {
14
- id: 'address',
15
- profits: 'u64',
16
- owner: 'address',
17
- itemCount: 'u32',
18
- allowExtensions: 'bool',
14
+ id: 'address',
15
+ profits: 'u64',
16
+ owner: 'address',
17
+ itemCount: 'u32',
18
+ allowExtensions: 'bool',
19
19
  });
20
20
 
21
21
  // Register the `PurchaseCap` for faster queries.
22
22
  bcs.registerStructType(KIOSK_PURCHASE_CAP, {
23
- id: 'address',
24
- kioskId: 'address',
25
- itemId: 'address',
26
- minPrice: 'u64',
23
+ id: 'address',
24
+ kioskId: 'address',
25
+ itemId: 'address',
26
+ minPrice: 'u64',
27
27
  });
28
28
 
29
29
  // Register the `TransferPolicyCreated` event data.
30
30
  bcs.registerStructType(TRANSFER_POLICY_CREATED_EVENT, {
31
- id: 'address',
31
+ id: 'address',
32
32
  });
33
33
 
34
34
  bcs.registerStructType(TRANSFER_POLICY_TYPE, {
35
- id: 'address',
36
- balance: 'u64',
37
- rules: ['vector', 'string'],
35
+ id: 'address',
36
+ balance: 'u64',
37
+ rules: ['vector', 'string'],
38
38
  });
39
39
 
40
40
  export { bcs };
package/src/constants.ts CHANGED
@@ -3,8 +3,8 @@
3
3
 
4
4
  /** The Transer Policy Rules package address on testnet */
5
5
  export const TESTNET_RULES_PACKAGE_ADDRESS =
6
- 'bd8fc1947cf119350184107a3087e2dc27efefa0dd82e25a1f699069fe81a585';
6
+ 'bd8fc1947cf119350184107a3087e2dc27efefa0dd82e25a1f699069fe81a585';
7
7
 
8
8
  /** The transfer policy rules package address on mainnet */
9
9
  export const MAINNET_RULES_PACKAGE_ADDRESS =
10
- '0x434b5bd8f6a7b05fede0ff46c6e511d71ea326ed38056e3bcd681d2d7c2a7879';
10
+ '0x434b5bd8f6a7b05fede0ff46c6e511d71ea326ed38056e3bcd681d2d7c2a7879';
@@ -2,118 +2,123 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import {
5
- JsonRpcProvider,
6
- ObjectId,
7
- ObjectType,
8
- PaginationArguments,
9
- SuiAddress,
5
+ JsonRpcProvider,
6
+ ObjectId,
7
+ PaginationArguments,
8
+ SuiAddress,
9
+ SuiObjectData,
10
+ SuiObjectResponse,
11
+ getObjectFields,
12
+ isValidSuiAddress,
10
13
  } from '@mysten/sui.js';
11
14
  import {
12
- attachListingsAndPrices,
13
- attachLockedItems,
14
- extractKioskData,
15
- getKioskObject,
15
+ attachListingsAndPrices,
16
+ attachLockedItems,
17
+ extractKioskData,
18
+ getAllDynamicFields,
19
+ getKioskObject,
16
20
  } from '../utils';
17
- import { Kiosk } from '../types';
21
+ import {
22
+ FetchKioskOptions,
23
+ KIOSK_OWNER_CAP,
24
+ KioskListing,
25
+ OwnedKiosks,
26
+ PagedKioskData,
27
+ } from '../types';
18
28
 
19
- /**
20
- * A dynamic field `Listing { ID, isExclusive }` attached to the Kiosk.
21
- * Holds a `u64` value - the price of the item.
22
- */
23
- export type KioskListing = {
24
- /** The ID of the Item */
25
- objectId: ObjectId;
26
- /**
27
- * Whether or not there's a `PurchaseCap` issued. `true` means that
28
- * the listing is controlled by some logic and can't be purchased directly.
29
- *
30
- * TODO: consider renaming the field for better indication.
31
- */
32
- isExclusive: boolean;
33
- /** The ID of the listing */
34
- listingId: ObjectId;
35
- price?: string;
36
- };
29
+ export async function fetchKiosk(
30
+ provider: JsonRpcProvider,
31
+ kioskId: SuiAddress,
32
+ pagination: PaginationArguments<string>,
33
+ options: FetchKioskOptions,
34
+ ): Promise<PagedKioskData> {
35
+ // TODO: Replace the `getAllDynamicFields` with a paginated
36
+ // response, once we have better RPC support for
37
+ // type filtering & batch fetching.
38
+ // This can't work with pagination currently.
39
+ const data = await getAllDynamicFields(provider, kioskId, pagination);
37
40
 
38
- /**
39
- * A dynamic field `Item { ID }` attached to the Kiosk.
40
- * Holds an Item `T`. The type of the item is known upfront.
41
- */
42
- export type KioskItem = {
43
- /** The ID of the Item */
44
- objectId: ObjectId;
45
- /** The type of the Item */
46
- type: ObjectType;
47
- /** Whether the item is Locked (there must be a `Lock` Dynamic Field) */
48
- isLocked: boolean;
49
- /** Optional listing */
50
- listing?: KioskListing;
51
- };
52
- /**
53
- * Aggregated data from the Kiosk.
54
- */
55
- export type KioskData = {
56
- items: KioskItem[];
57
- itemIds: ObjectId[];
58
- listingIds: ObjectId[];
59
- kiosk?: Kiosk;
60
- extensions: any[]; // type will be defined on later versions of the SDK.
61
- };
41
+ const listings: KioskListing[] = [];
42
+ const lockedItemIds: ObjectId[] = [];
62
43
 
63
- export type PagedKioskData = {
64
- data: KioskData;
65
- nextCursor: string | null;
66
- hasNextPage: boolean;
67
- };
44
+ // extracted kiosk data.
45
+ const kioskData = extractKioskData(data, listings, lockedItemIds);
68
46
 
69
- export type FetchKioskOptions = {
70
- withKioskFields?: boolean;
71
- withListingPrices?: boolean;
72
- };
47
+ // split the fetching in two queries as we are most likely passing different options for each kind.
48
+ // For items, we usually seek the Display.
49
+ // For listings we usually seek the DF value (price) / exclusivity.
50
+ const [kiosk, listingObjects] = await Promise.all([
51
+ options.withKioskFields ? getKioskObject(provider, kioskId) : Promise.resolve(undefined),
52
+ options.withListingPrices
53
+ ? provider.multiGetObjects({
54
+ ids: kioskData.listingIds,
55
+ options: {
56
+ showContent: true,
57
+ },
58
+ })
59
+ : Promise.resolve([]),
60
+ ]);
73
61
 
74
- export async function fetchKiosk(
75
- provider: JsonRpcProvider,
76
- kioskId: SuiAddress,
77
- pagination: PaginationArguments<string>,
78
- options: FetchKioskOptions,
79
- ): Promise<PagedKioskData> {
80
- const { data, nextCursor, hasNextPage } = await provider.getDynamicFields({
81
- parentId: kioskId,
82
- ...pagination,
83
- });
62
+ if (options.withKioskFields) kioskData.kiosk = kiosk;
63
+ // attach items listings. IF we have `options.withListingPrices === true`, it will also attach the prices.
64
+ attachListingsAndPrices(kioskData, listings, listingObjects);
65
+ // add `locked` status to items that are locked.
66
+ attachLockedItems(kioskData, lockedItemIds);
84
67
 
85
- const listings: KioskListing[] = [];
86
- const lockedItemIds: ObjectId[] = [];
68
+ return {
69
+ data: kioskData,
70
+ nextCursor: null,
71
+ hasNextPage: false,
72
+ };
73
+ }
74
+
75
+ /**
76
+ * A function to fetch all the user's kiosk Caps
77
+ * And a list of the kiosk address ids.
78
+ * Returns a list of `kioskOwnerCapIds` and `kioskIds`.
79
+ * Extra options allow pagination.
80
+ */
81
+ export async function getOwnedKiosks(
82
+ provider: JsonRpcProvider,
83
+ address: SuiAddress,
84
+ options?: {
85
+ pagination?: PaginationArguments<string>;
86
+ },
87
+ ): Promise<OwnedKiosks> {
88
+ if (!isValidSuiAddress(address))
89
+ return {
90
+ nextCursor: null,
91
+ hasNextPage: false,
92
+ kioskOwnerCaps: [],
93
+ kioskIds: [],
94
+ };
87
95
 
88
- // extracted kiosk data.
89
- const kioskData = extractKioskData(data, listings, lockedItemIds);
96
+ // fetch owned kiosk caps, paginated.
97
+ const { data, hasNextPage, nextCursor } = await provider.getOwnedObjects({
98
+ owner: address,
99
+ filter: { StructType: KIOSK_OWNER_CAP },
100
+ options: {
101
+ showContent: true,
102
+ },
103
+ ...(options?.pagination || {}),
104
+ });
90
105
 
91
- // split the fetching in two queries as we are most likely passing different options for each kind.
92
- // For items, we usually seek the Display.
93
- // For listings we usually seek the DF value (price) / exclusivity.
94
- const [kiosk, listingObjects] = await Promise.all([
95
- options.withKioskFields
96
- ? getKioskObject(provider, kioskId)
97
- : Promise.resolve(undefined),
98
- options.withListingPrices
99
- ? provider.multiGetObjects({
100
- ids: kioskData.listingIds,
101
- options: {
102
- showContent: true,
103
- },
104
- })
105
- : Promise.resolve([]),
106
- ]);
106
+ // get kioskIds from the OwnerCaps.
107
+ const kioskIdList = data?.map((x: SuiObjectResponse) => getObjectFields(x)?.for);
107
108
 
108
- if (options.withKioskFields) kioskData.kiosk = kiosk;
109
- // attach items listings. IF we have `options.withListingPrices === true`, it will also attach the prices.
110
- attachListingsAndPrices(kioskData, listings, listingObjects);
111
- // add `locked` status to items that are locked.
112
- attachLockedItems(kioskData, lockedItemIds);
109
+ // clean up data that might have an error in them.
110
+ // only return valid objects.
111
+ const filteredData = data.filter((x) => 'data' in x).map((x) => x.data) as SuiObjectData[];
113
112
 
114
- return {
115
- data: kioskData,
116
- nextCursor,
117
- hasNextPage,
118
- };
113
+ return {
114
+ nextCursor,
115
+ hasNextPage,
116
+ kioskOwnerCaps: filteredData.map((x, idx) => ({
117
+ digest: x.digest,
118
+ version: x.version,
119
+ objectId: x.objectId,
120
+ kioskId: kioskIdList[idx],
121
+ })),
122
+ kioskIds: kioskIdList,
123
+ };
119
124
  }
@@ -3,11 +3,7 @@
3
3
 
4
4
  import { JsonRpcProvider } from '@mysten/sui.js';
5
5
  import { bcs } from '../bcs';
6
- import {
7
- TRANSFER_POLICY_CREATED_EVENT,
8
- TRANSFER_POLICY_TYPE,
9
- TransferPolicy,
10
- } from '../types';
6
+ import { TRANSFER_POLICY_CREATED_EVENT, TRANSFER_POLICY_TYPE, TransferPolicy } from '../types';
11
7
 
12
8
  /**
13
9
  * Searches the `TransferPolicy`-s for the given type. The seach is performed via
@@ -19,41 +15,39 @@ import {
19
15
  * @param type
20
16
  */
21
17
  export async function queryTransferPolicy(
22
- provider: JsonRpcProvider,
23
- type: string,
18
+ provider: JsonRpcProvider,
19
+ type: string,
24
20
  ): Promise<TransferPolicy[]> {
25
- // console.log('event type: %s', `${TRANSFER_POLICY_CREATED_EVENT}<${type}>`);
26
- const { data } = await provider.queryEvents({
27
- query: {
28
- MoveEventType: `${TRANSFER_POLICY_CREATED_EVENT}<${type}>`,
29
- },
30
- });
21
+ // console.log('event type: %s', `${TRANSFER_POLICY_CREATED_EVENT}<${type}>`);
22
+ const { data } = await provider.queryEvents({
23
+ query: {
24
+ MoveEventType: `${TRANSFER_POLICY_CREATED_EVENT}<${type}>`,
25
+ },
26
+ });
31
27
 
32
- const search = data.map((event) => event.parsedJson as { id: string });
33
- const policies = await provider.multiGetObjects({
34
- ids: search.map((policy) => policy.id),
35
- options: { showBcs: true, showOwner: true },
36
- });
28
+ const search = data.map((event) => event.parsedJson as { id: string });
29
+ const policies = await provider.multiGetObjects({
30
+ ids: search.map((policy) => policy.id),
31
+ options: { showBcs: true, showOwner: true },
32
+ });
37
33
 
38
- return policies
39
- .filter((policy) => !!policy && 'data' in policy)
40
- .map(({ data: policy }) => {
41
- // should never happen; policies are objects and fetched via an event.
42
- // policies are filtered for null and undefined above.
43
- if (!policy || !policy.bcs || !('bcsBytes' in policy.bcs)) {
44
- throw new Error(
45
- `Invalid policy: ${policy?.objectId}, expected object, got package`,
46
- );
47
- }
34
+ return policies
35
+ .filter((policy) => !!policy && 'data' in policy)
36
+ .map(({ data: policy }) => {
37
+ // should never happen; policies are objects and fetched via an event.
38
+ // policies are filtered for null and undefined above.
39
+ if (!policy || !policy.bcs || !('bcsBytes' in policy.bcs)) {
40
+ throw new Error(`Invalid policy: ${policy?.objectId}, expected object, got package`);
41
+ }
48
42
 
49
- let parsed = bcs.de(TRANSFER_POLICY_TYPE, policy.bcs.bcsBytes, 'base64');
43
+ let parsed = bcs.de(TRANSFER_POLICY_TYPE, policy.bcs.bcsBytes, 'base64');
50
44
 
51
- return {
52
- id: policy?.objectId,
53
- type: `${TRANSFER_POLICY_TYPE}<${type}>`,
54
- owner: policy?.owner!,
55
- rules: parsed.rules,
56
- balance: parsed.balance,
57
- } as TransferPolicy;
58
- });
45
+ return {
46
+ id: policy?.objectId,
47
+ type: `${TRANSFER_POLICY_TYPE}<${type}>`,
48
+ owner: policy?.owner!,
49
+ rules: parsed.rules,
50
+ balance: parsed.balance,
51
+ } as TransferPolicy;
52
+ });
59
53
  }