@openfort/cli 0.1.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.
package/dist/cli.js ADDED
@@ -0,0 +1,2886 @@
1
+ import {
2
+ CREDENTIALS_PATH,
3
+ ensureConfigDir
4
+ } from "./chunk-SZO4OB6U.js";
5
+
6
+ // src/cli.ts
7
+ import { Cli as Cli12, z as z14, Errors as Errors4 } from "incur";
8
+ import Openfort from "@openfort/openfort-node";
9
+
10
+ // src/vars.ts
11
+ import { z } from "incur";
12
+ var varsSchema = z.object({
13
+ openfort: z.custom()
14
+ });
15
+
16
+ // src/constants.ts
17
+ var API_BASE_URL = process.env.OPENFORT_BASE_URL || "https://api.openfort.io";
18
+ var OPENFORT_SHIELD_URL = process.env.OPENFORT_SHIELD_URL || "https://shield.openfort.io";
19
+ var AUTH_PAGE_URL = process.env.OPENFORT_AUTH_PAGE_URL || "https://dashboard.openfort.io";
20
+ var CLI_CALLBACK_PORT = Number(process.env.OPENFORT_CLI_CALLBACK_PORT) || 8271;
21
+
22
+ // src/commands/login.ts
23
+ import { randomBytes } from "crypto";
24
+ import { createServer } from "http";
25
+ import { z as z2 } from "incur";
26
+
27
+ // src/env.ts
28
+ import { readFileSync, writeFileSync, existsSync } from "fs";
29
+ function loadEnvFile(envPath) {
30
+ const entries = /* @__PURE__ */ new Map();
31
+ if (!existsSync(envPath)) return entries;
32
+ const content = readFileSync(envPath, "utf-8");
33
+ for (const line of content.split("\n")) {
34
+ const trimmed = line.trim();
35
+ if (!trimmed || trimmed.startsWith("#")) continue;
36
+ const eqIndex = trimmed.indexOf("=");
37
+ if (eqIndex === -1) continue;
38
+ const key = trimmed.slice(0, eqIndex).trim();
39
+ const value = trimmed.slice(eqIndex + 1).trim();
40
+ entries.set(key, value);
41
+ }
42
+ return entries;
43
+ }
44
+ function writeEnvKey(envPath, key, value) {
45
+ const entries = loadEnvFile(envPath);
46
+ entries.set(key, value);
47
+ const lines = [];
48
+ for (const [k, v] of entries) {
49
+ lines.push(`${k}=${v}`);
50
+ }
51
+ writeFileSync(envPath, `${lines.join("\n")}
52
+ `);
53
+ }
54
+
55
+ // src/commands/login.ts
56
+ function base64url(buffer) {
57
+ return buffer.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
58
+ }
59
+ function generateState() {
60
+ return base64url(randomBytes(16));
61
+ }
62
+ function callbackPage(title, description, variant = "success") {
63
+ const iconColor = variant === "success" ? "hsl(142 71% 45%)" : "hsl(0 84% 60%)";
64
+ const icon = variant === "success" ? `<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="${iconColor}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>` : `<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="${iconColor}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>`;
65
+ return `<!DOCTYPE html>
66
+ <html lang="en">
67
+ <head>
68
+ <meta charset="UTF-8">
69
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
70
+ <title>${title} - Openfort CLI</title>
71
+ <style>
72
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
73
+ :root {
74
+ --background: hsl(0 0% 100%);
75
+ --foreground: hsl(20 14.3% 4.1%);
76
+ --card: hsl(0 0% 100%);
77
+ --card-foreground: hsl(20 14.3% 4.1%);
78
+ --border: hsl(20 5.9% 90%);
79
+ --muted-foreground: hsl(25 5.3% 44.7%);
80
+ --radius: 0.3rem;
81
+ }
82
+ @media (prefers-color-scheme: dark) {
83
+ :root {
84
+ --background: hsl(20 14.3% 4.1%);
85
+ --foreground: hsl(60 9.1% 97.8%);
86
+ --card: hsl(20 14.3% 4.1%);
87
+ --card-foreground: hsl(60 9.1% 97.8%);
88
+ --border: hsl(12 6.5% 15.1%);
89
+ --muted-foreground: hsl(24 5.4% 63.9%);
90
+ }
91
+ }
92
+ body {
93
+ font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
94
+ background-color: var(--background);
95
+ color: var(--foreground);
96
+ display: flex;
97
+ align-items: center;
98
+ justify-content: center;
99
+ min-height: 100vh;
100
+ padding: 1rem;
101
+ }
102
+ .card {
103
+ background-color: var(--card);
104
+ color: var(--card-foreground);
105
+ border: 1px solid var(--border);
106
+ border-radius: var(--radius);
107
+ width: 100%;
108
+ max-width: 28rem;
109
+ box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
110
+ }
111
+ .card-header {
112
+ display: flex;
113
+ flex-direction: column;
114
+ align-items: center;
115
+ gap: 0.5rem;
116
+ padding: 1.5rem;
117
+ text-align: center;
118
+ }
119
+ .card-icon { margin-bottom: 0.5rem; }
120
+ .card-title {
121
+ font-size: 1.5rem;
122
+ font-weight: 600;
123
+ line-height: 1.2;
124
+ letter-spacing: -0.025em;
125
+ }
126
+ .card-description {
127
+ font-size: 0.875rem;
128
+ color: var(--muted-foreground);
129
+ line-height: 1.5;
130
+ }
131
+ </style>
132
+ </head>
133
+ <body>
134
+ <div class="card">
135
+ <div class="card-header">
136
+ <div class="card-icon">${icon}</div>
137
+ <h1 class="card-title">${title}</h1>
138
+ <p class="card-description">${description}</p>
139
+ </div>
140
+ </div>
141
+ </body>
142
+ </html>`;
143
+ }
144
+ function waitForCallback(port, state) {
145
+ return new Promise((resolve, reject) => {
146
+ const timeout = setTimeout(() => {
147
+ server.close();
148
+ reject(new Error("Login timed out after 5 minutes. Please try again."));
149
+ }, 5 * 60 * 1e3);
150
+ const server = createServer((req, res) => {
151
+ const url = new URL(req.url, `http://localhost:${port}`);
152
+ if (url.pathname === "/callback") {
153
+ const apiKey = url.searchParams.get("api_key");
154
+ const publishableKey = url.searchParams.get("publishable_key");
155
+ const projectId = url.searchParams.get("project_id");
156
+ const project = url.searchParams.get("project");
157
+ const returnedState = url.searchParams.get("state");
158
+ const error = url.searchParams.get("error");
159
+ const errorDescription = url.searchParams.get("error_description");
160
+ if (error) {
161
+ res.writeHead(200, { "Content-Type": "text/html" });
162
+ res.end(callbackPage("Login failed", "Something went wrong. You can close this window.", "error"));
163
+ clearTimeout(timeout);
164
+ server.close();
165
+ reject(new Error(errorDescription || error));
166
+ return;
167
+ }
168
+ if (!apiKey || returnedState !== state) {
169
+ res.writeHead(400, { "Content-Type": "text/html" });
170
+ res.end(callbackPage("Invalid callback", "Missing API key or state mismatch. Please try logging in again.", "error"));
171
+ return;
172
+ }
173
+ res.writeHead(200, { "Content-Type": "text/html" });
174
+ res.end(callbackPage("Login successful!", "You can close this window and return to your terminal."));
175
+ clearTimeout(timeout);
176
+ server.close();
177
+ resolve({ apiKey, publishableKey: publishableKey || void 0, projectId: projectId || void 0, project: project || "unknown" });
178
+ } else {
179
+ res.writeHead(404);
180
+ res.end();
181
+ }
182
+ });
183
+ server.listen(port);
184
+ });
185
+ }
186
+ var loginConfig = {
187
+ description: "Log in to Openfort via browser and save your API key.",
188
+ output: z2.object({
189
+ apiKey: z2.string().describe("The API key saved to credentials"),
190
+ project: z2.string().describe("The project name"),
191
+ credentialsPath: z2.string().describe("Path to the credentials file")
192
+ }),
193
+ async run(c) {
194
+ const state = generateState();
195
+ const port = CLI_CALLBACK_PORT;
196
+ const redirectUri = `http://localhost:${port}/callback`;
197
+ const authUrl = new URL(`${AUTH_PAGE_URL}/oauth/consent`);
198
+ authUrl.searchParams.set("redirect_uri", redirectUri);
199
+ authUrl.searchParams.set("state", state);
200
+ console.log("\nOpen this URL in your browser to log in:\n");
201
+ console.log(` ${authUrl.toString()}
202
+ `);
203
+ console.log("Waiting for authentication...\n");
204
+ const { apiKey, publishableKey, projectId, project } = await waitForCallback(port, state);
205
+ ensureConfigDir();
206
+ writeEnvKey(CREDENTIALS_PATH, "OPENFORT_API_KEY", apiKey);
207
+ if (publishableKey) {
208
+ writeEnvKey(CREDENTIALS_PATH, "OPENFORT_PUBLISHABLE_KEY", publishableKey);
209
+ }
210
+ if (projectId) {
211
+ writeEnvKey(CREDENTIALS_PATH, "OPENFORT_PROJECT_ID", projectId);
212
+ }
213
+ console.log(`Saved API key for project "${project}" to ${CREDENTIALS_PATH}`);
214
+ return c.ok(
215
+ { apiKey, project, credentialsPath: CREDENTIALS_PATH },
216
+ {
217
+ cta: {
218
+ description: "Next steps:",
219
+ commands: [
220
+ { command: `wallet-keys create`, description: "Create and save wallet keys necessary for backend wallet creation" }
221
+ ]
222
+ }
223
+ }
224
+ );
225
+ }
226
+ };
227
+
228
+ // src/commands/accounts.ts
229
+ import { Cli, z as z3, Errors } from "incur";
230
+ function requireWalletCredentials() {
231
+ const missing = [];
232
+ if (!process.env.OPENFORT_WALLET_SECRET) missing.push("OPENFORT_WALLET_SECRET");
233
+ if (!process.env.OPENFORT_PUBLISHABLE_KEY) missing.push("OPENFORT_PUBLISHABLE_KEY");
234
+ if (missing.length > 0) {
235
+ throw new Errors.IncurError({
236
+ code: "MISSING_CREDENTIALS",
237
+ message: `Missing required credentials: ${missing.join(", ")}`,
238
+ hint: "Run: openfort wallet-keys create"
239
+ });
240
+ }
241
+ }
242
+ var evm = Cli.create("evm", {
243
+ description: "EVM wallet management.",
244
+ vars: varsSchema
245
+ });
246
+ evm.command("create", {
247
+ description: "Create a new EVM backend wallet.",
248
+ examples: [
249
+ { description: "Create a new EVM wallet" }
250
+ ],
251
+ output: z3.object({
252
+ id: z3.string().describe("Account ID"),
253
+ address: z3.string().describe("Wallet address"),
254
+ custody: z3.string().describe("Custody type")
255
+ }),
256
+ async run(c) {
257
+ requireWalletCredentials();
258
+ const account = await c.var.openfort.accounts.evm.backend.create();
259
+ return c.ok(
260
+ { id: account.id, address: account.address, custody: account.custody },
261
+ {
262
+ cta: {
263
+ description: "Next steps:",
264
+ commands: [
265
+ { command: `accounts evm get ${account.id}`, description: "View this account" },
266
+ { command: "policies create", description: "Create an access policy" }
267
+ ]
268
+ }
269
+ }
270
+ );
271
+ }
272
+ });
273
+ evm.command("list", {
274
+ description: "List EVM backend wallets.",
275
+ options: z3.object({
276
+ limit: z3.number().optional().describe("Max results"),
277
+ skip: z3.number().optional().describe("Offset")
278
+ }),
279
+ alias: { limit: "l" },
280
+ examples: [
281
+ { description: "List all EVM backend wallets" },
282
+ { options: { limit: 5 }, description: "Show first 5 wallets" }
283
+ ],
284
+ output: z3.object({
285
+ accounts: z3.array(z3.object({
286
+ id: z3.string(),
287
+ address: z3.string(),
288
+ custody: z3.string()
289
+ })),
290
+ total: z3.number().optional()
291
+ }),
292
+ async run(c) {
293
+ const res = await c.var.openfort.accounts.evm.backend.list({
294
+ limit: c.options.limit,
295
+ skip: c.options.skip
296
+ });
297
+ return c.ok({
298
+ accounts: res.accounts.map((a) => ({
299
+ id: a.id,
300
+ address: a.address,
301
+ custody: a.custody
302
+ })),
303
+ total: res.total
304
+ });
305
+ }
306
+ });
307
+ evm.command("list-delegated", {
308
+ description: "List EVM delegated accounts.",
309
+ options: z3.object({
310
+ limit: z3.number().optional().describe("Max results"),
311
+ skip: z3.number().optional().describe("Offset")
312
+ }),
313
+ alias: { limit: "l" },
314
+ examples: [
315
+ { description: "List all EVM delegated accounts" },
316
+ { options: { limit: 5 }, description: "Show first 5 accounts" }
317
+ ],
318
+ output: z3.object({
319
+ accounts: z3.array(z3.object({
320
+ id: z3.string(),
321
+ address: z3.string(),
322
+ custody: z3.string()
323
+ })),
324
+ total: z3.number().optional()
325
+ }),
326
+ async run(c) {
327
+ const res = await c.var.openfort.accounts.evm.list({
328
+ accountType: "Delegated Account",
329
+ limit: c.options.limit,
330
+ skip: c.options.skip
331
+ });
332
+ return c.ok({
333
+ accounts: res.data.map((a) => ({
334
+ id: a.id,
335
+ address: a.address,
336
+ custody: a.custody
337
+ })),
338
+ total: res.total
339
+ });
340
+ }
341
+ });
342
+ evm.command("list-smart", {
343
+ description: "List EVM smart accounts.",
344
+ options: z3.object({
345
+ limit: z3.number().optional().describe("Max results"),
346
+ skip: z3.number().optional().describe("Offset")
347
+ }),
348
+ alias: { limit: "l" },
349
+ examples: [
350
+ { description: "List all EVM smart accounts" },
351
+ { options: { limit: 5 }, description: "Show first 5 accounts" }
352
+ ],
353
+ output: z3.object({
354
+ accounts: z3.array(z3.object({
355
+ id: z3.string(),
356
+ address: z3.string(),
357
+ custody: z3.string()
358
+ })),
359
+ total: z3.number().optional()
360
+ }),
361
+ async run(c) {
362
+ const res = await c.var.openfort.accounts.evm.list({
363
+ accountType: "Smart Account",
364
+ limit: c.options.limit,
365
+ skip: c.options.skip
366
+ });
367
+ return c.ok({
368
+ accounts: res.data.map((a) => ({
369
+ id: a.id,
370
+ address: a.address,
371
+ custody: a.custody
372
+ })),
373
+ total: res.total
374
+ });
375
+ }
376
+ });
377
+ evm.command("get", {
378
+ description: "Get an EVM backend wallet by ID or address.",
379
+ args: z3.object({
380
+ id: z3.string().describe("Account ID or address")
381
+ }),
382
+ examples: [
383
+ { args: { id: "acc_1a2b3c4d" }, description: "Get wallet by ID" }
384
+ ],
385
+ output: z3.object({
386
+ id: z3.string(),
387
+ address: z3.string(),
388
+ custody: z3.string()
389
+ }),
390
+ async run(c) {
391
+ const a = await c.var.openfort.accounts.evm.backend.get({ id: c.args.id });
392
+ return c.ok({
393
+ id: a.id,
394
+ address: a.address,
395
+ custody: a.custody
396
+ });
397
+ }
398
+ });
399
+ evm.command("sign", {
400
+ description: "Sign data with an EVM backend wallet.",
401
+ args: z3.object({
402
+ id: z3.string().describe("Account ID (acc_...)")
403
+ }),
404
+ options: z3.object({
405
+ data: z3.string().describe("Data to sign (hex-encoded)")
406
+ }),
407
+ alias: { data: "d" },
408
+ output: z3.object({
409
+ account: z3.string(),
410
+ signature: z3.string()
411
+ }),
412
+ examples: [
413
+ {
414
+ args: { id: "acc_abc123" },
415
+ options: { data: "0x1234abcd" },
416
+ description: "Sign a message hash with a backend wallet"
417
+ }
418
+ ],
419
+ async run(c) {
420
+ requireWalletCredentials();
421
+ const signature = await c.var.openfort.accounts.evm.backend.sign({
422
+ id: c.args.id,
423
+ data: c.options.data
424
+ });
425
+ return c.ok({ account: c.args.id, signature });
426
+ }
427
+ });
428
+ evm.command("delete", {
429
+ description: "Delete an EVM backend wallet.",
430
+ args: z3.object({
431
+ id: z3.string().describe("Account ID (acc_...)")
432
+ }),
433
+ examples: [
434
+ { args: { id: "acc_1a2b3c4d" }, description: "Delete a wallet" }
435
+ ],
436
+ output: z3.object({
437
+ id: z3.string(),
438
+ deleted: z3.boolean()
439
+ }),
440
+ async run(c) {
441
+ const res = await c.var.openfort.accounts.evm.backend.delete(c.args.id);
442
+ return c.ok({ id: res.id, deleted: res.deleted });
443
+ }
444
+ });
445
+ evm.command("update", {
446
+ description: "Upgrade an EVM backend wallet to a delegated account (EIP-7702).",
447
+ args: z3.object({
448
+ id: z3.string().describe("Account ID (acc_...)")
449
+ }),
450
+ options: z3.object({
451
+ chainId: z3.number().describe("Chain ID to deploy on"),
452
+ implementationType: z3.string().describe("Smart account implementation type we will update to")
453
+ }),
454
+ examples: [
455
+ { args: { id: "acc_1a2b3c4d" }, options: { chainId: 8453, implementationType: "CaliburV9" }, description: "Upgrade to delegated account on Base" }
456
+ ],
457
+ output: z3.object({
458
+ id: z3.string(),
459
+ address: z3.string(),
460
+ accountType: z3.string(),
461
+ chainId: z3.number().optional(),
462
+ chainType: z3.string()
463
+ }),
464
+ async run(c) {
465
+ const account = await c.var.openfort.accounts.evm.backend.get({ id: c.args.id });
466
+ const res = await c.var.openfort.accounts.evm.backend.update({
467
+ walletId: account.walletId,
468
+ chainId: c.options.chainId,
469
+ accountId: account.id,
470
+ implementationType: c.options.implementationType
471
+ });
472
+ return c.ok(
473
+ {
474
+ id: res.id,
475
+ address: res.address,
476
+ accountType: res.accountType,
477
+ chainId: res.chainId,
478
+ chainType: res.chainType
479
+ },
480
+ {
481
+ cta: {
482
+ description: "Next steps:",
483
+ commands: [
484
+ { command: `accounts evm list-delegated`, description: "To see all accounts which were updated to delegated ones" }
485
+ ]
486
+ }
487
+ }
488
+ );
489
+ }
490
+ });
491
+ evm.command("sign", {
492
+ description: "Sign data with an EVM backend wallet.",
493
+ args: z3.object({
494
+ id: z3.string().describe("Account ID (acc_...)")
495
+ }),
496
+ options: z3.object({
497
+ data: z3.string().describe("Hex-encoded data to sign")
498
+ }),
499
+ examples: [
500
+ { args: { id: "acc_1a2b3c4d" }, options: { data: "0xdeadbeef" }, description: "Sign a message hash" }
501
+ ],
502
+ output: z3.object({
503
+ signature: z3.string()
504
+ }),
505
+ async run(c) {
506
+ requireWalletCredentials();
507
+ const signature = await c.var.openfort.accounts.evm.backend.sign({
508
+ id: c.args.id,
509
+ data: c.options.data
510
+ });
511
+ return c.ok({ signature });
512
+ }
513
+ });
514
+ evm.command("import", {
515
+ description: "Import a private key as an EVM backend wallet.",
516
+ options: z3.object({
517
+ privateKey: z3.string().describe("Private key (hex string)")
518
+ }),
519
+ examples: [
520
+ { options: { privateKey: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" }, description: "Import a private key" }
521
+ ],
522
+ output: z3.object({
523
+ id: z3.string(),
524
+ address: z3.string(),
525
+ custody: z3.string()
526
+ }),
527
+ async run(c) {
528
+ requireWalletCredentials();
529
+ const account = await c.var.openfort.accounts.evm.backend.import({
530
+ privateKey: c.options.privateKey
531
+ });
532
+ return c.ok({
533
+ id: account.id,
534
+ address: account.address,
535
+ custody: account.custody
536
+ });
537
+ }
538
+ });
539
+ evm.command("export", {
540
+ description: "Export an EVM backend wallet private key.",
541
+ args: z3.object({
542
+ id: z3.string().describe("Account ID (acc_...)")
543
+ }),
544
+ examples: [
545
+ { args: { id: "acc_1a2b3c4d" }, description: "Export private key" }
546
+ ],
547
+ output: z3.object({
548
+ privateKey: z3.string()
549
+ }),
550
+ async run(c) {
551
+ requireWalletCredentials();
552
+ const privateKey = await c.var.openfort.accounts.evm.backend.export({
553
+ id: c.args.id
554
+ });
555
+ return c.ok({ privateKey });
556
+ }
557
+ });
558
+ evm.command("send-transaction", {
559
+ description: "Send a gasless EVM transaction (auto-delegates via EIP-7702 if needed).",
560
+ args: z3.object({
561
+ id: z3.string().describe("Account ID (acc_...)")
562
+ }),
563
+ options: z3.object({
564
+ chainId: z3.number().describe("Chain ID"),
565
+ interactions: z3.string().describe('Interactions as JSON: [{"to":"0x...","data":"0x...","value":"0"}]'),
566
+ policy: z3.string().optional().describe("Policy ID for gas sponsorship (pol_...)")
567
+ }),
568
+ examples: [
569
+ {
570
+ args: { id: "acc_1a2b3c4d" },
571
+ options: {
572
+ chainId: 8453,
573
+ interactions: '[{"to":"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359","data":"0xa9059cbb...","value":"0"}]'
574
+ },
575
+ description: "Send a gasless transaction on Base"
576
+ }
577
+ ],
578
+ output: z3.object({
579
+ id: z3.string(),
580
+ chainId: z3.number(),
581
+ transactionHash: z3.string().optional()
582
+ }),
583
+ async run(c) {
584
+ const account = await c.var.openfort.accounts.evm.backend.get({ id: c.args.id });
585
+ const interactions = JSON.parse(c.options.interactions);
586
+ const res = await c.var.openfort.accounts.evm.backend.sendTransaction({
587
+ account,
588
+ chainId: c.options.chainId,
589
+ interactions,
590
+ policy: c.options.policy
591
+ });
592
+ return c.ok({
593
+ id: res.id,
594
+ chainId: res.chainId,
595
+ transactionHash: res.response?.transactionHash
596
+ });
597
+ }
598
+ });
599
+ var solana = Cli.create("solana", {
600
+ description: "Solana wallet management.",
601
+ vars: varsSchema
602
+ });
603
+ solana.command("create", {
604
+ description: "Create a new Solana backend wallet.",
605
+ examples: [
606
+ { description: "Create a new Solana wallet" }
607
+ ],
608
+ output: z3.object({
609
+ id: z3.string().describe("Account ID"),
610
+ address: z3.string().describe("Wallet address"),
611
+ custody: z3.string().describe("Custody type")
612
+ }),
613
+ async run(c) {
614
+ requireWalletCredentials();
615
+ const account = await c.var.openfort.accounts.solana.backend.create();
616
+ return c.ok(
617
+ { id: account.id, address: account.address, custody: account.custody },
618
+ {
619
+ cta: {
620
+ description: "Next steps:",
621
+ commands: [
622
+ { command: `accounts solana get ${account.id}`, description: "View this account" }
623
+ ]
624
+ }
625
+ }
626
+ );
627
+ }
628
+ });
629
+ solana.command("list", {
630
+ description: "List Solana backend wallets.",
631
+ options: z3.object({
632
+ limit: z3.number().optional().describe("Max results"),
633
+ skip: z3.number().optional().describe("Offset")
634
+ }),
635
+ alias: { limit: "l" },
636
+ examples: [
637
+ { description: "List all Solana wallets" }
638
+ ],
639
+ output: z3.object({
640
+ accounts: z3.array(z3.object({
641
+ id: z3.string(),
642
+ address: z3.string(),
643
+ custody: z3.string()
644
+ })),
645
+ total: z3.number().optional()
646
+ }),
647
+ async run(c) {
648
+ const res = await c.var.openfort.accounts.solana.backend.list({
649
+ limit: c.options.limit,
650
+ skip: c.options.skip
651
+ });
652
+ return c.ok({
653
+ accounts: res.accounts.map((a) => ({
654
+ id: a.id,
655
+ address: a.address,
656
+ custody: a.custody
657
+ })),
658
+ total: res.total
659
+ });
660
+ }
661
+ });
662
+ solana.command("get", {
663
+ description: "Get a Solana backend wallet by ID or address.",
664
+ args: z3.object({
665
+ id: z3.string().describe("Account ID or address")
666
+ }),
667
+ examples: [
668
+ { args: { id: "acc_1a2b3c4d" }, description: "Get wallet by ID" }
669
+ ],
670
+ output: z3.object({
671
+ id: z3.string(),
672
+ address: z3.string(),
673
+ custody: z3.string()
674
+ }),
675
+ async run(c) {
676
+ const a = await c.var.openfort.accounts.solana.backend.get({ id: c.args.id });
677
+ return c.ok({
678
+ id: a.id,
679
+ address: a.address,
680
+ custody: a.custody
681
+ });
682
+ }
683
+ });
684
+ solana.command("sign", {
685
+ description: "Sign data with a Solana backend wallet.",
686
+ args: z3.object({
687
+ id: z3.string().describe("Account ID (acc_...)")
688
+ }),
689
+ options: z3.object({
690
+ data: z3.string().describe("Data to sign (base64-encoded)")
691
+ }),
692
+ alias: { data: "d" },
693
+ output: z3.object({
694
+ account: z3.string(),
695
+ signature: z3.string()
696
+ }),
697
+ examples: [
698
+ {
699
+ args: { id: "acc_abc123" },
700
+ options: { data: "SGVsbG8gV29ybGQ=" },
701
+ description: "Sign a message with a Solana backend wallet"
702
+ }
703
+ ],
704
+ async run(c) {
705
+ requireWalletCredentials();
706
+ const signature = await c.var.openfort.accounts.solana.backend.sign(c.args.id, c.options.data);
707
+ return c.ok({ account: c.args.id, signature });
708
+ }
709
+ });
710
+ solana.command("delete", {
711
+ description: "Delete a Solana backend wallet.",
712
+ args: z3.object({
713
+ id: z3.string().describe("Account ID (acc_...)")
714
+ }),
715
+ examples: [
716
+ { args: { id: "acc_1a2b3c4d" }, description: "Delete a wallet" }
717
+ ],
718
+ output: z3.object({
719
+ id: z3.string(),
720
+ deleted: z3.boolean()
721
+ }),
722
+ async run(c) {
723
+ const res = await c.var.openfort.accounts.solana.backend.delete(c.args.id);
724
+ return c.ok({ id: res.id, deleted: res.deleted });
725
+ }
726
+ });
727
+ solana.command("sign", {
728
+ description: "Sign data with a Solana backend wallet.",
729
+ args: z3.object({
730
+ id: z3.string().describe("Account ID (acc_...)")
731
+ }),
732
+ options: z3.object({
733
+ data: z3.string().describe("Data to sign")
734
+ }),
735
+ examples: [
736
+ { args: { id: "acc_1a2b3c4d" }, options: { data: "hello" }, description: "Sign a message" }
737
+ ],
738
+ output: z3.object({
739
+ signature: z3.string()
740
+ }),
741
+ async run(c) {
742
+ requireWalletCredentials();
743
+ const signature = await c.var.openfort.accounts.solana.backend.sign(c.args.id, c.options.data);
744
+ return c.ok({ signature });
745
+ }
746
+ });
747
+ solana.command("import", {
748
+ description: "Import a private key as a Solana backend wallet.",
749
+ options: z3.object({
750
+ privateKey: z3.string().describe("Private key (hex-encoded 32 bytes or base58)")
751
+ }),
752
+ examples: [
753
+ { options: { privateKey: "abc123..." }, description: "Import a Solana private key" }
754
+ ],
755
+ output: z3.object({
756
+ id: z3.string(),
757
+ address: z3.string(),
758
+ custody: z3.string()
759
+ }),
760
+ async run(c) {
761
+ requireWalletCredentials();
762
+ const account = await c.var.openfort.accounts.solana.backend.import({
763
+ privateKey: c.options.privateKey
764
+ });
765
+ return c.ok({
766
+ id: account.id,
767
+ address: account.address,
768
+ custody: account.custody
769
+ });
770
+ }
771
+ });
772
+ solana.command("export", {
773
+ description: "Export a Solana backend wallet private key.",
774
+ args: z3.object({
775
+ id: z3.string().describe("Account ID (acc_...)")
776
+ }),
777
+ examples: [
778
+ { args: { id: "acc_1a2b3c4d" }, description: "Export private key" }
779
+ ],
780
+ output: z3.object({
781
+ privateKey: z3.string()
782
+ }),
783
+ async run(c) {
784
+ requireWalletCredentials();
785
+ const privateKey = await c.var.openfort.accounts.solana.backend.export({
786
+ id: c.args.id
787
+ });
788
+ return c.ok({ privateKey });
789
+ }
790
+ });
791
+ solana.command("transfer", {
792
+ description: "Transfer SOL or SPL tokens.",
793
+ args: z3.object({
794
+ id: z3.string().describe("Account ID (acc_...)")
795
+ }),
796
+ options: z3.object({
797
+ to: z3.string().describe("Destination address (base58)"),
798
+ amount: z3.string().describe("Amount in base units (lamports for SOL)"),
799
+ token: z3.string().optional().describe('Token: "sol" (default), "usdc", or mint address'),
800
+ cluster: z3.enum(["devnet", "mainnet-beta"]).default("mainnet-beta").describe("Cluster: devnet or mainnet-beta")
801
+ }),
802
+ examples: [
803
+ {
804
+ args: { id: "acc_1a2b3c4d" },
805
+ options: { to: "FDx9mf...", amount: "1000000", cluster: "devnet" },
806
+ description: "Transfer 0.001 SOL on devnet"
807
+ },
808
+ {
809
+ args: { id: "acc_1a2b3c4d" },
810
+ options: { to: "FDx9mf...", amount: "1000000", token: "usdc", cluster: "devnet" },
811
+ description: "Transfer 1 USDC on devnet"
812
+ }
813
+ ],
814
+ output: z3.object({
815
+ signature: z3.string()
816
+ }),
817
+ async run(c) {
818
+ const account = await c.var.openfort.accounts.solana.backend.get({ id: c.args.id });
819
+ const res = await c.var.openfort.accounts.solana.backend.transfer({
820
+ account,
821
+ to: c.options.to,
822
+ amount: BigInt(c.options.amount),
823
+ token: c.options.token,
824
+ cluster: c.options.cluster
825
+ });
826
+ return c.ok({ signature: res.signature });
827
+ }
828
+ });
829
+ var accounts = Cli.create("accounts", {
830
+ description: "Manage wallets and accounts.",
831
+ vars: varsSchema
832
+ });
833
+ accounts.command("list", {
834
+ description: "List all accounts across chains.",
835
+ options: z3.object({
836
+ limit: z3.number().optional().describe("Max results"),
837
+ skip: z3.number().optional().describe("Offset"),
838
+ chainType: z3.enum(["EVM", "SVM"]).optional().describe("Filter by chain type"),
839
+ custody: z3.enum(["Developer", "User"]).optional().describe("Filter by custody")
840
+ }),
841
+ alias: { limit: "l" },
842
+ examples: [
843
+ { description: "List all accounts across chains" },
844
+ { options: { chainType: "EVM" }, description: "Filter to EVM accounts only" },
845
+ { options: { custody: "Developer", limit: 10 }, description: "List developer-custody wallets" }
846
+ ],
847
+ output: z3.object({
848
+ data: z3.array(z3.object({
849
+ id: z3.string(),
850
+ wallet: z3.string().describe("Wallet ID"),
851
+ accountType: z3.string().describe("Account type"),
852
+ address: z3.string(),
853
+ ownerAddress: z3.string().optional(),
854
+ chainType: z3.string(),
855
+ chainId: z3.number().optional(),
856
+ custody: z3.string(),
857
+ createdAt: z3.number(),
858
+ updatedAt: z3.number()
859
+ })),
860
+ total: z3.number()
861
+ }),
862
+ async run(c) {
863
+ const res = await c.var.openfort.accounts.list({
864
+ limit: c.options.limit,
865
+ skip: c.options.skip,
866
+ chainType: c.options.chainType,
867
+ custody: c.options.custody
868
+ });
869
+ return c.ok({
870
+ data: res.data.map((a) => ({
871
+ id: a.id,
872
+ wallet: a.wallet,
873
+ accountType: a.accountType,
874
+ address: a.address,
875
+ ownerAddress: a.ownerAddress,
876
+ chainType: a.chainType,
877
+ chainId: a.chainId,
878
+ custody: a.custody,
879
+ createdAt: a.createdAt,
880
+ updatedAt: a.updatedAt
881
+ })),
882
+ total: res.total
883
+ });
884
+ }
885
+ });
886
+ accounts.command(evm);
887
+ accounts.command(solana);
888
+
889
+ // src/commands/contracts.ts
890
+ import { Cli as Cli2, z as z4 } from "incur";
891
+ var contractItem = z4.object({
892
+ id: z4.string(),
893
+ createdAt: z4.number(),
894
+ name: z4.string().nullable(),
895
+ chainId: z4.number(),
896
+ address: z4.string(),
897
+ deleted: z4.boolean(),
898
+ abi: z4.array(z4.any()),
899
+ publicVerification: z4.boolean()
900
+ });
901
+ var contracts = Cli2.create("contracts", {
902
+ description: "Manage smart contracts.",
903
+ vars: varsSchema
904
+ });
905
+ contracts.command("list", {
906
+ description: "List registered contracts.",
907
+ options: z4.object({
908
+ limit: z4.number().optional().describe("Max results"),
909
+ skip: z4.number().optional().describe("Offset")
910
+ }),
911
+ alias: { limit: "l" },
912
+ examples: [
913
+ { description: "List all contracts" },
914
+ { options: { limit: 5 }, description: "List first 5 contracts" }
915
+ ],
916
+ output: z4.object({
917
+ data: z4.array(contractItem),
918
+ total: z4.number()
919
+ }),
920
+ async run(c) {
921
+ const res = await c.var.openfort.contracts.list({
922
+ limit: c.options.limit,
923
+ skip: c.options.skip
924
+ });
925
+ return c.ok({
926
+ data: res.data.map((ct) => ({
927
+ id: ct.id,
928
+ createdAt: ct.createdAt,
929
+ name: ct.name,
930
+ chainId: ct.chainId,
931
+ address: ct.address,
932
+ deleted: ct.deleted,
933
+ abi: ct.abi,
934
+ publicVerification: ct.publicVerification
935
+ })),
936
+ total: res.total
937
+ });
938
+ }
939
+ });
940
+ contracts.command("create", {
941
+ description: "Register a smart contract.",
942
+ options: z4.object({
943
+ name: z4.string().describe("Contract name"),
944
+ address: z4.string().describe("Contract address"),
945
+ chainId: z4.number().describe("Chain ID"),
946
+ abi: z4.string().optional().describe("Contract ABI as JSON string")
947
+ }),
948
+ output: contractItem,
949
+ examples: [
950
+ {
951
+ options: { name: "USDC", address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", chainId: 137 },
952
+ description: "Register USDC on Polygon"
953
+ },
954
+ {
955
+ options: { name: "My NFT", address: "0x1234...", chainId: 1, abi: '[{"type":"function","name":"mint",...}]' },
956
+ description: "Register contract with ABI"
957
+ }
958
+ ],
959
+ async run(c) {
960
+ const res = await c.var.openfort.contracts.create({
961
+ name: c.options.name,
962
+ address: c.options.address,
963
+ chainId: c.options.chainId,
964
+ abi: c.options.abi ? JSON.parse(c.options.abi) : void 0
965
+ });
966
+ return c.ok(
967
+ {
968
+ id: res.id,
969
+ createdAt: res.createdAt,
970
+ name: res.name,
971
+ chainId: res.chainId,
972
+ address: res.address,
973
+ deleted: res.deleted,
974
+ abi: res.abi,
975
+ publicVerification: res.publicVerification
976
+ },
977
+ {
978
+ cta: {
979
+ description: "Next steps:",
980
+ commands: [
981
+ { command: `contracts get ${res.id}`, description: "View this contract" },
982
+ { command: "policies create", description: "Create a policy for this contract" }
983
+ ]
984
+ }
985
+ }
986
+ );
987
+ }
988
+ });
989
+ contracts.command("get", {
990
+ description: "Get a contract by ID.",
991
+ args: z4.object({
992
+ id: z4.string().describe("Contract ID (con_...)")
993
+ }),
994
+ examples: [
995
+ { args: { id: "con_1a2b3c4d" }, description: "Get contract details" }
996
+ ],
997
+ output: contractItem,
998
+ async run(c) {
999
+ const ct = await c.var.openfort.contracts.get(c.args.id);
1000
+ return c.ok({
1001
+ id: ct.id,
1002
+ createdAt: ct.createdAt,
1003
+ name: ct.name,
1004
+ chainId: ct.chainId,
1005
+ address: ct.address,
1006
+ deleted: ct.deleted,
1007
+ abi: ct.abi,
1008
+ publicVerification: ct.publicVerification
1009
+ });
1010
+ }
1011
+ });
1012
+ contracts.command("update", {
1013
+ description: "Update a contract.",
1014
+ args: z4.object({
1015
+ id: z4.string().describe("Contract ID (con_...)")
1016
+ }),
1017
+ options: z4.object({
1018
+ name: z4.string().optional().describe("New name"),
1019
+ address: z4.string().optional().describe("New address"),
1020
+ chainId: z4.number().optional().describe("New chain ID"),
1021
+ abi: z4.string().optional().describe("New ABI as JSON string")
1022
+ }),
1023
+ examples: [
1024
+ { args: { id: "con_1a2b3c4d" }, options: { name: "USDC v2" }, description: "Rename a contract" }
1025
+ ],
1026
+ output: contractItem,
1027
+ async run(c) {
1028
+ const res = await c.var.openfort.contracts.update(c.args.id, {
1029
+ name: c.options.name,
1030
+ address: c.options.address,
1031
+ chainId: c.options.chainId,
1032
+ abi: c.options.abi ? JSON.parse(c.options.abi) : void 0
1033
+ });
1034
+ return c.ok({
1035
+ id: res.id,
1036
+ createdAt: res.createdAt,
1037
+ name: res.name,
1038
+ chainId: res.chainId,
1039
+ address: res.address,
1040
+ deleted: res.deleted,
1041
+ abi: res.abi,
1042
+ publicVerification: res.publicVerification
1043
+ });
1044
+ }
1045
+ });
1046
+ contracts.command("delete", {
1047
+ description: "Delete a contract.",
1048
+ args: z4.object({
1049
+ id: z4.string().describe("Contract ID (con_...)")
1050
+ }),
1051
+ examples: [
1052
+ { args: { id: "con_1a2b3c4d" }, description: "Delete a contract" }
1053
+ ],
1054
+ output: z4.object({
1055
+ id: z4.string(),
1056
+ deleted: z4.boolean()
1057
+ }),
1058
+ async run(c) {
1059
+ const res = await c.var.openfort.contracts.delete(c.args.id);
1060
+ return c.ok({ id: res.id, deleted: res.deleted });
1061
+ }
1062
+ });
1063
+
1064
+ // src/commands/paymasters.ts
1065
+ import { Cli as Cli3, z as z5 } from "incur";
1066
+ var paymasterItem = z5.object({
1067
+ id: z5.string(),
1068
+ createdAt: z5.number(),
1069
+ address: z5.string(),
1070
+ url: z5.string().optional(),
1071
+ context: z5.record(z5.string(), z5.unknown()).optional()
1072
+ });
1073
+ var paymasters = Cli3.create("paymasters", {
1074
+ description: "Manage ERC-4337 paymasters.",
1075
+ vars: varsSchema
1076
+ });
1077
+ paymasters.command("create", {
1078
+ description: "Create a paymaster.",
1079
+ options: z5.object({
1080
+ address: z5.string().describe("Paymaster contract address"),
1081
+ name: z5.string().optional().describe("Paymaster name"),
1082
+ url: z5.string().optional().describe("Paymaster URL")
1083
+ }),
1084
+ examples: [
1085
+ { options: { address: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", name: "EntryPoint v0.6 Paymaster" }, description: "Create a paymaster for ERC-4337 v0.6" }
1086
+ ],
1087
+ output: paymasterItem,
1088
+ async run(c) {
1089
+ const res = await c.var.openfort.paymasters.create({
1090
+ address: c.options.address,
1091
+ name: c.options.name,
1092
+ url: c.options.url
1093
+ });
1094
+ return c.ok(
1095
+ {
1096
+ id: res.id,
1097
+ createdAt: res.createdAt,
1098
+ address: res.address,
1099
+ url: res.url,
1100
+ context: res.context
1101
+ },
1102
+ {
1103
+ cta: {
1104
+ description: "Next steps:",
1105
+ commands: [
1106
+ { command: `paymasters get ${res.id}`, description: "View this paymaster" },
1107
+ { command: "sponsorship create", description: "Create a fee sponsorship" }
1108
+ ]
1109
+ }
1110
+ }
1111
+ );
1112
+ }
1113
+ });
1114
+ paymasters.command("get", {
1115
+ description: "Get a paymaster by ID.",
1116
+ args: z5.object({
1117
+ id: z5.string().describe("Paymaster ID (pay_...)")
1118
+ }),
1119
+ examples: [
1120
+ { args: { id: "pay_1a2b3c4d" }, description: "Get paymaster details" }
1121
+ ],
1122
+ output: paymasterItem,
1123
+ async run(c) {
1124
+ const p = await c.var.openfort.paymasters.get(c.args.id);
1125
+ return c.ok({
1126
+ id: p.id,
1127
+ createdAt: p.createdAt,
1128
+ address: p.address,
1129
+ url: p.url,
1130
+ context: p.context
1131
+ });
1132
+ }
1133
+ });
1134
+ paymasters.command("update", {
1135
+ description: "Update a paymaster.",
1136
+ args: z5.object({
1137
+ id: z5.string().describe("Paymaster ID (pay_...)")
1138
+ }),
1139
+ options: z5.object({
1140
+ address: z5.string().describe("Paymaster address"),
1141
+ name: z5.string().optional().describe("New name"),
1142
+ url: z5.string().optional().describe("New URL")
1143
+ }),
1144
+ examples: [
1145
+ { args: { id: "pay_1a2b3c4d" }, options: { address: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", name: "Updated Paymaster" }, description: "Update paymaster name" }
1146
+ ],
1147
+ output: paymasterItem,
1148
+ async run(c) {
1149
+ const res = await c.var.openfort.paymasters.update(c.args.id, {
1150
+ address: c.options.address,
1151
+ name: c.options.name,
1152
+ url: c.options.url
1153
+ });
1154
+ return c.ok({
1155
+ id: res.id,
1156
+ createdAt: res.createdAt,
1157
+ address: res.address,
1158
+ url: res.url,
1159
+ context: res.context
1160
+ });
1161
+ }
1162
+ });
1163
+ paymasters.command("delete", {
1164
+ description: "Delete a paymaster.",
1165
+ args: z5.object({
1166
+ id: z5.string().describe("Paymaster ID (pay_...)")
1167
+ }),
1168
+ examples: [
1169
+ { args: { id: "pay_1a2b3c4d" }, description: "Delete a paymaster" }
1170
+ ],
1171
+ output: z5.object({
1172
+ id: z5.string(),
1173
+ deleted: z5.boolean()
1174
+ }),
1175
+ async run(c) {
1176
+ const res = await c.var.openfort.paymasters.delete(c.args.id);
1177
+ return c.ok({ id: res.id, deleted: res.deleted });
1178
+ }
1179
+ });
1180
+
1181
+ // src/commands/policies.ts
1182
+ import { Cli as Cli4, z as z6 } from "incur";
1183
+ var policyScopes = ["project", "account", "transaction"];
1184
+ var policies = Cli4.create("policies", {
1185
+ description: "Manage access-control policies.",
1186
+ vars: varsSchema
1187
+ });
1188
+ policies.command("list", {
1189
+ description: "List policies.",
1190
+ options: z6.object({
1191
+ limit: z6.number().optional().describe("Max results"),
1192
+ skip: z6.number().optional().describe("Offset"),
1193
+ scope: z6.enum(policyScopes).optional().describe("Filter by scope"),
1194
+ enabled: z6.boolean().optional().describe("Filter by enabled status")
1195
+ }),
1196
+ alias: { limit: "l" },
1197
+ examples: [
1198
+ { description: "List all policies" },
1199
+ { options: { scope: "project", enabled: true }, description: "List enabled project-scope policies" }
1200
+ ],
1201
+ output: z6.object({
1202
+ data: z6.array(z6.object({
1203
+ id: z6.string(),
1204
+ createdAt: z6.number(),
1205
+ scope: z6.string(),
1206
+ description: z6.string().nullable(),
1207
+ accountId: z6.string().nullable(),
1208
+ enabled: z6.boolean(),
1209
+ priority: z6.number()
1210
+ })),
1211
+ total: z6.number()
1212
+ }),
1213
+ async run(c) {
1214
+ const scopeFilter = c.options.scope ? [c.options.scope] : void 0;
1215
+ const res = await c.var.openfort.policies.list({
1216
+ limit: c.options.limit,
1217
+ skip: c.options.skip,
1218
+ scope: scopeFilter,
1219
+ enabled: c.options.enabled
1220
+ });
1221
+ return c.ok({
1222
+ data: res.data.map((p) => ({
1223
+ id: p.id,
1224
+ createdAt: p.createdAt,
1225
+ scope: p.scope,
1226
+ description: p.description,
1227
+ accountId: p.accountId,
1228
+ enabled: p.enabled,
1229
+ priority: p.priority
1230
+ })),
1231
+ total: res.total
1232
+ });
1233
+ }
1234
+ });
1235
+ policies.command("create", {
1236
+ description: "Create a policy with criteria-based rules.",
1237
+ options: z6.object({
1238
+ scope: z6.enum(policyScopes).describe("Policy scope"),
1239
+ description: z6.string().optional().describe("Policy description"),
1240
+ priority: z6.number().optional().describe("Priority (higher = evaluated first)"),
1241
+ rules: z6.string().describe("Rules as JSON string")
1242
+ }),
1243
+ output: z6.object({
1244
+ id: z6.string(),
1245
+ createdAt: z6.number(),
1246
+ scope: z6.string(),
1247
+ description: z6.string().nullable(),
1248
+ enabled: z6.boolean(),
1249
+ priority: z6.number()
1250
+ }),
1251
+ examples: [
1252
+ {
1253
+ options: {
1254
+ scope: "project",
1255
+ rules: '[{"action":"accept","operation":"sponsorEvmTransaction","criteria":[{"type":"evmNetwork","operator":"in","chainIds":[137]}]}]'
1256
+ },
1257
+ description: "Create a policy to sponsor transactions on Polygon"
1258
+ }
1259
+ ],
1260
+ async run(c) {
1261
+ const rules = JSON.parse(c.options.rules);
1262
+ const scope = c.options.scope;
1263
+ const res = await c.var.openfort.policies.create({
1264
+ scope,
1265
+ description: c.options.description,
1266
+ priority: c.options.priority,
1267
+ rules
1268
+ });
1269
+ return c.ok(
1270
+ {
1271
+ id: res.id,
1272
+ createdAt: res.createdAt,
1273
+ scope: res.scope,
1274
+ description: res.description,
1275
+ enabled: res.enabled,
1276
+ priority: res.priority
1277
+ },
1278
+ {
1279
+ cta: {
1280
+ description: "Next steps:",
1281
+ commands: [
1282
+ { command: `policies get ${res.id}`, description: "View this policy" },
1283
+ { command: `sponsorship create --policyId ${res.id}`, description: "Create a fee sponsorship" }
1284
+ ]
1285
+ }
1286
+ }
1287
+ );
1288
+ }
1289
+ });
1290
+ policies.command("get", {
1291
+ description: "Get a policy by ID.",
1292
+ args: z6.object({
1293
+ id: z6.string().describe("Policy ID (ply_...)")
1294
+ }),
1295
+ examples: [
1296
+ { args: { id: "ply_1a2b3c4d" }, description: "Get policy details with rules" }
1297
+ ],
1298
+ output: z6.object({
1299
+ id: z6.string(),
1300
+ createdAt: z6.number(),
1301
+ scope: z6.string(),
1302
+ description: z6.string().nullable(),
1303
+ accountId: z6.string().nullable(),
1304
+ enabled: z6.boolean(),
1305
+ priority: z6.number(),
1306
+ rules: z6.array(z6.any())
1307
+ }),
1308
+ async run(c) {
1309
+ const p = await c.var.openfort.policies.get(c.args.id);
1310
+ return c.ok({
1311
+ id: p.id,
1312
+ createdAt: p.createdAt,
1313
+ scope: p.scope,
1314
+ description: p.description,
1315
+ accountId: p.accountId,
1316
+ enabled: p.enabled,
1317
+ priority: p.priority,
1318
+ rules: p.rules
1319
+ });
1320
+ }
1321
+ });
1322
+ policies.command("update", {
1323
+ description: "Update a policy.",
1324
+ args: z6.object({
1325
+ id: z6.string().describe("Policy ID (ply_...)")
1326
+ }),
1327
+ options: z6.object({
1328
+ description: z6.string().optional().describe("New description"),
1329
+ enabled: z6.boolean().optional().describe("Enable or disable"),
1330
+ priority: z6.number().optional().describe("New priority"),
1331
+ rules: z6.string().optional().describe("New rules as JSON string")
1332
+ }),
1333
+ examples: [
1334
+ { args: { id: "ply_1a2b3c4d" }, options: { enabled: false }, description: "Disable a policy" },
1335
+ { args: { id: "ply_1a2b3c4d" }, options: { priority: 10 }, description: "Change policy priority" }
1336
+ ],
1337
+ output: z6.object({
1338
+ id: z6.string(),
1339
+ createdAt: z6.number(),
1340
+ scope: z6.string(),
1341
+ description: z6.string().nullable(),
1342
+ enabled: z6.boolean(),
1343
+ priority: z6.number()
1344
+ }),
1345
+ async run(c) {
1346
+ const res = await c.var.openfort.policies.update(c.args.id, {
1347
+ description: c.options.description,
1348
+ enabled: c.options.enabled,
1349
+ priority: c.options.priority,
1350
+ rules: c.options.rules ? JSON.parse(c.options.rules) : void 0
1351
+ });
1352
+ return c.ok({
1353
+ id: res.id,
1354
+ createdAt: res.createdAt,
1355
+ scope: res.scope,
1356
+ description: res.description,
1357
+ enabled: res.enabled,
1358
+ priority: res.priority
1359
+ });
1360
+ }
1361
+ });
1362
+ policies.command("delete", {
1363
+ description: "Delete a policy.",
1364
+ args: z6.object({
1365
+ id: z6.string().describe("Policy ID (ply_...)")
1366
+ }),
1367
+ examples: [
1368
+ { args: { id: "ply_1a2b3c4d" }, description: "Delete a policy" }
1369
+ ],
1370
+ output: z6.object({
1371
+ id: z6.string(),
1372
+ deleted: z6.boolean()
1373
+ }),
1374
+ async run(c) {
1375
+ const res = await c.var.openfort.policies.delete(c.args.id);
1376
+ return c.ok({ id: res.id, deleted: res.deleted });
1377
+ }
1378
+ });
1379
+ policies.command("evaluate", {
1380
+ description: "Pre-flight check if an operation would be allowed.",
1381
+ options: z6.object({
1382
+ operation: z6.string().describe("Operation to evaluate (e.g. signEvmTransaction)"),
1383
+ accountId: z6.string().optional().describe("Account ID")
1384
+ }),
1385
+ examples: [
1386
+ { options: { operation: "signEvmTransaction", accountId: "acc_1a2b3c4d" }, description: "Check if EVM signing is allowed" },
1387
+ { options: { operation: "sponsorEvmTransaction" }, description: "Check if gas sponsorship is allowed" }
1388
+ ],
1389
+ output: z6.object({
1390
+ allowed: z6.boolean(),
1391
+ reason: z6.string(),
1392
+ operation: z6.string(),
1393
+ accountId: z6.string().optional(),
1394
+ matchedPolicyId: z6.string().optional(),
1395
+ matchedRuleId: z6.string().optional()
1396
+ }),
1397
+ async run(c) {
1398
+ const res = await c.var.openfort.policies.evaluate({
1399
+ operation: c.options.operation,
1400
+ accountId: c.options.accountId
1401
+ });
1402
+ return c.ok({
1403
+ allowed: res.allowed,
1404
+ reason: res.reason,
1405
+ operation: res.operation,
1406
+ accountId: res.accountId,
1407
+ matchedPolicyId: res.matchedPolicyId,
1408
+ matchedRuleId: res.matchedRuleId
1409
+ });
1410
+ }
1411
+ });
1412
+
1413
+ // src/commands/sponsorship.ts
1414
+ import { Cli as Cli5, z as z7 } from "incur";
1415
+ var sponsorSchemas = ["pay_for_user", "charge_custom_tokens", "fixed_rate"];
1416
+ var sponsorshipItem = z7.object({
1417
+ id: z7.string(),
1418
+ createdAt: z7.number(),
1419
+ name: z7.string().nullable(),
1420
+ chainId: z7.number().nullable(),
1421
+ enabled: z7.boolean(),
1422
+ strategy: z7.object({
1423
+ sponsorSchema: z7.string(),
1424
+ tokenContract: z7.string().optional(),
1425
+ tokenContractAmount: z7.string().optional(),
1426
+ dynamicExchangeRate: z7.boolean().optional()
1427
+ }),
1428
+ paymasterId: z7.string().nullable(),
1429
+ policyId: z7.string().nullable()
1430
+ });
1431
+ var sponsorship = Cli5.create("sponsorship", {
1432
+ description: "Manage fee sponsorships for gas costs.",
1433
+ vars: varsSchema
1434
+ });
1435
+ sponsorship.command("list", {
1436
+ description: "List fee sponsorships.",
1437
+ options: z7.object({
1438
+ limit: z7.number().optional().describe("Max results"),
1439
+ skip: z7.number().optional().describe("Offset"),
1440
+ enabled: z7.boolean().optional().describe("Filter by enabled status")
1441
+ }),
1442
+ alias: { limit: "l" },
1443
+ examples: [
1444
+ { description: "List all sponsorships" },
1445
+ { options: { enabled: true }, description: "List active sponsorships only" }
1446
+ ],
1447
+ output: z7.object({
1448
+ data: z7.array(sponsorshipItem),
1449
+ total: z7.number()
1450
+ }),
1451
+ async run(c) {
1452
+ const res = await c.var.openfort.feeSponsorship.list({
1453
+ limit: c.options.limit,
1454
+ skip: c.options.skip,
1455
+ enabled: c.options.enabled
1456
+ });
1457
+ return c.ok({
1458
+ data: res.data.map((s) => ({
1459
+ id: s.id,
1460
+ createdAt: s.createdAt,
1461
+ name: s.name,
1462
+ chainId: s.chainId,
1463
+ enabled: s.enabled,
1464
+ strategy: s.strategy,
1465
+ paymasterId: s.paymasterId,
1466
+ policyId: s.policyId
1467
+ })),
1468
+ total: res.total
1469
+ });
1470
+ }
1471
+ });
1472
+ sponsorship.command("create", {
1473
+ description: "Create a fee sponsorship linked to a policy.",
1474
+ options: z7.object({
1475
+ policyId: z7.string().describe("Policy ID to link (ply_...)"),
1476
+ name: z7.string().optional().describe("Sponsorship name"),
1477
+ strategy: z7.enum(sponsorSchemas).default("pay_for_user").describe("Sponsorship strategy"),
1478
+ chainId: z7.number().optional().describe("Chain ID")
1479
+ }),
1480
+ output: sponsorshipItem,
1481
+ examples: [
1482
+ {
1483
+ options: { policyId: "ply_1a2b3c4d", strategy: "pay_for_user", name: "Polygon Gas Sponsor" },
1484
+ description: "Sponsor gas fees for users on Polygon"
1485
+ },
1486
+ {
1487
+ options: { policyId: "ply_1a2b3c4d", strategy: "charge_custom_tokens", chainId: 137 },
1488
+ description: "Pay gas with custom tokens on chain 137"
1489
+ }
1490
+ ],
1491
+ async run(c) {
1492
+ const strategy = { sponsorSchema: c.options.strategy };
1493
+ const res = await c.var.openfort.feeSponsorship.create({
1494
+ policyId: c.options.policyId,
1495
+ name: c.options.name,
1496
+ strategy,
1497
+ chainId: c.options.chainId
1498
+ });
1499
+ return c.ok(
1500
+ {
1501
+ id: res.id,
1502
+ createdAt: res.createdAt,
1503
+ name: res.name,
1504
+ chainId: res.chainId,
1505
+ enabled: res.enabled,
1506
+ strategy: res.strategy,
1507
+ paymasterId: res.paymasterId,
1508
+ policyId: res.policyId
1509
+ },
1510
+ {
1511
+ cta: {
1512
+ description: "Next steps:",
1513
+ commands: [
1514
+ { command: `sponsorship get ${res.id}`, description: "View this sponsorship" },
1515
+ { command: "transactions create", description: "Create a sponsored transaction" }
1516
+ ]
1517
+ }
1518
+ }
1519
+ );
1520
+ }
1521
+ });
1522
+ sponsorship.command("get", {
1523
+ description: "Get a fee sponsorship by ID.",
1524
+ args: z7.object({
1525
+ id: z7.string().describe("Fee sponsorship ID (pol_...)")
1526
+ }),
1527
+ examples: [
1528
+ { args: { id: "pol_1a2b3c4d" }, description: "Get sponsorship details" }
1529
+ ],
1530
+ output: sponsorshipItem,
1531
+ async run(c) {
1532
+ const s = await c.var.openfort.feeSponsorship.get(c.args.id);
1533
+ return c.ok({
1534
+ id: s.id,
1535
+ createdAt: s.createdAt,
1536
+ name: s.name,
1537
+ chainId: s.chainId,
1538
+ enabled: s.enabled,
1539
+ strategy: s.strategy,
1540
+ paymasterId: s.paymasterId,
1541
+ policyId: s.policyId
1542
+ });
1543
+ }
1544
+ });
1545
+ sponsorship.command("update", {
1546
+ description: "Update a fee sponsorship.",
1547
+ args: z7.object({
1548
+ id: z7.string().describe("Fee sponsorship ID (pol_...)")
1549
+ }),
1550
+ options: z7.object({
1551
+ name: z7.string().optional().describe("New name"),
1552
+ strategy: z7.enum(sponsorSchemas).optional().describe("New strategy"),
1553
+ policyId: z7.string().optional().describe("New policy ID")
1554
+ }),
1555
+ examples: [
1556
+ { args: { id: "pol_1a2b3c4d" }, options: { name: "Mainnet Gas Sponsor" }, description: "Rename a sponsorship" }
1557
+ ],
1558
+ output: sponsorshipItem,
1559
+ async run(c) {
1560
+ const strategy = c.options.strategy ? { sponsorSchema: c.options.strategy } : void 0;
1561
+ const res = await c.var.openfort.feeSponsorship.update(c.args.id, {
1562
+ name: c.options.name,
1563
+ strategy,
1564
+ policyId: c.options.policyId
1565
+ });
1566
+ return c.ok({
1567
+ id: res.id,
1568
+ createdAt: res.createdAt,
1569
+ name: res.name,
1570
+ chainId: res.chainId,
1571
+ enabled: res.enabled,
1572
+ strategy: res.strategy,
1573
+ paymasterId: res.paymasterId,
1574
+ policyId: res.policyId
1575
+ });
1576
+ }
1577
+ });
1578
+ sponsorship.command("enable", {
1579
+ description: "Enable a fee sponsorship.",
1580
+ args: z7.object({
1581
+ id: z7.string().describe("Fee sponsorship ID (pol_...)")
1582
+ }),
1583
+ examples: [
1584
+ { args: { id: "pol_1a2b3c4d" }, description: "Enable a sponsorship" }
1585
+ ],
1586
+ output: sponsorshipItem,
1587
+ async run(c) {
1588
+ const res = await c.var.openfort.feeSponsorship.enable(c.args.id);
1589
+ return c.ok({
1590
+ id: res.id,
1591
+ createdAt: res.createdAt,
1592
+ name: res.name,
1593
+ chainId: res.chainId,
1594
+ enabled: res.enabled,
1595
+ strategy: res.strategy,
1596
+ paymasterId: res.paymasterId,
1597
+ policyId: res.policyId
1598
+ });
1599
+ }
1600
+ });
1601
+ sponsorship.command("disable", {
1602
+ description: "Disable a fee sponsorship.",
1603
+ args: z7.object({
1604
+ id: z7.string().describe("Fee sponsorship ID (pol_...)")
1605
+ }),
1606
+ examples: [
1607
+ { args: { id: "pol_1a2b3c4d" }, description: "Disable a sponsorship" }
1608
+ ],
1609
+ output: sponsorshipItem,
1610
+ async run(c) {
1611
+ const res = await c.var.openfort.feeSponsorship.disable(c.args.id);
1612
+ return c.ok({
1613
+ id: res.id,
1614
+ createdAt: res.createdAt,
1615
+ name: res.name,
1616
+ chainId: res.chainId,
1617
+ enabled: res.enabled,
1618
+ strategy: res.strategy,
1619
+ paymasterId: res.paymasterId,
1620
+ policyId: res.policyId
1621
+ });
1622
+ }
1623
+ });
1624
+ sponsorship.command("delete", {
1625
+ description: "Delete a fee sponsorship.",
1626
+ args: z7.object({
1627
+ id: z7.string().describe("Fee sponsorship ID (pol_...)")
1628
+ }),
1629
+ examples: [
1630
+ { args: { id: "pol_1a2b3c4d" }, description: "Delete a sponsorship" }
1631
+ ],
1632
+ output: z7.object({
1633
+ id: z7.string(),
1634
+ deleted: z7.boolean()
1635
+ }),
1636
+ async run(c) {
1637
+ const res = await c.var.openfort.feeSponsorship.delete(c.args.id);
1638
+ return c.ok({ id: res.id, deleted: res.deleted });
1639
+ }
1640
+ });
1641
+
1642
+ // src/commands/subscriptions.ts
1643
+ import { Cli as Cli6, z as z8 } from "incur";
1644
+ var apiTopics = [
1645
+ "transaction_intent.broadcast",
1646
+ "transaction_intent.successful",
1647
+ "transaction_intent.cancelled",
1648
+ "transaction_intent.failed",
1649
+ "balance.project",
1650
+ "balance.contract",
1651
+ "balance.dev_account",
1652
+ "test",
1653
+ "user.created",
1654
+ "user.updated",
1655
+ "user.deleted",
1656
+ "account.created"
1657
+ ];
1658
+ var apiTriggerTypes = ["webhook", "email"];
1659
+ var triggers = Cli6.create("triggers", {
1660
+ description: "Manage subscription triggers.",
1661
+ vars: varsSchema
1662
+ });
1663
+ triggers.command("list", {
1664
+ description: "List triggers for a subscription.",
1665
+ args: z8.object({
1666
+ subscriptionId: z8.string().describe("Subscription ID (sub_...)")
1667
+ }),
1668
+ examples: [
1669
+ { args: { subscriptionId: "sub_1a2b3c4d" }, description: "List triggers" }
1670
+ ],
1671
+ output: z8.object({
1672
+ data: z8.array(z8.object({
1673
+ id: z8.string(),
1674
+ createdAt: z8.number(),
1675
+ target: z8.string(),
1676
+ type: z8.string()
1677
+ }))
1678
+ }),
1679
+ async run(c) {
1680
+ const res = await c.var.openfort.triggers.list(c.args.subscriptionId);
1681
+ return c.ok({
1682
+ data: res.data.map((t) => ({
1683
+ id: t.id,
1684
+ createdAt: t.createdAt,
1685
+ target: t.target,
1686
+ type: t.type
1687
+ }))
1688
+ });
1689
+ }
1690
+ });
1691
+ triggers.command("create", {
1692
+ description: "Create a trigger for a subscription.",
1693
+ args: z8.object({
1694
+ subscriptionId: z8.string().describe("Subscription ID (sub_...)")
1695
+ }),
1696
+ options: z8.object({
1697
+ target: z8.string().describe("Webhook URL or email address"),
1698
+ type: z8.enum(apiTriggerTypes).default("webhook").describe("Trigger type: webhook or email")
1699
+ }),
1700
+ examples: [
1701
+ {
1702
+ args: { subscriptionId: "sub_1a2b3c4d" },
1703
+ options: { target: "https://myapp.com/webhooks", type: "webhook" },
1704
+ description: "Create a webhook trigger"
1705
+ }
1706
+ ],
1707
+ output: z8.object({
1708
+ id: z8.string(),
1709
+ createdAt: z8.number(),
1710
+ target: z8.string(),
1711
+ type: z8.string()
1712
+ }),
1713
+ async run(c) {
1714
+ const res = await c.var.openfort.triggers.create(c.args.subscriptionId, {
1715
+ target: c.options.target,
1716
+ type: c.options.type
1717
+ });
1718
+ return c.ok({
1719
+ id: res.id,
1720
+ createdAt: res.createdAt,
1721
+ target: res.target,
1722
+ type: res.type
1723
+ });
1724
+ }
1725
+ });
1726
+ triggers.command("get", {
1727
+ description: "Get a trigger by ID.",
1728
+ args: z8.object({
1729
+ subscriptionId: z8.string().describe("Subscription ID (sub_...)"),
1730
+ triggerId: z8.string().describe("Trigger ID (tri_...)")
1731
+ }),
1732
+ examples: [
1733
+ { args: { subscriptionId: "sub_1a2b3c4d", triggerId: "tri_1a2b3c4d" }, description: "Get trigger details" }
1734
+ ],
1735
+ output: z8.object({
1736
+ id: z8.string(),
1737
+ createdAt: z8.number(),
1738
+ target: z8.string(),
1739
+ type: z8.string()
1740
+ }),
1741
+ async run(c) {
1742
+ const t = await c.var.openfort.triggers.get(c.args.subscriptionId, c.args.triggerId);
1743
+ return c.ok({
1744
+ id: t.id,
1745
+ createdAt: t.createdAt,
1746
+ target: t.target,
1747
+ type: t.type
1748
+ });
1749
+ }
1750
+ });
1751
+ triggers.command("delete", {
1752
+ description: "Delete a trigger.",
1753
+ args: z8.object({
1754
+ subscriptionId: z8.string().describe("Subscription ID (sub_...)"),
1755
+ triggerId: z8.string().describe("Trigger ID (tri_...)")
1756
+ }),
1757
+ examples: [
1758
+ { args: { subscriptionId: "sub_1a2b3c4d", triggerId: "tri_1a2b3c4d" }, description: "Delete a trigger" }
1759
+ ],
1760
+ output: z8.object({
1761
+ id: z8.string(),
1762
+ deleted: z8.boolean()
1763
+ }),
1764
+ async run(c) {
1765
+ const res = await c.var.openfort.triggers.delete(c.args.subscriptionId, c.args.triggerId);
1766
+ return c.ok({ id: res.id, deleted: res.deleted });
1767
+ }
1768
+ });
1769
+ var subscriptions = Cli6.create("subscriptions", {
1770
+ description: "Manage webhook subscriptions.",
1771
+ vars: varsSchema
1772
+ });
1773
+ subscriptions.command("list", {
1774
+ description: "List webhook subscriptions.",
1775
+ examples: [
1776
+ { description: "List all subscriptions" }
1777
+ ],
1778
+ output: z8.object({
1779
+ data: z8.array(z8.object({
1780
+ id: z8.string(),
1781
+ createdAt: z8.number(),
1782
+ topic: z8.string(),
1783
+ triggers: z8.array(z8.object({
1784
+ id: z8.string(),
1785
+ target: z8.string(),
1786
+ type: z8.string()
1787
+ }))
1788
+ })),
1789
+ total: z8.number()
1790
+ }),
1791
+ async run(c) {
1792
+ const res = await c.var.openfort.subscriptions.list();
1793
+ return c.ok({
1794
+ data: res.data.map((s) => ({
1795
+ id: s.id,
1796
+ createdAt: s.createdAt,
1797
+ topic: s.topic,
1798
+ triggers: s.triggers
1799
+ })),
1800
+ total: res.total
1801
+ });
1802
+ }
1803
+ });
1804
+ subscriptions.command("create", {
1805
+ description: "Create a webhook subscription.",
1806
+ options: z8.object({
1807
+ topic: z8.enum(apiTopics).describe("Event topic (e.g. transaction_intent.successful, user.created)"),
1808
+ triggers: z8.string().describe('Triggers as JSON: [{"type":"webhook","target":"https://..."}]')
1809
+ }),
1810
+ examples: [
1811
+ {
1812
+ options: {
1813
+ topic: "transaction_intent.successful",
1814
+ triggers: '[{"type":"webhook","target":"https://myapp.com/webhooks/openfort"}]'
1815
+ },
1816
+ description: "Get notified when transactions succeed"
1817
+ }
1818
+ ],
1819
+ output: z8.object({
1820
+ id: z8.string(),
1821
+ createdAt: z8.number(),
1822
+ topic: z8.string(),
1823
+ triggers: z8.array(z8.object({
1824
+ id: z8.string(),
1825
+ target: z8.string(),
1826
+ type: z8.string()
1827
+ }))
1828
+ }),
1829
+ async run(c) {
1830
+ const parsedTriggers = JSON.parse(c.options.triggers);
1831
+ const res = await c.var.openfort.subscriptions.create({
1832
+ topic: c.options.topic,
1833
+ triggers: parsedTriggers
1834
+ });
1835
+ return c.ok(
1836
+ {
1837
+ id: res.id,
1838
+ createdAt: res.createdAt,
1839
+ topic: res.topic,
1840
+ triggers: res.triggers
1841
+ },
1842
+ {
1843
+ cta: {
1844
+ description: "Next steps:",
1845
+ commands: [
1846
+ { command: `subscriptions get ${res.id}`, description: "View this subscription" },
1847
+ { command: "subscriptions list", description: "List all subscriptions" }
1848
+ ]
1849
+ }
1850
+ }
1851
+ );
1852
+ }
1853
+ });
1854
+ subscriptions.command("get", {
1855
+ description: "Get a subscription by ID.",
1856
+ args: z8.object({
1857
+ id: z8.string().describe("Subscription ID (sub_...)")
1858
+ }),
1859
+ examples: [
1860
+ { args: { id: "sub_1a2b3c4d" }, description: "Get subscription details" }
1861
+ ],
1862
+ output: z8.object({
1863
+ id: z8.string(),
1864
+ createdAt: z8.number(),
1865
+ topic: z8.string(),
1866
+ triggers: z8.array(z8.object({
1867
+ id: z8.string(),
1868
+ target: z8.string(),
1869
+ type: z8.string()
1870
+ }))
1871
+ }),
1872
+ async run(c) {
1873
+ const s = await c.var.openfort.subscriptions.get(c.args.id);
1874
+ return c.ok({
1875
+ id: s.id,
1876
+ createdAt: s.createdAt,
1877
+ topic: s.topic,
1878
+ triggers: s.triggers
1879
+ });
1880
+ }
1881
+ });
1882
+ subscriptions.command("delete", {
1883
+ description: "Delete a subscription.",
1884
+ args: z8.object({
1885
+ id: z8.string().describe("Subscription ID (sub_...)")
1886
+ }),
1887
+ examples: [
1888
+ { args: { id: "sub_1a2b3c4d" }, description: "Delete a subscription" }
1889
+ ],
1890
+ output: z8.object({
1891
+ id: z8.string(),
1892
+ deleted: z8.boolean()
1893
+ }),
1894
+ async run(c) {
1895
+ const res = await c.var.openfort.subscriptions.delete(c.args.id);
1896
+ return c.ok({ id: res.id, deleted: res.deleted });
1897
+ }
1898
+ });
1899
+ subscriptions.command(triggers);
1900
+
1901
+ // src/commands/sessions.ts
1902
+ import { Cli as Cli7, z as z9 } from "incur";
1903
+ var sessionItem = z9.object({
1904
+ id: z9.string(),
1905
+ createdAt: z9.number(),
1906
+ updatedAt: z9.number(),
1907
+ address: z9.string(),
1908
+ validAfter: z9.string(),
1909
+ validUntil: z9.string(),
1910
+ whitelist: z9.array(z9.string()).optional(),
1911
+ isActive: z9.boolean(),
1912
+ nextAction: z9.object({
1913
+ type: z9.string(),
1914
+ payload: z9.any().optional()
1915
+ }).optional()
1916
+ });
1917
+ var sessions = Cli7.create("sessions", {
1918
+ description: "Manage session keys.",
1919
+ vars: varsSchema
1920
+ });
1921
+ sessions.command("list", {
1922
+ description: "List session keys for a player.",
1923
+ options: z9.object({
1924
+ player: z9.string().describe("Player ID (pla_...)"),
1925
+ limit: z9.number().optional().describe("Max results"),
1926
+ skip: z9.number().optional().describe("Offset")
1927
+ }),
1928
+ alias: { limit: "l" },
1929
+ examples: [
1930
+ { options: { player: "pla_1a2b3c4d" }, description: "List sessions for a player" }
1931
+ ],
1932
+ output: z9.object({
1933
+ data: z9.array(z9.object({
1934
+ id: z9.string(),
1935
+ createdAt: z9.number(),
1936
+ address: z9.string(),
1937
+ isActive: z9.boolean()
1938
+ })),
1939
+ total: z9.number()
1940
+ }),
1941
+ async run(c) {
1942
+ const res = await c.var.openfort.sessions.list({
1943
+ player: c.options.player,
1944
+ limit: c.options.limit,
1945
+ skip: c.options.skip
1946
+ });
1947
+ return c.ok({
1948
+ data: res.data.map((s) => ({
1949
+ id: s.id,
1950
+ createdAt: s.createdAt,
1951
+ address: s.address,
1952
+ isActive: s.isActive
1953
+ })),
1954
+ total: res.total
1955
+ });
1956
+ }
1957
+ });
1958
+ sessions.command("create", {
1959
+ description: "Create a session key.",
1960
+ options: z9.object({
1961
+ address: z9.string().describe("Session key address"),
1962
+ chainId: z9.number().describe("Chain ID"),
1963
+ validAfter: z9.number().describe("Valid after (unix timestamp in seconds)"),
1964
+ validUntil: z9.number().describe("Valid until (unix timestamp in seconds)"),
1965
+ player: z9.string().optional().describe("Player ID (pla_...)"),
1966
+ account: z9.string().optional().describe("Account ID (acc_...)"),
1967
+ limit: z9.number().optional().describe("Max session uses"),
1968
+ policy: z9.string().optional().describe("Policy ID for gas sponsorship (pol_...)"),
1969
+ whitelist: z9.string().optional().describe("Whitelisted contract addresses as JSON array")
1970
+ }),
1971
+ examples: [
1972
+ {
1973
+ options: {
1974
+ address: "0x1234...",
1975
+ chainId: 137,
1976
+ validAfter: 17e8,
1977
+ validUntil: 1700086400,
1978
+ player: "pla_1a2b3c4d"
1979
+ },
1980
+ description: "Create a 24h session key on Polygon"
1981
+ }
1982
+ ],
1983
+ output: sessionItem,
1984
+ async run(c) {
1985
+ const res = await c.var.openfort.sessions.create({
1986
+ address: c.options.address,
1987
+ chainId: c.options.chainId,
1988
+ validAfter: c.options.validAfter,
1989
+ validUntil: c.options.validUntil,
1990
+ player: c.options.player,
1991
+ account: c.options.account,
1992
+ limit: c.options.limit,
1993
+ policy: c.options.policy,
1994
+ whitelist: c.options.whitelist ? JSON.parse(c.options.whitelist) : void 0
1995
+ });
1996
+ return c.ok(
1997
+ {
1998
+ id: res.id,
1999
+ createdAt: res.createdAt,
2000
+ updatedAt: res.updatedAt,
2001
+ address: res.address,
2002
+ validAfter: res.validAfter,
2003
+ validUntil: res.validUntil,
2004
+ whitelist: res.whitelist,
2005
+ isActive: res.isActive,
2006
+ nextAction: res.nextAction
2007
+ },
2008
+ {
2009
+ cta: {
2010
+ description: "Next steps:",
2011
+ commands: [
2012
+ { command: `sessions get ${res.id}`, description: "View this session" }
2013
+ ]
2014
+ }
2015
+ }
2016
+ );
2017
+ }
2018
+ });
2019
+ sessions.command("get", {
2020
+ description: "Get a session key by ID.",
2021
+ args: z9.object({
2022
+ id: z9.string().describe("Session ID (ses_...)")
2023
+ }),
2024
+ examples: [
2025
+ { args: { id: "ses_1a2b3c4d" }, description: "Get session details" }
2026
+ ],
2027
+ output: sessionItem,
2028
+ async run(c) {
2029
+ const s = await c.var.openfort.sessions.get(c.args.id);
2030
+ return c.ok({
2031
+ id: s.id,
2032
+ createdAt: s.createdAt,
2033
+ updatedAt: s.updatedAt,
2034
+ address: s.address,
2035
+ validAfter: s.validAfter,
2036
+ validUntil: s.validUntil,
2037
+ whitelist: s.whitelist,
2038
+ isActive: s.isActive,
2039
+ nextAction: s.nextAction
2040
+ });
2041
+ }
2042
+ });
2043
+ sessions.command("revoke", {
2044
+ description: "Revoke a session key.",
2045
+ options: z9.object({
2046
+ address: z9.string().describe("Session key address to revoke"),
2047
+ chainId: z9.number().describe("Chain ID"),
2048
+ player: z9.string().optional().describe("Player ID (pla_...)"),
2049
+ policy: z9.string().optional().describe("Policy ID (pol_...)")
2050
+ }),
2051
+ examples: [
2052
+ { options: { address: "0x1234...", chainId: 137 }, description: "Revoke a session key" }
2053
+ ],
2054
+ output: sessionItem,
2055
+ async run(c) {
2056
+ const res = await c.var.openfort.sessions.revoke({
2057
+ address: c.options.address,
2058
+ chainId: c.options.chainId,
2059
+ player: c.options.player,
2060
+ policy: c.options.policy
2061
+ });
2062
+ return c.ok({
2063
+ id: res.id,
2064
+ createdAt: res.createdAt,
2065
+ updatedAt: res.updatedAt,
2066
+ address: res.address,
2067
+ validAfter: res.validAfter,
2068
+ validUntil: res.validUntil,
2069
+ whitelist: res.whitelist,
2070
+ isActive: res.isActive,
2071
+ nextAction: res.nextAction
2072
+ });
2073
+ }
2074
+ });
2075
+ sessions.command("sign", {
2076
+ description: "Sign and broadcast a session userOperationHash.",
2077
+ args: z9.object({
2078
+ id: z9.string().describe("Session ID (ses_...)")
2079
+ }),
2080
+ options: z9.object({
2081
+ signature: z9.string().describe("Hex signature"),
2082
+ optimistic: z9.boolean().optional().describe("Return before on-chain confirmation")
2083
+ }),
2084
+ examples: [
2085
+ { args: { id: "ses_1a2b3c4d" }, options: { signature: "0xabcd1234..." }, description: "Sign a session" }
2086
+ ],
2087
+ output: sessionItem,
2088
+ async run(c) {
2089
+ const res = await c.var.openfort.sessions.signature(c.args.id, {
2090
+ signature: c.options.signature,
2091
+ optimistic: c.options.optimistic
2092
+ });
2093
+ return c.ok({
2094
+ id: res.id,
2095
+ createdAt: res.createdAt,
2096
+ updatedAt: res.updatedAt,
2097
+ address: res.address,
2098
+ validAfter: res.validAfter,
2099
+ validUntil: res.validUntil,
2100
+ whitelist: res.whitelist,
2101
+ isActive: res.isActive,
2102
+ nextAction: res.nextAction
2103
+ });
2104
+ }
2105
+ });
2106
+
2107
+ // src/commands/transactions.ts
2108
+ import { Cli as Cli8, z as z10 } from "incur";
2109
+ var transactionIntentItem = z10.object({
2110
+ id: z10.string(),
2111
+ createdAt: z10.number(),
2112
+ updatedAt: z10.number(),
2113
+ chainId: z10.number(),
2114
+ abstractionType: z10.string().describe("e.g. accountAbstractionV6, standard"),
2115
+ userOperationHash: z10.string().optional(),
2116
+ response: z10.object({
2117
+ createdAt: z10.number(),
2118
+ blockNumber: z10.number().optional(),
2119
+ transactionHash: z10.string().optional(),
2120
+ gasUsed: z10.string().optional(),
2121
+ gasFee: z10.string().optional(),
2122
+ status: z10.number().optional(),
2123
+ to: z10.string().optional(),
2124
+ error: z10.any().optional()
2125
+ }).optional(),
2126
+ interactions: z10.array(z10.object({
2127
+ to: z10.string().optional(),
2128
+ data: z10.string().optional(),
2129
+ value: z10.string().optional()
2130
+ })).optional(),
2131
+ nextAction: z10.object({
2132
+ type: z10.string(),
2133
+ payload: z10.any().optional()
2134
+ }).optional()
2135
+ });
2136
+ var transactions = Cli8.create("transactions", {
2137
+ description: "Manage transaction intents.",
2138
+ vars: varsSchema
2139
+ });
2140
+ transactions.command("list", {
2141
+ description: "List transaction intents.",
2142
+ options: z10.object({
2143
+ limit: z10.number().optional().describe("Max results"),
2144
+ skip: z10.number().optional().describe("Offset")
2145
+ }),
2146
+ alias: { limit: "l" },
2147
+ examples: [
2148
+ { description: "List all transactions" },
2149
+ { options: { limit: 10 }, description: "List last 10 transactions" }
2150
+ ],
2151
+ output: z10.object({
2152
+ data: z10.array(z10.object({
2153
+ id: z10.string(),
2154
+ createdAt: z10.number(),
2155
+ updatedAt: z10.number(),
2156
+ chainId: z10.number(),
2157
+ abstractionType: z10.string()
2158
+ })),
2159
+ total: z10.number()
2160
+ }),
2161
+ async run(c) {
2162
+ const res = await c.var.openfort.transactionIntents.list({
2163
+ limit: c.options.limit,
2164
+ skip: c.options.skip
2165
+ });
2166
+ return c.ok({
2167
+ data: res.data.map((t) => ({
2168
+ id: t.id,
2169
+ createdAt: t.createdAt,
2170
+ updatedAt: t.updatedAt,
2171
+ chainId: t.chainId,
2172
+ abstractionType: t.abstractionType
2173
+ })),
2174
+ total: res.total
2175
+ });
2176
+ }
2177
+ });
2178
+ transactions.command("create", {
2179
+ description: "Create a transaction intent.",
2180
+ options: z10.object({
2181
+ account: z10.string().describe("Account ID (acc_...)"),
2182
+ chainId: z10.number().describe("Chain ID"),
2183
+ interactions: z10.string().describe('Interactions as JSON: [{"to":"0x...","data":"0x...","value":"0"}]'),
2184
+ policy: z10.string().optional().describe("Policy ID for gas sponsorship"),
2185
+ signedAuthorization: z10.string().optional().describe("Signed EIP-7702 authorization hex (for delegated accounts)")
2186
+ }),
2187
+ output: transactionIntentItem,
2188
+ examples: [
2189
+ {
2190
+ options: {
2191
+ account: "acc_1a2b3c4d",
2192
+ chainId: 137,
2193
+ interactions: '[{"to":"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359","data":"0xa9059cbb000000...","value":"0"}]'
2194
+ },
2195
+ description: "Transfer USDC on Polygon"
2196
+ },
2197
+ {
2198
+ options: {
2199
+ account: "acc_1a2b3c4d",
2200
+ chainId: 137,
2201
+ interactions: '[{"to":"0x742d35Cc6634C0532925a3b844Bc9e7595f92cD5","value":"1000000000000000000"}]',
2202
+ policy: "ply_1a2b3c4d"
2203
+ },
2204
+ description: "Send 1 MATIC with gas sponsorship"
2205
+ }
2206
+ ],
2207
+ async run(c) {
2208
+ const interactions = JSON.parse(c.options.interactions);
2209
+ const res = await c.var.openfort.transactionIntents.create({
2210
+ account: c.options.account,
2211
+ chainId: c.options.chainId,
2212
+ interactions,
2213
+ policy: c.options.policy,
2214
+ signedAuthorization: c.options.signedAuthorization
2215
+ });
2216
+ return c.ok(
2217
+ {
2218
+ id: res.id,
2219
+ createdAt: res.createdAt,
2220
+ updatedAt: res.updatedAt,
2221
+ chainId: res.chainId,
2222
+ abstractionType: res.abstractionType,
2223
+ userOperationHash: res.userOperationHash,
2224
+ response: res.response,
2225
+ interactions: res.interactions,
2226
+ nextAction: res.nextAction
2227
+ },
2228
+ {
2229
+ cta: {
2230
+ description: "Next steps:",
2231
+ commands: [
2232
+ { command: `transactions get ${res.id}`, description: "Check transaction status" }
2233
+ ]
2234
+ }
2235
+ }
2236
+ );
2237
+ }
2238
+ });
2239
+ transactions.command("get", {
2240
+ description: "Get a transaction intent by ID.",
2241
+ args: z10.object({
2242
+ id: z10.string().describe("Transaction intent ID (tin_...)")
2243
+ }),
2244
+ examples: [
2245
+ { args: { id: "tin_1a2b3c4d" }, description: "Get transaction status and receipt" }
2246
+ ],
2247
+ output: transactionIntentItem,
2248
+ async run(c) {
2249
+ const t = await c.var.openfort.transactionIntents.get(c.args.id);
2250
+ return c.ok({
2251
+ id: t.id,
2252
+ createdAt: t.createdAt,
2253
+ updatedAt: t.updatedAt,
2254
+ chainId: t.chainId,
2255
+ abstractionType: t.abstractionType,
2256
+ userOperationHash: t.userOperationHash,
2257
+ response: t.response,
2258
+ interactions: t.interactions,
2259
+ nextAction: t.nextAction
2260
+ });
2261
+ }
2262
+ });
2263
+ transactions.command("sign", {
2264
+ description: "Sign and broadcast a transaction intent.",
2265
+ args: z10.object({
2266
+ id: z10.string().describe("Transaction intent ID (tin_...)")
2267
+ }),
2268
+ options: z10.object({
2269
+ signature: z10.string().describe("Hex signature"),
2270
+ optimistic: z10.boolean().optional().describe("Return before on-chain confirmation")
2271
+ }),
2272
+ examples: [
2273
+ { args: { id: "tin_1a2b3c4d" }, options: { signature: "0xabcd1234..." }, description: "Sign and broadcast a transaction" },
2274
+ { args: { id: "tin_1a2b3c4d" }, options: { signature: "0xabcd1234...", optimistic: true }, description: "Sign without waiting for on-chain confirmation" }
2275
+ ],
2276
+ output: transactionIntentItem,
2277
+ async run(c) {
2278
+ const res = await c.var.openfort.transactionIntents.signature(c.args.id, {
2279
+ signature: c.options.signature,
2280
+ optimistic: c.options.optimistic
2281
+ });
2282
+ return c.ok(
2283
+ {
2284
+ id: res.id,
2285
+ createdAt: res.createdAt,
2286
+ updatedAt: res.updatedAt,
2287
+ chainId: res.chainId,
2288
+ abstractionType: res.abstractionType,
2289
+ userOperationHash: res.userOperationHash,
2290
+ response: res.response,
2291
+ interactions: res.interactions,
2292
+ nextAction: res.nextAction
2293
+ },
2294
+ {
2295
+ cta: {
2296
+ description: "Next steps:",
2297
+ commands: [
2298
+ { command: `transactions get ${res.id}`, description: "Check transaction status" }
2299
+ ]
2300
+ }
2301
+ }
2302
+ );
2303
+ }
2304
+ });
2305
+ transactions.command("estimate", {
2306
+ description: "Estimate gas cost for a transaction.",
2307
+ options: z10.object({
2308
+ account: z10.string().describe("Account ID (acc_...)"),
2309
+ chainId: z10.number().describe("Chain ID"),
2310
+ interactions: z10.string().describe("Interactions as JSON"),
2311
+ policy: z10.string().optional().describe("Policy ID for gas sponsorship")
2312
+ }),
2313
+ examples: [
2314
+ {
2315
+ options: { account: "acc_1a2b3c4d", chainId: 137, interactions: '[{"to":"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359","data":"0xa9059cbb...","value":"0"}]' },
2316
+ description: "Estimate gas for a USDC transfer on Polygon"
2317
+ }
2318
+ ],
2319
+ output: z10.object({
2320
+ estimatedTXGas: z10.string(),
2321
+ estimatedTXGasFee: z10.string(),
2322
+ estimatedTXGasFeeUSD: z10.string(),
2323
+ estimatedTXGasFeeToken: z10.string().optional(),
2324
+ gasPrice: z10.string()
2325
+ }),
2326
+ async run(c) {
2327
+ const interactions = JSON.parse(c.options.interactions);
2328
+ const res = await c.var.openfort.transactionIntents.estimateCost({
2329
+ account: c.options.account,
2330
+ chainId: c.options.chainId,
2331
+ interactions,
2332
+ policy: c.options.policy
2333
+ });
2334
+ return c.ok({
2335
+ estimatedTXGas: res.estimatedTXGas,
2336
+ estimatedTXGasFee: res.estimatedTXGasFee,
2337
+ estimatedTXGasFeeUSD: res.estimatedTXGasFeeUSD,
2338
+ estimatedTXGasFeeToken: res.estimatedTXGasFeeToken,
2339
+ gasPrice: res.gasPrice
2340
+ });
2341
+ }
2342
+ });
2343
+
2344
+ // src/commands/shield.ts
2345
+ import { Cli as Cli9, z as z11, Errors as Errors2 } from "incur";
2346
+ var SHIELD_API_URL = OPENFORT_SHIELD_URL;
2347
+ var shield = Cli9.create("shield", {
2348
+ description: "Manage Shield (embedded wallet) API keys.",
2349
+ vars: varsSchema
2350
+ });
2351
+ shield.command("create", {
2352
+ description: "Create Shield API keys for embedded wallets.",
2353
+ options: z11.object({
2354
+ project: z11.string().optional().describe("Project ID (pro_...). Defaults to OPENFORT_PROJECT_ID env var.")
2355
+ }),
2356
+ alias: { project: "p" },
2357
+ output: z11.object({
2358
+ message: z11.string(),
2359
+ credentialsPath: z11.string()
2360
+ }),
2361
+ examples: [
2362
+ {
2363
+ options: { project: "pro_abc123" },
2364
+ description: "Create Shield keys for a project"
2365
+ }
2366
+ ],
2367
+ async run(c) {
2368
+ const publishableKey = process.env.OPENFORT_PUBLISHABLE_KEY;
2369
+ if (!publishableKey) {
2370
+ throw new Errors2.IncurError({
2371
+ code: "MISSING_PUBLISHABLE_KEY",
2372
+ message: "OPENFORT_PUBLISHABLE_KEY environment variable is required to create Shield keys.",
2373
+ hint: "Run: openfort login"
2374
+ });
2375
+ }
2376
+ const apiKey = process.env.OPENFORT_API_KEY;
2377
+ const environment = apiKey.startsWith("sk_live_") ? "live" : "test";
2378
+ const projectId = c.options.project || process.env.OPENFORT_PROJECT_ID;
2379
+ if (!projectId) {
2380
+ throw new Errors2.IncurError({
2381
+ code: "MISSING_PROJECT_ID",
2382
+ message: "Project ID is required. Pass --project or set OPENFORT_PROJECT_ID.",
2383
+ hint: "Run: openfort login"
2384
+ });
2385
+ }
2386
+ const registerRes = await fetch(`${SHIELD_API_URL}/register`, {
2387
+ method: "POST",
2388
+ headers: {
2389
+ "Content-Type": "application/json",
2390
+ "x-api-key": publishableKey
2391
+ },
2392
+ body: JSON.stringify({
2393
+ name: `${projectId}-${environment}`,
2394
+ generate_encryption_key: true,
2395
+ enable_2fa: false
2396
+ })
2397
+ });
2398
+ if (!registerRes.ok) {
2399
+ const text = await registerRes.text();
2400
+ throw new Errors2.IncurError({
2401
+ code: "SHIELD_REGISTER_FAILED",
2402
+ message: `Shield registration failed: ${text}`
2403
+ });
2404
+ }
2405
+ const shieldData = await registerRes.json();
2406
+ if (shieldData.error) {
2407
+ throw new Errors2.IncurError({
2408
+ code: "SHIELD_REGISTER_ERROR",
2409
+ message: `Shield registration error: ${shieldData.error}`
2410
+ });
2411
+ }
2412
+ const persistKey = async (type, uuid) => {
2413
+ const res = await fetch(`${API_BASE_URL}/v1/project/apikey`, {
2414
+ method: "PUT",
2415
+ headers: {
2416
+ "Content-Type": "application/json",
2417
+ Authorization: `Bearer ${apiKey}`
2418
+ },
2419
+ body: JSON.stringify({ type, uuid })
2420
+ });
2421
+ if (!res.ok) {
2422
+ const text = await res.text();
2423
+ throw new Errors2.IncurError({
2424
+ code: "PERSIST_KEY_FAILED",
2425
+ message: `Failed to persist ${type} key: ${text}`
2426
+ });
2427
+ }
2428
+ };
2429
+ await Promise.all([
2430
+ persistKey("pk_shield", shieldData.api_key),
2431
+ persistKey("sk_shield", shieldData.api_secret)
2432
+ ]);
2433
+ const linkRes = await fetch(`${SHIELD_API_URL}/project/providers`, {
2434
+ method: "POST",
2435
+ headers: {
2436
+ "Content-Type": "application/json",
2437
+ "x-api-key": shieldData.api_key,
2438
+ "x-api-secret": shieldData.api_secret
2439
+ },
2440
+ body: JSON.stringify({
2441
+ providers: {
2442
+ openfort: {
2443
+ publishable_key: `pk_${environment}_${publishableKey}`
2444
+ }
2445
+ }
2446
+ })
2447
+ });
2448
+ if (!linkRes.ok) {
2449
+ const text = await linkRes.text();
2450
+ throw new Errors2.IncurError({
2451
+ code: "SHIELD_LINK_FAILED",
2452
+ message: `Failed to link Openfort provider to Shield: ${text}`
2453
+ });
2454
+ }
2455
+ ensureConfigDir();
2456
+ writeEnvKey(CREDENTIALS_PATH, "SHIELD_PUBLISHABLE_KEY", shieldData.api_key);
2457
+ writeEnvKey(CREDENTIALS_PATH, "SHIELD_SECRET_KEY", shieldData.api_secret);
2458
+ writeEnvKey(CREDENTIALS_PATH, "SHIELD_ENCRYPTION_SHARE", shieldData.encryption_part);
2459
+ return c.ok(
2460
+ { message: `Shield keys were created and saved to ${CREDENTIALS_PATH}`, credentialsPath: CREDENTIALS_PATH },
2461
+ {
2462
+ cta: {
2463
+ description: "Next steps:",
2464
+ commands: [
2465
+ { command: "accounts evm list", description: "List your accounts" },
2466
+ { command: "contracts list", description: "List your contracts" },
2467
+ { command: "policies list", description: "List your policies" }
2468
+ ]
2469
+ }
2470
+ }
2471
+ );
2472
+ }
2473
+ });
2474
+
2475
+ // src/commands/users.ts
2476
+ import { Cli as Cli10, z as z12 } from "incur";
2477
+ var userItem = z12.object({
2478
+ id: z12.string(),
2479
+ createdAt: z12.number(),
2480
+ name: z12.string(),
2481
+ email: z12.string().nullable(),
2482
+ emailVerified: z12.boolean(),
2483
+ phoneNumber: z12.string().nullable(),
2484
+ phoneNumberVerified: z12.boolean(),
2485
+ isAnonymous: z12.boolean().optional(),
2486
+ linkedAccounts: z12.array(z12.object({
2487
+ provider: z12.string(),
2488
+ createdAt: z12.number(),
2489
+ updatedAt: z12.number(),
2490
+ accountId: z12.string().optional(),
2491
+ chainType: z12.string().optional(),
2492
+ connectorType: z12.string().optional(),
2493
+ walletClientType: z12.string().optional()
2494
+ }))
2495
+ });
2496
+ var users = Cli10.create("users", {
2497
+ description: "Manage authenticated users.",
2498
+ vars: varsSchema
2499
+ });
2500
+ users.command("list", {
2501
+ description: "List users.",
2502
+ options: z12.object({
2503
+ limit: z12.number().optional().describe("Max results"),
2504
+ skip: z12.number().optional().describe("Offset"),
2505
+ email: z12.string().optional().describe("Filter by email"),
2506
+ name: z12.string().optional().describe("Filter by name")
2507
+ }),
2508
+ alias: { limit: "l" },
2509
+ examples: [
2510
+ { description: "List all users" },
2511
+ { options: { email: "user@example.com" }, description: "Find user by email" }
2512
+ ],
2513
+ output: z12.object({
2514
+ data: z12.array(userItem),
2515
+ total: z12.number()
2516
+ }),
2517
+ async run(c) {
2518
+ const res = await c.var.openfort.iam.users.list({
2519
+ limit: c.options.limit,
2520
+ skip: c.options.skip,
2521
+ email: c.options.email,
2522
+ name: c.options.name
2523
+ });
2524
+ return c.ok({
2525
+ data: res.data.map((u) => ({
2526
+ id: u.id,
2527
+ createdAt: u.createdAt,
2528
+ name: u.name,
2529
+ email: u.email,
2530
+ emailVerified: u.emailVerified,
2531
+ phoneNumber: u.phoneNumber,
2532
+ phoneNumberVerified: u.phoneNumberVerified,
2533
+ isAnonymous: u.isAnonymous,
2534
+ linkedAccounts: u.linkedAccounts
2535
+ })),
2536
+ total: res.total
2537
+ });
2538
+ }
2539
+ });
2540
+ users.command("get", {
2541
+ description: "Get a user by ID.",
2542
+ args: z12.object({
2543
+ id: z12.string().describe("User ID (usr_...)")
2544
+ }),
2545
+ examples: [
2546
+ { args: { id: "usr_1a2b3c4d" }, description: "Get user profile and linked accounts" }
2547
+ ],
2548
+ output: userItem,
2549
+ async run(c) {
2550
+ const u = await c.var.openfort.iam.users.get(c.args.id);
2551
+ return c.ok({
2552
+ id: u.id,
2553
+ createdAt: u.createdAt,
2554
+ name: u.name,
2555
+ email: u.email,
2556
+ emailVerified: u.emailVerified,
2557
+ phoneNumber: u.phoneNumber,
2558
+ phoneNumberVerified: u.phoneNumberVerified,
2559
+ isAnonymous: u.isAnonymous,
2560
+ linkedAccounts: u.linkedAccounts
2561
+ });
2562
+ }
2563
+ });
2564
+ users.command("delete", {
2565
+ description: "Delete a user.",
2566
+ args: z12.object({
2567
+ id: z12.string().describe("User ID (usr_...)")
2568
+ }),
2569
+ examples: [
2570
+ { args: { id: "usr_1a2b3c4d" }, description: "Delete a user and their accounts" }
2571
+ ],
2572
+ output: z12.object({
2573
+ id: z12.string(),
2574
+ deleted: z12.boolean()
2575
+ }),
2576
+ async run(c) {
2577
+ const res = await c.var.openfort.iam.users.delete(c.args.id);
2578
+ return c.ok({ id: res.id, deleted: res.deleted });
2579
+ }
2580
+ });
2581
+
2582
+ // src/commands/wallet-keys.ts
2583
+ import { randomBytes as randomBytes2, subtle } from "crypto";
2584
+ import { Cli as Cli11, z as z13, Errors as Errors3 } from "incur";
2585
+ function arrayBufferToBase64(buffer) {
2586
+ return Buffer.from(buffer).toString("base64");
2587
+ }
2588
+ function arrayBufferToBase64Url(buffer) {
2589
+ return Buffer.from(buffer).toString("base64url");
2590
+ }
2591
+ function stringToArrayBuffer(str) {
2592
+ return new TextEncoder().encode(str).buffer;
2593
+ }
2594
+ function formatPEMBody(base64) {
2595
+ return base64.match(/.{1,64}/g)?.join("\n") || base64;
2596
+ }
2597
+ function sortObjectKeys(obj) {
2598
+ if (obj === null || typeof obj !== "object") return obj;
2599
+ if (Array.isArray(obj)) return obj.map(sortObjectKeys);
2600
+ const sorted = {};
2601
+ for (const key of Object.keys(obj).sort()) {
2602
+ sorted[key] = sortObjectKeys(obj[key]);
2603
+ }
2604
+ return sorted;
2605
+ }
2606
+ async function importPrivateKey(base64) {
2607
+ const binaryDer = Buffer.from(base64, "base64");
2608
+ return subtle.importKey(
2609
+ "pkcs8",
2610
+ binaryDer,
2611
+ { name: "ECDSA", namedCurve: "P-256" },
2612
+ false,
2613
+ ["sign"]
2614
+ );
2615
+ }
2616
+ async function generateKeyPair() {
2617
+ const keyPair = await subtle.generateKey(
2618
+ { name: "ECDSA", namedCurve: "P-256" },
2619
+ true,
2620
+ ["sign", "verify"]
2621
+ );
2622
+ const spki = await subtle.exportKey("spki", keyPair.publicKey);
2623
+ const pkcs8 = await subtle.exportKey("pkcs8", keyPair.privateKey);
2624
+ return {
2625
+ publicKey: formatPEMBody(arrayBufferToBase64(spki)),
2626
+ privateKey: formatPEMBody(arrayBufferToBase64(pkcs8)),
2627
+ privateKeyCrypto: keyPair.privateKey
2628
+ };
2629
+ }
2630
+ async function signWalletAuthJwt(privateKey, method, path, body) {
2631
+ const sortedJson = JSON.stringify(sortObjectKeys(body));
2632
+ const hashBuffer = await subtle.digest("SHA-256", stringToArrayBuffer(sortedJson));
2633
+ const reqHash = Buffer.from(hashBuffer).toString("hex");
2634
+ const now = Math.floor(Date.now() / 1e3);
2635
+ const jti = randomBytes2(16).toString("hex");
2636
+ const header = { alg: "ES256", typ: "JWT" };
2637
+ const payload = {
2638
+ uris: [`${method.toUpperCase()} ${path}`],
2639
+ reqHash,
2640
+ iat: now,
2641
+ nbf: now,
2642
+ jti
2643
+ };
2644
+ const headerB64 = arrayBufferToBase64Url(stringToArrayBuffer(JSON.stringify(header)));
2645
+ const payloadB64 = arrayBufferToBase64Url(stringToArrayBuffer(JSON.stringify(payload)));
2646
+ const signingInput = `${headerB64}.${payloadB64}`;
2647
+ const signature = await subtle.sign(
2648
+ { name: "ECDSA", hash: { name: "SHA-256" } },
2649
+ privateKey,
2650
+ stringToArrayBuffer(signingInput)
2651
+ );
2652
+ return `${signingInput}.${arrayBufferToBase64Url(signature)}`;
2653
+ }
2654
+ var walletKeys = Cli11.create("wallet-keys", {
2655
+ description: "Manage backend wallet keys.",
2656
+ vars: varsSchema
2657
+ });
2658
+ walletKeys.command("create", {
2659
+ description: "Create backend wallet keys (ECDSA P-256).",
2660
+ output: z13.object({
2661
+ message: z13.string(),
2662
+ credentialsPath: z13.string()
2663
+ }),
2664
+ examples: [
2665
+ {
2666
+ description: "Create backend wallet keys and save to credentials"
2667
+ }
2668
+ ],
2669
+ async run(c) {
2670
+ const apiKey = process.env.OPENFORT_API_KEY;
2671
+ const { publicKey, privateKey, privateKeyCrypto } = await generateKeyPair();
2672
+ const publicKeyPEM = `-----BEGIN PUBLIC KEY-----
2673
+ ${publicKey}
2674
+ -----END PUBLIC KEY-----`;
2675
+ const path = "/v2/accounts/backend/register-secret";
2676
+ const keyId = `ws_${Date.now()}`;
2677
+ const bodyWithoutToken = { publicKey: publicKeyPEM, keyId };
2678
+ const jwt = await signWalletAuthJwt(privateKeyCrypto, "POST", path, bodyWithoutToken);
2679
+ const registerRes = await fetch(`${API_BASE_URL}${path}`, {
2680
+ method: "POST",
2681
+ headers: {
2682
+ "Content-Type": "application/json",
2683
+ Authorization: `Bearer ${apiKey}`
2684
+ },
2685
+ body: JSON.stringify({
2686
+ ...bodyWithoutToken,
2687
+ walletAuthToken: jwt
2688
+ })
2689
+ });
2690
+ if (!registerRes.ok) {
2691
+ const text = await registerRes.text();
2692
+ throw new Errors3.IncurError({
2693
+ code: "REGISTER_SECRET_FAILED",
2694
+ message: `Failed to register wallet secret: ${text}`
2695
+ });
2696
+ }
2697
+ const storeRes = await fetch(`${API_BASE_URL}/v1/project/apikey`, {
2698
+ method: "PUT",
2699
+ headers: {
2700
+ "Content-Type": "application/json",
2701
+ Authorization: `Bearer ${apiKey}`
2702
+ },
2703
+ body: JSON.stringify({ type: "pk_wallet", uuid: publicKey })
2704
+ });
2705
+ if (!storeRes.ok) {
2706
+ const text = await storeRes.text();
2707
+ throw new Errors3.IncurError({
2708
+ code: "STORE_KEY_FAILED",
2709
+ message: `Failed to store wallet key reference: ${text}`
2710
+ });
2711
+ }
2712
+ ensureConfigDir();
2713
+ writeEnvKey(CREDENTIALS_PATH, "OPENFORT_WALLET_PUBLIC_KEY", publicKey.replaceAll("\n", ""));
2714
+ writeEnvKey(CREDENTIALS_PATH, "OPENFORT_WALLET_SECRET", privateKey.replaceAll("\n", ""));
2715
+ writeEnvKey(CREDENTIALS_PATH, "OPENFORT_WALLET_KEY_ID", keyId);
2716
+ return c.ok(
2717
+ { message: `Backend wallet keys were created and saved to ${CREDENTIALS_PATH}`, credentialsPath: CREDENTIALS_PATH },
2718
+ {
2719
+ cta: {
2720
+ description: "Next steps:",
2721
+ commands: [
2722
+ { command: `shield create`, description: "Create and save Shield API keys" }
2723
+ ]
2724
+ }
2725
+ }
2726
+ );
2727
+ }
2728
+ });
2729
+ walletKeys.command("revoke", {
2730
+ description: "Revoke the current backend wallet secret.",
2731
+ output: z13.object({
2732
+ keyId: z13.string(),
2733
+ revoked: z13.boolean(),
2734
+ revokedAt: z13.number()
2735
+ }),
2736
+ examples: [
2737
+ {
2738
+ description: "Revoke the current wallet secret"
2739
+ }
2740
+ ],
2741
+ async run(c) {
2742
+ const apiKey = process.env.OPENFORT_API_KEY;
2743
+ const keyId = process.env.OPENFORT_WALLET_KEY_ID;
2744
+ const privateKeyBase64 = process.env.OPENFORT_WALLET_SECRET;
2745
+ if (!keyId || !privateKeyBase64) {
2746
+ throw new Errors3.IncurError({
2747
+ code: "MISSING_WALLET_KEY",
2748
+ message: "OPENFORT_WALLET_KEY_ID and OPENFORT_WALLET_SECRET must be set. Create a wallet secret first with `wallet-keys create`."
2749
+ });
2750
+ }
2751
+ const privateKeyCrypto = await importPrivateKey(privateKeyBase64);
2752
+ const path = "/v2/accounts/backend/revoke-secret";
2753
+ const body = { keyId };
2754
+ const jwt = await signWalletAuthJwt(privateKeyCrypto, "POST", path, body);
2755
+ const res = await fetch(`${API_BASE_URL}${path}`, {
2756
+ method: "POST",
2757
+ headers: {
2758
+ "Content-Type": "application/json",
2759
+ Authorization: `Bearer ${apiKey}`,
2760
+ "x-wallet-auth": jwt
2761
+ },
2762
+ body: JSON.stringify(body)
2763
+ });
2764
+ if (!res.ok) {
2765
+ const text = await res.text();
2766
+ throw new Errors3.IncurError({
2767
+ code: "REVOKE_SECRET_FAILED",
2768
+ message: `Failed to revoke wallet secret: ${text}`
2769
+ });
2770
+ }
2771
+ const data = await res.json();
2772
+ return c.ok(data);
2773
+ }
2774
+ });
2775
+ walletKeys.command("rotate", {
2776
+ description: "Rotate backend wallet secret (generates new ECDSA P-256 key pair).",
2777
+ output: z13.object({
2778
+ message: z13.string(),
2779
+ credentialsPath: z13.string()
2780
+ }),
2781
+ examples: [
2782
+ {
2783
+ description: "Rotate wallet secret and save new keys to credentials"
2784
+ }
2785
+ ],
2786
+ async run(c) {
2787
+ const apiKey = process.env.OPENFORT_API_KEY;
2788
+ const { publicKey, privateKey, privateKeyCrypto } = await generateKeyPair();
2789
+ const newPublicKeyPEM = `-----BEGIN PUBLIC KEY-----
2790
+ ${publicKey}
2791
+ -----END PUBLIC KEY-----`;
2792
+ const path = "/v2/accounts/backend/rotate-secrets";
2793
+ const newKeyId = `ws_${Date.now()}`;
2794
+ const bodyWithoutToken = { newPublicKey: newPublicKeyPEM, newKeyId };
2795
+ const jwt = await signWalletAuthJwt(privateKeyCrypto, "POST", path, bodyWithoutToken);
2796
+ const rotateRes = await fetch(`${API_BASE_URL}${path}`, {
2797
+ method: "POST",
2798
+ headers: {
2799
+ "Content-Type": "application/json",
2800
+ Authorization: `Bearer ${apiKey}`
2801
+ },
2802
+ body: JSON.stringify({
2803
+ ...bodyWithoutToken,
2804
+ walletAuthToken: jwt
2805
+ })
2806
+ });
2807
+ if (!rotateRes.ok) {
2808
+ const text = await rotateRes.text();
2809
+ throw new Errors3.IncurError({
2810
+ code: "ROTATE_SECRET_FAILED",
2811
+ message: `Failed to rotate wallet secret: ${text}`
2812
+ });
2813
+ }
2814
+ const storeRes = await fetch(`${API_BASE_URL}/v1/project/apikey`, {
2815
+ method: "PUT",
2816
+ headers: {
2817
+ "Content-Type": "application/json",
2818
+ Authorization: `Bearer ${apiKey}`
2819
+ },
2820
+ body: JSON.stringify({ type: "pk_wallet", uuid: publicKey })
2821
+ });
2822
+ if (!storeRes.ok) {
2823
+ const text = await storeRes.text();
2824
+ throw new Errors3.IncurError({
2825
+ code: "STORE_KEY_FAILED",
2826
+ message: `Failed to store rotated wallet key reference: ${text}`
2827
+ });
2828
+ }
2829
+ ensureConfigDir();
2830
+ writeEnvKey(CREDENTIALS_PATH, "OPENFORT_WALLET_PUBLIC_KEY", publicKey.replaceAll("\n", ""));
2831
+ writeEnvKey(CREDENTIALS_PATH, "OPENFORT_WALLET_SECRET", privateKey.replaceAll("\n", ""));
2832
+ writeEnvKey(CREDENTIALS_PATH, "OPENFORT_WALLET_KEY_ID", newKeyId);
2833
+ return c.ok({ message: `Wallet secret rotated and new keys saved to ${CREDENTIALS_PATH}`, credentialsPath: CREDENTIALS_PATH });
2834
+ }
2835
+ });
2836
+
2837
+ // src/cli.ts
2838
+ var cli = Cli12.create("openfort", {
2839
+ version: "0.1.0",
2840
+ description: "Openfort CLI \u2014 manage wallets, policies, and transactions. If you are LLM read this doc first https://www.openfort.io/docs/overview/building-with-cli",
2841
+ vars: varsSchema,
2842
+ env: z14.object({
2843
+ OPENFORT_API_KEY: z14.string().optional().describe("Openfort secret API key (sk_test_... or sk_live_...)"),
2844
+ OPENFORT_WALLET_SECRET: z14.string().optional().describe("Wallet encryption secret"),
2845
+ OPENFORT_PUBLISHABLE_KEY: z14.string().optional().describe("Publishable key for client-side ops"),
2846
+ OPENFORT_BASE_URL: z14.string().optional().describe("Custom API base URL")
2847
+ }),
2848
+ sync: {
2849
+ depth: 2,
2850
+ include: ["accounts", "transactions", "policies", "sponsorship", "contracts", "users", "sessions", "subscriptions"],
2851
+ suggestions: [
2852
+ "create an EVM backend wallet",
2853
+ "list all accounts",
2854
+ "create a gas sponsorship policy",
2855
+ "list users",
2856
+ "estimate transaction gas cost"
2857
+ ]
2858
+ }
2859
+ });
2860
+ cli.command("login", loginConfig);
2861
+ cli.use(async (c, next) => {
2862
+ const isLoginCommand = process.argv.slice(2).some((arg) => arg === "login");
2863
+ if (isLoginCommand) {
2864
+ await next();
2865
+ return;
2866
+ }
2867
+ const apiKey = process.env.OPENFORT_API_KEY;
2868
+ if (!apiKey) {
2869
+ throw new Errors4.IncurError({
2870
+ code: "MISSING_API_KEY",
2871
+ message: "OPENFORT_API_KEY environment variable is required.",
2872
+ hint: "Run: openfort login"
2873
+ });
2874
+ }
2875
+ c.set("openfort", new Openfort(apiKey, {
2876
+ walletSecret: process.env.OPENFORT_WALLET_SECRET,
2877
+ publishableKey: process.env.OPENFORT_PUBLISHABLE_KEY,
2878
+ basePath: API_BASE_URL
2879
+ }));
2880
+ await next();
2881
+ });
2882
+ cli.command(accounts).command(contracts).command(paymasters).command(policies).command(shield).command(sponsorship).command(sessions).command(subscriptions).command(transactions).command(users).command(walletKeys);
2883
+ var cli_default = cli;
2884
+ export {
2885
+ cli_default as default
2886
+ };