@mysten/sui 1.24.0 → 1.25.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.
Files changed (42) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/cjs/transactions/Arguments.d.ts +2 -2
  3. package/dist/cjs/transactions/Transaction.d.ts +4 -4
  4. package/dist/cjs/transactions/TransactionData.d.ts +2 -2
  5. package/dist/cjs/transactions/data/v1.d.ts +4 -4
  6. package/dist/cjs/transactions/data/v2.d.ts +4 -4
  7. package/dist/cjs/transactions/plugins/NamedPackagesPlugin.d.ts +5 -7
  8. package/dist/cjs/transactions/plugins/NamedPackagesPlugin.js +84 -43
  9. package/dist/cjs/transactions/plugins/NamedPackagesPlugin.js.map +3 -3
  10. package/dist/cjs/transactions/plugins/utils.d.ts +10 -6
  11. package/dist/cjs/transactions/plugins/utils.js +64 -37
  12. package/dist/cjs/transactions/plugins/utils.js.map +2 -2
  13. package/dist/cjs/utils/sui-types.d.ts +1 -2
  14. package/dist/cjs/utils/sui-types.js +3 -1
  15. package/dist/cjs/utils/sui-types.js.map +2 -2
  16. package/dist/cjs/version.d.ts +2 -2
  17. package/dist/cjs/version.js +2 -2
  18. package/dist/cjs/version.js.map +1 -1
  19. package/dist/esm/transactions/Arguments.d.ts +2 -2
  20. package/dist/esm/transactions/Transaction.d.ts +4 -4
  21. package/dist/esm/transactions/TransactionData.d.ts +2 -2
  22. package/dist/esm/transactions/data/v1.d.ts +4 -4
  23. package/dist/esm/transactions/data/v2.d.ts +4 -4
  24. package/dist/esm/transactions/plugins/NamedPackagesPlugin.d.ts +5 -7
  25. package/dist/esm/transactions/plugins/NamedPackagesPlugin.js +91 -44
  26. package/dist/esm/transactions/plugins/NamedPackagesPlugin.js.map +3 -3
  27. package/dist/esm/transactions/plugins/utils.d.ts +10 -6
  28. package/dist/esm/transactions/plugins/utils.js +64 -37
  29. package/dist/esm/transactions/plugins/utils.js.map +2 -2
  30. package/dist/esm/utils/sui-types.d.ts +1 -2
  31. package/dist/esm/utils/sui-types.js +3 -1
  32. package/dist/esm/utils/sui-types.js.map +2 -2
  33. package/dist/esm/version.d.ts +2 -2
  34. package/dist/esm/version.js +2 -2
  35. package/dist/esm/version.js.map +1 -1
  36. package/dist/tsconfig.esm.tsbuildinfo +1 -1
  37. package/dist/tsconfig.tsbuildinfo +1 -1
  38. package/package.json +1 -1
  39. package/src/transactions/plugins/NamedPackagesPlugin.ts +118 -62
  40. package/src/transactions/plugins/utils.ts +115 -47
  41. package/src/utils/sui-types.ts +6 -2
  42. package/src/version.ts +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @mysten/sui.js
2
2
 
3
+ ## 1.25.0
4
+
5
+ ### Minor Changes
6
+
7
+ - e8b5d04: Update NamedPackagesPlugin to use the new MVR API and support single-types in the cache
8
+
3
9
  ## 1.24.0
4
10
 
5
11
  ### Minor Changes
@@ -25,8 +25,8 @@ export declare const Arguments: {
25
25
  type?: "object";
26
26
  };
27
27
  objectRef: (args_0: {
28
- objectId: string;
29
28
  version: string | number;
29
+ objectId: string;
30
30
  digest: string;
31
31
  }) => (tx: Transaction) => {
32
32
  $kind: "Input";
@@ -34,8 +34,8 @@ export declare const Arguments: {
34
34
  type?: "object";
35
35
  };
36
36
  receivingRef: (args_0: {
37
- objectId: string;
38
37
  version: string | number;
38
+ objectId: string;
39
39
  digest: string;
40
40
  }) => (tx: Transaction) => {
41
41
  $kind: "Input";
@@ -290,8 +290,8 @@ export declare class Transaction {
290
290
  })[];
291
291
  gasConfig: {
292
292
  payment?: {
293
- objectId: string;
294
293
  version: string | number | bigint;
294
+ objectId: string;
295
295
  digest: string;
296
296
  }[] | undefined;
297
297
  owner?: string | undefined;
@@ -311,8 +311,8 @@ export declare class Transaction {
311
311
  inputs: import("@mysten/bcs").EnumOutputShapeWithKeys<{
312
312
  Object: import("@mysten/bcs").EnumOutputShapeWithKeys<{
313
313
  ImmOrOwnedObject: {
314
- objectId: string;
315
314
  version: string | number;
315
+ objectId: string;
316
316
  digest: string;
317
317
  };
318
318
  SharedObject: {
@@ -321,8 +321,8 @@ export declare class Transaction {
321
321
  mutable: boolean;
322
322
  };
323
323
  Receiving: {
324
- objectId: string;
325
324
  version: string | number;
325
+ objectId: string;
326
326
  digest: string;
327
327
  };
328
328
  }, "ImmOrOwnedObject" | "SharedObject" | "Receiving">;
@@ -576,8 +576,8 @@ export declare class Transaction {
576
576
  }, "MoveCall" | "TransferObjects" | "SplitCoins" | "MergeCoins" | "Publish" | "MakeMoveVec" | "Upgrade" | "$Intent">[];
577
577
  gasData: {
578
578
  payment: {
579
- objectId: string;
580
579
  version: string | number;
580
+ objectId: string;
581
581
  digest: string;
582
582
  }[] | null;
583
583
  owner: string | null;
@@ -16,8 +16,8 @@ export declare class TransactionDataBuilder implements TransactionData {
16
16
  static getDigestFromBytes(bytes: Uint8Array): string;
17
17
  get gasConfig(): {
18
18
  payment: {
19
- objectId: string;
20
19
  version: string | number;
20
+ objectId: string;
21
21
  digest: string;
22
22
  }[] | null;
23
23
  owner: string | null;
@@ -26,8 +26,8 @@ export declare class TransactionDataBuilder implements TransactionData {
26
26
  };
27
27
  set gasConfig(value: {
28
28
  payment: {
29
- objectId: string;
30
29
  version: string | number;
30
+ objectId: string;
31
31
  digest: string;
32
32
  }[] | null;
33
33
  owner: string | null;
@@ -9,8 +9,8 @@ export declare const ObjectRef: import("valibot").ObjectSchema<{
9
9
  export declare const NormalizedCallArg: GenericSchema<import("@mysten/bcs").EnumInputShape<{
10
10
  Object: import("@mysten/bcs").EnumInputShape<{
11
11
  ImmOrOwned: {
12
- objectId: string;
13
12
  version: string | number | bigint;
13
+ objectId: string;
14
14
  digest: string;
15
15
  };
16
16
  Shared: {
@@ -19,8 +19,8 @@ export declare const NormalizedCallArg: GenericSchema<import("@mysten/bcs").Enum
19
19
  mutable: boolean;
20
20
  };
21
21
  Receiving: {
22
- objectId: string;
23
22
  version: string | number | bigint;
23
+ objectId: string;
24
24
  digest: string;
25
25
  };
26
26
  }>;
@@ -28,8 +28,8 @@ export declare const NormalizedCallArg: GenericSchema<import("@mysten/bcs").Enum
28
28
  }>, import("@mysten/bcs").EnumOutputShapeWithKeys<{
29
29
  Object: import("@mysten/bcs").EnumOutputShapeWithKeys<{
30
30
  ImmOrOwned: {
31
- objectId: string;
32
31
  version: string | number | bigint;
32
+ objectId: string;
33
33
  digest: string;
34
34
  };
35
35
  Shared: {
@@ -38,8 +38,8 @@ export declare const NormalizedCallArg: GenericSchema<import("@mysten/bcs").Enum
38
38
  mutable: boolean;
39
39
  };
40
40
  Receiving: {
41
- objectId: string;
42
41
  version: string | number | bigint;
42
+ objectId: string;
43
43
  digest: string;
44
44
  };
45
45
  }, "Receiving" | "Shared" | "ImmOrOwned">;
@@ -23,8 +23,8 @@ export declare const SerializedTransactionDataV2: import("valibot").ObjectSchema
23
23
  readonly inputs: import("valibot").ArraySchema<GenericSchema<EnumInputShape<{
24
24
  Object: EnumInputShape<{
25
25
  ImmOrOwnedObject: {
26
- objectId: string;
27
26
  version: string | number;
27
+ objectId: string;
28
28
  digest: string;
29
29
  };
30
30
  SharedObject: {
@@ -33,8 +33,8 @@ export declare const SerializedTransactionDataV2: import("valibot").ObjectSchema
33
33
  mutable: boolean;
34
34
  };
35
35
  Receiving: {
36
- objectId: string;
37
36
  version: string | number;
37
+ objectId: string;
38
38
  digest: string;
39
39
  };
40
40
  }>;
@@ -53,8 +53,8 @@ export declare const SerializedTransactionDataV2: import("valibot").ObjectSchema
53
53
  }>, EnumInputShape<{
54
54
  Object: EnumInputShape<{
55
55
  ImmOrOwnedObject: {
56
- objectId: string;
57
56
  version: string | number;
57
+ objectId: string;
58
58
  digest: string;
59
59
  };
60
60
  SharedObject: {
@@ -63,8 +63,8 @@ export declare const SerializedTransactionDataV2: import("valibot").ObjectSchema
63
63
  mutable: boolean;
64
64
  };
65
65
  Receiving: {
66
- objectId: string;
67
66
  version: string | number;
67
+ objectId: string;
68
68
  digest: string;
69
69
  };
70
70
  }>;
@@ -1,15 +1,11 @@
1
- import type { SuiGraphQLClient } from '../../graphql/client.js';
2
1
  import type { BuildTransactionOptions } from '../json-rpc-resolver.js';
3
2
  import type { TransactionDataBuilder } from '../TransactionData.js';
4
3
  import type { NamedPackagesPluginCache } from './utils.js';
5
4
  export type NamedPackagesPluginOptions = {
6
5
  /**
7
- * The SuiGraphQLClient to use for resolving names.
8
- * The endpoint should be the GraphQL endpoint of the network you are targeting.
9
- * For non-mainnet networks, if the plugin doesn't work as expected, you need to validate that the
10
- * RPC provider has support for the `packageByName` and `typeByName` queries (using external resolver).
6
+ * The URL of the MVR API to use for resolving names.
11
7
  */
12
- suiGraphQLClient: SuiGraphQLClient;
8
+ url: string;
13
9
  /**
14
10
  * The number of names to resolve in each batch request.
15
11
  * Needs to be calculated based on the GraphQL query limits.
@@ -19,6 +15,8 @@ export type NamedPackagesPluginOptions = {
19
15
  * Local overrides for the resolution plugin. Pass this to pre-populate
20
16
  * the cache with known packages / types (especially useful for local or CI testing).
21
17
  *
18
+ * The type cache expects ONLY first-level types to ensure the cache is more composable.
19
+ *
22
20
  * Expected format example:
23
21
  * {
24
22
  * packages: {
@@ -46,4 +44,4 @@ export type NamedPackagesPluginOptions = {
46
44
  *
47
45
  * You can also define `overrides` to pre-populate name resolutions locally (removes the GraphQL request).
48
46
  */
49
- export declare const namedPackagesPlugin: ({ suiGraphQLClient, pageSize, overrides, }: NamedPackagesPluginOptions) => (transactionData: TransactionDataBuilder, _buildOptions: BuildTransactionOptions, next: () => Promise<void>) => Promise<void>;
47
+ export declare const namedPackagesPlugin: ({ url, pageSize, overrides, }: NamedPackagesPluginOptions) => (transactionData: TransactionDataBuilder, _buildOptions: BuildTransactionOptions, next: () => Promise<void>) => Promise<void>;
@@ -21,58 +21,99 @@ __export(NamedPackagesPlugin_exports, {
21
21
  namedPackagesPlugin: () => namedPackagesPlugin
22
22
  });
23
23
  module.exports = __toCommonJS(NamedPackagesPlugin_exports);
24
+ var import_sui_types = require("../../utils/sui-types.js");
24
25
  var import_utils = require("./utils.js");
25
26
  const namedPackagesPlugin = ({
26
- suiGraphQLClient,
27
- pageSize = 10,
27
+ url,
28
+ pageSize = 50,
28
29
  overrides = { packages: {}, types: {} }
29
30
  }) => {
30
- const cache = {
31
- packages: { ...overrides.packages },
32
- types: { ...overrides.types }
33
- };
31
+ Object.keys(overrides.types).forEach((type) => {
32
+ if ((0, import_sui_types.parseStructTag)(type).typeParams.length > 0)
33
+ throw new Error(
34
+ "Type overrides must be first-level only. If you want to supply generic types, just pass each type individually."
35
+ );
36
+ });
37
+ const cache = overrides;
34
38
  return async (transactionData, _buildOptions, next) => {
35
- const names = (0, import_utils.findTransactionBlockNames)(transactionData);
36
- const batches = (0, import_utils.listToRequests)(
37
- {
38
- packages: names.packages.filter((x) => !cache.packages[x]),
39
- types: names.types.filter((x) => !cache.types[x])
40
- },
41
- pageSize
42
- );
43
- (await Promise.all(batches.map((batch) => query(suiGraphQLClient, batch)))).forEach((res) => {
44
- Object.assign(cache.types, res.types);
45
- Object.assign(cache.packages, res.packages);
39
+ const names = (0, import_utils.findNamesInTransaction)(transactionData);
40
+ const [packages, types] = await Promise.all([
41
+ resolvePackages(
42
+ names.packages.filter((x) => !cache.packages[x]),
43
+ url,
44
+ pageSize
45
+ ),
46
+ resolveTypes(
47
+ [...(0, import_utils.getFirstLevelNamedTypes)(names.types)].filter((x) => !cache.types[x]),
48
+ url,
49
+ pageSize
50
+ )
51
+ ]);
52
+ Object.assign(cache.packages, packages);
53
+ Object.assign(cache.types, types);
54
+ const composedTypes = (0, import_utils.populateNamedTypesFromCache)(names.types, cache.types);
55
+ (0, import_utils.replaceNames)(transactionData, {
56
+ packages: { ...cache.packages },
57
+ // we include the "composed" type cache too.
58
+ types: composedTypes
46
59
  });
47
- (0, import_utils.replaceNames)(transactionData, cache);
48
60
  await next();
49
61
  };
50
- async function query(client, requests) {
51
- const results = { packages: {}, types: {} };
52
- if (requests.length === 0) return results;
53
- const gqlQuery = `{
54
- ${requests.map((req) => {
55
- const request = req.type === "package" ? "packageByName" : "typeByName";
56
- const fields = req.type === "package" ? "address" : "repr";
57
- return `${gqlQueryKey(req.id)}: ${request}(name:"${req.name}") {
58
- ${fields}
59
- }`;
60
- })}
61
- }`;
62
- const result = await client.query({
63
- query: gqlQuery,
64
- variables: void 0
65
- });
66
- if (result.errors) throw new Error(JSON.stringify({ query: gqlQuery, errors: result.errors }));
67
- for (const req of requests) {
68
- const key = gqlQueryKey(req.id);
69
- if (!result.data || !result.data[key]) throw new Error(`No result found for: ${req.name}`);
70
- const data = result.data[key];
71
- if (req.type === "package") results.packages[req.name] = data.address;
72
- if (req.type === "moveType") results.types[req.name] = data.repr;
73
- }
62
+ async function resolvePackages(packages, apiUrl, pageSize2) {
63
+ if (packages.length === 0) return {};
64
+ const batches = (0, import_utils.batch)(packages, pageSize2);
65
+ const results = {};
66
+ await Promise.all(
67
+ batches.map(async (batch2) => {
68
+ const response = await fetch(`${apiUrl}/v1/resolution/bulk`, {
69
+ method: "POST",
70
+ headers: { "Content-Type": "application/json" },
71
+ body: JSON.stringify({
72
+ names: batch2
73
+ })
74
+ });
75
+ if (!response.ok) {
76
+ const errorBody = await response.json().catch(() => ({}));
77
+ throw new Error(`Failed to resolve packages: ${errorBody?.message}`);
78
+ }
79
+ const data = await response.json();
80
+ if (!data?.resolution) return;
81
+ for (const pkg of Object.keys(data?.resolution)) {
82
+ const pkgData = data.resolution[pkg]?.package_id;
83
+ if (!pkgData) continue;
84
+ results[pkg] = pkgData;
85
+ }
86
+ })
87
+ );
88
+ return results;
89
+ }
90
+ async function resolveTypes(types, apiUrl, pageSize2) {
91
+ if (types.length === 0) return {};
92
+ const batches = (0, import_utils.batch)(types, pageSize2);
93
+ const results = {};
94
+ await Promise.all(
95
+ batches.map(async (batch2) => {
96
+ const response = await fetch(`${apiUrl}/v1/struct-definition/bulk`, {
97
+ method: "POST",
98
+ headers: { "Content-Type": "application/json" },
99
+ body: JSON.stringify({
100
+ types: batch2
101
+ })
102
+ });
103
+ if (!response.ok) {
104
+ const errorBody = await response.json().catch(() => ({}));
105
+ throw new Error(`Failed to resolve types: ${errorBody?.message}`);
106
+ }
107
+ const data = await response.json();
108
+ if (!data?.resolution) return;
109
+ for (const type of Object.keys(data?.resolution)) {
110
+ const typeData = data.resolution[type]?.type_tag;
111
+ if (!typeData) continue;
112
+ results[type] = typeData;
113
+ }
114
+ })
115
+ );
74
116
  return results;
75
117
  }
76
118
  };
77
- const gqlQueryKey = (idx) => `key_${idx}`;
78
119
  //# sourceMappingURL=NamedPackagesPlugin.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/transactions/plugins/NamedPackagesPlugin.ts"],
4
- "sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { SuiGraphQLClient } from '../../graphql/client.js';\nimport type { BuildTransactionOptions } from '../json-rpc-resolver.js';\nimport type { TransactionDataBuilder } from '../TransactionData.js';\nimport type { NamedPackagesPluginCache, NameResolutionRequest } from './utils.js';\nimport { findTransactionBlockNames, listToRequests, replaceNames } from './utils.js';\n\nexport type NamedPackagesPluginOptions = {\n\t/**\n\t * The SuiGraphQLClient to use for resolving names.\n\t * The endpoint should be the GraphQL endpoint of the network you are targeting.\n\t * For non-mainnet networks, if the plugin doesn't work as expected, you need to validate that the\n\t * RPC provider has support for the `packageByName` and `typeByName` queries (using external resolver).\n\t */\n\tsuiGraphQLClient: SuiGraphQLClient;\n\t/**\n\t * The number of names to resolve in each batch request.\n\t * Needs to be calculated based on the GraphQL query limits.\n\t */\n\tpageSize?: number;\n\t/**\n\t * Local overrides for the resolution plugin. Pass this to pre-populate\n\t * the cache with known packages / types (especially useful for local or CI testing).\n\t *\n\t * \tExpected format example:\n\t * {\n\t * \t\tpackages: {\n\t * \t\t\t'@framework/std': '0x1234',\n\t * \t\t},\n\t * \t\ttypes: {\n\t * \t\t\t'@framework/std::string::String': '0x1234::string::String',\n\t * \t\t},\n\t * \t}\n\t *\n\t */\n\toverrides?: NamedPackagesPluginCache;\n};\n\n/**\n * @experimental This plugin is in experimental phase and there might be breaking changes in the future\n *\n * Adds named resolution so that you can use .move names in your transactions.\n * e.g. `@org/app::type::Type` will be resolved to `0x1234::type::Type`.\n * This plugin will resolve all names & types in the transaction block.\n *\n * To install this plugin globally in your app, use:\n * ```\n * Transaction.registerGlobalSerializationPlugin(\"namedPackagesPlugin\", namedPackagesPlugin({ suiGraphQLClient }));\n * ```\n *\n * You can also define `overrides` to pre-populate name resolutions locally (removes the GraphQL request).\n */\nexport const namedPackagesPlugin = ({\n\tsuiGraphQLClient,\n\tpageSize = 10,\n\toverrides = { packages: {}, types: {} },\n}: NamedPackagesPluginOptions) => {\n\tconst cache = {\n\t\tpackages: { ...overrides.packages },\n\t\ttypes: { ...overrides.types },\n\t};\n\n\treturn async (\n\t\ttransactionData: TransactionDataBuilder,\n\t\t_buildOptions: BuildTransactionOptions,\n\t\tnext: () => Promise<void>,\n\t) => {\n\t\tconst names = findTransactionBlockNames(transactionData);\n\t\tconst batches = listToRequests(\n\t\t\t{\n\t\t\t\tpackages: names.packages.filter((x) => !cache.packages[x]),\n\t\t\t\ttypes: names.types.filter((x) => !cache.types[x]),\n\t\t\t},\n\t\t\tpageSize,\n\t\t);\n\n\t\t// now we need to bulk resolve all the names + types, and replace them in the transaction data.\n\t\t(await Promise.all(batches.map((batch) => query(suiGraphQLClient, batch)))).forEach((res) => {\n\t\t\tObject.assign(cache.types, res.types);\n\t\t\tObject.assign(cache.packages, res.packages);\n\t\t});\n\n\t\treplaceNames(transactionData, cache);\n\n\t\tawait next();\n\t};\n\n\tasync function query(client: SuiGraphQLClient, requests: NameResolutionRequest[]) {\n\t\tconst results: NamedPackagesPluginCache = { packages: {}, types: {} };\n\t\t// avoid making a request if there are no names to resolve.\n\t\tif (requests.length === 0) return results;\n\n\t\t// Create multiple queries for each name / type we need to resolve\n\t\t// TODO: Replace with bulk APIs when available.\n\t\tconst gqlQuery = `{\n ${requests.map((req) => {\n\t\t\t\t\tconst request = req.type === 'package' ? 'packageByName' : 'typeByName';\n\t\t\t\t\tconst fields = req.type === 'package' ? 'address' : 'repr';\n\n\t\t\t\t\treturn `${gqlQueryKey(req.id)}: ${request}(name:\"${req.name}\") {\n ${fields}\n }`;\n\t\t\t\t})}\n }`;\n\n\t\tconst result = await client.query({\n\t\t\tquery: gqlQuery,\n\t\t\tvariables: undefined,\n\t\t});\n\n\t\tif (result.errors) throw new Error(JSON.stringify({ query: gqlQuery, errors: result.errors }));\n\n\t\t// Parse the results and create a map of `<name|type> -> <address|repr>`\n\t\tfor (const req of requests) {\n\t\t\tconst key = gqlQueryKey(req.id);\n\t\t\tif (!result.data || !result.data[key]) throw new Error(`No result found for: ${req.name}`);\n\t\t\tconst data = result.data[key] as { address?: string; repr?: string };\n\n\t\t\tif (req.type === 'package') results.packages[req.name] = data.address!;\n\t\t\tif (req.type === 'moveType') results.types[req.name] = data.repr!;\n\t\t}\n\n\t\treturn results;\n\t}\n};\n\nconst gqlQueryKey = (idx: number) => `key_${idx}`;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,mBAAwE;AA+CjE,MAAM,sBAAsB,CAAC;AAAA,EACnC;AAAA,EACA,WAAW;AAAA,EACX,YAAY,EAAE,UAAU,CAAC,GAAG,OAAO,CAAC,EAAE;AACvC,MAAkC;AACjC,QAAM,QAAQ;AAAA,IACb,UAAU,EAAE,GAAG,UAAU,SAAS;AAAA,IAClC,OAAO,EAAE,GAAG,UAAU,MAAM;AAAA,EAC7B;AAEA,SAAO,OACN,iBACA,eACA,SACI;AACJ,UAAM,YAAQ,wCAA0B,eAAe;AACvD,UAAM,cAAU;AAAA,MACf;AAAA,QACC,UAAU,MAAM,SAAS,OAAO,CAAC,MAAM,CAAC,MAAM,SAAS,CAAC,CAAC;AAAA,QACzD,OAAO,MAAM,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,MAAM,CAAC,CAAC;AAAA,MACjD;AAAA,MACA;AAAA,IACD;AAGA,KAAC,MAAM,QAAQ,IAAI,QAAQ,IAAI,CAAC,UAAU,MAAM,kBAAkB,KAAK,CAAC,CAAC,GAAG,QAAQ,CAAC,QAAQ;AAC5F,aAAO,OAAO,MAAM,OAAO,IAAI,KAAK;AACpC,aAAO,OAAO,MAAM,UAAU,IAAI,QAAQ;AAAA,IAC3C,CAAC;AAED,mCAAa,iBAAiB,KAAK;AAEnC,UAAM,KAAK;AAAA,EACZ;AAEA,iBAAe,MAAM,QAA0B,UAAmC;AACjF,UAAM,UAAoC,EAAE,UAAU,CAAC,GAAG,OAAO,CAAC,EAAE;AAEpE,QAAI,SAAS,WAAW,EAAG,QAAO;AAIlC,UAAM,WAAW;AAAA,UACT,SAAS,IAAI,CAAC,QAAQ;AAC3B,YAAM,UAAU,IAAI,SAAS,YAAY,kBAAkB;AAC3D,YAAM,SAAS,IAAI,SAAS,YAAY,YAAY;AAEpD,aAAO,GAAG,YAAY,IAAI,EAAE,CAAC,KAAK,OAAO,UAAU,IAAI,IAAI;AAAA,sBAC1C,MAAM;AAAA;AAAA,IAExB,CAAC,CAAC;AAAA;AAGJ,UAAM,SAAS,MAAM,OAAO,MAAM;AAAA,MACjC,OAAO;AAAA,MACP,WAAW;AAAA,IACZ,CAAC;AAED,QAAI,OAAO,OAAQ,OAAM,IAAI,MAAM,KAAK,UAAU,EAAE,OAAO,UAAU,QAAQ,OAAO,OAAO,CAAC,CAAC;AAG7F,eAAW,OAAO,UAAU;AAC3B,YAAM,MAAM,YAAY,IAAI,EAAE;AAC9B,UAAI,CAAC,OAAO,QAAQ,CAAC,OAAO,KAAK,GAAG,EAAG,OAAM,IAAI,MAAM,wBAAwB,IAAI,IAAI,EAAE;AACzF,YAAM,OAAO,OAAO,KAAK,GAAG;AAE5B,UAAI,IAAI,SAAS,UAAW,SAAQ,SAAS,IAAI,IAAI,IAAI,KAAK;AAC9D,UAAI,IAAI,SAAS,WAAY,SAAQ,MAAM,IAAI,IAAI,IAAI,KAAK;AAAA,IAC7D;AAEA,WAAO;AAAA,EACR;AACD;AAEA,MAAM,cAAc,CAAC,QAAgB,OAAO,GAAG;",
6
- "names": []
4
+ "sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { parseStructTag } from '../../utils/sui-types.js';\nimport type { BuildTransactionOptions } from '../json-rpc-resolver.js';\nimport type { TransactionDataBuilder } from '../TransactionData.js';\nimport type { NamedPackagesPluginCache } from './utils.js';\nimport {\n\tbatch,\n\tfindNamesInTransaction,\n\tgetFirstLevelNamedTypes,\n\tpopulateNamedTypesFromCache,\n\treplaceNames,\n} from './utils.js';\n\nexport type NamedPackagesPluginOptions = {\n\t/**\n\t * The URL of the MVR API to use for resolving names.\n\t */\n\turl: string;\n\t/**\n\t * The number of names to resolve in each batch request.\n\t * Needs to be calculated based on the GraphQL query limits.\n\t */\n\tpageSize?: number;\n\t/**\n\t * Local overrides for the resolution plugin. Pass this to pre-populate\n\t * the cache with known packages / types (especially useful for local or CI testing).\n\t *\n\t * The type cache expects ONLY first-level types to ensure the cache is more composable.\n\t *\n\t * \tExpected format example:\n\t * {\n\t * \t\tpackages: {\n\t * \t\t\t'@framework/std': '0x1234',\n\t * \t\t},\n\t * \t\ttypes: {\n\t * \t\t\t'@framework/std::string::String': '0x1234::string::String',\n\t * \t\t},\n\t * \t}\n\t *\n\t */\n\toverrides?: NamedPackagesPluginCache;\n};\n\n/**\n * @experimental This plugin is in experimental phase and there might be breaking changes in the future\n *\n * Adds named resolution so that you can use .move names in your transactions.\n * e.g. `@org/app::type::Type` will be resolved to `0x1234::type::Type`.\n * This plugin will resolve all names & types in the transaction block.\n *\n * To install this plugin globally in your app, use:\n * ```\n * Transaction.registerGlobalSerializationPlugin(\"namedPackagesPlugin\", namedPackagesPlugin({ suiGraphQLClient }));\n * ```\n *\n * You can also define `overrides` to pre-populate name resolutions locally (removes the GraphQL request).\n */\nexport const namedPackagesPlugin = ({\n\turl,\n\tpageSize = 50,\n\toverrides = { packages: {}, types: {} },\n}: NamedPackagesPluginOptions) => {\n\t// validate that types are first-level only.\n\tObject.keys(overrides.types).forEach((type) => {\n\t\tif (parseStructTag(type).typeParams.length > 0)\n\t\t\tthrow new Error(\n\t\t\t\t'Type overrides must be first-level only. If you want to supply generic types, just pass each type individually.',\n\t\t\t);\n\t});\n\n\tconst cache = overrides;\n\n\treturn async (\n\t\ttransactionData: TransactionDataBuilder,\n\t\t_buildOptions: BuildTransactionOptions,\n\t\tnext: () => Promise<void>,\n\t) => {\n\t\tconst names = findNamesInTransaction(transactionData);\n\n\t\tconst [packages, types] = await Promise.all([\n\t\t\tresolvePackages(\n\t\t\t\tnames.packages.filter((x) => !cache.packages[x]),\n\t\t\t\turl,\n\t\t\t\tpageSize,\n\t\t\t),\n\t\t\tresolveTypes(\n\t\t\t\t[...getFirstLevelNamedTypes(names.types)].filter((x) => !cache.types[x]),\n\t\t\t\turl,\n\t\t\t\tpageSize,\n\t\t\t),\n\t\t]);\n\n\t\t// save first-level mappings to cache.\n\t\tObject.assign(cache.packages, packages);\n\t\tObject.assign(cache.types, types);\n\n\t\tconst composedTypes = populateNamedTypesFromCache(names.types, cache.types);\n\n\t\t// when replacing names, we also need to replace the \"composed\" types collected above.\n\t\treplaceNames(transactionData, {\n\t\t\tpackages: { ...cache.packages },\n\t\t\t// we include the \"composed\" type cache too.\n\t\t\ttypes: composedTypes,\n\t\t});\n\n\t\tawait next();\n\t};\n\n\tasync function resolvePackages(packages: string[], apiUrl: string, pageSize: number) {\n\t\tif (packages.length === 0) return {};\n\n\t\tconst batches = batch(packages, pageSize);\n\t\tconst results: Record<string, string> = {};\n\n\t\tawait Promise.all(\n\t\t\tbatches.map(async (batch) => {\n\t\t\t\tconst response = await fetch(`${apiUrl}/v1/resolution/bulk`, {\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\t\tnames: batch,\n\t\t\t\t\t}),\n\t\t\t\t});\n\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tconst errorBody = await response.json().catch(() => ({}));\n\t\t\t\t\tthrow new Error(`Failed to resolve packages: ${errorBody?.message}`);\n\t\t\t\t}\n\n\t\t\t\tconst data = await response.json();\n\n\t\t\t\tif (!data?.resolution) return;\n\n\t\t\t\tfor (const pkg of Object.keys(data?.resolution)) {\n\t\t\t\t\tconst pkgData = data.resolution[pkg]?.package_id;\n\n\t\t\t\t\tif (!pkgData) continue;\n\n\t\t\t\t\tresults[pkg] = pkgData;\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\n\t\treturn results;\n\t}\n\n\tasync function resolveTypes(types: string[], apiUrl: string, pageSize: number) {\n\t\tif (types.length === 0) return {};\n\n\t\tconst batches = batch(types, pageSize);\n\t\tconst results: Record<string, string> = {};\n\n\t\tawait Promise.all(\n\t\t\tbatches.map(async (batch) => {\n\t\t\t\tconst response = await fetch(`${apiUrl}/v1/struct-definition/bulk`, {\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\t\ttypes: batch,\n\t\t\t\t\t}),\n\t\t\t\t});\n\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tconst errorBody = await response.json().catch(() => ({}));\n\t\t\t\t\tthrow new Error(`Failed to resolve types: ${errorBody?.message}`);\n\t\t\t\t}\n\n\t\t\t\tconst data = await response.json();\n\n\t\t\t\tif (!data?.resolution) return;\n\n\t\t\t\tfor (const type of Object.keys(data?.resolution)) {\n\t\t\t\t\tconst typeData = data.resolution[type]?.type_tag;\n\t\t\t\t\tif (!typeData) continue;\n\n\t\t\t\t\tresults[type] = typeData;\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\n\t\treturn results;\n\t}\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["pageSize", "batch"]
7
7
  }
@@ -12,16 +12,20 @@ export type NameResolutionRequest = {
12
12
  * Looks up all `.move` names in a transaction block.
13
13
  * Returns a list of all the names found.
14
14
  */
15
- export declare const findTransactionBlockNames: (builder: TransactionDataBuilder) => {
15
+ export declare function findNamesInTransaction(builder: TransactionDataBuilder): {
16
16
  packages: string[];
17
17
  types: string[];
18
18
  };
19
+ /**
20
+ * Extracts all first-level types from a list of types.
21
+ * E.g. for the input `['@mvr/demo::a::A<@mvr/demo::b::B>']`,
22
+ * the output will be `['@mvr/demo::a::A', '@mvr/demo::b::B']`.
23
+ */
24
+ export declare function getFirstLevelNamedTypes(types: string[]): Set<string>;
25
+ export declare function populateNamedTypesFromCache(types: string[], typeCache: Record<string, string>): Record<string, string>;
19
26
  /**
20
27
  * Replace all names & types in a transaction block
21
28
  * with their resolved names/types.
22
29
  */
23
- export declare const replaceNames: (builder: TransactionDataBuilder, cache: NamedPackagesPluginCache) => void;
24
- export declare const listToRequests: (names: {
25
- packages: string[];
26
- types: string[];
27
- }, batchSize: number) => NameResolutionRequest[][];
30
+ export declare function replaceNames(builder: TransactionDataBuilder, cache: NamedPackagesPluginCache): void;
31
+ export declare function batch<T>(arr: T[], size: number): T[][];
@@ -18,14 +18,17 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var utils_exports = {};
20
20
  __export(utils_exports, {
21
- findTransactionBlockNames: () => findTransactionBlockNames,
22
- listToRequests: () => listToRequests,
21
+ batch: () => batch,
22
+ findNamesInTransaction: () => findNamesInTransaction,
23
+ getFirstLevelNamedTypes: () => getFirstLevelNamedTypes,
24
+ populateNamedTypesFromCache: () => populateNamedTypesFromCache,
23
25
  replaceNames: () => replaceNames
24
26
  });
25
27
  module.exports = __toCommonJS(utils_exports);
26
28
  var import_move_registry = require("../../utils/move-registry.js");
29
+ var import_sui_types = require("../../utils/sui-types.js");
27
30
  const NAME_SEPARATOR = "/";
28
- const findTransactionBlockNames = (builder) => {
31
+ function findNamesInTransaction(builder) {
29
32
  const packages = /* @__PURE__ */ new Set();
30
33
  const types = /* @__PURE__ */ new Set();
31
34
  for (const command of builder.commands) {
@@ -39,7 +42,7 @@ const findTransactionBlockNames = (builder) => {
39
42
  const tx = command.MoveCall;
40
43
  if (!tx) continue;
41
44
  const pkg = tx.package.split("::")[0];
42
- if (pkg.includes(NAME_SEPARATOR)) {
45
+ if (hasMvrName(pkg)) {
43
46
  if (!(0, import_move_registry.isValidNamedPackage)(pkg)) throw new Error(`Invalid package name: ${pkg}`);
44
47
  packages.add(pkg);
45
48
  }
@@ -51,21 +54,46 @@ const findTransactionBlockNames = (builder) => {
51
54
  packages: [...packages],
52
55
  types: [...types]
53
56
  };
54
- };
55
- function getNamesFromTypeList(types) {
56
- const names = /* @__PURE__ */ new Set();
57
+ }
58
+ function getFirstLevelNamedTypes(types) {
59
+ const results = /* @__PURE__ */ new Set();
57
60
  for (const type of types) {
58
- if (type.includes(NAME_SEPARATOR)) {
59
- if (!(0, import_move_registry.isValidNamedType)(type)) throw new Error(`Invalid type with names: ${type}`);
60
- names.add(type);
61
- }
61
+ findMvrNames(type).forEach((name) => results.add(name));
62
+ }
63
+ return results;
64
+ }
65
+ function findMvrNames(type) {
66
+ const types = /* @__PURE__ */ new Set();
67
+ if (typeof type === "string" && !hasMvrName(type)) return types;
68
+ let tag = isStructTag(type) ? type : (0, import_sui_types.parseStructTag)(type);
69
+ if (hasMvrName(tag.address)) types.add(`${tag.address}::${tag.module}::${tag.name}`);
70
+ for (const param of tag.typeParams) {
71
+ findMvrNames(param).forEach((name) => types.add(name));
62
72
  }
63
- return [...names];
73
+ return types;
74
+ }
75
+ function populateNamedTypesFromCache(types, typeCache) {
76
+ const composedTypes = {};
77
+ types.forEach((type) => {
78
+ const normalized = (0, import_sui_types.normalizeStructTag)(findAndReplaceCachedTypes(type, typeCache));
79
+ composedTypes[type] = normalized;
80
+ });
81
+ return composedTypes;
82
+ }
83
+ function findAndReplaceCachedTypes(tag, typeCache) {
84
+ const type = isStructTag(tag) ? tag : (0, import_sui_types.parseStructTag)(tag);
85
+ let typeTag = `${type.address}::${type.module}::${type.name}`;
86
+ const cacheHit = typeCache[typeTag];
87
+ return {
88
+ ...type,
89
+ address: cacheHit ? cacheHit.split("::")[0] : type.address,
90
+ typeParams: type.typeParams.map((param) => findAndReplaceCachedTypes(param, typeCache))
91
+ };
64
92
  }
65
- const replaceNames = (builder, cache) => {
93
+ function replaceNames(builder, cache) {
66
94
  for (const command of builder.commands) {
67
95
  if (command.MakeMoveVec?.type) {
68
- if (!command.MakeMoveVec.type.includes(NAME_SEPARATOR)) continue;
96
+ if (!hasMvrName(command.MakeMoveVec.type)) continue;
69
97
  if (!cache.types[command.MakeMoveVec.type])
70
98
  throw new Error(`No resolution found for type: ${command.MakeMoveVec.type}`);
71
99
  command.MakeMoveVec.type = cache.types[command.MakeMoveVec.type];
@@ -74,44 +102,43 @@ const replaceNames = (builder, cache) => {
74
102
  if (!tx) continue;
75
103
  const nameParts = tx.package.split("::");
76
104
  const name = nameParts[0];
77
- if (name.includes(NAME_SEPARATOR) && !cache.packages[name])
105
+ if (hasMvrName(name) && !cache.packages[name])
78
106
  throw new Error(`No address found for package: ${name}`);
79
- if (name.includes(NAME_SEPARATOR)) {
107
+ if (hasMvrName(name)) {
80
108
  nameParts[0] = cache.packages[name];
81
109
  tx.package = nameParts.join("::");
82
110
  }
83
111
  const types = tx.typeArguments;
84
112
  if (!types) continue;
85
113
  for (let i = 0; i < types.length; i++) {
86
- if (!types[i].includes(NAME_SEPARATOR)) continue;
114
+ if (!hasMvrName(types[i])) continue;
87
115
  if (!cache.types[types[i]]) throw new Error(`No resolution found for type: ${types[i]}`);
88
116
  types[i] = cache.types[types[i]];
89
117
  }
90
118
  tx.typeArguments = types;
91
119
  }
92
- };
93
- const listToRequests = (names, batchSize) => {
94
- const results = [];
95
- const uniqueNames = deduplicate(names.packages);
96
- const uniqueTypes = deduplicate(names.types);
97
- for (const [idx, name] of uniqueNames.entries()) {
98
- results.push({ id: idx, type: "package", name });
99
- }
100
- for (const [idx, type] of uniqueTypes.entries()) {
101
- results.push({
102
- id: idx + uniqueNames.length,
103
- type: "moveType",
104
- name: type
105
- });
106
- }
107
- return batch(results, batchSize);
108
- };
109
- const deduplicate = (arr) => [...new Set(arr)];
110
- const batch = (arr, size) => {
120
+ }
121
+ function batch(arr, size) {
111
122
  const batches = [];
112
123
  for (let i = 0; i < arr.length; i += size) {
113
124
  batches.push(arr.slice(i, i + size));
114
125
  }
115
126
  return batches;
116
- };
127
+ }
128
+ function getNamesFromTypeList(types) {
129
+ const names = /* @__PURE__ */ new Set();
130
+ for (const type of types) {
131
+ if (hasMvrName(type)) {
132
+ if (!(0, import_move_registry.isValidNamedType)(type)) throw new Error(`Invalid type with names: ${type}`);
133
+ names.add(type);
134
+ }
135
+ }
136
+ return names;
137
+ }
138
+ function hasMvrName(nameOrType) {
139
+ return nameOrType.includes(NAME_SEPARATOR) || nameOrType.includes("@") || nameOrType.includes(".sui");
140
+ }
141
+ function isStructTag(type) {
142
+ return typeof type === "object" && "address" in type && "module" in type && "name" in type && "typeParams" in type;
143
+ }
117
144
  //# sourceMappingURL=utils.js.map