@bankr/cli 0.1.0 → 0.2.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 CHANGED
@@ -3,6 +3,8 @@ import { readFileSync } from "node:fs";
3
3
  import { Command } from "commander";
4
4
  import { input } from "@inquirer/prompts";
5
5
  import { balancesCommand } from "./commands/balances.js";
6
+ import { portfolioCommand } from "./commands/portfolio.js";
7
+ import { transferCommand } from "./commands/transfer.js";
6
8
  import { skillsCommand } from "./commands/capabilities.js";
7
9
  import { cancelCommand } from "./commands/cancel.js";
8
10
  import { configGetCommand, configSetCommand } from "./commands/config.js";
@@ -17,7 +19,9 @@ import { signCommand } from "./commands/sign.js";
17
19
  import { soundsDisableCommand, soundsEnableCommand, soundsInstallCommand, soundsListCommand, soundsMuteCommand, soundsSearchCommand, soundsStatusCommand, soundsTestCommand, soundsUnmuteCommand, soundsUseCommand, soundsVolumeCommand, } from "./commands/sounds.js";
18
20
  import { statusCommand } from "./commands/status.js";
19
21
  import { submitCommand, submitJsonCommand } from "./commands/submit.js";
22
+ import { updateCommand } from "./commands/update.js";
20
23
  import { whoamiCommand } from "./commands/whoami.js";
24
+ import { tokensSearchCommand, tokensInfoCommand } from "./commands/tokens.js";
21
25
  import { profileViewCommand, profileCreateCommand, profileUpdateCommand, profileDeleteCommand, profileAddUpdateCommand, } from "./commands/profile.js";
22
26
  import * as output from "./lib/output.js";
23
27
  const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
@@ -74,7 +78,7 @@ function colorizeHelp(text) {
74
78
  }
75
79
  program
76
80
  .name("bankr")
77
- .description("Bankr AI agent CLI")
81
+ .description("Bankr AI agent CLI\n\n Docs: https://docs.bankr.bot\n Skills: https://docs.bankr.bot/openclaw/installation")
78
82
  .version(pkg.version, "-v, --version", "Show CLI version")
79
83
  .helpOption("-h, --help", "Display help")
80
84
  .addHelpCommand("help [command]", "Display help for command")
@@ -89,6 +93,7 @@ program
89
93
  setConfigPath(configPath);
90
94
  }
91
95
  });
96
+ // ── Core commands ───────────────────────────────────────────────────────
92
97
  const loginCmd = program
93
98
  .command("login")
94
99
  .description("Authenticate with the Bankr API")
@@ -110,8 +115,13 @@ loginCmd
110
115
  .option("--code <otp>", "OTP code (step 2 of headless login)")
111
116
  .option("--accept-terms", "Accept Terms of Service (skips prompt)")
112
117
  .option("--key-name <name>", "API key name (default: CLI)")
113
- .option("--read-write", "Enable write operations on the API key")
118
+ .option("--read-write", "Disable read-only mode (allow transactions)")
119
+ .option("--no-wallet-api", "Disable Wallet API (enabled by default)")
120
+ .option("--agent-api", "Enable Agent API (AI prompts)")
121
+ .option("--no-token-launch", "Disable Token Launch API (enabled by default)")
114
122
  .option("--llm", "Enable LLM gateway on the API key")
123
+ .option("--allowed-ips <ips>", "Comma-separated IP allowlist (requests from other IPs will be blocked)")
124
+ .option("--allowed-recipients <addresses>", "Comma-separated EVM/Solana addresses (agent will only send funds to these)")
115
125
  .action(async (address, opts, cmd) => {
116
126
  const parentOpts = cmd.parent.opts();
117
127
  await loginCommand({
@@ -122,7 +132,12 @@ loginCmd
122
132
  acceptTerms: opts.acceptTerms,
123
133
  keyName: opts.keyName,
124
134
  readWrite: opts.readWrite,
135
+ walletApi: opts.walletApi,
136
+ agentApi: opts.agentApi,
137
+ tokenLaunch: opts.tokenLaunch,
125
138
  llm: opts.llm,
139
+ allowedIps: opts.allowedIps,
140
+ allowedRecipients: opts.allowedRecipients,
126
141
  });
127
142
  });
128
143
  loginCmd
@@ -131,7 +146,12 @@ loginCmd
131
146
  .requiredOption("--private-key <key>", "Ethereum private key (0x...)")
132
147
  .option("--partner-key <key>", "Partner API key for fee attribution")
133
148
  .option("--key-name <name>", "API key name (default: SIWE-<date>)")
134
- .option("--read-write", "Enable write operations on the API key")
149
+ .option("--read-write", "Disable read-only mode (allow transactions)")
150
+ .option("--no-wallet-api", "Disable Wallet API (enabled by default)")
151
+ .option("--agent-api", "Enable Agent API (AI prompts)")
152
+ .option("--no-token-launch", "Disable Token Launch API (enabled by default)")
153
+ .option("--allowed-ips <ips>", "Comma-separated IP allowlist (requests from other IPs will be blocked)")
154
+ .option("--allowed-recipients <addresses>", "Comma-separated EVM/Solana addresses (agent will only send funds to these)")
135
155
  .action(async (opts, cmd) => {
136
156
  const parentOpts = cmd.parent.opts();
137
157
  await loginCommand({
@@ -141,25 +161,126 @@ loginCmd
141
161
  partnerKey: opts.partnerKey,
142
162
  keyName: opts.keyName,
143
163
  readWrite: opts.readWrite,
164
+ walletApi: opts.walletApi,
165
+ agentApi: opts.agentApi,
166
+ tokenLaunch: opts.tokenLaunch,
167
+ allowedIps: opts.allowedIps,
168
+ allowedRecipients: opts.allowedRecipients,
144
169
  });
145
170
  });
146
- program
147
- .command("logout")
148
- .description("Clear stored credentials")
149
- .action(logoutCommand);
150
171
  program
151
172
  .command("whoami")
152
- .description("Show current authentication info")
173
+ .description("Show wallet info and account details")
153
174
  .action(whoamiCommand);
154
- program
155
- .command("balances")
156
- .description("Show wallet token balances across chains")
157
- .option("--chain <chains>", "Chain(s) to fetch: base, polygon, mainnet, unichain, solana (comma-separated)")
175
+ // Wallet commands (non-agentic operations)
176
+ const walletCmd = program
177
+ .command("wallet")
178
+ .description("Wallet info, portfolio, transfer, sign, and submit")
179
+ .action(async () => {
180
+ await whoamiCommand();
181
+ });
182
+ walletCmd
183
+ .command("portfolio")
184
+ .description("Show wallet portfolio: balances, PnL, and NFTs")
185
+ .option("--chain <chains>", "Chain(s): base, polygon, mainnet, unichain, solana (comma-separated)")
186
+ .option("--pnl", "Include profit/loss per token")
187
+ .option("--nfts", "Include NFT holdings")
188
+ .option("--all", "Include everything (pnl + nfts)")
158
189
  .option("--json", "Output raw JSON")
190
+ .option("--low-value", "Include low-value tokens (under $1)")
159
191
  .action(async (opts) => {
160
- await balancesCommand({ chain: opts.chain, json: opts.json });
192
+ await portfolioCommand(opts);
161
193
  });
162
- program
194
+ walletCmd
195
+ .command("transfer")
196
+ .description("Transfer tokens to an EVM address")
197
+ .requiredOption("--to <address>", "Recipient address")
198
+ .requiredOption("--amount <amount>", "Amount to send (human-readable)")
199
+ .option("--token <symbol or address>", "Token symbol (USDC) or contract address")
200
+ .option("--native", "Send native token (ETH, POL) instead of ERC20")
201
+ .option("--chain <chain>", "EVM chain: base, polygon, mainnet, unichain (default: base)")
202
+ .action(async (opts) => {
203
+ await transferCommand({
204
+ to: opts.to,
205
+ amount: opts.amount,
206
+ token: opts.token,
207
+ native: opts.native,
208
+ chain: opts.chain,
209
+ });
210
+ });
211
+ walletCmd
212
+ .command("sign")
213
+ .description("Sign messages, typed data, or transactions")
214
+ .requiredOption("-t, --type <type>", "Signature type: personal_sign, eth_signTypedData_v4, eth_signTransaction")
215
+ .option("-m, --message <message>", "Message to sign (for personal_sign)")
216
+ .option("--typed-data <json>", "EIP-712 typed data as JSON (for eth_signTypedData_v4)")
217
+ .option("--transaction <json>", "Transaction as JSON (for eth_signTransaction)")
218
+ .action(async (opts) => {
219
+ await signCommand({
220
+ type: opts.type,
221
+ message: opts.message,
222
+ typedData: opts.typedData,
223
+ transaction: opts.transaction,
224
+ });
225
+ });
226
+ const walletSubmitCmd = walletCmd
227
+ .command("submit")
228
+ .description("Submit a transaction to the blockchain");
229
+ walletSubmitCmd
230
+ .command("tx")
231
+ .description("Submit transaction with explicit parameters")
232
+ .requiredOption("--to <address>", "Destination address")
233
+ .requiredOption("--chain-id <id>", "Chain ID (8453=Base, 1=Ethereum, 137=Polygon)")
234
+ .option("--value <wei>", "Value in wei")
235
+ .option("--data <hex>", "Calldata (hex string)")
236
+ .option("--gas <limit>", "Gas limit")
237
+ .option("--gas-price <wei>", "Gas price (legacy)")
238
+ .option("--max-fee-per-gas <wei>", "Max fee per gas (EIP-1559)")
239
+ .option("--max-priority-fee-per-gas <wei>", "Max priority fee (EIP-1559)")
240
+ .option("--nonce <n>", "Transaction nonce")
241
+ .option("-d, --description <text>", "Description for logging")
242
+ .option("--no-wait", "Don't wait for confirmation")
243
+ .action(async (opts) => {
244
+ await submitCommand({
245
+ to: opts.to,
246
+ chainId: opts.chainId,
247
+ value: opts.value,
248
+ data: opts.data,
249
+ gas: opts.gas,
250
+ gasPrice: opts.gasPrice,
251
+ maxFeePerGas: opts.maxFeePerGas,
252
+ maxPriorityFeePerGas: opts.maxPriorityFeePerGas,
253
+ nonce: opts.nonce,
254
+ description: opts.description,
255
+ noWait: !opts.wait,
256
+ });
257
+ });
258
+ walletSubmitCmd
259
+ .command("json <transaction>")
260
+ .description("Submit transaction from JSON: {to, chainId, value?, data?}")
261
+ .option("-d, --description <text>", "Description for logging")
262
+ .option("--no-wait", "Don't wait for confirmation")
263
+ .action(async (transaction, opts) => {
264
+ await submitJsonCommand(transaction, {
265
+ noWait: !opts.wait,
266
+ description: opts.description,
267
+ });
268
+ });
269
+ // Agent commands (agentic operations that use LLM)
270
+ const agentCmd = program
271
+ .command("agent [text...]")
272
+ .description("AI agent commands (prompt, status, cancel, profile, skills)")
273
+ .option("--thread <id>", "Continue a specific conversation thread")
274
+ .option("-c, --continue", "Continue the most recent thread")
275
+ .action(async (text, opts) => {
276
+ const joined = text.join(" ").trim();
277
+ if (!joined) {
278
+ agentCmd.help();
279
+ return;
280
+ }
281
+ await promptCommand(joined || (await readPromptInput()), opts);
282
+ });
283
+ agentCmd
163
284
  .command("prompt [text...]")
164
285
  .description("Send a prompt to the Bankr AI agent")
165
286
  .option("--thread <id>", "Continue a specific conversation thread")
@@ -168,73 +289,18 @@ program
168
289
  const joined = text.join(" ").trim();
169
290
  await promptCommand(joined || (await readPromptInput()), opts);
170
291
  });
171
- program
292
+ agentCmd
172
293
  .command("status <jobId>")
173
294
  .description("Check the status of a job")
174
295
  .action(statusCommand);
175
- program
296
+ agentCmd
176
297
  .command("cancel <jobId>")
177
298
  .description("Cancel a running job")
178
299
  .action(cancelCommand);
179
- const configCmd = program
180
- .command("config")
181
- .description("Manage CLI configuration");
182
- configCmd
183
- .command("get [key]")
184
- .description("Get config value(s). Keys: apiKey, apiUrl, llmKey, llmUrl")
185
- .action(configGetCommand);
186
- configCmd
187
- .command("set <key> <value>")
188
- .description("Set a config value. Keys: apiKey, apiUrl, llmKey, llmUrl")
189
- .action(configSetCommand);
190
- program
300
+ agentCmd
191
301
  .command("skills")
192
302
  .description("Show all Bankr AI agent skills with examples")
193
303
  .action(skillsCommand);
194
- const soundsCmd = program
195
- .command("sounds")
196
- .description("Manage CESP sound packs")
197
- .action(soundsStatusCommand);
198
- soundsCmd
199
- .command("enable")
200
- .description("Enable sounds")
201
- .action(soundsEnableCommand);
202
- soundsCmd
203
- .command("disable")
204
- .description("Disable sounds")
205
- .action(soundsDisableCommand);
206
- soundsCmd
207
- .command("install <pack>")
208
- .description("Install a sound pack from the CESP registry")
209
- .action(soundsInstallCommand);
210
- soundsCmd
211
- .command("search [query]")
212
- .description("Search available packs in the CESP registry")
213
- .action(soundsSearchCommand);
214
- soundsCmd
215
- .command("list")
216
- .description("List installed sound packs")
217
- .action(soundsListCommand);
218
- soundsCmd
219
- .command("use <pack>")
220
- .description("Set active sound pack")
221
- .action(soundsUseCommand);
222
- soundsCmd
223
- .command("volume [level]")
224
- .description("Get or set volume (0.0-1.0)")
225
- .action(soundsVolumeCommand);
226
- soundsCmd
227
- .command("mute")
228
- .description("Mute all sounds")
229
- .action(soundsMuteCommand);
230
- soundsCmd
231
- .command("unmute")
232
- .description("Unmute sounds")
233
- .action(soundsUnmuteCommand);
234
- soundsCmd
235
- .command("test [category]")
236
- .description("Play a test sound")
237
- .action(soundsTestCommand);
238
304
  program
239
305
  .command("launch")
240
306
  .description("Launch a token on Base (interactive wizard)")
@@ -280,7 +346,8 @@ feesCmd
280
346
  .option("--all", "Claim all tokens without selection prompt")
281
347
  .option("-y, --yes", "Skip confirmation prompt")
282
348
  .action(feesClaimWalletCommand);
283
- const profileCmd = program
349
+ // Profile under agent namespace
350
+ const profileCmd = agentCmd
284
351
  .command("profile")
285
352
  .description("Manage your agent profile page")
286
353
  .option("--json", "Output raw JSON")
@@ -342,64 +409,6 @@ profileCmd
342
409
  json: opts.json,
343
410
  });
344
411
  });
345
- program
346
- .command("sign")
347
- .description("Sign messages, typed data, or transactions")
348
- .requiredOption("-t, --type <type>", "Signature type: personal_sign, eth_signTypedData_v4, eth_signTransaction")
349
- .option("-m, --message <message>", "Message to sign (for personal_sign)")
350
- .option("--typed-data <json>", "EIP-712 typed data as JSON (for eth_signTypedData_v4)")
351
- .option("--transaction <json>", "Transaction as JSON (for eth_signTransaction)")
352
- .action(async (opts) => {
353
- await signCommand({
354
- type: opts.type,
355
- message: opts.message,
356
- typedData: opts.typedData,
357
- transaction: opts.transaction,
358
- });
359
- });
360
- const submitCmd = program
361
- .command("submit")
362
- .description("Submit a transaction to the blockchain");
363
- submitCmd
364
- .command("tx")
365
- .description("Submit transaction with explicit parameters")
366
- .requiredOption("--to <address>", "Destination address")
367
- .requiredOption("--chain-id <id>", "Chain ID (8453=Base, 1=Ethereum, 137=Polygon)")
368
- .option("--value <wei>", "Value in wei")
369
- .option("--data <hex>", "Calldata (hex string)")
370
- .option("--gas <limit>", "Gas limit")
371
- .option("--gas-price <wei>", "Gas price (legacy)")
372
- .option("--max-fee-per-gas <wei>", "Max fee per gas (EIP-1559)")
373
- .option("--max-priority-fee-per-gas <wei>", "Max priority fee (EIP-1559)")
374
- .option("--nonce <n>", "Transaction nonce")
375
- .option("-d, --description <text>", "Description for logging")
376
- .option("--no-wait", "Don't wait for confirmation")
377
- .action(async (opts) => {
378
- await submitCommand({
379
- to: opts.to,
380
- chainId: opts.chainId,
381
- value: opts.value,
382
- data: opts.data,
383
- gas: opts.gas,
384
- gasPrice: opts.gasPrice,
385
- maxFeePerGas: opts.maxFeePerGas,
386
- maxPriorityFeePerGas: opts.maxPriorityFeePerGas,
387
- nonce: opts.nonce,
388
- description: opts.description,
389
- noWait: !opts.wait,
390
- });
391
- });
392
- submitCmd
393
- .command("json <transaction>")
394
- .description("Submit transaction from JSON: {to, chainId, value?, data?}")
395
- .option("-d, --description <text>", "Description for logging")
396
- .option("--no-wait", "Don't wait for confirmation")
397
- .action(async (transaction, opts) => {
398
- await submitJsonCommand(transaction, {
399
- noWait: !opts.wait,
400
- description: opts.description,
401
- });
402
- });
403
412
  const llmCmd = program
404
413
  .command("llm")
405
414
  .description("LLM Gateway tools")
@@ -470,13 +479,250 @@ llmCmd
470
479
  const args = idx >= 0 ? process.argv.slice(idx + 1) : [];
471
480
  await opencodeCommand(args);
472
481
  });
482
+ // Token search and info
483
+ const tokensCmd = program
484
+ .command("tokens")
485
+ .description("Token search and info")
486
+ .action(() => {
487
+ tokensCmd.help();
488
+ });
489
+ tokensCmd
490
+ .command("search <query>")
491
+ .description("Search tokens by name, symbol, or address")
492
+ .option("--chain <chainId>", "Chain ID (default: 8453 for Base)")
493
+ .action(async (query, opts) => {
494
+ await tokensSearchCommand(query, opts);
495
+ });
496
+ tokensCmd
497
+ .command("info <address>")
498
+ .description("Get detailed token info by contract address")
499
+ .option("--chain <chainId>", "Chain ID (default: 8453 for Base)")
500
+ .action(async (address, opts) => {
501
+ await tokensInfoCommand(address, opts);
502
+ });
503
+ // ── Utility commands ────────────────────────────────────────────────────
504
+ const configCmd = program
505
+ .command("config")
506
+ .description("Manage CLI configuration");
507
+ configCmd
508
+ .command("get [key]")
509
+ .description("Get config value(s). Keys: apiKey, apiUrl, llmKey, llmUrl")
510
+ .action(configGetCommand);
511
+ configCmd
512
+ .command("set <key> <value>")
513
+ .description("Set a config value. Keys: apiKey, apiUrl, llmKey, llmUrl")
514
+ .action(configSetCommand);
515
+ const soundsCmd = program
516
+ .command("sounds")
517
+ .description("Manage CESP sound packs")
518
+ .action(soundsStatusCommand);
519
+ soundsCmd
520
+ .command("enable")
521
+ .description("Enable sounds")
522
+ .action(soundsEnableCommand);
523
+ soundsCmd
524
+ .command("disable")
525
+ .description("Disable sounds")
526
+ .action(soundsDisableCommand);
527
+ soundsCmd
528
+ .command("install <pack>")
529
+ .description("Install a sound pack from the CESP registry")
530
+ .action(soundsInstallCommand);
531
+ soundsCmd
532
+ .command("search [query]")
533
+ .description("Search available packs in the CESP registry")
534
+ .action(soundsSearchCommand);
535
+ soundsCmd
536
+ .command("list")
537
+ .description("List installed sound packs")
538
+ .action(soundsListCommand);
539
+ soundsCmd
540
+ .command("use <pack>")
541
+ .description("Set active sound pack")
542
+ .action(soundsUseCommand);
543
+ soundsCmd
544
+ .command("volume [level]")
545
+ .description("Get or set volume (0.0-1.0)")
546
+ .action(soundsVolumeCommand);
547
+ soundsCmd
548
+ .command("mute")
549
+ .description("Mute all sounds")
550
+ .action(soundsMuteCommand);
551
+ soundsCmd
552
+ .command("unmute")
553
+ .description("Unmute sounds")
554
+ .action(soundsUnmuteCommand);
555
+ soundsCmd
556
+ .command("test [category]")
557
+ .description("Play a test sound")
558
+ .action(soundsTestCommand);
559
+ program
560
+ .command("logout")
561
+ .description("Clear stored credentials")
562
+ .action(logoutCommand);
563
+ // ── Deprecated aliases (kept for backward compat) ──────────────────────
564
+ program
565
+ .command("balances")
566
+ .description("Deprecated: use `bankr wallet portfolio` instead")
567
+ .option("--chain <chains>", "Chain(s) to fetch (comma-separated)")
568
+ .option("--json", "Output raw JSON")
569
+ .option("--low-value", "Include low-value tokens (under $1)")
570
+ .action(async (opts) => {
571
+ await balancesCommand({
572
+ chain: opts.chain,
573
+ json: opts.json,
574
+ showLowValueTokens: opts.lowValue,
575
+ });
576
+ });
577
+ program
578
+ .command("prompt [text...]")
579
+ .description("Deprecated: use `bankr agent <prompt>` instead")
580
+ .option("--thread <id>")
581
+ .option("-c, --continue")
582
+ .action(async (text, opts) => {
583
+ const joined = text.join(" ").trim();
584
+ await promptCommand(joined || (await readPromptInput()), opts);
585
+ });
586
+ program
587
+ .command("status <jobId>")
588
+ .description("Deprecated: use `bankr agent status` instead")
589
+ .action(statusCommand);
590
+ program
591
+ .command("cancel <jobId>")
592
+ .description("Deprecated: use `bankr agent cancel` instead")
593
+ .action(cancelCommand);
594
+ const profileAliasCmd = program
595
+ .command("profile")
596
+ .description("Deprecated: use `bankr agent profile` instead")
597
+ .option("--json", "Output raw JSON")
598
+ .action(async (opts) => {
599
+ await profileViewCommand({ json: opts.json });
600
+ });
601
+ profileAliasCmd
602
+ .command("create")
603
+ .option("--name <name>", "Project name")
604
+ .option("--description <text>", "Project description")
605
+ .option("--token <address>", "Token contract address")
606
+ .option("--image <url>", "Profile image URL")
607
+ .option("--website <url>", "Project website URL")
608
+ .option("--json", "Output raw JSON")
609
+ .action(async (opts) => {
610
+ await profileCreateCommand({
611
+ name: opts.name,
612
+ description: opts.description,
613
+ token: opts.token,
614
+ image: opts.image,
615
+ website: opts.website,
616
+ json: opts.json,
617
+ });
618
+ });
619
+ profileAliasCmd
620
+ .command("update")
621
+ .option("--name <name>", "Project name")
622
+ .option("--description <text>", "Project description")
623
+ .option("--token <address>", "Token contract address")
624
+ .option("--image <url>", "Profile image URL")
625
+ .option("--website <url>", "Project website URL")
626
+ .option("--json", "Output raw JSON")
627
+ .action(async (opts) => {
628
+ await profileUpdateCommand({
629
+ name: opts.name,
630
+ description: opts.description,
631
+ token: opts.token,
632
+ image: opts.image,
633
+ website: opts.website,
634
+ json: opts.json,
635
+ });
636
+ });
637
+ profileAliasCmd.command("delete").action(profileDeleteCommand);
638
+ profileAliasCmd
639
+ .command("add-update")
640
+ .option("--title <title>", "Update title")
641
+ .option("--content <text>", "Update content")
642
+ .option("--json", "Output raw JSON")
643
+ .action(async (opts) => {
644
+ await profileAddUpdateCommand({
645
+ title: opts.title,
646
+ content: opts.content,
647
+ json: opts.json,
648
+ });
649
+ });
650
+ program
651
+ .command("sign")
652
+ .description("Deprecated: use `bankr wallet sign` instead")
653
+ .requiredOption("-t, --type <type>", "Signature type")
654
+ .option("-m, --message <message>", "Message to sign")
655
+ .option("--typed-data <json>", "EIP-712 typed data as JSON")
656
+ .option("--transaction <json>", "Transaction as JSON")
657
+ .action(async (opts) => {
658
+ await signCommand({
659
+ type: opts.type,
660
+ message: opts.message,
661
+ typedData: opts.typedData,
662
+ transaction: opts.transaction,
663
+ });
664
+ });
665
+ const submitAliasCmd = program
666
+ .command("submit")
667
+ .description("Deprecated: use `bankr wallet submit` instead");
668
+ submitAliasCmd
669
+ .command("tx")
670
+ .description("Submit transaction with explicit parameters")
671
+ .requiredOption("--to <address>", "Destination address")
672
+ .requiredOption("--chain-id <id>", "Chain ID")
673
+ .option("--value <wei>", "Value in wei")
674
+ .option("--data <hex>", "Calldata")
675
+ .option("--gas <limit>", "Gas limit")
676
+ .option("--gas-price <wei>", "Gas price")
677
+ .option("--max-fee-per-gas <wei>", "Max fee per gas")
678
+ .option("--max-priority-fee-per-gas <wei>", "Max priority fee")
679
+ .option("--nonce <n>", "Transaction nonce")
680
+ .option("-d, --description <text>", "Description")
681
+ .option("--no-wait", "Don't wait for confirmation")
682
+ .action(async (opts) => {
683
+ await submitCommand({
684
+ to: opts.to,
685
+ chainId: opts.chainId,
686
+ value: opts.value,
687
+ data: opts.data,
688
+ gas: opts.gas,
689
+ gasPrice: opts.gasPrice,
690
+ maxFeePerGas: opts.maxFeePerGas,
691
+ maxPriorityFeePerGas: opts.maxPriorityFeePerGas,
692
+ nonce: opts.nonce,
693
+ description: opts.description,
694
+ noWait: !opts.wait,
695
+ });
696
+ });
697
+ submitAliasCmd
698
+ .command("json <transaction>")
699
+ .description("Submit from JSON")
700
+ .option("-d, --description <text>", "Description")
701
+ .option("--no-wait", "Don't wait for confirmation")
702
+ .action(async (transaction, opts) => {
703
+ await submitJsonCommand(transaction, {
704
+ noWait: !opts.wait,
705
+ description: opts.description,
706
+ });
707
+ });
708
+ program
709
+ .command("update")
710
+ .description("Update the Bankr CLI to the latest version")
711
+ .option("--check", "Check for updates without installing")
712
+ .action(async (opts) => {
713
+ await updateCommand({ check: opts.check });
714
+ });
473
715
  // Default: treat unrecognized arguments as a prompt
474
- program.arguments("[text...]").action(async (text) => {
716
+ program
717
+ .arguments("[text...]")
718
+ .option("--thread <id>", "Continue a specific conversation thread")
719
+ .option("-c, --continue", "Continue the most recent thread")
720
+ .action(async (text, opts) => {
475
721
  if (text.length === 0) {
476
722
  program.help();
477
723
  return;
478
724
  }
479
- await promptCommand(text.join(" "));
725
+ await promptCommand(text.join(" "), opts);
480
726
  });
481
727
  async function main() {
482
728
  try {
@@ -1,5 +1,6 @@
1
1
  export declare function balancesCommand(opts: {
2
2
  chain?: string;
3
3
  json?: boolean;
4
+ showLowValueTokens?: boolean;
4
5
  }): Promise<void>;
5
6
  //# sourceMappingURL=balances.d.ts.map
@@ -1,42 +1,13 @@
1
1
  import chalk from "chalk";
2
2
  import { getBalances, } from "../lib/api.js";
3
3
  import * as output from "../lib/output.js";
4
+ import { formatUsd, formatBalance } from "../lib/output.js";
5
+ import { CHAIN_LABELS, VALID_CHAINS } from "../lib/chains.js";
4
6
  const BRAND = chalk.hex("#FF613D");
5
7
  const DIM = chalk.dim;
6
8
  const BOLD = chalk.bold;
7
9
  const GREEN = chalk.greenBright;
8
10
  const WHITE = chalk.whiteBright;
9
- const CHAIN_LABELS = {
10
- base: "Base",
11
- polygon: "Polygon",
12
- mainnet: "Ethereum",
13
- unichain: "Unichain",
14
- solana: "Solana",
15
- };
16
- const VALID_CHAINS = new Set([
17
- "base",
18
- "polygon",
19
- "mainnet",
20
- "unichain",
21
- "solana",
22
- ]);
23
- function formatUsd(value) {
24
- const num = typeof value === "string" ? parseFloat(value) : value;
25
- if (isNaN(num) || num === 0)
26
- return DIM("$0.00");
27
- return `$${num.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
28
- }
29
- function formatBalance(value, decimals = 6) {
30
- const num = typeof value === "string" ? parseFloat(value) : value;
31
- if (isNaN(num) || num === 0)
32
- return "0";
33
- if (num < 0.000001)
34
- return "<0.000001";
35
- return num.toLocaleString("en-US", {
36
- minimumFractionDigits: 0,
37
- maximumFractionDigits: decimals,
38
- });
39
- }
40
11
  function printChainBalances(chain, data) {
41
12
  const label = CHAIN_LABELS[chain] || chain;
42
13
  const total = parseFloat(data.total);
@@ -78,7 +49,7 @@ export async function balancesCommand(opts) {
78
49
  const spin = output.spinner("Fetching balances...");
79
50
  let data;
80
51
  try {
81
- data = await getBalances(chains);
52
+ data = await getBalances(chains, opts.showLowValueTokens);
82
53
  spin.succeed("Balances loaded");
83
54
  }
84
55
  catch (err) {
@@ -104,6 +75,10 @@ export async function balancesCommand(opts) {
104
75
  }
105
76
  console.log();
106
77
  output.label("Total", GREEN(formatUsd(grandTotal)));
78
+ if (opts.showLowValueTokens) {
79
+ console.log();
80
+ output.info("Including low-value tokens");
81
+ }
107
82
  // Print each chain
108
83
  for (const [chain, chainData] of chainEntries) {
109
84
  printChainBalances(chain, chainData);