@bankr/cli 0.3.1 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli.js +128 -80
- package/dist/commands/club.d.ts +1 -0
- package/dist/commands/club.js +47 -5
- package/dist/commands/fees.js +10 -2
- package/dist/commands/launch.js +16 -23
- package/dist/commands/llm.js +167 -41
- package/dist/commands/login.d.ts +0 -1
- package/dist/commands/login.js +28 -23
- package/dist/commands/prompt.js +5 -0
- package/dist/commands/swap.d.ts +8 -0
- package/dist/commands/swap.js +107 -0
- package/dist/commands/transfer.js +38 -25
- package/dist/commands/webhooks.js +2 -7
- package/dist/commands/x402.js +57 -41
- package/dist/lib/api.d.ts +43 -0
- package/dist/lib/api.js +27 -7
- package/dist/lib/config.d.ts +0 -1
- package/dist/lib/output.d.ts +1 -0
- package/dist/lib/output.js +3 -0
- package/dist/lib/tokens.d.ts +21 -0
- package/dist/lib/tokens.js +40 -0
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -159,7 +159,7 @@ Environment variables override stored values:
|
|
|
159
159
|
|
|
160
160
|
## API Key
|
|
161
161
|
|
|
162
|
-
Generate an API key at [bankr.bot/api](https://bankr.bot/api). Keys start with `bk_` and require Agent API access to be enabled.
|
|
162
|
+
Generate an API key at [bankr.bot/api-keys](https://bankr.bot/api-keys). Keys start with `bk_` and require Agent API access to be enabled.
|
|
163
163
|
|
|
164
164
|
## License
|
|
165
165
|
|
package/dist/cli.js
CHANGED
|
@@ -5,6 +5,7 @@ import { input } from "@inquirer/prompts";
|
|
|
5
5
|
import { balancesCommand } from "./commands/balances.js";
|
|
6
6
|
import { portfolioCommand } from "./commands/portfolio.js";
|
|
7
7
|
import { transferCommand } from "./commands/transfer.js";
|
|
8
|
+
import { swapCommand } from "./commands/swap.js";
|
|
8
9
|
import { skillsCommand } from "./commands/capabilities.js";
|
|
9
10
|
import { cancelCommand } from "./commands/cancel.js";
|
|
10
11
|
import { configGetCommand, configSetCommand } from "./commands/config.js";
|
|
@@ -48,6 +49,10 @@ async function readPromptInput() {
|
|
|
48
49
|
}
|
|
49
50
|
return text;
|
|
50
51
|
}
|
|
52
|
+
if (output.isNonInteractive()) {
|
|
53
|
+
output.error('No prompt provided. Pass it as an argument: bankr agent "your prompt"');
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
51
56
|
// Interactive input — shell expansion does not apply here
|
|
52
57
|
const text = await input({
|
|
53
58
|
message: "Enter your prompt:",
|
|
@@ -61,15 +66,6 @@ function colorizeHelp(text) {
|
|
|
61
66
|
return text
|
|
62
67
|
.split("\n")
|
|
63
68
|
.map((line) => {
|
|
64
|
-
// "Usage: ..." line
|
|
65
|
-
if (line.startsWith("Usage:"))
|
|
66
|
-
return output.fmt.brandBold(line);
|
|
67
|
-
// Section headers: "Options:" and "Commands:"
|
|
68
|
-
if (/^(Options|Commands):/.test(line))
|
|
69
|
-
return output.fmt.brandBold(line);
|
|
70
|
-
// Description line (standalone, no leading whitespace, no colon)
|
|
71
|
-
if (line === "Bankr AI agent CLI")
|
|
72
|
-
return output.fmt.brandBold(line);
|
|
73
69
|
// Command/option rows: leading whitespace then content
|
|
74
70
|
if (/^\s{2,}\S/.test(line)) {
|
|
75
71
|
const match = line.match(/^(\s+)([\w<>[\].\-,/ ]+?)(\s{2,}.+)$/);
|
|
@@ -86,19 +82,27 @@ program
|
|
|
86
82
|
.description("Bankr AI agent CLI\n\n Docs: https://docs.bankr.bot\n Skills: https://docs.bankr.bot/skills/overview")
|
|
87
83
|
.version(pkg.version, "-v, --version", "Show CLI version")
|
|
88
84
|
.helpOption("-h, --help", "Display help")
|
|
89
|
-
.
|
|
85
|
+
.helpCommand(false)
|
|
90
86
|
.option("--config <path>", "Path to config file (default: ~/.bankr/config.json)")
|
|
87
|
+
.option("--ni, --not-interactive", "Non-interactive mode: skip confirmation prompts (implies --yes) and fail fast on required input. Also enabled by BANKR_NOT_INTERACTIVE=1")
|
|
88
|
+
.configureHelp({
|
|
89
|
+
styleTitle: (str) => output.fmt.brandBold(str),
|
|
90
|
+
})
|
|
91
91
|
.configureOutput({
|
|
92
92
|
writeOut: (str) => process.stdout.write(colorizeHelp(str)),
|
|
93
93
|
writeErr: (str) => process.stderr.write(colorizeHelp(str)),
|
|
94
94
|
})
|
|
95
95
|
.hook("preAction", (thisCommand) => {
|
|
96
|
-
const
|
|
97
|
-
if (
|
|
98
|
-
|
|
96
|
+
const opts = thisCommand.opts();
|
|
97
|
+
if (opts.notInteractive) {
|
|
98
|
+
process.env.BANKR_NOT_INTERACTIVE = "1";
|
|
99
|
+
}
|
|
100
|
+
if (opts.config) {
|
|
101
|
+
setConfigPath(opts.config);
|
|
99
102
|
}
|
|
100
103
|
});
|
|
101
104
|
// ── Core commands ───────────────────────────────────────────────────────
|
|
105
|
+
program.commandsGroup("Account");
|
|
102
106
|
const loginCmd = program
|
|
103
107
|
.command("login")
|
|
104
108
|
.description("Authenticate with the Bankr API")
|
|
@@ -120,10 +124,12 @@ loginCmd
|
|
|
120
124
|
.option("--code <otp>", "OTP code (step 2 of headless login)")
|
|
121
125
|
.option("--accept-terms", "Accept Terms of Service (skips prompt)")
|
|
122
126
|
.option("--key-name <name>", "API key name (default: CLI)")
|
|
127
|
+
.optionsGroup("API Permissions")
|
|
123
128
|
.option("--read-write", "Disable read-only mode (allow transactions)")
|
|
124
129
|
.option("--no-wallet-api", "Disable Wallet API (enabled by default)")
|
|
125
130
|
.option("--no-token-launch", "Disable Token Launch API (enabled by default)")
|
|
126
131
|
.option("--llm", "Enable LLM gateway on the API key")
|
|
132
|
+
.optionsGroup("Security")
|
|
127
133
|
.option("--allowed-ips <ips>", "Comma-separated IP/CIDR allowlist, e.g. 1.2.3.4,10.0.0.0/24")
|
|
128
134
|
.option("--allowed-recipients <addresses>", "Comma-separated EVM/Solana addresses (agent will only send funds to these)")
|
|
129
135
|
.action(async (address, opts, cmd) => {
|
|
@@ -147,11 +153,12 @@ loginCmd
|
|
|
147
153
|
.command("siwe")
|
|
148
154
|
.description("Sign in with Ethereum wallet (SIWE, for headless agents)")
|
|
149
155
|
.requiredOption("--private-key <key>", "Ethereum private key (0x...)")
|
|
150
|
-
.option("--partner-key <key>", "Partner API key for fee attribution")
|
|
151
156
|
.option("--key-name <name>", "API key name (default: SIWE-<date>)")
|
|
157
|
+
.optionsGroup("API Permissions")
|
|
152
158
|
.option("--read-write", "Disable read-only mode (allow transactions)")
|
|
153
159
|
.option("--no-wallet-api", "Disable Wallet API (enabled by default)")
|
|
154
160
|
.option("--no-token-launch", "Disable Token Launch API (enabled by default)")
|
|
161
|
+
.optionsGroup("Security")
|
|
155
162
|
.option("--allowed-ips <ips>", "Comma-separated IP/CIDR allowlist, e.g. 1.2.3.4,10.0.0.0/24")
|
|
156
163
|
.option("--allowed-recipients <addresses>", "Comma-separated EVM/Solana addresses (agent will only send funds to these)")
|
|
157
164
|
.action(async (opts, cmd) => {
|
|
@@ -160,7 +167,6 @@ loginCmd
|
|
|
160
167
|
apiUrl: parentOpts.apiUrl,
|
|
161
168
|
siwe: true,
|
|
162
169
|
privateKey: opts.privateKey,
|
|
163
|
-
partnerKey: opts.partnerKey,
|
|
164
170
|
keyName: opts.keyName,
|
|
165
171
|
readWrite: opts.readWrite,
|
|
166
172
|
walletApi: opts.walletApi,
|
|
@@ -174,6 +180,7 @@ program
|
|
|
174
180
|
.description("Show wallet info and account details")
|
|
175
181
|
.action(whoamiCommand);
|
|
176
182
|
// Wallet commands (non-agentic operations)
|
|
183
|
+
program.commandsGroup("Wallet");
|
|
177
184
|
const walletCmd = program
|
|
178
185
|
.command("wallet")
|
|
179
186
|
.description("Wallet info, portfolio, transfer, sign, and submit")
|
|
@@ -209,6 +216,23 @@ walletCmd
|
|
|
209
216
|
chain: opts.chain,
|
|
210
217
|
});
|
|
211
218
|
});
|
|
219
|
+
walletCmd
|
|
220
|
+
.command("swap")
|
|
221
|
+
.description("Swap tokens on an EVM chain (same-chain)")
|
|
222
|
+
.requiredOption("--from <symbol or address>", "Token to sell: symbol (ETH, USDC) or contract address")
|
|
223
|
+
.requiredOption("--to <symbol or address>", "Token to buy: symbol (ETH, USDC) or contract address")
|
|
224
|
+
.requiredOption("--amount <amount>", "Amount of --from to sell (human-readable)")
|
|
225
|
+
.option("--chain <chain>", "EVM chain: base, polygon, mainnet, unichain, worldchain, arbitrum, bnb (default: base)")
|
|
226
|
+
.option("--quote-only", "Print the quote without executing the swap")
|
|
227
|
+
.action(async (opts) => {
|
|
228
|
+
await swapCommand({
|
|
229
|
+
from: opts.from,
|
|
230
|
+
to: opts.to,
|
|
231
|
+
amount: opts.amount,
|
|
232
|
+
chain: opts.chain,
|
|
233
|
+
quoteOnly: opts.quoteOnly,
|
|
234
|
+
});
|
|
235
|
+
});
|
|
212
236
|
walletCmd
|
|
213
237
|
.command("sign")
|
|
214
238
|
.description("Sign messages, typed data, or transactions")
|
|
@@ -268,6 +292,7 @@ walletSubmitCmd
|
|
|
268
292
|
});
|
|
269
293
|
});
|
|
270
294
|
// Agent commands (agentic operations that use LLM)
|
|
295
|
+
program.commandsGroup("Agent");
|
|
271
296
|
const agentCmd = program
|
|
272
297
|
.command("agent [text...]")
|
|
273
298
|
.description("AI agent commands (prompt, status, cancel, profile, skills)")
|
|
@@ -278,10 +303,14 @@ const agentCmd = program
|
|
|
278
303
|
opts.model ?? (opts.model = cmd.parent?.opts()?.model);
|
|
279
304
|
const joined = text.join(" ").trim();
|
|
280
305
|
if (!joined) {
|
|
306
|
+
if (output.isNonInteractive()) {
|
|
307
|
+
output.error('No prompt provided. Pass it as an argument: bankr agent "your prompt"');
|
|
308
|
+
process.exit(1);
|
|
309
|
+
}
|
|
281
310
|
agentCmd.help();
|
|
282
311
|
return;
|
|
283
312
|
}
|
|
284
|
-
await promptCommand(joined
|
|
313
|
+
await promptCommand(joined, opts);
|
|
285
314
|
});
|
|
286
315
|
agentCmd
|
|
287
316
|
.command("prompt [text...]")
|
|
@@ -308,16 +337,21 @@ agentCmd
|
|
|
308
337
|
.command("skills")
|
|
309
338
|
.description("Show all Bankr AI agent skills with examples")
|
|
310
339
|
.action(skillsCommand);
|
|
340
|
+
program.commandsGroup("Tokens");
|
|
311
341
|
program
|
|
312
342
|
.command("launch")
|
|
313
343
|
.description("Launch a token on Base (interactive wizard)")
|
|
344
|
+
.optionsGroup("Token")
|
|
314
345
|
.option("--name <name>", "Token name")
|
|
315
346
|
.option("--symbol <symbol>", "Token symbol (default: auto-generated from name)")
|
|
316
347
|
.option("--image <url>", "Token image URL")
|
|
348
|
+
.optionsGroup("Links")
|
|
317
349
|
.option("--tweet <url>", "Associated tweet URL")
|
|
318
350
|
.option("--website <url>", "Project website URL")
|
|
351
|
+
.optionsGroup("Fees")
|
|
319
352
|
.option("--fee <recipient>", "Fee recipient (username, ENS, or address)")
|
|
320
353
|
.option("--fee-type <type>", "Fee recipient type: x, farcaster, ens, wallet (default: x)")
|
|
354
|
+
.optionsGroup("")
|
|
321
355
|
.option("-y, --yes", "Skip confirmation prompt")
|
|
322
356
|
.option("--simulate", "Simulate the deploy without broadcasting a transaction")
|
|
323
357
|
.action(async (opts) => {
|
|
@@ -333,6 +367,7 @@ program
|
|
|
333
367
|
simulate: opts.simulate,
|
|
334
368
|
});
|
|
335
369
|
});
|
|
370
|
+
program.commandsGroup("Tokens");
|
|
336
371
|
const feesCmd = program
|
|
337
372
|
.command("fees [address]")
|
|
338
373
|
.description("View and claim creator token fee earnings")
|
|
@@ -416,6 +451,7 @@ profileCmd
|
|
|
416
451
|
json: opts.json,
|
|
417
452
|
});
|
|
418
453
|
});
|
|
454
|
+
program.commandsGroup("LLM");
|
|
419
455
|
const llmCmd = program
|
|
420
456
|
.command("llm")
|
|
421
457
|
.description("LLM Gateway tools")
|
|
@@ -487,6 +523,7 @@ llmCmd
|
|
|
487
523
|
await opencodeCommand(args);
|
|
488
524
|
});
|
|
489
525
|
// Token search and info
|
|
526
|
+
program.commandsGroup("Tokens");
|
|
490
527
|
const tokensCmd = program
|
|
491
528
|
.command("tokens")
|
|
492
529
|
.description("Token search and info")
|
|
@@ -507,62 +544,7 @@ tokensCmd
|
|
|
507
544
|
.action(async (address, opts) => {
|
|
508
545
|
await tokensInfoCommand(address, opts);
|
|
509
546
|
});
|
|
510
|
-
|
|
511
|
-
const configCmd = program
|
|
512
|
-
.command("config")
|
|
513
|
-
.description("Manage CLI configuration");
|
|
514
|
-
configCmd
|
|
515
|
-
.command("get [key]")
|
|
516
|
-
.description("Get config value(s). Keys: apiKey, apiUrl, llmKey, llmUrl")
|
|
517
|
-
.action(configGetCommand);
|
|
518
|
-
configCmd
|
|
519
|
-
.command("set <key> <value>")
|
|
520
|
-
.description("Set a config value. Keys: apiKey, apiUrl, llmKey, llmUrl")
|
|
521
|
-
.action(configSetCommand);
|
|
522
|
-
const soundsCmd = program
|
|
523
|
-
.command("sounds")
|
|
524
|
-
.description("Manage CESP sound packs")
|
|
525
|
-
.action(soundsStatusCommand);
|
|
526
|
-
soundsCmd
|
|
527
|
-
.command("enable")
|
|
528
|
-
.description("Enable sounds")
|
|
529
|
-
.action(soundsEnableCommand);
|
|
530
|
-
soundsCmd
|
|
531
|
-
.command("disable")
|
|
532
|
-
.description("Disable sounds")
|
|
533
|
-
.action(soundsDisableCommand);
|
|
534
|
-
soundsCmd
|
|
535
|
-
.command("install <pack>")
|
|
536
|
-
.description("Install a sound pack from the CESP registry")
|
|
537
|
-
.action(soundsInstallCommand);
|
|
538
|
-
soundsCmd
|
|
539
|
-
.command("search [query]")
|
|
540
|
-
.description("Search available packs in the CESP registry")
|
|
541
|
-
.action(soundsSearchCommand);
|
|
542
|
-
soundsCmd
|
|
543
|
-
.command("list")
|
|
544
|
-
.description("List installed sound packs")
|
|
545
|
-
.action(soundsListCommand);
|
|
546
|
-
soundsCmd
|
|
547
|
-
.command("use <pack>")
|
|
548
|
-
.description("Set active sound pack")
|
|
549
|
-
.action(soundsUseCommand);
|
|
550
|
-
soundsCmd
|
|
551
|
-
.command("volume [level]")
|
|
552
|
-
.description("Get or set volume (0.0-1.0)")
|
|
553
|
-
.action(soundsVolumeCommand);
|
|
554
|
-
soundsCmd
|
|
555
|
-
.command("mute")
|
|
556
|
-
.description("Mute all sounds")
|
|
557
|
-
.action(soundsMuteCommand);
|
|
558
|
-
soundsCmd
|
|
559
|
-
.command("unmute")
|
|
560
|
-
.description("Unmute sounds")
|
|
561
|
-
.action(soundsUnmuteCommand);
|
|
562
|
-
soundsCmd
|
|
563
|
-
.command("test [category]")
|
|
564
|
-
.description("Play a test sound")
|
|
565
|
-
.action(soundsTestCommand);
|
|
547
|
+
program.commandsGroup("Account");
|
|
566
548
|
program
|
|
567
549
|
.command("logout")
|
|
568
550
|
.description("Clear stored credentials")
|
|
@@ -736,14 +718,8 @@ submitAliasCmd
|
|
|
736
718
|
description: opts.description,
|
|
737
719
|
});
|
|
738
720
|
});
|
|
739
|
-
program
|
|
740
|
-
.command("update")
|
|
741
|
-
.description("Update the Bankr CLI to the latest version")
|
|
742
|
-
.option("--check", "Check for updates without installing")
|
|
743
|
-
.action(async (opts) => {
|
|
744
|
-
await updateCommand({ check: opts.check });
|
|
745
|
-
});
|
|
746
721
|
// ── File Storage ────────────────────────────────────────────────────────
|
|
722
|
+
program.commandsGroup("Protocol");
|
|
747
723
|
const filesCmd = program
|
|
748
724
|
.command("files")
|
|
749
725
|
.description("Manage your file storage")
|
|
@@ -814,6 +790,7 @@ filesCmd
|
|
|
814
790
|
.description("Show file metadata")
|
|
815
791
|
.action(filesInfoCommand);
|
|
816
792
|
// ── Bankr Club ────────────────────────────────────────────────────────
|
|
793
|
+
program.commandsGroup("Account");
|
|
817
794
|
const clubCmd = program
|
|
818
795
|
.command("club")
|
|
819
796
|
.description("View Bankr Club membership, sign up, or cancel")
|
|
@@ -824,8 +801,9 @@ clubCmd
|
|
|
824
801
|
.action(clubStatusCommand);
|
|
825
802
|
clubCmd
|
|
826
803
|
.command("signup")
|
|
827
|
-
.description("Sign up for Bankr Club (
|
|
804
|
+
.description("Sign up for Bankr Club (default: USDC; --token BNKR | ETH | <0x...>)")
|
|
828
805
|
.option("--yearly", "Subscribe yearly instead of monthly")
|
|
806
|
+
.option("--token <symbolOrAddress>", "Payment token: USDC (default), BNKR, ETH, or a 0x... Base address")
|
|
829
807
|
.option("-y, --yes", "Skip confirmation prompt")
|
|
830
808
|
.action(clubSignupCommand);
|
|
831
809
|
clubCmd
|
|
@@ -834,6 +812,7 @@ clubCmd
|
|
|
834
812
|
.option("-y, --yes", "Skip confirmation prompt")
|
|
835
813
|
.action(clubCancelCommand);
|
|
836
814
|
// ── x402 Endpoint Hosting ─────────────────────────────────────────────
|
|
815
|
+
program.commandsGroup("Protocol");
|
|
837
816
|
const x402Cmd = program
|
|
838
817
|
.command("x402")
|
|
839
818
|
.description("Deploy and manage x402 paid API endpoints");
|
|
@@ -889,6 +868,7 @@ x402EnvCmd
|
|
|
889
868
|
.description("Remove an env var")
|
|
890
869
|
.action(x402EnvUnsetCommand);
|
|
891
870
|
// ── User Webhooks ─────────────────────────────────────────────────────
|
|
871
|
+
program.commandsGroup("Protocol");
|
|
892
872
|
const webhooksCmd = program
|
|
893
873
|
.command("webhooks")
|
|
894
874
|
.description("Deploy and manage user webhooks that trigger the Bankr agent on external events");
|
|
@@ -960,6 +940,70 @@ x402Cmd
|
|
|
960
940
|
.option("-y, --yes", "Skip payment confirmation")
|
|
961
941
|
.option("--raw", "Output raw JSON (unformatted)")
|
|
962
942
|
.action(async (url, opts) => x402CallCommand(url, opts));
|
|
943
|
+
// ── Settings ────────────────────────────────────────────────────────────
|
|
944
|
+
program.commandsGroup("Settings");
|
|
945
|
+
const configCmd = program
|
|
946
|
+
.command("config")
|
|
947
|
+
.description("Manage CLI configuration");
|
|
948
|
+
configCmd
|
|
949
|
+
.command("get [key]")
|
|
950
|
+
.description("Get config value(s). Keys: apiKey, apiUrl, llmKey, llmUrl")
|
|
951
|
+
.action(configGetCommand);
|
|
952
|
+
configCmd
|
|
953
|
+
.command("set <key> <value>")
|
|
954
|
+
.description("Set a config value. Keys: apiKey, apiUrl, llmKey, llmUrl")
|
|
955
|
+
.action(configSetCommand);
|
|
956
|
+
const soundsCmd = program
|
|
957
|
+
.command("sounds")
|
|
958
|
+
.description("Manage CESP sound packs")
|
|
959
|
+
.action(soundsStatusCommand);
|
|
960
|
+
soundsCmd
|
|
961
|
+
.command("enable")
|
|
962
|
+
.description("Enable sounds")
|
|
963
|
+
.action(soundsEnableCommand);
|
|
964
|
+
soundsCmd
|
|
965
|
+
.command("disable")
|
|
966
|
+
.description("Disable sounds")
|
|
967
|
+
.action(soundsDisableCommand);
|
|
968
|
+
soundsCmd
|
|
969
|
+
.command("install <pack>")
|
|
970
|
+
.description("Install a sound pack from the CESP registry")
|
|
971
|
+
.action(soundsInstallCommand);
|
|
972
|
+
soundsCmd
|
|
973
|
+
.command("search [query]")
|
|
974
|
+
.description("Search available packs in the CESP registry")
|
|
975
|
+
.action(soundsSearchCommand);
|
|
976
|
+
soundsCmd
|
|
977
|
+
.command("list")
|
|
978
|
+
.description("List installed sound packs")
|
|
979
|
+
.action(soundsListCommand);
|
|
980
|
+
soundsCmd
|
|
981
|
+
.command("use <pack>")
|
|
982
|
+
.description("Set active sound pack")
|
|
983
|
+
.action(soundsUseCommand);
|
|
984
|
+
soundsCmd
|
|
985
|
+
.command("volume [level]")
|
|
986
|
+
.description("Get or set volume (0.0-1.0)")
|
|
987
|
+
.action(soundsVolumeCommand);
|
|
988
|
+
soundsCmd
|
|
989
|
+
.command("mute")
|
|
990
|
+
.description("Mute all sounds")
|
|
991
|
+
.action(soundsMuteCommand);
|
|
992
|
+
soundsCmd
|
|
993
|
+
.command("unmute")
|
|
994
|
+
.description("Unmute sounds")
|
|
995
|
+
.action(soundsUnmuteCommand);
|
|
996
|
+
soundsCmd
|
|
997
|
+
.command("test [category]")
|
|
998
|
+
.description("Play a test sound")
|
|
999
|
+
.action(soundsTestCommand);
|
|
1000
|
+
program
|
|
1001
|
+
.command("update")
|
|
1002
|
+
.description("Update the Bankr CLI to the latest version")
|
|
1003
|
+
.option("--check", "Check for updates without installing")
|
|
1004
|
+
.action(async (opts) => {
|
|
1005
|
+
await updateCommand({ check: opts.check });
|
|
1006
|
+
});
|
|
963
1007
|
// Default: treat unrecognized arguments as a prompt
|
|
964
1008
|
program
|
|
965
1009
|
.arguments("[text...]")
|
|
@@ -968,6 +1012,10 @@ program
|
|
|
968
1012
|
.option("-m, --model <model>", "Use Max Mode with a specific model (e.g. claude-opus-4.6)")
|
|
969
1013
|
.action(async (text, opts) => {
|
|
970
1014
|
if (text.length === 0) {
|
|
1015
|
+
if (output.isNonInteractive()) {
|
|
1016
|
+
output.error('No prompt provided. Pass it as an argument: bankr "your prompt"');
|
|
1017
|
+
process.exit(1);
|
|
1018
|
+
}
|
|
971
1019
|
program.help();
|
|
972
1020
|
return;
|
|
973
1021
|
}
|
package/dist/commands/club.d.ts
CHANGED
package/dist/commands/club.js
CHANGED
|
@@ -8,6 +8,33 @@ function authHeaders() {
|
|
|
8
8
|
"User-Agent": CLI_USER_AGENT,
|
|
9
9
|
};
|
|
10
10
|
}
|
|
11
|
+
// Common Base tokens accepted as `--token` shortcuts. Lowercase to bypass
|
|
12
|
+
// viem's strict EIP-55 checksum on the API's isAddress() check; the route
|
|
13
|
+
// resolves to lowercase server-side anyway. Inlined here (not imported
|
|
14
|
+
// from the monorepo) because @bankr/cli is published standalone.
|
|
15
|
+
const TOKEN_ALIASES = {
|
|
16
|
+
USDC: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
|
|
17
|
+
BNKR: "0x22af33fe49fd1fa80c7149773dde5890d3c76f3b",
|
|
18
|
+
// Native-asset sentinel address used by 0x and most aggregators.
|
|
19
|
+
ETH: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
|
|
20
|
+
};
|
|
21
|
+
const ADDRESS_RE = /^0x[a-fA-F0-9]{40}$/;
|
|
22
|
+
/**
|
|
23
|
+
* Resolve a user-supplied `--token` value to a Base ERC-20 address.
|
|
24
|
+
* Accepts a known symbol (USDC | BNKR | ETH, case-insensitive) or any
|
|
25
|
+
* 0x-prefixed 40-char address. Returns null for invalid input.
|
|
26
|
+
*/
|
|
27
|
+
function resolvePaymentToken(input) {
|
|
28
|
+
if (!input)
|
|
29
|
+
return null;
|
|
30
|
+
const normalized = input.trim();
|
|
31
|
+
const upper = normalized.toUpperCase();
|
|
32
|
+
if (TOKEN_ALIASES[upper])
|
|
33
|
+
return TOKEN_ALIASES[upper];
|
|
34
|
+
if (ADDRESS_RE.test(normalized))
|
|
35
|
+
return normalized;
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
11
38
|
async function fetchStatus() {
|
|
12
39
|
const res = await fetch(`${getApiUrl()}/bankr-club/`, {
|
|
13
40
|
headers: authHeaders(),
|
|
@@ -63,8 +90,20 @@ export async function clubSignupCommand(opts) {
|
|
|
63
90
|
output.warn("You already have an active Bankr Club subscription.");
|
|
64
91
|
return;
|
|
65
92
|
}
|
|
93
|
+
let tokenAddress;
|
|
94
|
+
if (opts.token) {
|
|
95
|
+
const resolved = resolvePaymentToken(opts.token);
|
|
96
|
+
if (!resolved) {
|
|
97
|
+
output.error(`Unknown token "${opts.token}". Use one of USDC, BNKR, ETH, or pass a 0x-prefixed Base address.`);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
tokenAddress = resolved;
|
|
101
|
+
}
|
|
66
102
|
const yearly = !!opts.yearly;
|
|
67
|
-
|
|
103
|
+
// Reused for /quote and /sign-up so both endpoints agree on the token.
|
|
104
|
+
// The API rejects sign-up with `quote-token-mismatch` if they diverge.
|
|
105
|
+
const tokenParam = tokenAddress ? `&token=${tokenAddress}` : "";
|
|
106
|
+
const quoteRes = await fetch(`${getApiUrl()}/bankr-club/quote?yearly=${yearly}${tokenParam}`, { headers: authHeaders() });
|
|
68
107
|
if (!quoteRes.ok) {
|
|
69
108
|
const body = await quoteRes
|
|
70
109
|
.json()
|
|
@@ -72,13 +111,15 @@ export async function clubSignupCommand(opts) {
|
|
|
72
111
|
throw new Error(body.error || quoteRes.statusText);
|
|
73
112
|
}
|
|
74
113
|
const quote = (await quoteRes.json());
|
|
114
|
+
const symbol = quote.tokenSymbol ?? "USDC";
|
|
75
115
|
output.label("Plan", yearly ? "Yearly" : "Monthly");
|
|
76
|
-
output.label("Price", `${output.formatUsd(quote.usdPrice)} (in $
|
|
77
|
-
output.label("Cost", `${quote.
|
|
116
|
+
output.label("Price", `${output.formatUsd(quote.usdPrice)} (in ${symbol})`);
|
|
117
|
+
output.label("Cost", `${quote.priceInToken} ${symbol}`);
|
|
78
118
|
output.dim(`Quote expires ${new Date(quote.expiresAt * 1000).toLocaleString()}.`);
|
|
79
119
|
output.blank();
|
|
80
|
-
output.dim(
|
|
120
|
+
output.dim(`Payment is deducted from your ${symbol} balance in your Bankr wallet.`);
|
|
81
121
|
const ok = opts.yes ||
|
|
122
|
+
output.isNonInteractive() ||
|
|
82
123
|
(await confirm({
|
|
83
124
|
message: "Confirm subscription?",
|
|
84
125
|
default: false,
|
|
@@ -89,7 +130,7 @@ export async function clubSignupCommand(opts) {
|
|
|
89
130
|
return;
|
|
90
131
|
}
|
|
91
132
|
const spinner = output.spinner("Signing up for Bankr Club...");
|
|
92
|
-
const signUpRes = await fetch(`${getApiUrl()}/bankr-club/sign-up?yearly=${yearly}`, { headers: authHeaders() });
|
|
133
|
+
const signUpRes = await fetch(`${getApiUrl()}/bankr-club/sign-up?yearly=${yearly}${tokenParam}`, { headers: authHeaders() });
|
|
93
134
|
spinner.stop();
|
|
94
135
|
if (!signUpRes.ok) {
|
|
95
136
|
const body = await signUpRes
|
|
@@ -121,6 +162,7 @@ export async function clubCancelCommand(opts) {
|
|
|
121
162
|
return;
|
|
122
163
|
}
|
|
123
164
|
const ok = opts.yes ||
|
|
165
|
+
output.isNonInteractive() ||
|
|
124
166
|
(await confirm({
|
|
125
167
|
message: "Cancel Bankr Club? You'll keep access until the current billing period ends.",
|
|
126
168
|
default: false,
|
package/dist/commands/fees.js
CHANGED
|
@@ -386,7 +386,7 @@ export async function feesCommand(address, opts) {
|
|
|
386
386
|
export async function feesClaimCommand(tokenAddress, opts) {
|
|
387
387
|
requireApiKey();
|
|
388
388
|
// Confirm — we send one request that builds, signs, and broadcasts.
|
|
389
|
-
if (!opts.yes) {
|
|
389
|
+
if (!opts.yes && !output.isNonInteractive()) {
|
|
390
390
|
console.log();
|
|
391
391
|
output.keyValue("Token", tokenAddress);
|
|
392
392
|
output.keyValue("Action", "Claim trading fees");
|
|
@@ -452,6 +452,10 @@ export async function feesClaimWalletCommand(address, opts) {
|
|
|
452
452
|
if (address && !isAddress(address)) {
|
|
453
453
|
address = undefined;
|
|
454
454
|
}
|
|
455
|
+
if (output.isNonInteractive() && !opts.all) {
|
|
456
|
+
output.error("Use --all to select all tokens in non-interactive mode, or run interactively to choose");
|
|
457
|
+
process.exit(1);
|
|
458
|
+
}
|
|
455
459
|
// Load .env from cwd if present (no dependency needed)
|
|
456
460
|
try {
|
|
457
461
|
const { readFileSync, existsSync } = await import("node:fs");
|
|
@@ -492,6 +496,10 @@ export async function feesClaimWalletCommand(address, opts) {
|
|
|
492
496
|
process.exit(1);
|
|
493
497
|
}
|
|
494
498
|
else {
|
|
499
|
+
if (output.isNonInteractive()) {
|
|
500
|
+
output.error("Private key required in non-interactive mode. Use --private-key or set BANKR_PRIVATE_KEY");
|
|
501
|
+
process.exit(1);
|
|
502
|
+
}
|
|
495
503
|
privateKey = await password({
|
|
496
504
|
message: "Enter private key for this wallet (0x...):",
|
|
497
505
|
mask: "*",
|
|
@@ -680,7 +688,7 @@ export async function feesClaimWalletCommand(address, opts) {
|
|
|
680
688
|
console.log(` ${DIM("To:")} ${tx.to} ${DIM("Gas:")} ~${gasCostEth.toFixed(6)} ETH`);
|
|
681
689
|
console.log();
|
|
682
690
|
}
|
|
683
|
-
if (!opts.yes) {
|
|
691
|
+
if (!opts.yes && !output.isNonInteractive()) {
|
|
684
692
|
const proceed = await confirm({
|
|
685
693
|
message: `Submit ${readyTxs.length} claim transaction${readyTxs.length !== 1 ? "s" : ""}?`,
|
|
686
694
|
default: true,
|
package/dist/commands/launch.js
CHANGED
|
@@ -25,7 +25,16 @@ function feeTypeLabel(type) {
|
|
|
25
25
|
return "Wallet";
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
+
async function promptOrSkip(message) {
|
|
29
|
+
if (output.isNonInteractive())
|
|
30
|
+
return "";
|
|
31
|
+
return input({ message, theme: output.bankrTheme });
|
|
32
|
+
}
|
|
28
33
|
async function collectInteractive(options) {
|
|
34
|
+
if (output.isNonInteractive() && !options.name) {
|
|
35
|
+
output.error("--name is required in non-interactive mode");
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
29
38
|
const tokenName = options.name ??
|
|
30
39
|
(await input({
|
|
31
40
|
message: "What do you want to call your token?",
|
|
@@ -33,32 +42,17 @@ async function collectInteractive(options) {
|
|
|
33
42
|
required: true,
|
|
34
43
|
}));
|
|
35
44
|
const tokenSymbol = options.symbol ??
|
|
36
|
-
(await
|
|
37
|
-
message: "Token symbol (press Enter to auto-generate from name):",
|
|
38
|
-
theme: output.bankrTheme,
|
|
39
|
-
}));
|
|
45
|
+
(await promptOrSkip("Token symbol (press Enter to auto-generate from name):"));
|
|
40
46
|
const imageUrl = options.image ??
|
|
41
|
-
(await
|
|
42
|
-
message: "Image URL for your token (press Enter to skip):",
|
|
43
|
-
theme: output.bankrTheme,
|
|
44
|
-
}));
|
|
47
|
+
(await promptOrSkip("Image URL for your token (press Enter to skip):"));
|
|
45
48
|
const tweetUrl = options.tweet ??
|
|
46
|
-
(await
|
|
47
|
-
message: "Associate with a tweet? Paste URL (press Enter to skip):",
|
|
48
|
-
theme: output.bankrTheme,
|
|
49
|
-
}));
|
|
49
|
+
(await promptOrSkip("Associate with a tweet? Paste URL (press Enter to skip):"));
|
|
50
50
|
const websiteUrl = options.website ??
|
|
51
|
-
(await
|
|
52
|
-
message: "Project website URL (press Enter to skip):",
|
|
53
|
-
theme: output.bankrTheme,
|
|
54
|
-
}));
|
|
51
|
+
(await promptOrSkip("Project website URL (press Enter to skip):"));
|
|
55
52
|
let feeRecipient = options.fee ??
|
|
56
|
-
(await
|
|
57
|
-
message: "Direct fees to someone? Enter username, ENS, or address (press Enter to skip):",
|
|
58
|
-
theme: output.bankrTheme,
|
|
59
|
-
}));
|
|
53
|
+
(await promptOrSkip("Direct fees to someone? Enter username, ENS, or address (press Enter to skip):"));
|
|
60
54
|
let feeRecipientType = parseFeeType(options.feeType);
|
|
61
|
-
if (feeRecipient && !options.feeType) {
|
|
55
|
+
if (feeRecipient && !options.feeType && !output.isNonInteractive()) {
|
|
62
56
|
feeRecipientType = await select({
|
|
63
57
|
message: "What type of identifier is this?",
|
|
64
58
|
choices: [
|
|
@@ -108,8 +102,7 @@ export async function launchCommand(options) {
|
|
|
108
102
|
output.keyValue("Mode", "Simulation (dry run)");
|
|
109
103
|
}
|
|
110
104
|
console.log();
|
|
111
|
-
|
|
112
|
-
if (!options.yes) {
|
|
105
|
+
if (!options.yes && !output.isNonInteractive()) {
|
|
113
106
|
const proceed = await confirm({
|
|
114
107
|
message: options.simulate
|
|
115
108
|
? "Simulate this token launch?"
|