@bankr/cli 0.3.11 → 0.3.13

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 CHANGED
@@ -49,7 +49,7 @@ bankr login --api-key bk_YOUR_KEY --llm-key YOUR_LLM_KEY
49
49
  bankr login --url
50
50
 
51
51
  # Log in with a custom API URL
52
- bankr login --api-url https://api-staging.bankr.bot
52
+ bankr login --api-url https://api.bankr.bot
53
53
 
54
54
  # Show current auth info and validate connection
55
55
  bankr whoami
@@ -138,7 +138,7 @@ bankr config get
138
138
  bankr config get apiUrl
139
139
 
140
140
  # Set a value
141
- bankr config set apiUrl https://api-staging.bankr.bot
141
+ bankr config set apiUrl https://api.bankr.bot
142
142
 
143
143
  # Set a separate LLM gateway key
144
144
  bankr config set llmKey YOUR_LLM_KEY
package/dist/cli.js CHANGED
@@ -255,7 +255,7 @@ walletSubmitCmd
255
255
  .command("tx")
256
256
  .description("Submit transaction with explicit parameters")
257
257
  .requiredOption("--to <address>", "Destination address")
258
- .requiredOption("--chain-id <id>", "Chain ID (8453=Base, 1=Ethereum, 137=Polygon)")
258
+ .requiredOption("--chain-id <id>", "Chain ID (8453=Base, 1=Ethereum, 137=Polygon, 4663=Robinhood Chain)")
259
259
  .option("--value <wei>", "Value in wei")
260
260
  .option("--data <hex>", "Calldata (hex string)")
261
261
  .option("--gas <limit>", "Gas limit")
@@ -340,11 +340,12 @@ agentCmd
340
340
  program.commandsGroup("Tokens");
341
341
  program
342
342
  .command("launch")
343
- .description("Launch a token on Base (interactive wizard)")
343
+ .description("Launch a token on Base or Robinhood Chain (interactive wizard)")
344
344
  .optionsGroup("Token")
345
345
  .option("--name <name>", "Token name")
346
346
  .option("--symbol <symbol>", "Token symbol (default: auto-generated from name)")
347
347
  .option("--image <url>", "Token image URL")
348
+ .option("--chain <chain>", "Chain to launch on: base, robinhood (default: base)")
348
349
  .optionsGroup("Links")
349
350
  .option("--tweet <url>", "Associated tweet URL")
350
351
  .option("--website <url>", "Project website URL")
@@ -359,6 +360,7 @@ program
359
360
  name: opts.name,
360
361
  symbol: opts.symbol,
361
362
  image: opts.image,
363
+ chain: opts.chain,
362
364
  tweet: opts.tweet,
363
365
  website: opts.website,
364
366
  fee: opts.fee,
@@ -1,6 +1,7 @@
1
1
  import { confirm } from "@inquirer/prompts";
2
2
  import { CLI_USER_AGENT, getApiUrl, requireApiKey } from "../lib/config.js";
3
3
  import * as output from "../lib/output.js";
4
+ import { getErrorMessage } from "../lib/errors.js";
4
5
  function authHeaders() {
5
6
  return {
6
7
  "X-API-Key": requireApiKey(),
@@ -78,7 +79,7 @@ export async function clubStatusCommand() {
78
79
  }
79
80
  catch (err) {
80
81
  spinner.stop();
81
- output.error(err instanceof Error ? err.message : String(err));
82
+ output.error(getErrorMessage(err));
82
83
  process.exit(1);
83
84
  }
84
85
  }
@@ -142,7 +143,7 @@ export async function clubSignupCommand(opts) {
142
143
  output.dim("Run `bankr club` to see your status.");
143
144
  }
144
145
  catch (err) {
145
- output.error(err instanceof Error ? err.message : String(err));
146
+ output.error(getErrorMessage(err));
146
147
  process.exit(1);
147
148
  }
148
149
  }
@@ -186,7 +187,7 @@ export async function clubCancelCommand(opts) {
186
187
  output.dim("You'll keep Bankr Club access until the end of the current billing period.");
187
188
  }
188
189
  catch (err) {
189
- output.error(err instanceof Error ? err.message : String(err));
190
+ output.error(getErrorMessage(err));
190
191
  process.exit(1);
191
192
  }
192
193
  }
@@ -4,6 +4,7 @@ import { isAddress } from "viem";
4
4
  import { getCreatorFees, getBeneficiaryFeesStreaming, getTokenCreatorFees, getUserInfo, claimTokenLaunchFees, } from "../lib/api.js";
5
5
  import { emitCESP } from "../lib/cesp/engine.js";
6
6
  import { requireApiKey } from "../lib/config.js";
7
+ import { txExplorer } from "../lib/explorer.js";
7
8
  import * as output from "../lib/output.js";
8
9
  // ---------------------------------------------------------------------------
9
10
  // Constants
@@ -212,7 +213,11 @@ function renderDashboard(data) {
212
213
  console.log(` ${l}`);
213
214
  }
214
215
  console.log(`${DIM(` Wallet: ${data.address}`)}`);
215
- console.log(`${DIM(` Chain: Base \u00b7 Tokens: ${data.tokens.length} \u00b7 Period: ${data.days} days`)}`);
216
+ // Tokens can span launch chains ("chain" absent on pre-multichain rows).
217
+ const chainNames = [
218
+ ...new Set(data.tokens.map((t) => (t.chain ?? "base") === "robinhood" ? "Robinhood" : "Base")),
219
+ ].join(" + ") || "Base";
220
+ console.log(`${DIM(` Chain: ${chainNames} \u00b7 Tokens: ${data.tokens.length} \u00b7 Period: ${data.days} days`)}`);
216
221
  if (data.tokens.length === 0) {
217
222
  console.log(`\n ${DIM("No tokens found where this wallet is a creator beneficiary.")}`);
218
223
  console.log("");
@@ -430,7 +435,8 @@ export async function feesClaimCommand(tokenAddress, opts) {
430
435
  }
431
436
  console.log();
432
437
  if (result.transactionHash) {
433
- output.dim(`View on Basescan: https://basescan.org/tx/${result.transactionHash}`);
438
+ const explorer = txExplorer(result.chainId, result.transactionHash);
439
+ output.dim(`View on ${explorer.name}: ${explorer.url}`);
434
440
  }
435
441
  if (!ok) {
436
442
  process.exit(1);
@@ -631,10 +637,17 @@ export async function feesClaimWalletCommand(address, opts) {
631
637
  ],
632
638
  },
633
639
  ];
640
+ // Robinhood-chain launches can't be claimed here: this flow signs and
641
+ // broadcasts on Base only, and a Base tx to a robinhood initializer is a
642
+ // gas-burning no-op. Skip them loudly.
643
+ const baseChainTokens = selectedTokens.filter((t) => (t.chain ?? "base") === "base");
644
+ if (baseChainTokens.length < selectedTokens.length) {
645
+ output.warn(`${selectedTokens.length - baseChainTokens.length} Robinhood Chain token(s) skipped — CLI claiming supports Base only for now. Claim at https://bankr.bot/launches instead.`);
646
+ }
634
647
  // Filter to tokens with initializer (required for local tx building)
635
- const buildableTokens = selectedTokens.filter((t) => t.initializer);
636
- if (buildableTokens.length < selectedTokens.length) {
637
- output.warn(`${selectedTokens.length - buildableTokens.length} token(s) missing initializer data — skipped`);
648
+ const buildableTokens = baseChainTokens.filter((t) => t.initializer);
649
+ if (buildableTokens.length < baseChainTokens.length) {
650
+ output.warn(`${baseChainTokens.length - buildableTokens.length} token(s) missing initializer data — skipped`);
638
651
  }
639
652
  if (buildableTokens.length === 0) {
640
653
  output.error("No transactions could be built");
@@ -2,6 +2,7 @@ import { readFileSync, statSync, writeFileSync } from "node:fs";
2
2
  import { basename } from "node:path";
3
3
  import { CLI_USER_AGENT, getApiUrl, requireApiKey } from "../lib/config.js";
4
4
  import * as output from "../lib/output.js";
5
+ import { getErrorMessage } from "../lib/errors.js";
5
6
  async function readStdin() {
6
7
  if (process.stdin.isTTY) {
7
8
  throw new Error("No content provided. Pipe content via stdin or pass --from <file>.");
@@ -54,7 +55,7 @@ export async function filesListCommand(opts) {
54
55
  }
55
56
  catch (err) {
56
57
  spinner.stop();
57
- output.error(err instanceof Error ? err.message : String(err));
58
+ output.error(getErrorMessage(err));
58
59
  process.exit(1);
59
60
  }
60
61
  }
@@ -102,7 +103,7 @@ export async function filesUploadCommand(filePath, opts) {
102
103
  }
103
104
  catch (err) {
104
105
  spinner.stop();
105
- output.error(err instanceof Error ? err.message : String(err));
106
+ output.error(getErrorMessage(err));
106
107
  process.exit(1);
107
108
  }
108
109
  }
@@ -124,7 +125,7 @@ export async function filesDownloadCommand(fileId) {
124
125
  }
125
126
  catch (err) {
126
127
  spinner.stop();
127
- output.error(err instanceof Error ? err.message : String(err));
128
+ output.error(getErrorMessage(err));
128
129
  process.exit(1);
129
130
  }
130
131
  }
@@ -149,7 +150,7 @@ export async function filesMkdirCommand(name, opts) {
149
150
  }
150
151
  catch (err) {
151
152
  spinner.stop();
152
- output.error(err instanceof Error ? err.message : String(err));
153
+ output.error(getErrorMessage(err));
153
154
  process.exit(1);
154
155
  }
155
156
  }
@@ -170,7 +171,7 @@ export async function filesRmCommand(fileId) {
170
171
  }
171
172
  catch (err) {
172
173
  spinner.stop();
173
- output.error(err instanceof Error ? err.message : String(err));
174
+ output.error(getErrorMessage(err));
174
175
  process.exit(1);
175
176
  }
176
177
  }
@@ -202,7 +203,7 @@ export async function filesStorageCommand() {
202
203
  }
203
204
  catch (err) {
204
205
  spinner.stop();
205
- output.error(err instanceof Error ? err.message : String(err));
206
+ output.error(getErrorMessage(err));
206
207
  process.exit(1);
207
208
  }
208
209
  }
@@ -239,7 +240,7 @@ export async function filesCatCommand(fileId, opts) {
239
240
  }
240
241
  catch (err) {
241
242
  spinner.stop();
242
- output.error(err instanceof Error ? err.message : String(err));
243
+ output.error(getErrorMessage(err));
243
244
  process.exit(1);
244
245
  }
245
246
  }
@@ -315,7 +316,7 @@ export async function filesEditCommand(fileId, opts) {
315
316
  }
316
317
  catch (err) {
317
318
  spinner.stop();
318
- output.error(err instanceof Error ? err.message : String(err));
319
+ output.error(getErrorMessage(err));
319
320
  process.exit(1);
320
321
  }
321
322
  }
@@ -341,7 +342,7 @@ export async function filesWriteCommand(fileId, opts) {
341
342
  }
342
343
  catch (err) {
343
344
  spinner.stop();
344
- output.error(err instanceof Error ? err.message : String(err));
345
+ output.error(getErrorMessage(err));
345
346
  process.exit(1);
346
347
  }
347
348
  }
@@ -380,7 +381,7 @@ export async function filesSearchCommand(query, opts) {
380
381
  }
381
382
  catch (err) {
382
383
  spinner.stop();
383
- output.error(err instanceof Error ? err.message : String(err));
384
+ output.error(getErrorMessage(err));
384
385
  process.exit(1);
385
386
  }
386
387
  }
@@ -403,7 +404,7 @@ export async function filesMvCommand(fileId, folder) {
403
404
  }
404
405
  catch (err) {
405
406
  spinner.stop();
406
- output.error(err instanceof Error ? err.message : String(err));
407
+ output.error(getErrorMessage(err));
407
408
  process.exit(1);
408
409
  }
409
410
  }
@@ -426,7 +427,7 @@ export async function filesRenameCommand(fileId, name) {
426
427
  }
427
428
  catch (err) {
428
429
  spinner.stop();
429
- output.error(err instanceof Error ? err.message : String(err));
430
+ output.error(getErrorMessage(err));
430
431
  process.exit(1);
431
432
  }
432
433
  }
@@ -455,7 +456,7 @@ export async function filesInfoCommand(fileId) {
455
456
  }
456
457
  catch (err) {
457
458
  spinner.stop();
458
- output.error(err instanceof Error ? err.message : String(err));
459
+ output.error(getErrorMessage(err));
459
460
  process.exit(1);
460
461
  }
461
462
  }
@@ -2,6 +2,7 @@ export interface LaunchOptions {
2
2
  name?: string;
3
3
  symbol?: string;
4
4
  image?: string;
5
+ chain?: string;
5
6
  tweet?: string;
6
7
  website?: string;
7
8
  fee?: string;
@@ -1,9 +1,24 @@
1
1
  import { confirm, input, select } from "@inquirer/prompts";
2
- import { deployToken } from "../lib/api.js";
2
+ import { deployToken, } from "../lib/api.js";
3
3
  import { emitCESP } from "../lib/cesp/engine.js";
4
4
  import { requireApiKey } from "../lib/config.js";
5
5
  import * as output from "../lib/output.js";
6
6
  const VALID_FEE_TYPES = ["x", "farcaster", "ens", "wallet"];
7
+ const VALID_CHAINS = ["base", "robinhood"];
8
+ function chainLabel(chain) {
9
+ return chain === "robinhood" ? "Robinhood Chain" : "Base";
10
+ }
11
+ function parseChain(value) {
12
+ if (!value)
13
+ return undefined;
14
+ const lower = value.toLowerCase();
15
+ if (VALID_CHAINS.includes(lower))
16
+ return lower;
17
+ // Launching is irreversible and chain-selecting — a mistyped chain must be
18
+ // a hard usage error, never a silent fallback to Base.
19
+ output.error(`Unknown chain "${value}". Valid chains: ${VALID_CHAINS.join(", ")}.`);
20
+ process.exit(1);
21
+ }
7
22
  function parseFeeType(value) {
8
23
  if (!value)
9
24
  return "x";
@@ -45,6 +60,21 @@ async function collectInteractive(options) {
45
60
  (await promptOrSkip("Token symbol (press Enter to auto-generate from name):"));
46
61
  const imageUrl = options.image ??
47
62
  (await promptOrSkip("Image URL for your token (press Enter to skip):"));
63
+ // Chain: --chain flag wins; otherwise interactive select (default Base).
64
+ // Non-interactive runs without --chain launch on Base.
65
+ let chain = parseChain(options.chain);
66
+ if (!chain && !output.isNonInteractive()) {
67
+ chain = await select({
68
+ message: "Which chain do you want to launch on?",
69
+ choices: [
70
+ { name: "Base", value: "base" },
71
+ { name: "Robinhood Chain", value: "robinhood" },
72
+ ],
73
+ default: "base",
74
+ theme: output.bankrTheme,
75
+ });
76
+ }
77
+ chain ?? (chain = "base");
48
78
  const tweetUrl = options.tweet ??
49
79
  (await promptOrSkip("Associate with a tweet? Paste URL (press Enter to skip):"));
50
80
  const websiteUrl = options.website ??
@@ -71,6 +101,7 @@ async function collectInteractive(options) {
71
101
  tokenName: tokenName.trim(),
72
102
  tokenSymbol: tokenSymbol.trim(),
73
103
  imageUrl: imageUrl.trim(),
104
+ chain,
74
105
  tweetUrl: tweetUrl.trim(),
75
106
  websiteUrl: websiteUrl.trim(),
76
107
  feeRecipient: feeRecipient.trim(),
@@ -97,7 +128,7 @@ export async function launchCommand(options) {
97
128
  output.keyValue("Fee recipient", state.feeRecipient
98
129
  ? `${state.feeRecipient} (${feeTypeLabel(state.feeRecipientType)})`
99
130
  : "(self)");
100
- output.keyValue("Chain", "Base");
131
+ output.keyValue("Chain", chainLabel(state.chain));
101
132
  if (options.simulate) {
102
133
  output.keyValue("Mode", "Simulation (dry run)");
103
134
  }
@@ -123,6 +154,7 @@ export async function launchCommand(options) {
123
154
  tokenName: state.tokenName,
124
155
  tokenSymbol: state.tokenSymbol || undefined,
125
156
  image: state.imageUrl || undefined,
157
+ chain: state.chain,
126
158
  tweetUrl: state.tweetUrl || undefined,
127
159
  websiteUrl: state.websiteUrl || undefined,
128
160
  feeRecipient: state.feeRecipient
@@ -14,6 +14,15 @@ const IMAGE_INPUT = ["text", "image"];
14
14
  const TEXT_INPUT = ["text"];
15
15
  const GATEWAY_MODELS = [
16
16
  // Claude
17
+ {
18
+ id: "claude-fable-5",
19
+ name: "Claude Fable 5",
20
+ owned_by: "anthropic",
21
+ contextWindow: 1000000,
22
+ maxTokens: 128000,
23
+ input: IMAGE_INPUT,
24
+ cost: { input: 10.0, output: 50.0, cacheRead: 1.0, cacheWrite: 12.5 },
25
+ },
17
26
  {
18
27
  id: "claude-opus-4.8",
19
28
  name: "Claude Opus 4.8",
@@ -124,6 +133,15 @@ const GATEWAY_MODELS = [
124
133
  cost: { input: 0.3, output: 2.5, cacheRead: 0.03, cacheWrite: 0.0833 },
125
134
  },
126
135
  // OpenAI
136
+ {
137
+ id: "gpt-5.5",
138
+ name: "GPT 5.5",
139
+ owned_by: "openai",
140
+ contextWindow: 1050000,
141
+ maxTokens: 128000,
142
+ input: IMAGE_INPUT,
143
+ cost: { input: 5.0, output: 30.0, cacheRead: 0.5, cacheWrite: 0 },
144
+ },
127
145
  {
128
146
  id: "gpt-5.4",
129
147
  name: "GPT 5.4",
@@ -997,7 +1015,7 @@ export async function setupCursorCommand() {
997
1015
  const { models } = await resolveModels();
998
1016
  const activeModels = models.filter((m) => !m.deprecation);
999
1017
  // Pick one model per provider as recommended examples
1000
- const recommendedIds = ["claude-opus-4.8", "gemini-3.1-pro", "gpt-5.2"];
1018
+ const recommendedIds = ["claude-fable-5", "gemini-3.1-pro", "gpt-5.5"];
1001
1019
  const recommended = recommendedIds.filter((id) => activeModels.some((m) => m.id === id));
1002
1020
  output.brandBold("Cursor — Bankr LLM Gateway");
1003
1021
  console.log();
@@ -11,6 +11,7 @@ const VALID_MAX_MODE_MODELS = new Set([
11
11
  "claude-opus-4.7",
12
12
  "claude-opus-4.6",
13
13
  "claude-opus-4.5",
14
+ "claude-sonnet-5",
14
15
  "claude-sonnet-4.6",
15
16
  "claude-sonnet-4.5",
16
17
  "claude-haiku-4.5",
@@ -29,6 +30,7 @@ const VALID_MAX_MODE_MODELS = new Set([
29
30
  "deepseek-v3.2",
30
31
  // Qwen (OpenRouter)
31
32
  "qwen3-coder",
33
+ "qwen3.7-max",
32
34
  "qwen3.7-plus",
33
35
  "qwen3.5-plus",
34
36
  // MiniMax (direct)
@@ -17,6 +17,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
17
17
  import { join } from "node:path";
18
18
  import { confirm } from "@inquirer/prompts";
19
19
  import * as output from "../lib/output.js";
20
+ import { getErrorMessage } from "../lib/errors.js";
20
21
  import { getApiUrl, requireApiKey, CLI_USER_AGENT } from "../lib/config.js";
21
22
  // ── Config file ─────────────────────────────────────────────────────────
22
23
  const CONFIG_FILENAME = "bankr.webhooks.json";
@@ -487,7 +488,7 @@ export async function webhooksDeployCommand(name) {
487
488
  }
488
489
  catch (err) {
489
490
  spin.fail("Deploy failed");
490
- output.error(err instanceof Error ? err.message : String(err));
491
+ output.error(getErrorMessage(err));
491
492
  process.exit(1);
492
493
  }
493
494
  }
@@ -515,7 +516,7 @@ export async function webhooksListCommand() {
515
516
  }
516
517
  catch (err) {
517
518
  spin.fail("Failed to list webhooks");
518
- output.error(err instanceof Error ? err.message : String(err));
519
+ output.error(getErrorMessage(err));
519
520
  process.exit(1);
520
521
  }
521
522
  }
@@ -533,7 +534,7 @@ export async function webhooksPauseResumeCommand(name, action) {
533
534
  }
534
535
  catch (err) {
535
536
  spin.fail(`Failed to ${action} ${name}`);
536
- output.error(err instanceof Error ? err.message : String(err));
537
+ output.error(getErrorMessage(err));
537
538
  process.exit(1);
538
539
  }
539
540
  }
@@ -556,7 +557,7 @@ export async function webhooksDeleteCommand(name) {
556
557
  }
557
558
  catch (err) {
558
559
  spin.fail(`Failed to delete ${name}`);
559
- output.error(err instanceof Error ? err.message : String(err));
560
+ output.error(getErrorMessage(err));
560
561
  process.exit(1);
561
562
  }
562
563
  }
@@ -582,7 +583,7 @@ export async function webhooksLogsCommand(name) {
582
583
  }
583
584
  catch (err) {
584
585
  spin.fail("Failed to fetch logs");
585
- output.error(err instanceof Error ? err.message : String(err));
586
+ output.error(getErrorMessage(err));
586
587
  process.exit(1);
587
588
  }
588
589
  }
@@ -611,7 +612,7 @@ export async function webhooksEnvSetCommand(keyValue) {
611
612
  }
612
613
  catch (err) {
613
614
  spin.fail(`Failed to set ${key}`);
614
- output.error(err instanceof Error ? err.message : String(err));
615
+ output.error(getErrorMessage(err));
615
616
  process.exit(1);
616
617
  }
617
618
  }
@@ -632,7 +633,7 @@ export async function webhooksEnvListCommand() {
632
633
  }
633
634
  catch (err) {
634
635
  spin.fail("Failed to list env vars");
635
- output.error(err instanceof Error ? err.message : String(err));
636
+ output.error(getErrorMessage(err));
636
637
  process.exit(1);
637
638
  }
638
639
  }
@@ -645,7 +646,7 @@ export async function webhooksEnvUnsetCommand(key) {
645
646
  }
646
647
  catch (err) {
647
648
  spin.fail(`Failed to remove ${key}`);
648
- output.error(err instanceof Error ? err.message : String(err));
649
+ output.error(getErrorMessage(err));
649
650
  process.exit(1);
650
651
  }
651
652
  }
@@ -20,6 +20,7 @@ import { join } from "node:path";
20
20
  import chalk from "chalk";
21
21
  import { input, select, confirm } from "@inquirer/prompts";
22
22
  import * as output from "../lib/output.js";
23
+ import { getErrorMessage } from "../lib/errors.js";
23
24
  import { getApiUrl, requireApiKey, CLI_USER_AGENT } from "../lib/config.js";
24
25
  // ── Config file helpers ─────────────────────────────────────────────────
25
26
  const CONFIG_FILENAME = "bankr.x402.json";
@@ -422,7 +423,7 @@ export async function x402DeployCommand(name) {
422
423
  }
423
424
  catch (err) {
424
425
  spin.fail("Deploy failed");
425
- output.error(err instanceof Error ? err.message : String(err));
426
+ output.error(getErrorMessage(err));
426
427
  process.exit(1);
427
428
  }
428
429
  }
@@ -452,7 +453,7 @@ export async function x402ListCommand() {
452
453
  }
453
454
  catch (err) {
454
455
  spin.fail("Failed to list endpoints");
455
- output.error(err instanceof Error ? err.message : String(err));
456
+ output.error(getErrorMessage(err));
456
457
  process.exit(1);
457
458
  }
458
459
  }
@@ -473,7 +474,7 @@ export async function x402PauseResumeCommand(name, action) {
473
474
  }
474
475
  catch (err) {
475
476
  spin.fail(`Failed to ${action} ${name}`);
476
- output.error(err instanceof Error ? err.message : String(err));
477
+ output.error(getErrorMessage(err));
477
478
  process.exit(1);
478
479
  }
479
480
  }
@@ -499,7 +500,7 @@ export async function x402DeleteCommand(name) {
499
500
  }
500
501
  catch (err) {
501
502
  spin.fail(`Failed to delete ${name}`);
502
- output.error(err instanceof Error ? err.message : String(err));
503
+ output.error(getErrorMessage(err));
503
504
  process.exit(1);
504
505
  }
505
506
  }
@@ -533,7 +534,7 @@ export async function x402RevenueCommand(name) {
533
534
  }
534
535
  catch (err) {
535
536
  spin.fail("Failed to fetch revenue");
536
- output.error(err instanceof Error ? err.message : String(err));
537
+ output.error(getErrorMessage(err));
537
538
  process.exit(1);
538
539
  }
539
540
  }
@@ -564,7 +565,7 @@ export async function x402EnvSetCommand(keyValue) {
564
565
  }
565
566
  catch (err) {
566
567
  spin.fail(`Failed to set ${key}`);
567
- output.error(err instanceof Error ? err.message : String(err));
568
+ output.error(getErrorMessage(err));
568
569
  process.exit(1);
569
570
  }
570
571
  }
@@ -589,7 +590,7 @@ export async function x402EnvListCommand() {
589
590
  }
590
591
  catch (err) {
591
592
  spin.fail("Failed to list env vars");
592
- output.error(err instanceof Error ? err.message : String(err));
593
+ output.error(getErrorMessage(err));
593
594
  process.exit(1);
594
595
  }
595
596
  }
@@ -608,7 +609,7 @@ export async function x402EnvUnsetCommand(key) {
608
609
  }
609
610
  catch (err) {
610
611
  spin.fail(`Failed to remove ${key}`);
611
- output.error(err instanceof Error ? err.message : String(err));
612
+ output.error(getErrorMessage(err));
612
613
  process.exit(1);
613
614
  }
614
615
  }
@@ -875,7 +876,7 @@ export async function x402SchemaCommand(url, opts = {}) {
875
876
  }
876
877
  catch (err) {
877
878
  spin.fail("Schema lookup failed");
878
- output.error(err instanceof Error ? err.message : String(err));
879
+ output.error(getErrorMessage(err));
879
880
  process.exit(1);
880
881
  }
881
882
  }
@@ -1229,7 +1230,7 @@ export async function x402CallCommand(url, opts = {}) {
1229
1230
  }
1230
1231
  catch (err) {
1231
1232
  spin.fail("Call failed");
1232
- output.error(err instanceof Error ? err.message : String(err));
1233
+ output.error(getErrorMessage(err));
1233
1234
  process.exit(1);
1234
1235
  }
1235
1236
  }
@@ -1276,7 +1277,7 @@ export async function x402SearchCommand(queryParts, opts = {}) {
1276
1277
  }
1277
1278
  catch (err) {
1278
1279
  spin.fail("Search failed");
1279
- output.error(err instanceof Error ? err.message : String(err));
1280
+ output.error(getErrorMessage(err));
1280
1281
  process.exit(1);
1281
1282
  }
1282
1283
  }
package/dist/lib/api.d.ts CHANGED
@@ -191,11 +191,14 @@ export interface SubmitResponse {
191
191
  }
192
192
  export declare function submit(request: SubmitRequest): Promise<SubmitResponse>;
193
193
  export type FeeRecipientType = "wallet" | "x" | "farcaster" | "ens";
194
+ /** Chains the deploy endpoint accepts (mirrors the API's zod enum). */
195
+ export type LaunchChain = "base" | "robinhood";
194
196
  export interface DeployTokenRequest {
195
197
  tokenName: string;
196
198
  tokenSymbol?: string;
197
199
  image?: string;
198
200
  description?: string;
201
+ chain?: LaunchChain;
199
202
  tweetUrl?: string;
200
203
  websiteUrl?: string;
201
204
  feeRecipient?: {
@@ -222,6 +225,8 @@ export interface CreatorFeesTokenResult {
222
225
  tokenAddress: string;
223
226
  name: string;
224
227
  symbol: string;
228
+ /** Launch chain ("base" | "robinhood"); absent on older API versions → base. */
229
+ chain?: string;
225
230
  poolId: string;
226
231
  initializer?: string;
227
232
  share: string;
@@ -6,6 +6,7 @@ export const CHAIN_LABELS = {
6
6
  worldchain: "World Chain",
7
7
  arbitrum: "Arbitrum",
8
8
  bnb: "BNB Chain",
9
+ robinhood: "Robinhood Chain",
9
10
  solana: "Solana",
10
11
  };
11
12
  export const VALID_CHAINS = new Set([
@@ -16,6 +17,7 @@ export const VALID_CHAINS = new Set([
16
17
  "worldchain",
17
18
  "arbitrum",
18
19
  "bnb",
20
+ "robinhood",
19
21
  "solana",
20
22
  ]);
21
23
  export const CHAIN_IDS = {
@@ -26,6 +28,7 @@ export const CHAIN_IDS = {
26
28
  worldchain: 480,
27
29
  arbitrum: 42161,
28
30
  bnb: 56,
31
+ robinhood: 4663,
29
32
  };
30
33
  export const NATIVE_SYMBOLS = {
31
34
  base: "ETH",
@@ -35,5 +38,6 @@ export const NATIVE_SYMBOLS = {
35
38
  arbitrum: "ETH",
36
39
  polygon: "POL",
37
40
  bnb: "BNB",
41
+ robinhood: "ETH",
38
42
  };
39
43
  //# sourceMappingURL=chains.js.map
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Pulls a message out of an unknown thrown value. `throw "..."` is legal
3
+ * JS so the value may not be an Error; `String(error)` covers strings,
4
+ * primitives, and objects without a usable `.message`.
5
+ */
6
+ export declare function getErrorMessage(error: unknown): string;
7
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Pulls a message out of an unknown thrown value. `throw "..."` is legal
3
+ * JS so the value may not be an Error; `String(error)` covers strings,
4
+ * primitives, and objects without a usable `.message`.
5
+ */
6
+ export function getErrorMessage(error) {
7
+ return error instanceof Error ? error.message : String(error);
8
+ }
9
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1,7 @@
1
+ /** Per-chain tx explorer links for launch-chain transactions. */
2
+ /** Unknown chain ids fall back to Basescan (pre-multichain behavior). */
3
+ export declare function txExplorer(chainId: number | undefined, txHash: string): {
4
+ name: string;
5
+ url: string;
6
+ };
7
+ //# sourceMappingURL=explorer.d.ts.map
@@ -0,0 +1,14 @@
1
+ /** Per-chain tx explorer links for launch-chain transactions. */
2
+ const EXPLORERS = {
3
+ 8453: { name: "Basescan", baseUrl: "https://basescan.org" },
4
+ 4663: {
5
+ name: "Blockscout",
6
+ baseUrl: "https://robinhoodchain.blockscout.com",
7
+ },
8
+ };
9
+ /** Unknown chain ids fall back to Basescan (pre-multichain behavior). */
10
+ export function txExplorer(chainId, txHash) {
11
+ const explorer = EXPLORERS[chainId ?? 8453] ?? EXPLORERS[8453];
12
+ return { name: explorer.name, url: `${explorer.baseUrl}/tx/${txHash}` };
13
+ }
14
+ //# sourceMappingURL=explorer.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bankr/cli",
3
- "version": "0.3.11",
3
+ "version": "0.3.13",
4
4
  "description": "Official CLI for the Bankr AI agent platform",
5
5
  "type": "module",
6
6
  "bin": {