@kairoguard/sdk 0.0.8 → 0.0.9
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/dist/backend.d.ts +11 -0
- package/dist/backend.js +3 -0
- package/dist/cli.js +58 -6
- package/dist/client.d.ts +15 -0
- package/dist/client.js +102 -10
- package/dist/policy-templates.d.ts +16 -0
- package/dist/policy-templates.js +56 -0
- package/package.json +1 -1
package/dist/backend.d.ts
CHANGED
|
@@ -232,6 +232,16 @@ export interface PolicyDetailsResponse {
|
|
|
232
232
|
policy?: Record<string, unknown>;
|
|
233
233
|
error?: string;
|
|
234
234
|
}
|
|
235
|
+
export interface ReaffirmPolicyBindingParams {
|
|
236
|
+
bindingObjectId: string;
|
|
237
|
+
registryObjectId?: string;
|
|
238
|
+
}
|
|
239
|
+
export interface ReaffirmPolicyBindingResponse {
|
|
240
|
+
success: boolean;
|
|
241
|
+
digest: string;
|
|
242
|
+
activeVersionObjectId?: string;
|
|
243
|
+
error?: string;
|
|
244
|
+
}
|
|
235
245
|
export interface DWalletFullResponse {
|
|
236
246
|
success: boolean;
|
|
237
247
|
dWallet?: unknown;
|
|
@@ -273,6 +283,7 @@ export declare class BackendClient {
|
|
|
273
283
|
getGovernance(governanceId: string): Promise<GovernanceGetResponse>;
|
|
274
284
|
getGovernanceProposal(proposalId: string): Promise<GovernanceProposalGetResponse>;
|
|
275
285
|
getPolicy(policyObjectId: string): Promise<PolicyDetailsResponse>;
|
|
286
|
+
reaffirmPolicyBinding(params: ReaffirmPolicyBindingParams): Promise<ReaffirmPolicyBindingResponse>;
|
|
276
287
|
getDWalletFull(dWalletId: string): Promise<DWalletFullResponse>;
|
|
277
288
|
getSuiObject(objectId: string): Promise<SuiObjectResponse>;
|
|
278
289
|
policySign(params: Record<string, unknown>): Promise<Record<string, unknown>>;
|
package/dist/backend.js
CHANGED
|
@@ -89,6 +89,9 @@ export class BackendClient {
|
|
|
89
89
|
async getPolicy(policyObjectId) {
|
|
90
90
|
return this.request("GET", `/api/policies/${policyObjectId}`);
|
|
91
91
|
}
|
|
92
|
+
async reaffirmPolicyBinding(params) {
|
|
93
|
+
return this.request("POST", "/api/policy/binding/reaffirm", params);
|
|
94
|
+
}
|
|
92
95
|
async getDWalletFull(dWalletId) {
|
|
93
96
|
return this.request("GET", `/api/dwallet/full/${dWalletId}`);
|
|
94
97
|
}
|
package/dist/cli.js
CHANGED
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
|
+
import { createInterface } from "node:readline/promises";
|
|
6
|
+
import { stdin as input, stdout as output } from "node:process";
|
|
5
7
|
import { verifyAuditBundle } from "./auditBundle.js";
|
|
6
8
|
import { BackendClient, DEFAULT_BACKEND_URL } from "./backend.js";
|
|
7
9
|
import { KairoClient } from "./client.js";
|
|
10
|
+
import { POLICY_TEMPLATE_PRESETS, buildPolicyTemplatePayload } from "./policy-templates.js";
|
|
8
11
|
import { SKILL_MD, API_REFERENCE_MD, SDK_REFERENCE_MD } from "./skill-templates.js";
|
|
9
12
|
const CONFIG_DIR = join(homedir(), ".kairo");
|
|
10
13
|
const CONFIG_PATH = join(CONFIG_DIR, "config.json");
|
|
@@ -39,6 +42,9 @@ function flag(args, name) {
|
|
|
39
42
|
return undefined;
|
|
40
43
|
return args[idx + 1];
|
|
41
44
|
}
|
|
45
|
+
function hasFlag(args, name) {
|
|
46
|
+
return args.includes(name);
|
|
47
|
+
}
|
|
42
48
|
function requireFlag(args, name, label) {
|
|
43
49
|
const v = flag(args, name);
|
|
44
50
|
if (!v) {
|
|
@@ -47,6 +53,24 @@ function requireFlag(args, name, label) {
|
|
|
47
53
|
}
|
|
48
54
|
return v;
|
|
49
55
|
}
|
|
56
|
+
async function promptPolicyTemplateId() {
|
|
57
|
+
const rl = createInterface({ input, output });
|
|
58
|
+
try {
|
|
59
|
+
console.log("Choose a default policy template:");
|
|
60
|
+
console.log(` 1) ${POLICY_TEMPLATE_PRESETS["tpl-1"].label}`);
|
|
61
|
+
console.log(` 2) ${POLICY_TEMPLATE_PRESETS["tpl-2"].label}`);
|
|
62
|
+
console.log(` 3) ${POLICY_TEMPLATE_PRESETS["tpl-3"].label}`);
|
|
63
|
+
const answer = (await rl.question("Template [1/2/3] (default 2): ")).trim();
|
|
64
|
+
if (answer === "1")
|
|
65
|
+
return "tpl-1";
|
|
66
|
+
if (answer === "3")
|
|
67
|
+
return "tpl-3";
|
|
68
|
+
return "tpl-2";
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
rl.close();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
50
74
|
// ── Commands ────────────────────────────────────────────────────────────────
|
|
51
75
|
async function cmdInit(args) {
|
|
52
76
|
const apiKey = args[0];
|
|
@@ -88,17 +112,41 @@ async function cmdWalletCreate(args) {
|
|
|
88
112
|
}
|
|
89
113
|
const policyId = flag(args, "--policy-id");
|
|
90
114
|
const stableId = flag(args, "--stable-id");
|
|
115
|
+
const autoProvision = hasFlag(args, "--auto-provision");
|
|
91
116
|
const cfg = requireConfig();
|
|
117
|
+
let resolvedPolicyId = policyId;
|
|
118
|
+
if (autoProvision && !resolvedPolicyId) {
|
|
119
|
+
const templateId = await promptPolicyTemplateId();
|
|
120
|
+
const templatePayload = buildPolicyTemplatePayload(templateId);
|
|
121
|
+
const stable = stableId ?? `agent-policy-${Date.now()}`;
|
|
122
|
+
const client = getClient();
|
|
123
|
+
const created = await client.createPolicyV4({
|
|
124
|
+
stableId: stable,
|
|
125
|
+
version: "1.0.0",
|
|
126
|
+
allowNamespaces: templatePayload.allowNamespaces,
|
|
127
|
+
rules: templatePayload.rules,
|
|
128
|
+
});
|
|
129
|
+
if (!created.success || !created.policyObjectId?.startsWith("0x")) {
|
|
130
|
+
throw new Error(created.error ?? "Failed to create default policy from template");
|
|
131
|
+
}
|
|
132
|
+
await client.registerPolicyVersionFromPolicy({ policyObjectId: created.policyObjectId });
|
|
133
|
+
resolvedPolicyId = created.policyObjectId;
|
|
134
|
+
console.log(`Created + registered policy ${resolvedPolicyId} using ${templatePayload.template.id}.`);
|
|
135
|
+
}
|
|
92
136
|
const kairo = new KairoClient({
|
|
93
137
|
apiKey: cfg.apiKey,
|
|
94
138
|
backendUrl: cfg.backendUrl,
|
|
95
139
|
});
|
|
96
140
|
const wallet = await kairo.createWallet({
|
|
97
141
|
curve: curveRaw,
|
|
98
|
-
policyObjectId:
|
|
142
|
+
policyObjectId: resolvedPolicyId,
|
|
99
143
|
stableId,
|
|
100
144
|
});
|
|
101
145
|
console.log(JSON.stringify(wallet, null, 2));
|
|
146
|
+
if (!resolvedPolicyId) {
|
|
147
|
+
console.log("Wallet created but not provisioned. To show it in dashboard policies, run: " +
|
|
148
|
+
`kairo vault-provision --wallet-id ${wallet.walletId} --policy-id <policyObjectId> [--stable-id <id>]`);
|
|
149
|
+
}
|
|
102
150
|
}
|
|
103
151
|
async function cmdRegister(args) {
|
|
104
152
|
const label = requireFlag(args, "--label", "name");
|
|
@@ -141,9 +189,13 @@ async function cmdVaultStatus(args) {
|
|
|
141
189
|
async function cmdVaultProvision(args) {
|
|
142
190
|
const walletId = requireFlag(args, "--wallet-id", "dwalletId");
|
|
143
191
|
const policyId = requireFlag(args, "--policy-id", "objectId");
|
|
144
|
-
const stableId =
|
|
145
|
-
const
|
|
146
|
-
const
|
|
192
|
+
const stableId = flag(args, "--stable-id");
|
|
193
|
+
const cfg = requireConfig();
|
|
194
|
+
const kairo = new KairoClient({
|
|
195
|
+
apiKey: cfg.apiKey,
|
|
196
|
+
backendUrl: cfg.backendUrl,
|
|
197
|
+
});
|
|
198
|
+
const res = await kairo.provision(walletId, policyId, stableId);
|
|
147
199
|
console.log(JSON.stringify(res, null, 2));
|
|
148
200
|
}
|
|
149
201
|
async function cmdReceiptMint(args) {
|
|
@@ -204,14 +256,14 @@ Setup:
|
|
|
204
256
|
|
|
205
257
|
Wallet & Policy:
|
|
206
258
|
health Server health check
|
|
207
|
-
wallet-create [--curve secp256k1|ed25519] [--policy-id <id>] [--stable-id <id>]
|
|
259
|
+
wallet-create [--curve secp256k1|ed25519] [--policy-id <id>] [--stable-id <id>] [--auto-provision]
|
|
208
260
|
Create a new dWallet via SDK DKG flow
|
|
209
261
|
register --label <name> Register new API key
|
|
210
262
|
policy-create --stable-id <id> --allow <addrs> Create policy
|
|
211
263
|
policy-register --policy-id <id> Register policy version
|
|
212
264
|
policy-details --policy-id <id> Get policy details
|
|
213
265
|
vault-status --wallet-id <id> Check vault registration
|
|
214
|
-
vault-provision --wallet-id <id> --policy-id <id> --stable-id <id>
|
|
266
|
+
vault-provision --wallet-id <id> --policy-id <id> [--stable-id <id>]
|
|
215
267
|
receipt-mint --policy-id <id> --binding-id <id> --destination <hex> --intent-hash <hex>
|
|
216
268
|
|
|
217
269
|
Utility:
|
package/dist/client.d.ts
CHANGED
|
@@ -153,6 +153,18 @@ export declare class KairoClient {
|
|
|
153
153
|
listWallets(): WalletInfo[];
|
|
154
154
|
/** Get a wallet from local key store by ID. */
|
|
155
155
|
getWallet(walletId: string): WalletInfo | null;
|
|
156
|
+
/**
|
|
157
|
+
* Provision an existing local wallet into the policy vault.
|
|
158
|
+
* Persists binding/policy metadata to local keystore.
|
|
159
|
+
*/
|
|
160
|
+
provision(walletId: string, policyObjectId: string, stableId?: string): Promise<{
|
|
161
|
+
bindingObjectId: string;
|
|
162
|
+
digest: string;
|
|
163
|
+
}>;
|
|
164
|
+
reaffirmBinding(walletId: string): Promise<{
|
|
165
|
+
digest: string;
|
|
166
|
+
activeVersionObjectId?: string;
|
|
167
|
+
}>;
|
|
156
168
|
/**
|
|
157
169
|
* Governance-first policy update: creates a new policy + version, then proposes
|
|
158
170
|
* a change for approvers. This method does NOT execute/reaffirm directly.
|
|
@@ -182,6 +194,9 @@ export declare class KairoClient {
|
|
|
182
194
|
private pollPresignStatus;
|
|
183
195
|
private pollSignStatus;
|
|
184
196
|
private mintPolicyReceipt;
|
|
197
|
+
private resolvePolicyVersion;
|
|
198
|
+
private isReaffirmRequiredError;
|
|
199
|
+
private requestSignWithReaffirmRetry;
|
|
185
200
|
private computeUserSignMessageWithExtensionFallback;
|
|
186
201
|
private rebuildSigningMaterialFromChain;
|
|
187
202
|
private resolveEvmRpcUrl;
|
package/dist/client.js
CHANGED
|
@@ -173,13 +173,8 @@ export class KairoClient {
|
|
|
173
173
|
// 10. Provision into vault (binding + registration) if policy is provided
|
|
174
174
|
let bindingObjectId;
|
|
175
175
|
if (opts?.policyObjectId) {
|
|
176
|
-
const provisionResult = await this.
|
|
177
|
-
|
|
178
|
-
policyObjectId: opts.policyObjectId,
|
|
179
|
-
stableId: opts.stableId ?? `agent-wallet-${walletId.slice(0, 8)}`,
|
|
180
|
-
});
|
|
181
|
-
bindingObjectId = provisionResult.bindingObjectId ?? undefined;
|
|
182
|
-
this.store.save({ ...record, bindingObjectId });
|
|
176
|
+
const provisionResult = await this.provision(walletId, opts.policyObjectId, opts.stableId);
|
|
177
|
+
bindingObjectId = provisionResult.bindingObjectId;
|
|
183
178
|
}
|
|
184
179
|
return {
|
|
185
180
|
walletId,
|
|
@@ -212,6 +207,44 @@ export class KairoClient {
|
|
|
212
207
|
createdAt: r.createdAt,
|
|
213
208
|
};
|
|
214
209
|
}
|
|
210
|
+
/**
|
|
211
|
+
* Provision an existing local wallet into the policy vault.
|
|
212
|
+
* Persists binding/policy metadata to local keystore.
|
|
213
|
+
*/
|
|
214
|
+
async provision(walletId, policyObjectId, stableId) {
|
|
215
|
+
const wallet = this.requireWalletRecord(walletId);
|
|
216
|
+
if (!policyObjectId?.startsWith("0x")) {
|
|
217
|
+
throw new Error("policyObjectId must be a valid 0x object id");
|
|
218
|
+
}
|
|
219
|
+
const result = await this.backend.provision({
|
|
220
|
+
dwalletObjectId: walletId,
|
|
221
|
+
policyObjectId,
|
|
222
|
+
stableId: stableId ?? `agent-wallet-${walletId.slice(0, 8)}`,
|
|
223
|
+
});
|
|
224
|
+
const bindingObjectId = String(result.bindingObjectId ?? "");
|
|
225
|
+
if (!bindingObjectId.startsWith("0x")) {
|
|
226
|
+
throw new Error("Provision succeeded but no bindingObjectId was returned");
|
|
227
|
+
}
|
|
228
|
+
this.store.save({
|
|
229
|
+
...wallet,
|
|
230
|
+
bindingObjectId,
|
|
231
|
+
policyObjectId,
|
|
232
|
+
});
|
|
233
|
+
return { bindingObjectId, digest: result.digest };
|
|
234
|
+
}
|
|
235
|
+
async reaffirmBinding(walletId) {
|
|
236
|
+
const wallet = this.requireWalletRecord(walletId);
|
|
237
|
+
if (!wallet.bindingObjectId?.startsWith("0x")) {
|
|
238
|
+
throw new Error("Wallet is missing bindingObjectId. Provision the wallet before reaffirming.");
|
|
239
|
+
}
|
|
240
|
+
const result = await this.backend.reaffirmPolicyBinding({
|
|
241
|
+
bindingObjectId: wallet.bindingObjectId,
|
|
242
|
+
});
|
|
243
|
+
return {
|
|
244
|
+
digest: result.digest,
|
|
245
|
+
activeVersionObjectId: result.activeVersionObjectId,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
215
248
|
/**
|
|
216
249
|
* Governance-first policy update: creates a new policy + version, then proposes
|
|
217
250
|
* a change for approvers. This method does NOT execute/reaffirm directly.
|
|
@@ -403,7 +436,8 @@ export class KairoClient {
|
|
|
403
436
|
if (!dWalletCapId) {
|
|
404
437
|
throw new Error("Wallet record is missing dWalletCapId. Recreate/provision this wallet before signing.");
|
|
405
438
|
}
|
|
406
|
-
const
|
|
439
|
+
const resolvedPolicyVersion = await this.resolvePolicyVersion(wallet, opts?.policyVersion);
|
|
440
|
+
const req = await this.requestSignWithReaffirmRetry(wallet, {
|
|
407
441
|
dWalletId: wallet.walletId,
|
|
408
442
|
dWalletCapId,
|
|
409
443
|
encryptedUserSecretKeyShareId: wallet.encryptedUserSecretKeyShareId ?? "",
|
|
@@ -414,7 +448,7 @@ export class KairoClient {
|
|
|
414
448
|
policyReceiptId,
|
|
415
449
|
policyBindingObjectId: wallet.bindingObjectId,
|
|
416
450
|
policyObjectId: wallet.policyObjectId,
|
|
417
|
-
policyVersion:
|
|
451
|
+
policyVersion: resolvedPolicyVersion,
|
|
418
452
|
ethTx: opts?.ethTx,
|
|
419
453
|
});
|
|
420
454
|
if (!req.success) {
|
|
@@ -627,7 +661,7 @@ export class KairoClient {
|
|
|
627
661
|
if (!wallet.policyObjectId || !wallet.bindingObjectId) {
|
|
628
662
|
throw new Error("Wallet is missing policy binding metadata. Ensure it is provisioned with policyObjectId and bindingObjectId.");
|
|
629
663
|
}
|
|
630
|
-
const
|
|
664
|
+
const mintOnce = () => this.backend.mintReceipt({
|
|
631
665
|
policyObjectId: wallet.policyObjectId,
|
|
632
666
|
bindingObjectId: wallet.bindingObjectId,
|
|
633
667
|
namespace: ctx.namespace,
|
|
@@ -638,6 +672,12 @@ export class KairoClient {
|
|
|
638
672
|
nativeValueHex: ctx.nativeValue.toString(16).padStart(64, "0"),
|
|
639
673
|
contextDataHex: ctx.contextDataHex ? stripHexPrefix(ctx.contextDataHex) : undefined,
|
|
640
674
|
});
|
|
675
|
+
let response = await mintOnce();
|
|
676
|
+
const initialError = String(response?.error ?? "");
|
|
677
|
+
if (response.success === false && this.isReaffirmRequiredError(initialError)) {
|
|
678
|
+
await this.reaffirmBinding(wallet.walletId);
|
|
679
|
+
response = await mintOnce();
|
|
680
|
+
}
|
|
641
681
|
if (response.success === false) {
|
|
642
682
|
throw new Error(String(response.error ?? "Failed to mint policy receipt"));
|
|
643
683
|
}
|
|
@@ -650,6 +690,38 @@ export class KairoClient {
|
|
|
650
690
|
}
|
|
651
691
|
return receiptId;
|
|
652
692
|
}
|
|
693
|
+
async resolvePolicyVersion(wallet, override) {
|
|
694
|
+
const explicit = String(override ?? "").trim();
|
|
695
|
+
if (explicit)
|
|
696
|
+
return explicit;
|
|
697
|
+
if (!wallet.policyObjectId?.startsWith("0x")) {
|
|
698
|
+
throw new Error("Wallet is missing policyObjectId. Provision the wallet before signing.");
|
|
699
|
+
}
|
|
700
|
+
const response = await this.backend.getPolicy(wallet.policyObjectId);
|
|
701
|
+
if (!response.success || !response.policy) {
|
|
702
|
+
throw new Error(response.error ?? "Failed to resolve policy details for signing");
|
|
703
|
+
}
|
|
704
|
+
const version = decodeMoveString(response.policy.version).trim();
|
|
705
|
+
if (!version) {
|
|
706
|
+
throw new Error("Policy version is missing on-chain. Pass policyVersion explicitly.");
|
|
707
|
+
}
|
|
708
|
+
return version;
|
|
709
|
+
}
|
|
710
|
+
isReaffirmRequiredError(err) {
|
|
711
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
712
|
+
return /requires confirmation/i.test(message) || /reaffirm/i.test(message);
|
|
713
|
+
}
|
|
714
|
+
async requestSignWithReaffirmRetry(wallet, payload) {
|
|
715
|
+
try {
|
|
716
|
+
return await this.backend.requestSign(payload);
|
|
717
|
+
}
|
|
718
|
+
catch (error) {
|
|
719
|
+
if (!this.isReaffirmRequiredError(error))
|
|
720
|
+
throw error;
|
|
721
|
+
await this.reaffirmBinding(wallet.walletId);
|
|
722
|
+
return this.backend.requestSign(payload);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
653
725
|
async computeUserSignMessageWithExtensionFallback(wallet, protocolParams, presignBytes, messageBytes) {
|
|
654
726
|
try {
|
|
655
727
|
return await createUserSignMessageWithPublicOutput(protocolParams, new Uint8Array(wallet.userPublicOutput), new Uint8Array(wallet.userSecretKeyShare), presignBytes, messageBytes, Hash.KECCAK256, SignatureAlgorithm.ECDSASecp256k1, Curve.SECP256K1);
|
|
@@ -733,6 +805,26 @@ function toBigInt(value) {
|
|
|
733
805
|
return BigInt(value);
|
|
734
806
|
return value.startsWith("0x") ? BigInt(value) : BigInt(value);
|
|
735
807
|
}
|
|
808
|
+
function decodeMoveString(value) {
|
|
809
|
+
if (typeof value === "string")
|
|
810
|
+
return value;
|
|
811
|
+
if (Array.isArray(value) && value.every((x) => Number.isInteger(x) && x >= 0 && x <= 255)) {
|
|
812
|
+
try {
|
|
813
|
+
return new TextDecoder().decode(Uint8Array.from(value));
|
|
814
|
+
}
|
|
815
|
+
catch {
|
|
816
|
+
return "";
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
if (value && typeof value === "object") {
|
|
820
|
+
const obj = value;
|
|
821
|
+
return (decodeMoveString(obj.bytes) ||
|
|
822
|
+
decodeMoveString(obj.data) ||
|
|
823
|
+
decodeMoveString(obj.value) ||
|
|
824
|
+
decodeMoveString(obj.fields));
|
|
825
|
+
}
|
|
826
|
+
return "";
|
|
827
|
+
}
|
|
736
828
|
function buildNormalizedEncryptedShare(fields) {
|
|
737
829
|
const { state } = normalizeMoveEnumState(fields.state);
|
|
738
830
|
const candidate = {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface PolicyTemplatePreset {
|
|
2
|
+
id: "tpl-1" | "tpl-2" | "tpl-3";
|
|
3
|
+
label: string;
|
|
4
|
+
singleTxUsd: number;
|
|
5
|
+
dailyLimitUsd: number;
|
|
6
|
+
}
|
|
7
|
+
export declare const POLICY_TEMPLATE_PRESETS: Record<PolicyTemplatePreset["id"], PolicyTemplatePreset>;
|
|
8
|
+
export declare function buildPolicyTemplatePayload(templateId: string): {
|
|
9
|
+
template: PolicyTemplatePreset;
|
|
10
|
+
allowNamespaces: number[];
|
|
11
|
+
rules: Array<{
|
|
12
|
+
ruleType: number;
|
|
13
|
+
namespace?: number;
|
|
14
|
+
params: string;
|
|
15
|
+
}>;
|
|
16
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export const POLICY_TEMPLATE_PRESETS = {
|
|
2
|
+
"tpl-1": {
|
|
3
|
+
id: "tpl-1",
|
|
4
|
+
label: "Conservative ($200/tx, $1k/day)",
|
|
5
|
+
singleTxUsd: 200,
|
|
6
|
+
dailyLimitUsd: 1_000,
|
|
7
|
+
},
|
|
8
|
+
"tpl-2": {
|
|
9
|
+
id: "tpl-2",
|
|
10
|
+
label: "Standard ($2k/tx, $10k/day)",
|
|
11
|
+
singleTxUsd: 2_000,
|
|
12
|
+
dailyLimitUsd: 10_000,
|
|
13
|
+
},
|
|
14
|
+
"tpl-3": {
|
|
15
|
+
id: "tpl-3",
|
|
16
|
+
label: "High-limit ($10k/tx, $50k/day)",
|
|
17
|
+
singleTxUsd: 10_000,
|
|
18
|
+
dailyLimitUsd: 50_000,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
function stripHexPrefix(value) {
|
|
22
|
+
return value.startsWith("0x") ? value.slice(2) : value;
|
|
23
|
+
}
|
|
24
|
+
function encodeU256(value) {
|
|
25
|
+
const big = typeof value === "bigint" ? value : BigInt(value);
|
|
26
|
+
return `0x${big.toString(16).padStart(64, "0")}`;
|
|
27
|
+
}
|
|
28
|
+
function encodeMaxNativeRule(maxNativeBaseUnits) {
|
|
29
|
+
return encodeU256(maxNativeBaseUnits);
|
|
30
|
+
}
|
|
31
|
+
function encodeDailyPeriodLimitRule(maxDailyBaseUnits) {
|
|
32
|
+
const periodTypeDaily = 1;
|
|
33
|
+
return `0x${periodTypeDaily.toString(16).padStart(2, "0")}${stripHexPrefix(encodeU256(maxDailyBaseUnits))}`;
|
|
34
|
+
}
|
|
35
|
+
export function buildPolicyTemplatePayload(templateId) {
|
|
36
|
+
const template = POLICY_TEMPLATE_PRESETS[templateId] ?? POLICY_TEMPLATE_PRESETS["tpl-2"];
|
|
37
|
+
const maxNativeBaseUnits = BigInt(Math.round(template.singleTxUsd * 1_000_000));
|
|
38
|
+
const dailyLimitBaseUnits = BigInt(Math.round(template.dailyLimitUsd * 1_000_000));
|
|
39
|
+
return {
|
|
40
|
+
template,
|
|
41
|
+
// Default to EVM namespace so newly onboarded users can sign EVM txs immediately.
|
|
42
|
+
allowNamespaces: [1],
|
|
43
|
+
rules: [
|
|
44
|
+
{
|
|
45
|
+
ruleType: 1,
|
|
46
|
+
namespace: 0,
|
|
47
|
+
params: encodeMaxNativeRule(maxNativeBaseUnits),
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
ruleType: 10,
|
|
51
|
+
namespace: 0,
|
|
52
|
+
params: encodeDailyPeriodLimitRule(dailyLimitBaseUnits),
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
};
|
|
56
|
+
}
|