@openfort/cli 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -58
- package/dist/cli.js +108 -85
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -1,40 +1,17 @@
|
|
|
1
|
-

|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
<div align="center">
|
|
5
|
-
<h4>
|
|
6
|
-
<a href="https://www.openfort.io/">
|
|
7
|
-
Website
|
|
8
|
-
</a>
|
|
9
|
-
<span> | </span>
|
|
10
|
-
<a href="https://www.openfort.io/docs/overview/building-with-cli">
|
|
11
|
-
Documentation
|
|
12
|
-
</a>
|
|
13
|
-
<span> | </span>
|
|
14
|
-
<a href="https://x.com/openfort_hq">
|
|
15
|
-
X
|
|
16
|
-
</a>
|
|
17
|
-
</h4>
|
|
18
|
-
</div>
|
|
19
|
-
|
|
20
1
|
# Openfort CLI
|
|
21
2
|
|
|
22
|
-
[
|
|
23
|
-
[](https://www.openfort.io/docs/overview/building-with-cli)
|
|
24
|
-
[](https://www.npmjs.org/package/@openfort/cli)
|
|
3
|
+
The official CLI for [Openfort](https://openfort.io).
|
|
25
4
|
|
|
26
|
-
|
|
5
|
+
Built for humans, AI agents, and CI/CD pipelines.
|
|
27
6
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
- 🔔 **Subscriptions** — set up webhooks and event subscriptions
|
|
37
|
-
- 🤖 **AI-friendly** — works as an MCP tool for LLM agents
|
|
7
|
+
```
|
|
8
|
+
██████╗ ██████╗ ███████╗███╗ ██╗███████╗ ██████╗ ██████╗ ████████╗
|
|
9
|
+
██╔═══██╗██╔══██╗██╔════╝████╗ ██║██╔════╝██╔═══██╗██╔══██╗╚══██╔══╝
|
|
10
|
+
██║ ██║██████╔╝█████╗ ██╔██╗ ██║█████╗ ██║ ██║██████╔╝ ██║
|
|
11
|
+
██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║██╔══╝ ██║ ██║██╔══██╗ ██║
|
|
12
|
+
╚██████╔╝██║ ███████╗██║ ╚████║██║ ╚██████╔╝██║ ██║ ██║
|
|
13
|
+
╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝
|
|
14
|
+
```
|
|
38
15
|
|
|
39
16
|
## Quick Start
|
|
40
17
|
|
|
@@ -48,46 +25,86 @@ npm install -g @openfort/cli
|
|
|
48
25
|
openfort login
|
|
49
26
|
```
|
|
50
27
|
|
|
51
|
-
### 3.
|
|
28
|
+
### 3. Set up backend wallet signing keys
|
|
29
|
+
```bash
|
|
30
|
+
openfort backend-wallet setup
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 4. Use
|
|
52
34
|
```bash
|
|
53
|
-
# List accounts
|
|
35
|
+
# List all accounts across chains
|
|
54
36
|
openfort accounts list
|
|
55
37
|
|
|
56
|
-
# Create
|
|
57
|
-
openfort accounts create
|
|
38
|
+
# Create an EVM backend wallet
|
|
39
|
+
openfort accounts evm create
|
|
40
|
+
|
|
41
|
+
# Create a Solana backend wallet
|
|
42
|
+
openfort accounts solana create
|
|
58
43
|
|
|
59
44
|
# List policies
|
|
60
45
|
openfort policies list
|
|
61
46
|
|
|
62
47
|
# Send a transaction
|
|
63
|
-
openfort transactions create --
|
|
48
|
+
openfort transactions create --account acc_1a2b3c4d --chainId 137 --interactions '[{"to":"0x...","value":"0"}]'
|
|
49
|
+
|
|
50
|
+
# Estimate gas cost
|
|
51
|
+
openfort transactions estimate --account acc_1a2b3c4d --chainId 137 --interactions '[{"to":"0x...","value":"0"}]'
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## AI Agent Integration
|
|
55
|
+
|
|
56
|
+
### MCP (Model Context Protocol)
|
|
57
|
+
|
|
58
|
+
Register the CLI as an MCP server for your AI agent:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
openfort mcp add
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
This registers Openfort tools in Claude Code, Cursor, and Amp. Agents can then call any CLI command as a tool.
|
|
65
|
+
|
|
66
|
+
### Skills
|
|
67
|
+
|
|
68
|
+
Install agent skill files for discovery:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
openfort skills add
|
|
64
72
|
```
|
|
65
73
|
|
|
66
74
|
## Environment Variables
|
|
67
75
|
|
|
68
|
-
| Variable
|
|
69
|
-
|
|
70
|
-
| `OPENFORT_API_KEY`
|
|
71
|
-
| `OPENFORT_WALLET_SECRET`
|
|
72
|
-
| `OPENFORT_PUBLISHABLE_KEY` | Publishable key for client-side ops
|
|
73
|
-
| `OPENFORT_BASE_URL`
|
|
76
|
+
| Variable | Description |
|
|
77
|
+
| -------------------------- | ----------------------------------------------- |
|
|
78
|
+
| `OPENFORT_API_KEY` | Secret API key (`sk_test_...` or `sk_live_...`) |
|
|
79
|
+
| `OPENFORT_WALLET_SECRET` | Wallet encryption secret |
|
|
80
|
+
| `OPENFORT_PUBLISHABLE_KEY` | Publishable key for client-side ops |
|
|
81
|
+
| `OPENFORT_BASE_URL` | Custom API base URL |
|
|
74
82
|
|
|
75
83
|
## Commands
|
|
76
84
|
|
|
77
|
-
| Command
|
|
78
|
-
|
|
79
|
-
| `login`
|
|
80
|
-
| `accounts`
|
|
81
|
-
| `contracts`
|
|
82
|
-
| `paymasters`
|
|
83
|
-
| `policies`
|
|
84
|
-
| `sponsorship`
|
|
85
|
-
| `sessions`
|
|
86
|
-
| `subscriptions`
|
|
87
|
-
| `transactions`
|
|
88
|
-
| `users`
|
|
89
|
-
| `wallet
|
|
90
|
-
| `
|
|
85
|
+
| Command | Description |
|
|
86
|
+
| ----------------- | ------------------------------------------------------------------- |
|
|
87
|
+
| `login` | Log in to Openfort via browser and save your API key |
|
|
88
|
+
| `accounts` | Manage wallets and accounts (EVM and Solana subcommands) |
|
|
89
|
+
| `contracts` | Manage smart contracts |
|
|
90
|
+
| `paymasters` | Manage ERC-4337 paymasters |
|
|
91
|
+
| `policies` | Manage rules and conditions for backend wallets and fee sponsorship |
|
|
92
|
+
| `sponsorship` | Manage fee sponsorship strategies linked to policies |
|
|
93
|
+
| `sessions` | Manage session keys |
|
|
94
|
+
| `subscriptions` | Manage webhook subscriptions and triggers |
|
|
95
|
+
| `transactions` | Manage transaction intents |
|
|
96
|
+
| `users` | Manage authenticated users |
|
|
97
|
+
| `backend-wallet` | Configure backend wallet signing keys |
|
|
98
|
+
| `embedded-wallet` | Configure embedded wallet (Shield) API keys |
|
|
99
|
+
| `message` | Message utilities (e.g. keccak256 hashing) |
|
|
100
|
+
|
|
101
|
+
## Alias
|
|
102
|
+
|
|
103
|
+
The CLI is also available as `of`:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
of accounts list
|
|
107
|
+
```
|
|
91
108
|
|
|
92
109
|
## Documentation
|
|
93
110
|
|
package/dist/cli.js
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
} from "./chunk-QJGHQ7ID.js";
|
|
6
6
|
|
|
7
7
|
// src/cli.ts
|
|
8
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
8
9
|
import { Cli as Cli13, z as z15, Errors as Errors4 } from "incur";
|
|
9
10
|
import Openfort from "@openfort/openfort-node";
|
|
10
11
|
|
|
@@ -198,10 +199,12 @@ var loginConfig = {
|
|
|
198
199
|
const authUrl = new URL(`${AUTH_PAGE_URL}/oauth/consent`);
|
|
199
200
|
authUrl.searchParams.set("redirect_uri", redirectUri);
|
|
200
201
|
authUrl.searchParams.set("state", state);
|
|
201
|
-
|
|
202
|
-
|
|
202
|
+
if (!c.agent) {
|
|
203
|
+
console.log("\nOpen this URL in your browser to log in:\n");
|
|
204
|
+
console.log(` ${authUrl.toString()}
|
|
203
205
|
`);
|
|
204
|
-
|
|
206
|
+
console.log("Waiting for authentication...\n");
|
|
207
|
+
}
|
|
205
208
|
const { apiKey, publishableKey, projectId, project } = await waitForCallback(port, state);
|
|
206
209
|
ensureConfigDir();
|
|
207
210
|
writeEnvKey(CREDENTIALS_PATH, "OPENFORT_API_KEY", apiKey);
|
|
@@ -211,14 +214,16 @@ var loginConfig = {
|
|
|
211
214
|
if (projectId) {
|
|
212
215
|
writeEnvKey(CREDENTIALS_PATH, "OPENFORT_PROJECT_ID", projectId);
|
|
213
216
|
}
|
|
214
|
-
|
|
217
|
+
if (!c.agent) {
|
|
218
|
+
console.log(`Saved API key for project "${project}" to ${CREDENTIALS_PATH}`);
|
|
219
|
+
}
|
|
215
220
|
return c.ok(
|
|
216
221
|
{ apiKey, project, credentialsPath: CREDENTIALS_PATH },
|
|
217
222
|
{
|
|
218
223
|
cta: {
|
|
219
224
|
description: "Next steps:",
|
|
220
225
|
commands: [
|
|
221
|
-
{ command: `wallet
|
|
226
|
+
{ command: `backend-wallet setup`, description: "Set up signing keys for backend wallets" }
|
|
222
227
|
]
|
|
223
228
|
}
|
|
224
229
|
}
|
|
@@ -227,19 +232,23 @@ var loginConfig = {
|
|
|
227
232
|
};
|
|
228
233
|
|
|
229
234
|
// src/commands/accounts.ts
|
|
230
|
-
import { Cli, z as z3,
|
|
231
|
-
|
|
235
|
+
import { Cli, z as z3, middleware } from "incur";
|
|
236
|
+
var requireWallet = middleware((c, next) => {
|
|
232
237
|
const missing = [];
|
|
233
238
|
if (!process.env.OPENFORT_WALLET_SECRET) missing.push("OPENFORT_WALLET_SECRET");
|
|
234
239
|
if (!process.env.OPENFORT_PUBLISHABLE_KEY) missing.push("OPENFORT_PUBLISHABLE_KEY");
|
|
235
240
|
if (missing.length > 0) {
|
|
236
|
-
|
|
241
|
+
return c.error({
|
|
237
242
|
code: "MISSING_CREDENTIALS",
|
|
238
243
|
message: `Missing required credentials: ${missing.join(", ")}`,
|
|
239
|
-
|
|
244
|
+
cta: {
|
|
245
|
+
description: "Set up wallet credentials:",
|
|
246
|
+
commands: [{ command: "backend-wallet setup", description: "Set up signing keys for backend wallets" }]
|
|
247
|
+
}
|
|
240
248
|
});
|
|
241
249
|
}
|
|
242
|
-
|
|
250
|
+
return next();
|
|
251
|
+
});
|
|
243
252
|
var evm = Cli.create("evm", {
|
|
244
253
|
description: "EVM wallet management.",
|
|
245
254
|
vars: varsSchema
|
|
@@ -247,15 +256,16 @@ var evm = Cli.create("evm", {
|
|
|
247
256
|
evm.command("create", {
|
|
248
257
|
description: "Create a new EVM backend wallet.",
|
|
249
258
|
examples: [
|
|
250
|
-
{ description: "Create a new EVM wallet" }
|
|
259
|
+
{ description: "Create a new EVM backend wallet (developer custody)" }
|
|
251
260
|
],
|
|
261
|
+
hint: "Requires OPENFORT_WALLET_SECRET and OPENFORT_PUBLISHABLE_KEY.",
|
|
262
|
+
middleware: [requireWallet],
|
|
252
263
|
output: z3.object({
|
|
253
264
|
id: z3.string().describe("Account ID"),
|
|
254
265
|
address: z3.string().describe("Wallet address"),
|
|
255
266
|
custody: z3.string().describe("Custody type")
|
|
256
267
|
}),
|
|
257
268
|
async run(c) {
|
|
258
|
-
requireWalletCredentials();
|
|
259
269
|
const account = await c.var.openfort.accounts.evm.backend.create();
|
|
260
270
|
return c.ok(
|
|
261
271
|
{ id: account.id, address: account.address, custody: account.custody },
|
|
@@ -421,7 +431,7 @@ evm.command("update", {
|
|
|
421
431
|
}),
|
|
422
432
|
options: z3.object({
|
|
423
433
|
chainId: z3.number().describe("Chain ID to deploy on"),
|
|
424
|
-
implementationType: z3.string().describe("
|
|
434
|
+
implementationType: z3.string().describe("Target implementation type (e.g. CaliburV9)")
|
|
425
435
|
}),
|
|
426
436
|
examples: [
|
|
427
437
|
{ args: { id: "acc_1a2b3c4d" }, options: { chainId: 8453, implementationType: "CaliburV9" }, description: "Upgrade to delegated account on Base" }
|
|
@@ -453,7 +463,7 @@ evm.command("update", {
|
|
|
453
463
|
cta: {
|
|
454
464
|
description: "Next steps:",
|
|
455
465
|
commands: [
|
|
456
|
-
{ command: `accounts evm list-delegated`, description: "
|
|
466
|
+
{ command: `accounts evm list-delegated`, description: "List all delegated accounts" }
|
|
457
467
|
]
|
|
458
468
|
}
|
|
459
469
|
}
|
|
@@ -471,11 +481,12 @@ evm.command("sign", {
|
|
|
471
481
|
examples: [
|
|
472
482
|
{ args: { id: "acc_1a2b3c4d" }, options: { data: "0xdeadbeef" }, description: "Sign a message hash" }
|
|
473
483
|
],
|
|
484
|
+
hint: "Requires OPENFORT_WALLET_SECRET and OPENFORT_PUBLISHABLE_KEY.",
|
|
485
|
+
middleware: [requireWallet],
|
|
474
486
|
output: z3.object({
|
|
475
487
|
signature: z3.string()
|
|
476
488
|
}),
|
|
477
489
|
async run(c) {
|
|
478
|
-
requireWalletCredentials();
|
|
479
490
|
const signature = await c.var.openfort.accounts.evm.backend.sign({
|
|
480
491
|
id: c.args.id,
|
|
481
492
|
data: c.options.data
|
|
@@ -491,13 +502,14 @@ evm.command("import", {
|
|
|
491
502
|
examples: [
|
|
492
503
|
{ options: { privateKey: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" }, description: "Import a private key" }
|
|
493
504
|
],
|
|
505
|
+
hint: "Requires OPENFORT_WALLET_SECRET and OPENFORT_PUBLISHABLE_KEY.",
|
|
506
|
+
middleware: [requireWallet],
|
|
494
507
|
output: z3.object({
|
|
495
508
|
id: z3.string(),
|
|
496
509
|
address: z3.string(),
|
|
497
510
|
custody: z3.string()
|
|
498
511
|
}),
|
|
499
512
|
async run(c) {
|
|
500
|
-
requireWalletCredentials();
|
|
501
513
|
const account = await c.var.openfort.accounts.evm.backend.import({
|
|
502
514
|
privateKey: c.options.privateKey
|
|
503
515
|
});
|
|
@@ -516,11 +528,11 @@ evm.command("export", {
|
|
|
516
528
|
examples: [
|
|
517
529
|
{ args: { id: "acc_1a2b3c4d" }, description: "Export private key" }
|
|
518
530
|
],
|
|
531
|
+
middleware: [requireWallet],
|
|
519
532
|
output: z3.object({
|
|
520
533
|
privateKey: z3.string()
|
|
521
534
|
}),
|
|
522
535
|
async run(c) {
|
|
523
|
-
requireWalletCredentials();
|
|
524
536
|
const privateKey = await c.var.openfort.accounts.evm.backend.export({
|
|
525
537
|
id: c.args.id
|
|
526
538
|
});
|
|
@@ -535,7 +547,7 @@ evm.command("send-transaction", {
|
|
|
535
547
|
options: z3.object({
|
|
536
548
|
chainId: z3.number().describe("Chain ID"),
|
|
537
549
|
interactions: z3.string().describe('Interactions as JSON: [{"to":"0x...","data":"0x...","value":"0"}]'),
|
|
538
|
-
policy: z3.string().optional().describe("
|
|
550
|
+
policy: z3.string().optional().describe("Fee sponsorship ID (pol_...)")
|
|
539
551
|
}),
|
|
540
552
|
examples: [
|
|
541
553
|
{
|
|
@@ -547,6 +559,7 @@ evm.command("send-transaction", {
|
|
|
547
559
|
description: "Send a gasless transaction on Base"
|
|
548
560
|
}
|
|
549
561
|
],
|
|
562
|
+
middleware: [requireWallet],
|
|
550
563
|
output: z3.object({
|
|
551
564
|
id: z3.string(),
|
|
552
565
|
chainId: z3.number(),
|
|
@@ -575,15 +588,16 @@ var solana = Cli.create("solana", {
|
|
|
575
588
|
solana.command("create", {
|
|
576
589
|
description: "Create a new Solana backend wallet.",
|
|
577
590
|
examples: [
|
|
578
|
-
{ description: "Create a new Solana wallet" }
|
|
591
|
+
{ description: "Create a new Solana backend wallet (developer custody)" }
|
|
579
592
|
],
|
|
593
|
+
hint: "Requires OPENFORT_WALLET_SECRET and OPENFORT_PUBLISHABLE_KEY.",
|
|
594
|
+
middleware: [requireWallet],
|
|
580
595
|
output: z3.object({
|
|
581
596
|
id: z3.string().describe("Account ID"),
|
|
582
597
|
address: z3.string().describe("Wallet address"),
|
|
583
598
|
custody: z3.string().describe("Custody type")
|
|
584
599
|
}),
|
|
585
600
|
async run(c) {
|
|
586
|
-
requireWalletCredentials();
|
|
587
601
|
const account = await c.var.openfort.accounts.solana.backend.create();
|
|
588
602
|
return c.ok(
|
|
589
603
|
{ id: account.id, address: account.address, custody: account.custody },
|
|
@@ -662,6 +676,8 @@ solana.command("sign", {
|
|
|
662
676
|
data: z3.string().describe("Data to sign (base64-encoded)")
|
|
663
677
|
}),
|
|
664
678
|
alias: { data: "d" },
|
|
679
|
+
hint: "Requires OPENFORT_WALLET_SECRET and OPENFORT_PUBLISHABLE_KEY.",
|
|
680
|
+
middleware: [requireWallet],
|
|
665
681
|
output: z3.object({
|
|
666
682
|
account: z3.string(),
|
|
667
683
|
signature: z3.string()
|
|
@@ -674,7 +690,6 @@ solana.command("sign", {
|
|
|
674
690
|
}
|
|
675
691
|
],
|
|
676
692
|
async run(c) {
|
|
677
|
-
requireWalletCredentials();
|
|
678
693
|
const signature = await c.var.openfort.accounts.solana.backend.sign(c.args.id, c.options.data);
|
|
679
694
|
return c.ok({ account: c.args.id, signature });
|
|
680
695
|
}
|
|
@@ -696,26 +711,6 @@ solana.command("delete", {
|
|
|
696
711
|
return c.ok({ id: res.id, deleted: res.deleted });
|
|
697
712
|
}
|
|
698
713
|
});
|
|
699
|
-
solana.command("sign", {
|
|
700
|
-
description: "Sign data with a Solana backend wallet.",
|
|
701
|
-
args: z3.object({
|
|
702
|
-
id: z3.string().describe("Account ID (acc_...)")
|
|
703
|
-
}),
|
|
704
|
-
options: z3.object({
|
|
705
|
-
data: z3.string().describe("Data to sign")
|
|
706
|
-
}),
|
|
707
|
-
examples: [
|
|
708
|
-
{ args: { id: "acc_1a2b3c4d" }, options: { data: "hello" }, description: "Sign a message" }
|
|
709
|
-
],
|
|
710
|
-
output: z3.object({
|
|
711
|
-
signature: z3.string()
|
|
712
|
-
}),
|
|
713
|
-
async run(c) {
|
|
714
|
-
requireWalletCredentials();
|
|
715
|
-
const signature = await c.var.openfort.accounts.solana.backend.sign(c.args.id, c.options.data);
|
|
716
|
-
return c.ok({ signature });
|
|
717
|
-
}
|
|
718
|
-
});
|
|
719
714
|
solana.command("import", {
|
|
720
715
|
description: "Import a private key as a Solana backend wallet.",
|
|
721
716
|
options: z3.object({
|
|
@@ -724,13 +719,14 @@ solana.command("import", {
|
|
|
724
719
|
examples: [
|
|
725
720
|
{ options: { privateKey: "abc123..." }, description: "Import a Solana private key" }
|
|
726
721
|
],
|
|
722
|
+
hint: "Requires OPENFORT_WALLET_SECRET and OPENFORT_PUBLISHABLE_KEY.",
|
|
723
|
+
middleware: [requireWallet],
|
|
727
724
|
output: z3.object({
|
|
728
725
|
id: z3.string(),
|
|
729
726
|
address: z3.string(),
|
|
730
727
|
custody: z3.string()
|
|
731
728
|
}),
|
|
732
729
|
async run(c) {
|
|
733
|
-
requireWalletCredentials();
|
|
734
730
|
const account = await c.var.openfort.accounts.solana.backend.import({
|
|
735
731
|
privateKey: c.options.privateKey
|
|
736
732
|
});
|
|
@@ -749,11 +745,11 @@ solana.command("export", {
|
|
|
749
745
|
examples: [
|
|
750
746
|
{ args: { id: "acc_1a2b3c4d" }, description: "Export private key" }
|
|
751
747
|
],
|
|
748
|
+
middleware: [requireWallet],
|
|
752
749
|
output: z3.object({
|
|
753
750
|
privateKey: z3.string()
|
|
754
751
|
}),
|
|
755
752
|
async run(c) {
|
|
756
|
-
requireWalletCredentials();
|
|
757
753
|
const privateKey = await c.var.openfort.accounts.solana.backend.export({
|
|
758
754
|
id: c.args.id
|
|
759
755
|
});
|
|
@@ -783,6 +779,7 @@ solana.command("transfer", {
|
|
|
783
779
|
description: "Transfer 1 USDC on devnet"
|
|
784
780
|
}
|
|
785
781
|
],
|
|
782
|
+
middleware: [requireWallet],
|
|
786
783
|
output: z3.object({
|
|
787
784
|
signature: z3.string()
|
|
788
785
|
}),
|
|
@@ -924,7 +921,7 @@ contracts.command("create", {
|
|
|
924
921
|
description: "Register USDC on Polygon"
|
|
925
922
|
},
|
|
926
923
|
{
|
|
927
|
-
options: { name: "My
|
|
924
|
+
options: { name: "My Token", address: "0x1234...", chainId: 1, abi: '[{"type":"function","name":"mint","inputs":[],"outputs":[],"stateMutability":"nonpayable"}]' },
|
|
928
925
|
description: "Register contract with ABI"
|
|
929
926
|
}
|
|
930
927
|
],
|
|
@@ -1109,7 +1106,7 @@ paymasters.command("update", {
|
|
|
1109
1106
|
id: z5.string().describe("Paymaster ID (pay_...)")
|
|
1110
1107
|
}),
|
|
1111
1108
|
options: z5.object({
|
|
1112
|
-
address: z5.string().describe("Paymaster address"),
|
|
1109
|
+
address: z5.string().optional().describe("Paymaster address"),
|
|
1113
1110
|
name: z5.string().optional().describe("New name"),
|
|
1114
1111
|
url: z5.string().optional().describe("New URL")
|
|
1115
1112
|
}),
|
|
@@ -1154,7 +1151,7 @@ paymasters.command("delete", {
|
|
|
1154
1151
|
import { Cli as Cli4, z as z6 } from "incur";
|
|
1155
1152
|
var policyScopes = ["project", "account", "transaction"];
|
|
1156
1153
|
var policies = Cli4.create("policies", {
|
|
1157
|
-
description: "Manage
|
|
1154
|
+
description: "Manage rules and conditions for backend wallets and fee sponsorship.",
|
|
1158
1155
|
vars: varsSchema
|
|
1159
1156
|
});
|
|
1160
1157
|
policies.command("list", {
|
|
@@ -1227,6 +1224,14 @@ policies.command("create", {
|
|
|
1227
1224
|
rules: '[{"action":"accept","operation":"sponsorEvmTransaction","criteria":[{"type":"evmNetwork","operator":"in","chainIds":[137]}]}]'
|
|
1228
1225
|
},
|
|
1229
1226
|
description: "Create a policy to sponsor transactions on Polygon"
|
|
1227
|
+
},
|
|
1228
|
+
{
|
|
1229
|
+
options: {
|
|
1230
|
+
scope: "account",
|
|
1231
|
+
description: "Allow signing for a specific account",
|
|
1232
|
+
rules: '[{"action":"accept","operation":"signEvmTransaction"}]'
|
|
1233
|
+
},
|
|
1234
|
+
description: "Allow EVM transaction signing"
|
|
1230
1235
|
}
|
|
1231
1236
|
],
|
|
1232
1237
|
async run(c) {
|
|
@@ -1401,7 +1406,7 @@ var sponsorshipItem = z7.object({
|
|
|
1401
1406
|
policyId: z7.string().nullable()
|
|
1402
1407
|
});
|
|
1403
1408
|
var sponsorship = Cli5.create("sponsorship", {
|
|
1404
|
-
description: "Manage fee
|
|
1409
|
+
description: "Manage fee sponsorship strategies linked to policies.",
|
|
1405
1410
|
vars: varsSchema
|
|
1406
1411
|
});
|
|
1407
1412
|
sponsorship.command("list", {
|
|
@@ -1937,7 +1942,7 @@ sessions.command("create", {
|
|
|
1937
1942
|
player: z9.string().optional().describe("Player ID (pla_...)"),
|
|
1938
1943
|
account: z9.string().optional().describe("Account ID (acc_...)"),
|
|
1939
1944
|
limit: z9.number().optional().describe("Max session uses"),
|
|
1940
|
-
policy: z9.string().optional().describe("Policy ID for gas sponsorship
|
|
1945
|
+
policy: z9.string().optional().describe("Policy ID (ply_...) for gas sponsorship"),
|
|
1941
1946
|
whitelist: z9.string().optional().describe("Whitelisted contract addresses as JSON array")
|
|
1942
1947
|
}),
|
|
1943
1948
|
examples: [
|
|
@@ -2018,7 +2023,7 @@ sessions.command("revoke", {
|
|
|
2018
2023
|
address: z9.string().describe("Session key address to revoke"),
|
|
2019
2024
|
chainId: z9.number().describe("Chain ID"),
|
|
2020
2025
|
player: z9.string().optional().describe("Player ID (pla_...)"),
|
|
2021
|
-
policy: z9.string().optional().describe("Policy ID (
|
|
2026
|
+
policy: z9.string().optional().describe("Policy ID (ply_...) for gas sponsorship")
|
|
2022
2027
|
}),
|
|
2023
2028
|
examples: [
|
|
2024
2029
|
{ options: { address: "0x1234...", chainId: 137 }, description: "Revoke a session key" }
|
|
@@ -2153,7 +2158,7 @@ transactions.command("create", {
|
|
|
2153
2158
|
account: z10.string().describe("Account ID (acc_...)"),
|
|
2154
2159
|
chainId: z10.number().describe("Chain ID"),
|
|
2155
2160
|
interactions: z10.string().describe('Interactions as JSON: [{"to":"0x...","data":"0x...","value":"0"}]'),
|
|
2156
|
-
policy: z10.string().optional().describe("Policy ID for gas sponsorship"),
|
|
2161
|
+
policy: z10.string().optional().describe("Policy ID (ply_...) for gas sponsorship"),
|
|
2157
2162
|
signedAuthorization: z10.string().optional().describe("Signed EIP-7702 authorization hex (for delegated accounts)")
|
|
2158
2163
|
}),
|
|
2159
2164
|
output: transactionIntentItem,
|
|
@@ -2171,9 +2176,9 @@ transactions.command("create", {
|
|
|
2171
2176
|
account: "acc_1a2b3c4d",
|
|
2172
2177
|
chainId: 137,
|
|
2173
2178
|
interactions: '[{"to":"0x742d35Cc6634C0532925a3b844Bc9e7595f92cD5","value":"1000000000000000000"}]',
|
|
2174
|
-
policy: "
|
|
2179
|
+
policy: "pol_1a2b3c4d"
|
|
2175
2180
|
},
|
|
2176
|
-
description: "Send 1
|
|
2181
|
+
description: "Send 1 POL with gas sponsorship"
|
|
2177
2182
|
}
|
|
2178
2183
|
],
|
|
2179
2184
|
async run(c) {
|
|
@@ -2280,7 +2285,7 @@ transactions.command("estimate", {
|
|
|
2280
2285
|
account: z10.string().describe("Account ID (acc_...)"),
|
|
2281
2286
|
chainId: z10.number().describe("Chain ID"),
|
|
2282
2287
|
interactions: z10.string().describe("Interactions as JSON"),
|
|
2283
|
-
policy: z10.string().optional().describe("
|
|
2288
|
+
policy: z10.string().optional().describe("Fee sponsorship ID (pol_...) for gas sponsorship")
|
|
2284
2289
|
}),
|
|
2285
2290
|
examples: [
|
|
2286
2291
|
{
|
|
@@ -2313,15 +2318,15 @@ transactions.command("estimate", {
|
|
|
2313
2318
|
}
|
|
2314
2319
|
});
|
|
2315
2320
|
|
|
2316
|
-
// src/commands/
|
|
2321
|
+
// src/commands/embedded-wallet.ts
|
|
2317
2322
|
import { Cli as Cli9, z as z11, Errors as Errors2 } from "incur";
|
|
2318
2323
|
var SHIELD_API_URL = OPENFORT_SHIELD_URL;
|
|
2319
|
-
var
|
|
2320
|
-
description: "
|
|
2324
|
+
var embeddedWallet = Cli9.create("embedded-wallet", {
|
|
2325
|
+
description: "Configure embedded wallet (Shield) API keys.",
|
|
2321
2326
|
vars: varsSchema
|
|
2322
2327
|
});
|
|
2323
|
-
|
|
2324
|
-
description: "
|
|
2328
|
+
embeddedWallet.command("setup", {
|
|
2329
|
+
description: "Generate and register embedded wallet (Shield) API keys.",
|
|
2325
2330
|
options: z11.object({
|
|
2326
2331
|
project: z11.string().optional().describe("Project ID (pro_...). Defaults to OPENFORT_PROJECT_ID env var.")
|
|
2327
2332
|
}),
|
|
@@ -2333,9 +2338,10 @@ shield.command("create", {
|
|
|
2333
2338
|
examples: [
|
|
2334
2339
|
{
|
|
2335
2340
|
options: { project: "pro_abc123" },
|
|
2336
|
-
description: "
|
|
2341
|
+
description: "Set up embedded wallet keys for a project"
|
|
2337
2342
|
}
|
|
2338
2343
|
],
|
|
2344
|
+
hint: 'Requires OPENFORT_PUBLISHABLE_KEY and OPENFORT_PROJECT_ID. Run "openfort login" first.',
|
|
2339
2345
|
async run(c) {
|
|
2340
2346
|
const publishableKey = process.env.OPENFORT_PUBLISHABLE_KEY;
|
|
2341
2347
|
if (!publishableKey) {
|
|
@@ -2371,7 +2377,8 @@ shield.command("create", {
|
|
|
2371
2377
|
const text = await registerRes.text();
|
|
2372
2378
|
throw new Errors2.IncurError({
|
|
2373
2379
|
code: "SHIELD_REGISTER_FAILED",
|
|
2374
|
-
message: `Shield registration failed: ${text}
|
|
2380
|
+
message: `Shield registration failed: ${text}`,
|
|
2381
|
+
retryable: true
|
|
2375
2382
|
});
|
|
2376
2383
|
}
|
|
2377
2384
|
const shieldData = await registerRes.json();
|
|
@@ -2394,7 +2401,8 @@ shield.command("create", {
|
|
|
2394
2401
|
const text = await res.text();
|
|
2395
2402
|
throw new Errors2.IncurError({
|
|
2396
2403
|
code: "PERSIST_KEY_FAILED",
|
|
2397
|
-
message: `Failed to persist ${type} key: ${text}
|
|
2404
|
+
message: `Failed to persist ${type} key: ${text}`,
|
|
2405
|
+
retryable: true
|
|
2398
2406
|
});
|
|
2399
2407
|
}
|
|
2400
2408
|
};
|
|
@@ -2421,7 +2429,8 @@ shield.command("create", {
|
|
|
2421
2429
|
const text = await linkRes.text();
|
|
2422
2430
|
throw new Errors2.IncurError({
|
|
2423
2431
|
code: "SHIELD_LINK_FAILED",
|
|
2424
|
-
message: `Failed to link Openfort provider to Shield: ${text}
|
|
2432
|
+
message: `Failed to link Openfort provider to Shield: ${text}`,
|
|
2433
|
+
retryable: true
|
|
2425
2434
|
});
|
|
2426
2435
|
}
|
|
2427
2436
|
ensureConfigDir();
|
|
@@ -2429,7 +2438,7 @@ shield.command("create", {
|
|
|
2429
2438
|
writeEnvKey(CREDENTIALS_PATH, "SHIELD_SECRET_KEY", shieldData.api_secret);
|
|
2430
2439
|
writeEnvKey(CREDENTIALS_PATH, "SHIELD_ENCRYPTION_SHARE", shieldData.encryption_part);
|
|
2431
2440
|
return c.ok(
|
|
2432
|
-
{ message: `
|
|
2441
|
+
{ message: `Embedded wallet keys were created and saved to ${CREDENTIALS_PATH}`, credentialsPath: CREDENTIALS_PATH },
|
|
2433
2442
|
{
|
|
2434
2443
|
cta: {
|
|
2435
2444
|
description: "Next steps:",
|
|
@@ -2551,7 +2560,7 @@ users.command("delete", {
|
|
|
2551
2560
|
}
|
|
2552
2561
|
});
|
|
2553
2562
|
|
|
2554
|
-
// src/commands/wallet
|
|
2563
|
+
// src/commands/backend-wallet.ts
|
|
2555
2564
|
import { randomBytes as randomBytes2, subtle } from "crypto";
|
|
2556
2565
|
import { Cli as Cli11, z as z13, Errors as Errors3 } from "incur";
|
|
2557
2566
|
function arrayBufferToBase64(buffer) {
|
|
@@ -2623,21 +2632,22 @@ async function signWalletAuthJwt(privateKey, method, path, body) {
|
|
|
2623
2632
|
);
|
|
2624
2633
|
return `${signingInput}.${arrayBufferToBase64Url(signature)}`;
|
|
2625
2634
|
}
|
|
2626
|
-
var
|
|
2627
|
-
description: "
|
|
2635
|
+
var backendWallet = Cli11.create("backend-wallet", {
|
|
2636
|
+
description: "Configure backend wallet signing keys.",
|
|
2628
2637
|
vars: varsSchema
|
|
2629
2638
|
});
|
|
2630
|
-
|
|
2631
|
-
description: "
|
|
2639
|
+
backendWallet.command("setup", {
|
|
2640
|
+
description: "Generate and register backend wallet signing keys (ECDSA P-256).",
|
|
2632
2641
|
output: z13.object({
|
|
2633
2642
|
message: z13.string(),
|
|
2634
2643
|
credentialsPath: z13.string()
|
|
2635
2644
|
}),
|
|
2636
2645
|
examples: [
|
|
2637
2646
|
{
|
|
2638
|
-
description: "
|
|
2647
|
+
description: "Set up backend wallet signing keys and save to credentials"
|
|
2639
2648
|
}
|
|
2640
2649
|
],
|
|
2650
|
+
hint: 'Requires OPENFORT_API_KEY. Run "openfort login" first.',
|
|
2641
2651
|
async run(c) {
|
|
2642
2652
|
const apiKey = process.env.OPENFORT_API_KEY;
|
|
2643
2653
|
const { publicKey, privateKey, privateKeyCrypto } = await generateKeyPair();
|
|
@@ -2663,7 +2673,8 @@ ${publicKey}
|
|
|
2663
2673
|
const text = await registerRes.text();
|
|
2664
2674
|
throw new Errors3.IncurError({
|
|
2665
2675
|
code: "REGISTER_SECRET_FAILED",
|
|
2666
|
-
message: `Failed to register wallet secret: ${text}
|
|
2676
|
+
message: `Failed to register wallet secret: ${text}`,
|
|
2677
|
+
retryable: true
|
|
2667
2678
|
});
|
|
2668
2679
|
}
|
|
2669
2680
|
const storeRes = await fetch(`${API_BASE_URL}/v1/project/apikey`, {
|
|
@@ -2678,7 +2689,8 @@ ${publicKey}
|
|
|
2678
2689
|
const text = await storeRes.text();
|
|
2679
2690
|
throw new Errors3.IncurError({
|
|
2680
2691
|
code: "STORE_KEY_FAILED",
|
|
2681
|
-
message: `Failed to store wallet key reference: ${text}
|
|
2692
|
+
message: `Failed to store wallet key reference: ${text}`,
|
|
2693
|
+
retryable: true
|
|
2682
2694
|
});
|
|
2683
2695
|
}
|
|
2684
2696
|
ensureConfigDir();
|
|
@@ -2691,15 +2703,15 @@ ${publicKey}
|
|
|
2691
2703
|
cta: {
|
|
2692
2704
|
description: "Next steps:",
|
|
2693
2705
|
commands: [
|
|
2694
|
-
{ command: `
|
|
2706
|
+
{ command: `embedded-wallet setup`, description: "Set up embedded wallet keys" }
|
|
2695
2707
|
]
|
|
2696
2708
|
}
|
|
2697
2709
|
}
|
|
2698
2710
|
);
|
|
2699
2711
|
}
|
|
2700
2712
|
});
|
|
2701
|
-
|
|
2702
|
-
description: "Revoke the current backend wallet secret.",
|
|
2713
|
+
backendWallet.command("revoke", {
|
|
2714
|
+
description: "Revoke the current backend wallet signing secret.",
|
|
2703
2715
|
output: z13.object({
|
|
2704
2716
|
keyId: z13.string(),
|
|
2705
2717
|
revoked: z13.boolean(),
|
|
@@ -2710,6 +2722,7 @@ walletKeys.command("revoke", {
|
|
|
2710
2722
|
description: "Revoke the current wallet secret"
|
|
2711
2723
|
}
|
|
2712
2724
|
],
|
|
2725
|
+
hint: 'Requires OPENFORT_WALLET_KEY_ID and OPENFORT_WALLET_SECRET. Run "openfort backend-wallet setup" first.',
|
|
2713
2726
|
async run(c) {
|
|
2714
2727
|
const apiKey = process.env.OPENFORT_API_KEY;
|
|
2715
2728
|
const keyId = process.env.OPENFORT_WALLET_KEY_ID;
|
|
@@ -2717,7 +2730,8 @@ walletKeys.command("revoke", {
|
|
|
2717
2730
|
if (!keyId || !privateKeyBase64) {
|
|
2718
2731
|
throw new Errors3.IncurError({
|
|
2719
2732
|
code: "MISSING_WALLET_KEY",
|
|
2720
|
-
message: "OPENFORT_WALLET_KEY_ID and OPENFORT_WALLET_SECRET must be set.
|
|
2733
|
+
message: "OPENFORT_WALLET_KEY_ID and OPENFORT_WALLET_SECRET must be set. Run `backend-wallet setup` first.",
|
|
2734
|
+
hint: "Run: openfort backend-wallet setup"
|
|
2721
2735
|
});
|
|
2722
2736
|
}
|
|
2723
2737
|
const privateKeyCrypto = await importPrivateKey(privateKeyBase64);
|
|
@@ -2737,15 +2751,16 @@ walletKeys.command("revoke", {
|
|
|
2737
2751
|
const text = await res.text();
|
|
2738
2752
|
throw new Errors3.IncurError({
|
|
2739
2753
|
code: "REVOKE_SECRET_FAILED",
|
|
2740
|
-
message: `Failed to revoke wallet secret: ${text}
|
|
2754
|
+
message: `Failed to revoke wallet secret: ${text}`,
|
|
2755
|
+
retryable: true
|
|
2741
2756
|
});
|
|
2742
2757
|
}
|
|
2743
2758
|
const data = await res.json();
|
|
2744
2759
|
return c.ok(data);
|
|
2745
2760
|
}
|
|
2746
2761
|
});
|
|
2747
|
-
|
|
2748
|
-
description: "Rotate backend wallet secret (generates new ECDSA P-256 key pair).",
|
|
2762
|
+
backendWallet.command("rotate", {
|
|
2763
|
+
description: "Rotate backend wallet signing secret (generates new ECDSA P-256 key pair).",
|
|
2749
2764
|
output: z13.object({
|
|
2750
2765
|
message: z13.string(),
|
|
2751
2766
|
credentialsPath: z13.string()
|
|
@@ -2755,6 +2770,7 @@ walletKeys.command("rotate", {
|
|
|
2755
2770
|
description: "Rotate wallet secret and save new keys to credentials"
|
|
2756
2771
|
}
|
|
2757
2772
|
],
|
|
2773
|
+
hint: 'Requires OPENFORT_API_KEY. Run "openfort login" first.',
|
|
2758
2774
|
async run(c) {
|
|
2759
2775
|
const apiKey = process.env.OPENFORT_API_KEY;
|
|
2760
2776
|
const { publicKey, privateKey, privateKeyCrypto } = await generateKeyPair();
|
|
@@ -2780,7 +2796,8 @@ ${publicKey}
|
|
|
2780
2796
|
const text = await rotateRes.text();
|
|
2781
2797
|
throw new Errors3.IncurError({
|
|
2782
2798
|
code: "ROTATE_SECRET_FAILED",
|
|
2783
|
-
message: `Failed to rotate wallet secret: ${text}
|
|
2799
|
+
message: `Failed to rotate wallet secret: ${text}`,
|
|
2800
|
+
retryable: true
|
|
2784
2801
|
});
|
|
2785
2802
|
}
|
|
2786
2803
|
const storeRes = await fetch(`${API_BASE_URL}/v1/project/apikey`, {
|
|
@@ -2795,7 +2812,8 @@ ${publicKey}
|
|
|
2795
2812
|
const text = await storeRes.text();
|
|
2796
2813
|
throw new Errors3.IncurError({
|
|
2797
2814
|
code: "STORE_KEY_FAILED",
|
|
2798
|
-
message: `Failed to store rotated wallet key reference: ${text}
|
|
2815
|
+
message: `Failed to store rotated wallet key reference: ${text}`,
|
|
2816
|
+
retryable: true
|
|
2799
2817
|
});
|
|
2800
2818
|
}
|
|
2801
2819
|
ensureConfigDir();
|
|
@@ -2831,9 +2849,11 @@ message.command("hash", {
|
|
|
2831
2849
|
});
|
|
2832
2850
|
|
|
2833
2851
|
// src/cli.ts
|
|
2852
|
+
var pkg = JSON.parse(readFileSync2(new URL("../package.json", import.meta.url), "utf-8"));
|
|
2834
2853
|
var cli = Cli13.create("openfort", {
|
|
2835
|
-
version:
|
|
2836
|
-
|
|
2854
|
+
version: pkg.version,
|
|
2855
|
+
aliases: ["of"],
|
|
2856
|
+
description: "Openfort CLI \u2014 manage wallets, policies, and transactions from the terminal.",
|
|
2837
2857
|
vars: varsSchema,
|
|
2838
2858
|
env: z15.object({
|
|
2839
2859
|
OPENFORT_API_KEY: z15.string().optional().describe("Openfort secret API key (sk_test_... or sk_live_...)"),
|
|
@@ -2843,14 +2863,17 @@ var cli = Cli13.create("openfort", {
|
|
|
2843
2863
|
}),
|
|
2844
2864
|
sync: {
|
|
2845
2865
|
depth: 2,
|
|
2846
|
-
include: ["accounts", "transactions", "policies", "sponsorship", "contracts", "users", "sessions", "subscriptions"],
|
|
2866
|
+
include: ["_root", "accounts", "transactions", "policies", "sponsorship", "contracts", "users", "sessions", "subscriptions", "backend-wallet", "embedded-wallet"],
|
|
2847
2867
|
suggestions: [
|
|
2848
2868
|
"create an EVM backend wallet",
|
|
2849
2869
|
"list all accounts",
|
|
2850
|
-
"create a gas sponsorship
|
|
2870
|
+
"create a policy for gas sponsorship",
|
|
2851
2871
|
"list users",
|
|
2852
2872
|
"estimate transaction gas cost"
|
|
2853
2873
|
]
|
|
2874
|
+
},
|
|
2875
|
+
mcp: {
|
|
2876
|
+
agents: ["claude-code", "cursor", "amp"]
|
|
2854
2877
|
}
|
|
2855
2878
|
});
|
|
2856
2879
|
cli.command("login", loginConfig);
|
|
@@ -2875,7 +2898,7 @@ cli.use(async (c, next) => {
|
|
|
2875
2898
|
}));
|
|
2876
2899
|
await next();
|
|
2877
2900
|
});
|
|
2878
|
-
cli.command(accounts).command(contracts).command(paymasters).command(policies).command(
|
|
2901
|
+
cli.command(accounts).command(contracts).command(paymasters).command(policies).command(embeddedWallet).command(sponsorship).command(sessions).command(subscriptions).command(transactions).command(users).command(backendWallet).command(message);
|
|
2879
2902
|
var cli_default = cli;
|
|
2880
2903
|
export {
|
|
2881
2904
|
cli_default as default
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openfort/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Openfort CLI — manage wallets, policies, and transactions from the terminal.",
|
|
5
5
|
"author": "Openfort (https://www.openfort.io)",
|
|
6
6
|
"bugs": "https://github.com/openfort-xyz/cli/issues",
|
|
7
7
|
"homepage": "https://github.com/openfort-xyz/cli#readme",
|
|
8
|
-
"repository":
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/openfort-xyz/cli"
|
|
11
|
+
},
|
|
9
12
|
"type": "module",
|
|
10
13
|
"bin": {
|
|
11
14
|
"openfort": "./dist/bin.js",
|
|
@@ -31,6 +34,7 @@
|
|
|
31
34
|
"scripts": {
|
|
32
35
|
"dev": "node --import tsx src/bin.ts",
|
|
33
36
|
"build": "tsup",
|
|
37
|
+
"gen": "pnpm build && incur gen --entry ./dist/cli.js",
|
|
34
38
|
"openfort": "node --import tsx src/bin.ts",
|
|
35
39
|
"skills": "pnpm openfort skills add",
|
|
36
40
|
"changeset": "changeset",
|