@mysten/pas 0.0.1
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/README.md +1 -0
- package/dist/client.d.mts +117 -0
- package/dist/client.d.mts.map +1 -0
- package/dist/client.mjs +89 -0
- package/dist/client.mjs.map +1 -0
- package/dist/constants.mjs +9 -0
- package/dist/constants.mjs.map +1 -0
- package/dist/contracts/pas/deps/std/type_name.mjs +17 -0
- package/dist/contracts/pas/deps/std/type_name.mjs.map +1 -0
- package/dist/contracts/pas/deps/sui/vec_map.mjs +37 -0
- package/dist/contracts/pas/deps/sui/vec_map.mjs.map +1 -0
- package/dist/contracts/pas/deps/sui/vec_set.mjs +26 -0
- package/dist/contracts/pas/deps/sui/vec_set.mjs.map +1 -0
- package/dist/contracts/pas/policy.mjs +33 -0
- package/dist/contracts/pas/policy.mjs.map +1 -0
- package/dist/contracts/pas/versioning.mjs +25 -0
- package/dist/contracts/pas/versioning.mjs.map +1 -0
- package/dist/contracts/ptb/ptb.mjs +162 -0
- package/dist/contracts/ptb/ptb.mjs.map +1 -0
- package/dist/contracts/sui/dynamic_field.mjs +22 -0
- package/dist/contracts/sui/dynamic_field.mjs.map +1 -0
- package/dist/contracts/utils/index.mjs +37 -0
- package/dist/contracts/utils/index.mjs.map +1 -0
- package/dist/derivation.mjs +70 -0
- package/dist/derivation.mjs.map +1 -0
- package/dist/error.d.mts +16 -0
- package/dist/error.d.mts.map +1 -0
- package/dist/error.mjs +26 -0
- package/dist/error.mjs.map +1 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.mjs +4 -0
- package/dist/intents.mjs +494 -0
- package/dist/intents.mjs.map +1 -0
- package/dist/resolution.mjs +185 -0
- package/dist/resolution.mjs.map +1 -0
- package/dist/types.d.mts +34 -0
- package/dist/types.d.mts.map +1 -0
- package/package.json +59 -0
- package/src/client.ts +173 -0
- package/src/constants.ts +15 -0
- package/src/contracts/pas/account.ts +343 -0
- package/src/contracts/pas/clawback_funds.ts +114 -0
- package/src/contracts/pas/deps/std/type_name.ts +24 -0
- package/src/contracts/pas/deps/sui/vec_map.ts +33 -0
- package/src/contracts/pas/deps/sui/vec_set.ts +22 -0
- package/src/contracts/pas/keys.ts +90 -0
- package/src/contracts/pas/namespace.ts +207 -0
- package/src/contracts/pas/policy.ts +212 -0
- package/src/contracts/pas/request.ts +87 -0
- package/src/contracts/pas/send_funds.ts +174 -0
- package/src/contracts/pas/templates.ts +101 -0
- package/src/contracts/pas/unlock_funds.ts +155 -0
- package/src/contracts/pas/versioning.ts +69 -0
- package/src/contracts/ptb/ptb.ts +821 -0
- package/src/contracts/sui/dynamic_field.ts +171 -0
- package/src/contracts/utils/index.ts +235 -0
- package/src/derivation.ts +107 -0
- package/src/error.ts +29 -0
- package/src/index.ts +6 -0
- package/src/intents.ts +852 -0
- package/src/resolution.ts +294 -0
- package/src/types.ts +34 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { PASClientError } from "./error.mjs";
|
|
2
|
+
import { TypeName } from "./contracts/pas/deps/std/type_name.mjs";
|
|
3
|
+
import { Policy } from "./contracts/pas/policy.mjs";
|
|
4
|
+
import { Command, MoveCall } from "./contracts/ptb/ptb.mjs";
|
|
5
|
+
import { Field } from "./contracts/sui/dynamic_field.mjs";
|
|
6
|
+
import { normalizeStructTag } from "@mysten/sui/utils";
|
|
7
|
+
import { Inputs, TransactionCommands } from "@mysten/sui/transactions";
|
|
8
|
+
|
|
9
|
+
//#region src/resolution.ts
|
|
10
|
+
const OBJECT_BY_ID_EXT = "object_by_id";
|
|
11
|
+
const OBJECT_BY_TYPE_EXT = "object_by_type";
|
|
12
|
+
const RECEIVING_BY_ID_EXT = "receiving_by_id";
|
|
13
|
+
/**
|
|
14
|
+
* Extracts all object IDs referenced by template commands, regardless of
|
|
15
|
+
* how they are specified (fully resolved refs, shared refs, or ext lookups).
|
|
16
|
+
*/
|
|
17
|
+
function collectTemplateObjectIds(commands) {
|
|
18
|
+
const ids = /* @__PURE__ */ new Set();
|
|
19
|
+
for (const cmd of commands) for (const arg of cmd.arguments) {
|
|
20
|
+
const obj = arg.Input?.Object;
|
|
21
|
+
if (!obj) continue;
|
|
22
|
+
switch (obj.$kind) {
|
|
23
|
+
case "ImmOrOwnedObject":
|
|
24
|
+
ids.add(obj.ImmOrOwnedObject.object_id);
|
|
25
|
+
break;
|
|
26
|
+
case "SharedObject":
|
|
27
|
+
ids.add(obj.SharedObject.object_id);
|
|
28
|
+
break;
|
|
29
|
+
case "Receiving":
|
|
30
|
+
ids.add(obj.Receiving.object_id);
|
|
31
|
+
break;
|
|
32
|
+
case "Ext": {
|
|
33
|
+
const [kind, value] = obj.Ext.split(":");
|
|
34
|
+
switch (kind) {
|
|
35
|
+
case OBJECT_BY_ID_EXT:
|
|
36
|
+
case RECEIVING_BY_ID_EXT:
|
|
37
|
+
ids.add(value);
|
|
38
|
+
break;
|
|
39
|
+
default: throw new PASClientError(`Unsupported external object kind: ${kind}`);
|
|
40
|
+
}
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
default: throw new PASClientError("Invariant violation: unhandled variant in `collectTemplateObjectIds`");
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return ids;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Parses the Policy object to extract the required approval type names for a given action.
|
|
50
|
+
*
|
|
51
|
+
* The Policy's `required_approvals` is a `VecMap<String, VecSet<TypeName>>` where:
|
|
52
|
+
* - Key is the action name (e.g., "send_funds")
|
|
53
|
+
* - Value is a set of approval TypeNames that must be satisfied
|
|
54
|
+
*
|
|
55
|
+
* @param policyObject - The Policy object fetched with content
|
|
56
|
+
* @returns The list of approval TypeName strings for the given action, or undefined if not found
|
|
57
|
+
*/
|
|
58
|
+
function getRequiredApprovals(policyObject, actionType) {
|
|
59
|
+
const entry = Policy.parse(policyObject.content).required_approvals.contents.find((e) => e.key === actionType);
|
|
60
|
+
if (!entry) return void 0;
|
|
61
|
+
return entry.value.contents.map((tn) => tn.name);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Parses a Command from a Template dynamic field object.
|
|
65
|
+
*
|
|
66
|
+
* Each Template DF is a `Field<TypeName, Command>` where:
|
|
67
|
+
* - TypeName is the approval type (e.g., the `with_defining_ids` of `TransferApproval`)
|
|
68
|
+
* - Command is the move call instruction to execute for that approval
|
|
69
|
+
*
|
|
70
|
+
* @param templateDF - The Template DF object fetched with content
|
|
71
|
+
* @returns The parsed Command, or undefined if parsing fails
|
|
72
|
+
*/
|
|
73
|
+
function getCommandFromTemplate(template) {
|
|
74
|
+
return parseCommand(Field(TypeName, Command).parse(template.content).value);
|
|
75
|
+
}
|
|
76
|
+
function parseCommand([key, cmd]) {
|
|
77
|
+
if (key !== 0) throw new PASClientError(`Unknown command type: ${key}`);
|
|
78
|
+
return MoveCall.parse(new Uint8Array(cmd));
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Builds a `Command` (TransactionCommands.MoveCall) from a parsed template command,
|
|
82
|
+
* suitable for use with `transactionData.replaceCommand()`.
|
|
83
|
+
*
|
|
84
|
+
* Resolves template argument placeholders (pas:request, pas:policy, etc.) into
|
|
85
|
+
* concrete Argument references, and converts object/pure inputs via the provided
|
|
86
|
+
* `addInput` callback.
|
|
87
|
+
*
|
|
88
|
+
* @param command - The parsed MoveCall from a template object
|
|
89
|
+
* @param args - The resolved arguments and addInput helper
|
|
90
|
+
* @param commandOffset - Absolute PTB index where the first template command will
|
|
91
|
+
* land. Raw `Result` and `NestedResult` values from the on-chain BCS are
|
|
92
|
+
* template-relative (i.e. `Result(0)` means "first command in this template").
|
|
93
|
+
* We rebase them by adding this offset so they point at the correct position
|
|
94
|
+
* in the final transaction.
|
|
95
|
+
* @returns A Command object ready for `replaceCommand`
|
|
96
|
+
*/
|
|
97
|
+
function buildMoveCallCommandFromTemplate(command, args, commandOffset) {
|
|
98
|
+
const resolvedArgs = [];
|
|
99
|
+
for (const arg of command.arguments) if (arg.Ext) throw new PASClientError(`There are no supported ext arguments in this client.`);
|
|
100
|
+
else if (arg.GasCoin) throw new PASClientError(`Gas coin is not supported in PAS client.`);
|
|
101
|
+
else if (arg.NestedResult != null) resolvedArgs.push({
|
|
102
|
+
$kind: "NestedResult",
|
|
103
|
+
NestedResult: [arg.NestedResult[0] + commandOffset, arg.NestedResult[1]]
|
|
104
|
+
});
|
|
105
|
+
else if (arg.Result != null) resolvedArgs.push({
|
|
106
|
+
$kind: "Result",
|
|
107
|
+
Result: arg.Result + commandOffset
|
|
108
|
+
});
|
|
109
|
+
else if (arg.Input) if (arg.Input.Pure) resolvedArgs.push(args.addInput("pure", Inputs.Pure(new Uint8Array(arg.Input.Pure))));
|
|
110
|
+
else if (arg.Input.Object) switch (arg.Input.Object.$kind) {
|
|
111
|
+
case "ImmOrOwnedObject":
|
|
112
|
+
resolvedArgs.push(args.addInput("object", Inputs.ObjectRef({
|
|
113
|
+
objectId: arg.Input.Object.ImmOrOwnedObject.object_id,
|
|
114
|
+
version: arg.Input.Object.ImmOrOwnedObject.sequence_number,
|
|
115
|
+
digest: arg.Input.Object.ImmOrOwnedObject.digest
|
|
116
|
+
})));
|
|
117
|
+
break;
|
|
118
|
+
case "SharedObject":
|
|
119
|
+
resolvedArgs.push(args.addInput("object", Inputs.SharedObjectRef({
|
|
120
|
+
objectId: arg.Input.Object.SharedObject.object_id,
|
|
121
|
+
initialSharedVersion: arg.Input.Object.SharedObject.initial_shared_version,
|
|
122
|
+
mutable: arg.Input.Object.SharedObject.is_mutable
|
|
123
|
+
})));
|
|
124
|
+
break;
|
|
125
|
+
case "Receiving":
|
|
126
|
+
resolvedArgs.push(args.addInput("object", Inputs.ReceivingRef({
|
|
127
|
+
objectId: arg.Input.Object.Receiving.object_id,
|
|
128
|
+
version: arg.Input.Object.Receiving.sequence_number,
|
|
129
|
+
digest: arg.Input.Object.Receiving.digest
|
|
130
|
+
})));
|
|
131
|
+
break;
|
|
132
|
+
case "Ext":
|
|
133
|
+
const [kind, value] = arg.Input.Object.Ext.split(":");
|
|
134
|
+
switch (kind) {
|
|
135
|
+
case OBJECT_BY_ID_EXT:
|
|
136
|
+
case RECEIVING_BY_ID_EXT:
|
|
137
|
+
resolvedArgs.push(args.addInput("object", {
|
|
138
|
+
$kind: "UnresolvedObject",
|
|
139
|
+
UnresolvedObject: { objectId: value }
|
|
140
|
+
}));
|
|
141
|
+
break;
|
|
142
|
+
case OBJECT_BY_TYPE_EXT: throw new PASClientError(`There are no supported object by type arguments in this client.`);
|
|
143
|
+
default: throw new PASClientError(`Unknown external object argument: ${kind}`);
|
|
144
|
+
}
|
|
145
|
+
break;
|
|
146
|
+
default: throw new PASClientError(`Not supported object argument: ${JSON.stringify(arg.Input.Object)}`);
|
|
147
|
+
}
|
|
148
|
+
else if (arg.Input.Ext) resolvedArgs.push(resolveRawPasRequest(args, {
|
|
149
|
+
namespace: arg.Input.Ext[0],
|
|
150
|
+
value: arg.Input.Ext[1]
|
|
151
|
+
}));
|
|
152
|
+
else throw new PASClientError(`Unsupported input kind: ${arg.Input.$kind}`);
|
|
153
|
+
const typeArgs = [];
|
|
154
|
+
for (const typeArg of command.type_arguments) typeArgs.push(normalizeStructTag(typeArg).toString());
|
|
155
|
+
if (!command.module_name || !command.function) throw new PASClientError("Module name or function name is missing from the on-chain policy. This means that the issuer has not set up the policy correctly.");
|
|
156
|
+
return TransactionCommands.MoveCall({
|
|
157
|
+
package: command.package_id,
|
|
158
|
+
module: command.module_name,
|
|
159
|
+
function: command.function,
|
|
160
|
+
arguments: resolvedArgs,
|
|
161
|
+
typeArguments: typeArgs.length > 0 ? typeArgs : []
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
function resolveRawPasRequest(args, extInput) {
|
|
165
|
+
if (!extInput.namespace.endsWith("templates::PAS")) throw new PASClientError(`Unsupported namespace: ${extInput.namespace}`);
|
|
166
|
+
switch (extInput.value) {
|
|
167
|
+
case "request":
|
|
168
|
+
if (!args.request) throw new PASClientError(`Request is not set in the context.`);
|
|
169
|
+
return args.request;
|
|
170
|
+
case "policy":
|
|
171
|
+
if (!args.policy) throw new PASClientError(`Policy is not set in the context.`);
|
|
172
|
+
return args.policy;
|
|
173
|
+
case "sender_account":
|
|
174
|
+
if (!args.senderAccount) throw new PASClientError(`Sender account is not set in the context.`);
|
|
175
|
+
return args.senderAccount;
|
|
176
|
+
case "receiver_account":
|
|
177
|
+
if (!args.receiverAccount) throw new PASClientError(`Receiver account is not set in the context.`);
|
|
178
|
+
return args.receiverAccount;
|
|
179
|
+
default: throw new PASClientError(`Unknown pas request: ${extInput.value}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
//#endregion
|
|
184
|
+
export { buildMoveCallCommandFromTemplate, collectTemplateObjectIds, getCommandFromTemplate, getRequiredApprovals };
|
|
185
|
+
//# sourceMappingURL=resolution.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolution.mjs","names":[],"sources":["../src/resolution.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { SuiClientTypes } from '@mysten/sui/client';\nimport { Inputs, TransactionCommands } from '@mysten/sui/transactions';\nimport type { Argument, CallArg, Command as SdkCommand } from '@mysten/sui/transactions';\nimport { normalizeStructTag } from '@mysten/sui/utils';\n\nimport { TypeName } from './contracts/pas/deps/std/type_name.js';\nimport { Policy } from './contracts/pas/policy.js';\nimport { Command, MoveCall } from './contracts/ptb/ptb.js';\nimport { PASClientError } from './error.js';\nimport { Field } from './contracts/sui/dynamic_field.js';\n\nconst OBJECT_BY_ID_EXT = 'object_by_id';\nconst OBJECT_BY_TYPE_EXT = 'object_by_type';\nconst RECEIVING_BY_ID_EXT = 'receiving_by_id';\n\ntype ParsedTemplateCommand = ReturnType<typeof parseCommand>;\n\n/**\n * Extracts all object IDs referenced by template commands, regardless of\n * how they are specified (fully resolved refs, shared refs, or ext lookups).\n */\nexport function collectTemplateObjectIds(commands: ParsedTemplateCommand[]): Set<string> {\n\tconst ids = new Set<string>();\n\tfor (const cmd of commands) {\n\t\tfor (const arg of cmd.arguments) {\n\t\t\tconst obj = arg.Input?.Object;\n\t\t\tif (!obj) continue;\n\n\t\t\tswitch (obj.$kind) {\n\t\t\t\tcase 'ImmOrOwnedObject':\n\t\t\t\t\tids.add(obj.ImmOrOwnedObject.object_id);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'SharedObject':\n\t\t\t\t\tids.add(obj.SharedObject.object_id);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'Receiving':\n\t\t\t\t\tids.add(obj.Receiving.object_id);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'Ext': {\n\t\t\t\t\tconst [kind, value] = obj.Ext.split(':');\n\t\t\t\t\tswitch (kind) {\n\t\t\t\t\t\tcase OBJECT_BY_ID_EXT:\n\t\t\t\t\t\tcase RECEIVING_BY_ID_EXT:\n\t\t\t\t\t\t\tids.add(value);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tthrow new PASClientError(`Unsupported external object kind: ${kind}`);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new PASClientError(\n\t\t\t\t\t\t'Invariant violation: unhandled variant in `collectTemplateObjectIds`',\n\t\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\treturn ids;\n}\n/**\n * Supported PAS action types that can be resolved via Policies.\n */\nexport type PASActionType = 'send_funds' | 'unlock_funds' | 'clawback_funds';\n\n/**\n * Parses the Policy object to extract the required approval type names for a given action.\n *\n * The Policy's `required_approvals` is a `VecMap<String, VecSet<TypeName>>` where:\n * - Key is the action name (e.g., \"send_funds\")\n * - Value is a set of approval TypeNames that must be satisfied\n *\n * @param policyObject - The Policy object fetched with content\n * @returns The list of approval TypeName strings for the given action, or undefined if not found\n */\nexport function getRequiredApprovals(\n\tpolicyObject: SuiClientTypes.Object<{ content: true }>,\n\tactionType: PASActionType,\n): string[] | undefined {\n\tconst policy = Policy.parse(policyObject.content);\n\n\tconst entry = policy.required_approvals.contents.find((e) => e.key === actionType);\n\n\tif (!entry) return undefined;\n\n\treturn entry.value.contents.map((tn) => tn.name);\n}\n\n/**\n * Parses a Command from a Template dynamic field object.\n *\n * Each Template DF is a `Field<TypeName, Command>` where:\n * - TypeName is the approval type (e.g., the `with_defining_ids` of `TransferApproval`)\n * - Command is the move call instruction to execute for that approval\n *\n * @param templateDF - The Template DF object fetched with content\n * @returns The parsed Command, or undefined if parsing fails\n */\nexport function getCommandFromTemplate(\n\ttemplate: SuiClientTypes.Object<{ content: true }>,\n): ParsedTemplateCommand {\n\tconst df = Field(TypeName, Command).parse(template.content);\n\treturn parseCommand(df.value);\n}\n\nfunction parseCommand([key, cmd]: ReturnType<typeof Command.parse>) {\n\t// Support only `Command` for now.\n\tif (key !== 0) throw new PASClientError(`Unknown command type: ${key}`);\n\n\t// TODO: switch to support more commands like `TransferObjects` etc.\n\treturn MoveCall.parse(new Uint8Array(cmd));\n}\n\n// ---------------------------------------------------------------------------\n// Command builder (for use with TransactionDataBuilder / replaceCommand)\n// ---------------------------------------------------------------------------\n\n/**\n * Arguments for building a MoveCall Command from a template.\n * Used by the intent resolver which works directly with TransactionDataBuilder.\n */\ninterface RawCommandBuildArgs {\n\t/** Adds an input to the parent transaction and returns the Argument ref. */\n\taddInput: (type: 'object' | 'pure', arg: CallArg) => Argument;\n\t/** The sender account argument (already resolved) */\n\tsenderAccount?: Argument;\n\t/** The receiver account argument (already resolved) */\n\treceiverAccount?: Argument;\n\t/** The policy argument (already resolved) */\n\tpolicy?: Argument;\n\t/** The request argument (already resolved) */\n\trequest?: Argument;\n}\n\n/**\n * Builds a `Command` (TransactionCommands.MoveCall) from a parsed template command,\n * suitable for use with `transactionData.replaceCommand()`.\n *\n * Resolves template argument placeholders (pas:request, pas:policy, etc.) into\n * concrete Argument references, and converts object/pure inputs via the provided\n * `addInput` callback.\n *\n * @param command - The parsed MoveCall from a template object\n * @param args - The resolved arguments and addInput helper\n * @param commandOffset - Absolute PTB index where the first template command will\n * land. Raw `Result` and `NestedResult` values from the on-chain BCS are\n * template-relative (i.e. `Result(0)` means \"first command in this template\").\n * We rebase them by adding this offset so they point at the correct position\n * in the final transaction.\n * @returns A Command object ready for `replaceCommand`\n */\nexport function buildMoveCallCommandFromTemplate(\n\tcommand: ParsedTemplateCommand,\n\targs: RawCommandBuildArgs,\n\tcommandOffset: number,\n): SdkCommand {\n\tconst resolvedArgs: Argument[] = [];\n\n\tfor (const arg of command.arguments) {\n\t\tif (arg.Ext) throw new PASClientError(`There are no supported ext arguments in this client.`);\n\t\telse if (arg.GasCoin) throw new PASClientError(`Gas coin is not supported in PAS client.`);\n\t\telse if (arg.NestedResult != null)\n\t\t\tresolvedArgs.push({\n\t\t\t\t$kind: 'NestedResult',\n\t\t\t\tNestedResult: [arg.NestedResult[0] + commandOffset, arg.NestedResult[1]],\n\t\t\t});\n\t\telse if (arg.Result != null)\n\t\t\tresolvedArgs.push({ $kind: 'Result', Result: arg.Result + commandOffset });\n\t\telse if (arg.Input) {\n\t\t\tif (arg.Input.Pure)\n\t\t\t\tresolvedArgs.push(args.addInput('pure', Inputs.Pure(new Uint8Array(arg.Input.Pure))));\n\t\t\telse if (arg.Input.Object) {\n\t\t\t\tswitch (arg.Input.Object.$kind) {\n\t\t\t\t\tcase 'ImmOrOwnedObject':\n\t\t\t\t\t\tresolvedArgs.push(\n\t\t\t\t\t\t\targs.addInput(\n\t\t\t\t\t\t\t\t'object',\n\t\t\t\t\t\t\t\tInputs.ObjectRef({\n\t\t\t\t\t\t\t\t\tobjectId: arg.Input.Object.ImmOrOwnedObject.object_id,\n\t\t\t\t\t\t\t\t\tversion: arg.Input.Object.ImmOrOwnedObject.sequence_number,\n\t\t\t\t\t\t\t\t\tdigest: arg.Input.Object.ImmOrOwnedObject.digest,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'SharedObject':\n\t\t\t\t\t\tresolvedArgs.push(\n\t\t\t\t\t\t\targs.addInput(\n\t\t\t\t\t\t\t\t'object',\n\t\t\t\t\t\t\t\tInputs.SharedObjectRef({\n\t\t\t\t\t\t\t\t\tobjectId: arg.Input.Object.SharedObject.object_id,\n\t\t\t\t\t\t\t\t\tinitialSharedVersion: arg.Input.Object.SharedObject.initial_shared_version,\n\t\t\t\t\t\t\t\t\tmutable: arg.Input.Object.SharedObject.is_mutable,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'Receiving':\n\t\t\t\t\t\tresolvedArgs.push(\n\t\t\t\t\t\t\targs.addInput(\n\t\t\t\t\t\t\t\t'object',\n\t\t\t\t\t\t\t\tInputs.ReceivingRef({\n\t\t\t\t\t\t\t\t\tobjectId: arg.Input.Object.Receiving.object_id,\n\t\t\t\t\t\t\t\t\tversion: arg.Input.Object.Receiving.sequence_number,\n\t\t\t\t\t\t\t\t\tdigest: arg.Input.Object.Receiving.digest,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'Ext':\n\t\t\t\t\t\tconst [kind, value] = arg.Input.Object.Ext.split(':');\n\n\t\t\t\t\t\tswitch (kind) {\n\t\t\t\t\t\t\tcase OBJECT_BY_ID_EXT:\n\t\t\t\t\t\t\tcase RECEIVING_BY_ID_EXT:\n\t\t\t\t\t\t\t\tresolvedArgs.push(\n\t\t\t\t\t\t\t\t\targs.addInput('object', {\n\t\t\t\t\t\t\t\t\t\t$kind: 'UnresolvedObject',\n\t\t\t\t\t\t\t\t\t\tUnresolvedObject: { objectId: value },\n\t\t\t\t\t\t\t\t\t} as CallArg),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase OBJECT_BY_TYPE_EXT:\n\t\t\t\t\t\t\t\tthrow new PASClientError(\n\t\t\t\t\t\t\t\t\t`There are no supported object by type arguments in this client.`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tthrow new PASClientError(`Unknown external object argument: ${kind}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthrow new PASClientError(\n\t\t\t\t\t\t\t`Not supported object argument: ${JSON.stringify(arg.Input.Object)}`,\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else if (arg.Input.Ext) {\n\t\t\t\tresolvedArgs.push(\n\t\t\t\t\tresolveRawPasRequest(args, {\n\t\t\t\t\t\tnamespace: arg.Input.Ext[0],\n\t\t\t\t\t\tvalue: arg.Input.Ext[1],\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthrow new PASClientError(`Unsupported input kind: ${arg.Input.$kind}`);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst typeArgs: string[] = [];\n\tfor (const typeArg of command.type_arguments)\n\t\ttypeArgs.push(normalizeStructTag(typeArg).toString());\n\n\tif (!command.module_name || !command.function)\n\t\tthrow new PASClientError(\n\t\t\t'Module name or function name is missing from the on-chain policy. This means that the issuer has not set up the policy correctly.',\n\t\t);\n\n\treturn TransactionCommands.MoveCall({\n\t\tpackage: command.package_id,\n\t\tmodule: command.module_name,\n\t\tfunction: command.function,\n\t\targuments: resolvedArgs,\n\t\ttypeArguments: typeArgs.length > 0 ? typeArgs : [],\n\t});\n}\n\nfunction resolveRawPasRequest(\n\targs: RawCommandBuildArgs,\n\textInput: { namespace: string; value: string },\n): Argument {\n\tif (!extInput.namespace.endsWith('templates::PAS'))\n\t\tthrow new PASClientError(`Unsupported namespace: ${extInput.namespace}`);\n\n\tswitch (extInput.value) {\n\t\tcase 'request':\n\t\t\tif (!args.request) throw new PASClientError(`Request is not set in the context.`);\n\t\t\treturn args.request;\n\t\tcase 'policy':\n\t\t\tif (!args.policy) throw new PASClientError(`Policy is not set in the context.`);\n\t\t\treturn args.policy;\n\t\tcase 'sender_account':\n\t\t\tif (!args.senderAccount)\n\t\t\t\tthrow new PASClientError(`Sender account is not set in the context.`);\n\t\t\treturn args.senderAccount;\n\t\tcase 'receiver_account':\n\t\t\tif (!args.receiverAccount)\n\t\t\t\tthrow new PASClientError(`Receiver account is not set in the context.`);\n\t\t\treturn args.receiverAccount;\n\t\tdefault:\n\t\t\tthrow new PASClientError(`Unknown pas request: ${extInput.value}`);\n\t}\n}\n"],"mappings":"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"}
|
package/dist/types.d.mts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ClientWithCoreApi } from "@mysten/sui/client";
|
|
2
|
+
|
|
3
|
+
//#region src/types.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Configuration for the PAS package on a specific network
|
|
7
|
+
*/
|
|
8
|
+
interface PASPackageConfig {
|
|
9
|
+
/** The package ID of the PAS package */
|
|
10
|
+
packageId: string;
|
|
11
|
+
/** The namespace ID of the PAS package */
|
|
12
|
+
namespaceId: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Configuration for the PAS client
|
|
16
|
+
*/
|
|
17
|
+
interface PASClientConfig {
|
|
18
|
+
/** The Sui client to use */
|
|
19
|
+
suiClient: ClientWithCoreApi;
|
|
20
|
+
/** The package configuration (if network is not provided or supported) */
|
|
21
|
+
packageConfig?: PASPackageConfig;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Options for creating a PAS client plugin
|
|
25
|
+
*/
|
|
26
|
+
interface PASOptions<Name extends string = 'pas'> {
|
|
27
|
+
/** The name of the plugin */
|
|
28
|
+
name?: Name;
|
|
29
|
+
/** The package configuration */
|
|
30
|
+
packageConfig?: PASPackageConfig;
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { PASClientConfig, PASOptions, PASPackageConfig };
|
|
34
|
+
//# sourceMappingURL=types.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.mts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":";;;;;;AAQA;AAUiB,UAVA,gBAAA,CAYL;EAQK;;;;;;;;UAVA,eAAA;;aAEL;;kBAEK;;;;;UAMA;;SAET;;kBAES"}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mysten/pas",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Permissioned Assets Standard SDK",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"author": "Mysten Labs <build@mystenlabs.com>",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "./dist/index.mjs",
|
|
10
|
+
"types": "./dist/index.d.mts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.mts",
|
|
14
|
+
"import": "./dist/index.mjs",
|
|
15
|
+
"default": "./dist/index.mjs"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"sideEffects": false,
|
|
19
|
+
"files": [
|
|
20
|
+
"CHANGELOG.md",
|
|
21
|
+
"dist",
|
|
22
|
+
"src"
|
|
23
|
+
],
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=18"
|
|
26
|
+
},
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/MystenLabs/ts-sdks.git"
|
|
30
|
+
},
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/mystenlabs/ts-sdks/issues"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"clean": "rm -rf tsconfig.tsbuildinfo ./dist",
|
|
36
|
+
"build": "rm -rf dist && tsc --noEmit && tsdown",
|
|
37
|
+
"test": "NODE_OPTIONS='--expose-gc' vitest run",
|
|
38
|
+
"test:e2e": "vitest run e2e",
|
|
39
|
+
"codegen": "sui-ts-codegen generate && pnpm lint:fix",
|
|
40
|
+
"prettier:check": "prettier -c --ignore-unknown .",
|
|
41
|
+
"prettier:fix": "prettier -w --ignore-unknown .",
|
|
42
|
+
"oxlint:check": "oxlint .",
|
|
43
|
+
"oxlint:fix": "oxlint --fix",
|
|
44
|
+
"lint": "pnpm run oxlint:check && pnpm run prettier:check",
|
|
45
|
+
"lint:fix": "pnpm run oxlint:fix && pnpm run prettier:fix"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@mysten/codegen": "workspace:^",
|
|
49
|
+
"@mysten/sui": "workspace:^",
|
|
50
|
+
"@types/node": "^25.0.8",
|
|
51
|
+
"ts-retry-promise": "^0.8.1",
|
|
52
|
+
"tsdown": "0.20.0-beta.1",
|
|
53
|
+
"typescript": "^5.9.3",
|
|
54
|
+
"vitest": "^4.0.17"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"@mysten/sui": "workspace:^"
|
|
58
|
+
}
|
|
59
|
+
}
|
package/src/client.ts
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
// Copyright (c) Mysten Labs, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { ClientWithCoreApi } from '@mysten/sui/client';
|
|
5
|
+
|
|
6
|
+
import { TESTNET_PAS_PACKAGE_CONFIG } from './constants.js';
|
|
7
|
+
import {
|
|
8
|
+
deriveAccountAddress,
|
|
9
|
+
derivePolicyAddress,
|
|
10
|
+
deriveTemplateAddress,
|
|
11
|
+
deriveTemplateRegistryAddress,
|
|
12
|
+
} from './derivation.js';
|
|
13
|
+
import { PASClientError } from './error.js';
|
|
14
|
+
import {
|
|
15
|
+
accountForAddressIntent,
|
|
16
|
+
sendBalanceIntent,
|
|
17
|
+
unlockBalanceIntent,
|
|
18
|
+
unlockUnrestrictedBalanceIntent,
|
|
19
|
+
} from './intents.js';
|
|
20
|
+
import type { PASClientConfig, PASOptions, PASPackageConfig } from './types.js';
|
|
21
|
+
|
|
22
|
+
export function pas<const Name extends string = 'pas'>({
|
|
23
|
+
packageConfig,
|
|
24
|
+
name = 'pas' as Name,
|
|
25
|
+
...options
|
|
26
|
+
}: PASOptions<Name> = {}): {
|
|
27
|
+
name: Name;
|
|
28
|
+
register: (client: ClientWithCoreApi) => PASClient;
|
|
29
|
+
} {
|
|
30
|
+
return {
|
|
31
|
+
name,
|
|
32
|
+
register: (client: ClientWithCoreApi) =>
|
|
33
|
+
new PASClient({ packageConfig, suiClient: client, ...options }),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export class PASClient {
|
|
38
|
+
#packageConfig: PASPackageConfig;
|
|
39
|
+
|
|
40
|
+
constructor(config: PASClientConfig) {
|
|
41
|
+
const network = config.suiClient.network;
|
|
42
|
+
|
|
43
|
+
// Mainnet: no custom config allowed (avoid accidental republishing).
|
|
44
|
+
if (network === 'mainnet' && config.packageConfig) {
|
|
45
|
+
throw new PASClientError(
|
|
46
|
+
'Custom package configuration is not allowed on mainnet. Use the built-in mainnet config when mainnet is supported.',
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (config.packageConfig) {
|
|
51
|
+
this.#packageConfig = config.packageConfig;
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!network || (network !== 'mainnet' && network !== 'testnet')) {
|
|
56
|
+
throw new PASClientError(
|
|
57
|
+
'PAS client requires a known network (mainnet, testnet) or a custom package configuration.',
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// TODO: Remove when we add mainnet data
|
|
62
|
+
if (network === 'mainnet') {
|
|
63
|
+
throw new PASClientError('Mainnet is not supported yet.');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.#packageConfig = TESTNET_PAS_PACKAGE_CONFIG;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Get the package configuration
|
|
71
|
+
*/
|
|
72
|
+
getPackageConfig() {
|
|
73
|
+
return this.#packageConfig;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Derives the account address for a given owner address.
|
|
78
|
+
*
|
|
79
|
+
* @param owner - The owner address (can be a user address or object address)
|
|
80
|
+
* @returns The derived account object ID
|
|
81
|
+
*/
|
|
82
|
+
deriveAccountAddress(owner: string): string {
|
|
83
|
+
return deriveAccountAddress(owner, this.#packageConfig);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Derives the policy address for a given asset type T.
|
|
88
|
+
* By default wraps with `Balance<T>` to match the on-chain convention.
|
|
89
|
+
*
|
|
90
|
+
* @param assetType - The full type of the asset (e.g., "0x2::sui::SUI")
|
|
91
|
+
* @returns The derived policy object ID
|
|
92
|
+
*/
|
|
93
|
+
derivePolicyAddress(assetType: string): string {
|
|
94
|
+
return derivePolicyAddress(assetType, this.#packageConfig);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Derives the templates object address for a given package configuration.
|
|
99
|
+
*
|
|
100
|
+
* @returns The derived templates object ID
|
|
101
|
+
*/
|
|
102
|
+
deriveTemplateRegistryAddress(): string {
|
|
103
|
+
return deriveTemplateRegistryAddress(this.#packageConfig);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Derives the template DF address for a given approval type name.
|
|
108
|
+
*
|
|
109
|
+
* @param approvalTypeName - The fully qualified approval type name
|
|
110
|
+
* @returns The derived dynamic field object ID
|
|
111
|
+
*/
|
|
112
|
+
deriveTemplateAddress(approvalTypeName: string): string {
|
|
113
|
+
return deriveTemplateAddress(this.deriveTemplateRegistryAddress(), approvalTypeName);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Intent-based transaction builders. Each method returns a synchronous closure
|
|
118
|
+
* that registers a `$Intent` placeholder in the transaction. The actual PTB commands
|
|
119
|
+
* are resolved lazily at `tx.build()` time via the shared PAS resolver plugin.
|
|
120
|
+
*/
|
|
121
|
+
get call() {
|
|
122
|
+
return {
|
|
123
|
+
/**
|
|
124
|
+
* Creates a transfer funds intent. At build time, it auto-resolves the issuer's
|
|
125
|
+
* approval template commands by reading the Policy and Templates objects on-chain.
|
|
126
|
+
* If the recipient account does not exist, it will be created and shared automatically.
|
|
127
|
+
*
|
|
128
|
+
* @param options - Transfer options
|
|
129
|
+
* @param options.from - The sender's address (owner of the source account)
|
|
130
|
+
* @param options.to - The receiver's address (owner of the destination account)
|
|
131
|
+
* @param options.amount - The amount to transfer
|
|
132
|
+
* @param options.assetType - The full asset type (e.g., "0x2::sui::SUI")
|
|
133
|
+
* @returns A sync closure `(tx: Transaction) => TransactionResult`
|
|
134
|
+
*/
|
|
135
|
+
sendBalance: sendBalanceIntent(this.#packageConfig),
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Creates an unlock balance intent. At build time, it resolves the issuer's
|
|
139
|
+
* approval template commands. This will fail if the issuer has not configured
|
|
140
|
+
* unlock approvals for the asset type.
|
|
141
|
+
*
|
|
142
|
+
* @param options - Unlock options
|
|
143
|
+
* @param options.from - The sender's address (owner of the source account)
|
|
144
|
+
* @param options.amount - The amount to unlock
|
|
145
|
+
* @param options.assetType - The full asset type (e.g., "0x2::sui::SUI")
|
|
146
|
+
* @returns A sync closure `(tx: Transaction) => TransactionResult`
|
|
147
|
+
*/
|
|
148
|
+
unlockBalance: unlockBalanceIntent(this.#packageConfig),
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Creates an unlock balance intent for unrestricted (non-managed) assets.
|
|
152
|
+
* Use this when no Policy exists for the asset type (e.g., SUI).
|
|
153
|
+
*
|
|
154
|
+
* @param options - Unlock options
|
|
155
|
+
* @param options.from - The sender's address (owner of the source account)
|
|
156
|
+
* @param options.amount - The amount to unlock
|
|
157
|
+
* @param options.assetType - The full asset type (e.g., "0x2::sui::SUI")
|
|
158
|
+
* @returns A sync closure `(tx: Transaction) => TransactionResult`
|
|
159
|
+
*/
|
|
160
|
+
unlockUnrestrictedBalance: unlockUnrestrictedBalanceIntent(this.#packageConfig),
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Returns a account object for the given address. At build time, if the account
|
|
164
|
+
* already exists on-chain it resolves to an object reference; otherwise it
|
|
165
|
+
* creates the account and shares it.
|
|
166
|
+
*
|
|
167
|
+
* @param owner - The owner address
|
|
168
|
+
* @returns A sync closure `(tx: Transaction) => TransactionResult` (the account)
|
|
169
|
+
*/
|
|
170
|
+
accountForAddress: accountForAddressIntent(this.#packageConfig),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
}
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Copyright (c) Mysten Labs, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { PASPackageConfig } from './types.js';
|
|
5
|
+
|
|
6
|
+
export const TESTNET_PAS_PACKAGE_CONFIG: PASPackageConfig = {
|
|
7
|
+
packageId: '0x7e77592474ea9759b46ca5c6515ed4840952cd80d60ee54a1614382811d46730',
|
|
8
|
+
namespaceId: '0xf7c77ac8bbbdf47f7b1cf8ac8aa489cfc4dff25847f3e2e1db53bde5c454be2b',
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// TODO: also update `client.ts` when adding these variables
|
|
12
|
+
export const MAINNET_PAS_PACKAGE_CONFIG: PASPackageConfig = {
|
|
13
|
+
packageId: '', // TODO: Replace with actual mainnet package ID
|
|
14
|
+
namespaceId: '', // TODO: Replace with actual mainnet namespace ID
|
|
15
|
+
};
|