@bankr/cli 0.1.0-beta.6 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +27 -1
  2. package/dist/cli.js +222 -4
  3. package/dist/commands/balances.d.ts +5 -0
  4. package/dist/commands/balances.js +113 -0
  5. package/dist/commands/fees.d.ts +18 -0
  6. package/dist/commands/fees.js +793 -0
  7. package/dist/commands/launch.d.ts +13 -0
  8. package/dist/commands/launch.js +174 -0
  9. package/dist/commands/llm.d.ts +11 -0
  10. package/dist/commands/llm.js +319 -3
  11. package/dist/commands/login.d.ts +9 -0
  12. package/dist/commands/login.js +464 -147
  13. package/dist/commands/profile.d.ts +26 -0
  14. package/dist/commands/profile.js +183 -0
  15. package/dist/commands/prompt.js +5 -0
  16. package/dist/commands/sign.js +3 -0
  17. package/dist/commands/sounds.d.ts +12 -0
  18. package/dist/commands/sounds.js +262 -0
  19. package/dist/commands/submit.js +14 -4
  20. package/dist/index.d.ts +2 -2
  21. package/dist/index.js +1 -1
  22. package/dist/lib/api.d.ts +213 -0
  23. package/dist/lib/api.js +177 -3
  24. package/dist/lib/cesp/engine.d.ts +13 -0
  25. package/dist/lib/cesp/engine.js +132 -0
  26. package/dist/lib/cesp/player.d.ts +6 -0
  27. package/dist/lib/cesp/player.js +50 -0
  28. package/dist/lib/cesp/types.d.ts +38 -0
  29. package/dist/lib/cesp/types.js +2 -0
  30. package/dist/lib/config.d.ts +4 -0
  31. package/dist/lib/config.js +1 -0
  32. package/dist/lib/output.d.ts +1 -0
  33. package/dist/lib/output.js +3 -0
  34. package/package.json +4 -2
  35. package/dist/cli.d.ts.map +0 -1
  36. package/dist/cli.js.map +0 -1
  37. package/dist/commands/cancel.d.ts.map +0 -1
  38. package/dist/commands/cancel.js.map +0 -1
  39. package/dist/commands/capabilities.d.ts.map +0 -1
  40. package/dist/commands/capabilities.js.map +0 -1
  41. package/dist/commands/config.d.ts.map +0 -1
  42. package/dist/commands/config.js.map +0 -1
  43. package/dist/commands/llm.d.ts.map +0 -1
  44. package/dist/commands/llm.js.map +0 -1
  45. package/dist/commands/login.d.ts.map +0 -1
  46. package/dist/commands/login.js.map +0 -1
  47. package/dist/commands/logout.d.ts.map +0 -1
  48. package/dist/commands/logout.js.map +0 -1
  49. package/dist/commands/prompt.d.ts.map +0 -1
  50. package/dist/commands/prompt.js.map +0 -1
  51. package/dist/commands/sign.d.ts.map +0 -1
  52. package/dist/commands/sign.js.map +0 -1
  53. package/dist/commands/status.d.ts.map +0 -1
  54. package/dist/commands/status.js.map +0 -1
  55. package/dist/commands/submit.d.ts.map +0 -1
  56. package/dist/commands/submit.js.map +0 -1
  57. package/dist/commands/whoami.d.ts.map +0 -1
  58. package/dist/commands/whoami.js.map +0 -1
  59. package/dist/index.d.ts.map +0 -1
  60. package/dist/index.js.map +0 -1
  61. package/dist/lib/api.d.ts.map +0 -1
  62. package/dist/lib/api.js.map +0 -1
  63. package/dist/lib/config.d.ts.map +0 -1
  64. package/dist/lib/config.js.map +0 -1
  65. package/dist/lib/output.d.ts.map +0 -1
  66. package/dist/lib/output.js.map +0 -1
@@ -0,0 +1,13 @@
1
+ export interface LaunchOptions {
2
+ name?: string;
3
+ symbol?: string;
4
+ image?: string;
5
+ tweet?: string;
6
+ website?: string;
7
+ fee?: string;
8
+ feeType?: string;
9
+ yes?: boolean;
10
+ simulate?: boolean;
11
+ }
12
+ export declare function launchCommand(options: LaunchOptions): Promise<void>;
13
+ //# sourceMappingURL=launch.d.ts.map
@@ -0,0 +1,174 @@
1
+ import { confirm, input, select } from "@inquirer/prompts";
2
+ import { deployToken } from "../lib/api.js";
3
+ import { emitCESP } from "../lib/cesp/engine.js";
4
+ import { requireApiKey } from "../lib/config.js";
5
+ import * as output from "../lib/output.js";
6
+ const VALID_FEE_TYPES = ["x", "farcaster", "ens", "wallet"];
7
+ function parseFeeType(value) {
8
+ if (!value)
9
+ return "x";
10
+ const lower = value.toLowerCase();
11
+ if (VALID_FEE_TYPES.includes(lower))
12
+ return lower;
13
+ output.warn(`Unknown fee type "${value}". Valid types: ${VALID_FEE_TYPES.join(", ")}. Defaulting to "x".`);
14
+ return "x";
15
+ }
16
+ function feeTypeLabel(type) {
17
+ switch (type) {
18
+ case "x":
19
+ return "X";
20
+ case "farcaster":
21
+ return "Farcaster";
22
+ case "ens":
23
+ return "ENS";
24
+ case "wallet":
25
+ return "Wallet";
26
+ }
27
+ }
28
+ async function collectInteractive(options) {
29
+ const tokenName = options.name ??
30
+ (await input({
31
+ message: "What do you want to call your token?",
32
+ theme: output.bankrTheme,
33
+ required: true,
34
+ }));
35
+ const tokenSymbol = options.symbol ??
36
+ (await input({
37
+ message: "Token symbol (press Enter to auto-generate from name):",
38
+ theme: output.bankrTheme,
39
+ }));
40
+ const imageUrl = options.image ??
41
+ (await input({
42
+ message: "Image URL for your token (press Enter to skip):",
43
+ theme: output.bankrTheme,
44
+ }));
45
+ const tweetUrl = options.tweet ??
46
+ (await input({
47
+ message: "Associate with a tweet? Paste URL (press Enter to skip):",
48
+ theme: output.bankrTheme,
49
+ }));
50
+ const websiteUrl = options.website ??
51
+ (await input({
52
+ message: "Project website URL (press Enter to skip):",
53
+ theme: output.bankrTheme,
54
+ }));
55
+ let feeRecipient = options.fee ??
56
+ (await input({
57
+ message: "Direct fees to someone? Enter username, ENS, or address (press Enter to skip):",
58
+ theme: output.bankrTheme,
59
+ }));
60
+ let feeRecipientType = parseFeeType(options.feeType);
61
+ if (feeRecipient && !options.feeType) {
62
+ feeRecipientType = await select({
63
+ message: "What type of identifier is this?",
64
+ choices: [
65
+ { name: "X (Twitter)", value: "x" },
66
+ { name: "Farcaster", value: "farcaster" },
67
+ { name: "ENS", value: "ens" },
68
+ { name: "Wallet address", value: "wallet" },
69
+ ],
70
+ theme: output.bankrTheme,
71
+ });
72
+ }
73
+ if (!feeRecipient) {
74
+ feeRecipient = "";
75
+ }
76
+ return {
77
+ tokenName: tokenName.trim(),
78
+ tokenSymbol: tokenSymbol.trim(),
79
+ imageUrl: imageUrl.trim(),
80
+ tweetUrl: tweetUrl.trim(),
81
+ websiteUrl: websiteUrl.trim(),
82
+ feeRecipient: feeRecipient.trim(),
83
+ feeRecipientType,
84
+ };
85
+ }
86
+ export async function launchCommand(options) {
87
+ requireApiKey();
88
+ // Collect token details
89
+ const state = await collectInteractive(options);
90
+ if (!state.tokenName) {
91
+ output.error("Token name is required.");
92
+ process.exit(1);
93
+ }
94
+ // Display summary
95
+ console.log();
96
+ output.brandBold(" Token launch summary");
97
+ console.log();
98
+ output.keyValue("Name", state.tokenName);
99
+ output.keyValue("Symbol", state.tokenSymbol || "(auto)");
100
+ output.keyValue("Image", state.imageUrl || "(none)");
101
+ output.keyValue("Tweet", state.tweetUrl || "(none)");
102
+ output.keyValue("Website", state.websiteUrl || "(none)");
103
+ output.keyValue("Fee recipient", state.feeRecipient
104
+ ? `${state.feeRecipient} (${feeTypeLabel(state.feeRecipientType)})`
105
+ : "(self)");
106
+ output.keyValue("Chain", "Base");
107
+ if (options.simulate) {
108
+ output.keyValue("Mode", "Simulation (dry run)");
109
+ }
110
+ console.log();
111
+ // Confirm unless --yes
112
+ if (!options.yes) {
113
+ const proceed = await confirm({
114
+ message: options.simulate
115
+ ? "Simulate this token launch?"
116
+ : "Launch this token?",
117
+ default: true,
118
+ theme: output.bankrTheme,
119
+ });
120
+ if (!proceed) {
121
+ output.dim("Launch cancelled.");
122
+ return;
123
+ }
124
+ }
125
+ // Deploy directly via REST endpoint (no LLM agent)
126
+ const spin = output.spinner(options.simulate ? "Simulating token deploy..." : "Deploying your token...");
127
+ const startTime = Date.now();
128
+ try {
129
+ const result = await deployToken({
130
+ tokenName: state.tokenName,
131
+ tokenSymbol: state.tokenSymbol || undefined,
132
+ image: state.imageUrl || undefined,
133
+ tweetUrl: state.tweetUrl || undefined,
134
+ websiteUrl: state.websiteUrl || undefined,
135
+ feeRecipient: state.feeRecipient
136
+ ? { type: state.feeRecipientType, value: state.feeRecipient }
137
+ : undefined,
138
+ simulateOnly: options.simulate,
139
+ });
140
+ const elapsed = output.formatDuration(Date.now() - startTime);
141
+ spin.succeed(result.simulated
142
+ ? `Simulation complete in ${elapsed}`
143
+ : `Token deployed in ${elapsed}`);
144
+ emitCESP("task.complete");
145
+ console.log();
146
+ output.keyValue("Token Address", result.tokenAddress);
147
+ output.keyValue("Pool ID", result.poolId);
148
+ if (result.txHash) {
149
+ output.keyValue("Transaction", result.txHash);
150
+ }
151
+ output.keyValue("Chain", result.chain);
152
+ if (result.feeDistribution) {
153
+ console.log();
154
+ output.brandBold(" Fee distribution");
155
+ console.log();
156
+ for (const [role, info] of Object.entries(result.feeDistribution)) {
157
+ const pct = (info.bps / 100).toFixed(1);
158
+ const label = role === "alt"
159
+ ? "Ecosystem"
160
+ : role.charAt(0).toUpperCase() + role.slice(1);
161
+ output.keyValue(` ${label} (${pct}%)`, info.address);
162
+ }
163
+ }
164
+ console.log();
165
+ output.dim(`View token: https://bankr.bot/launches/${result.tokenAddress}`);
166
+ }
167
+ catch (err) {
168
+ spin.fail("Token launch failed");
169
+ emitCESP("task.error");
170
+ output.error(err.message);
171
+ process.exit(1);
172
+ }
173
+ }
174
+ //# sourceMappingURL=launch.js.map
@@ -1,5 +1,16 @@
1
1
  export declare function modelsCommand(): Promise<void>;
2
2
  export declare function creditsCommand(): Promise<void>;
3
+ export declare function creditsAddCommand(amount: string, opts: {
4
+ token?: string;
5
+ yes?: boolean;
6
+ }): Promise<void>;
7
+ export declare function creditsAutoCommand(opts: {
8
+ enable?: boolean;
9
+ disable?: boolean;
10
+ amount?: string;
11
+ threshold?: string;
12
+ tokens?: string;
13
+ }): Promise<void>;
3
14
  export declare function setupOpenclawCommand(opts: {
4
15
  install?: boolean;
5
16
  }): Promise<void>;
@@ -2,8 +2,11 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
2
2
  import { homedir } from "os";
3
3
  import { dirname, join } from "path";
4
4
  import { spawn } from "child_process";
5
- import { getLlmKey, getLlmUrl } from "../lib/config.js";
5
+ import { CLI_USER_AGENT, getApiUrl, getLlmKey, getLlmUrl, requireApiKey, } from "../lib/config.js";
6
+ import { getBalances } from "../lib/api.js";
6
7
  import * as output from "../lib/output.js";
8
+ import { bankrTheme } from "../lib/output.js";
9
+ const ERR_LLM_NOT_ENABLED = "LLM Gateway not enabled on this API key. Enable at bankr.bot/api";
7
10
  /**
8
11
  * Fallback model catalog — used when the gateway is unreachable or unauthenticated.
9
12
  * resolveModels() fetches live data from GET /v1/models; this list is the offline safety net.
@@ -22,6 +25,12 @@ const GATEWAY_MODELS = [
22
25
  owned_by: "anthropic",
23
26
  cost: { input: 15.0, output: 75.0, cacheRead: 1.5, cacheWrite: 18.75 },
24
27
  },
28
+ {
29
+ id: "claude-sonnet-4.6",
30
+ name: "Claude Sonnet 4.6",
31
+ owned_by: "anthropic",
32
+ cost: { input: 3.0, output: 15.0, cacheRead: 0.3, cacheWrite: 3.75 },
33
+ },
25
34
  {
26
35
  id: "claude-sonnet-4.5",
27
36
  name: "Claude Sonnet 4.5",
@@ -105,7 +114,7 @@ async function resolveModels() {
105
114
  return { models: GATEWAY_MODELS, live: false };
106
115
  try {
107
116
  const res = await fetch(`${getLlmUrl()}/v1/models`, {
108
- headers: { "X-API-Key": llmKey },
117
+ headers: { "X-API-Key": llmKey, "User-Agent": CLI_USER_AGENT },
109
118
  signal: AbortSignal.timeout(5000),
110
119
  });
111
120
  if (!res.ok)
@@ -195,7 +204,7 @@ export async function creditsCommand() {
195
204
  const spin = output.spinner("Fetching credit balance…");
196
205
  try {
197
206
  const res = await fetch(`${llmUrl}/v1/credits`, {
198
- headers: { "X-API-Key": llmKey },
207
+ headers: { "X-API-Key": llmKey, "User-Agent": CLI_USER_AGENT },
199
208
  signal: AbortSignal.timeout(10000),
200
209
  });
201
210
  spin.stop();
@@ -228,6 +237,313 @@ export async function creditsCommand() {
228
237
  process.exit(1);
229
238
  }
230
239
  }
240
+ /* ─────────────────────── bankr llm credits add ──────────────────────────── */
241
+ export async function creditsAddCommand(amount, opts) {
242
+ const apiKey = requireApiKey();
243
+ const apiUrl = getApiUrl();
244
+ const llmKey = getLlmKey();
245
+ const llmUrl = getLlmUrl();
246
+ // Validate amount
247
+ const amountUsd = Number(amount);
248
+ if (Number.isNaN(amountUsd) || amountUsd < 1 || amountUsd > 1000) {
249
+ output.error("Amount must be between $1 and $1,000");
250
+ process.exit(1);
251
+ }
252
+ // Fetch current balance for display (skip when --yes since user won't see it)
253
+ let currentBalance = "unknown";
254
+ if (llmKey && !opts.yes) {
255
+ const balSpin = output.spinner("Fetching balance…");
256
+ try {
257
+ const balRes = await fetch(`${llmUrl}/v1/credits`, {
258
+ headers: { "X-API-Key": llmKey, "User-Agent": CLI_USER_AGENT },
259
+ signal: AbortSignal.timeout(10000),
260
+ });
261
+ balSpin.stop();
262
+ if (balRes.ok) {
263
+ const bal = (await balRes.json());
264
+ currentBalance = `$${bal.balanceUsd.toFixed(2)}`;
265
+ }
266
+ else if (balRes.status === 402) {
267
+ currentBalance = "$0.00";
268
+ }
269
+ }
270
+ catch (err) {
271
+ balSpin.stop();
272
+ // Non-fatal — proceed without balance display
273
+ output.dim(` (Could not fetch balance: ${err.message})`);
274
+ }
275
+ }
276
+ // Show confirmation
277
+ console.log();
278
+ output.label("Add Credits", `$${amountUsd.toFixed(2)}`);
279
+ output.keyValue("Source token", opts.token ?? "USDC (default)");
280
+ output.keyValue("Current balance", currentBalance);
281
+ console.log();
282
+ if (!opts.yes) {
283
+ const { confirm } = await import("@inquirer/prompts");
284
+ const proceed = await confirm({
285
+ message: "Proceed?",
286
+ default: true,
287
+ theme: bankrTheme,
288
+ });
289
+ if (!proceed) {
290
+ output.dim("Cancelled.");
291
+ return;
292
+ }
293
+ }
294
+ const spin = output.spinner("Adding credits…");
295
+ try {
296
+ const body = { amountUsd };
297
+ if (opts.token) {
298
+ body.sourceToken = opts.token;
299
+ }
300
+ const res = await fetch(`${apiUrl}/llm/credits/topup`, {
301
+ method: "POST",
302
+ headers: {
303
+ "X-API-Key": apiKey,
304
+ "Content-Type": "application/json",
305
+ "User-Agent": CLI_USER_AGENT,
306
+ },
307
+ body: JSON.stringify(body),
308
+ signal: AbortSignal.timeout(60000),
309
+ });
310
+ spin.stop();
311
+ if (res.status === 402) {
312
+ output.error("Insufficient wallet balance. Add funds to your wallet first.");
313
+ process.exit(1);
314
+ }
315
+ if (res.status === 403) {
316
+ output.error(ERR_LLM_NOT_ENABLED);
317
+ process.exit(1);
318
+ }
319
+ if (res.status === 502) {
320
+ output.error("Token swap failed. Try USDC or a different token.");
321
+ process.exit(1);
322
+ }
323
+ if (!res.ok) {
324
+ const errBody = (await res.json().catch(() => ({})));
325
+ output.error(errBody.error ?? `Failed to add credits (HTTP ${res.status})`);
326
+ process.exit(1);
327
+ }
328
+ const result = (await res.json());
329
+ console.log();
330
+ output.success(`Added $${result.creditsGranted.toFixed(2)} credits`);
331
+ output.label("New Balance", `$${result.newBalance.toFixed(2)}`);
332
+ if (result.txHash) {
333
+ output.keyValue("Transaction", `https://basescan.org/tx/${result.txHash}`);
334
+ }
335
+ }
336
+ catch (err) {
337
+ spin.stop();
338
+ output.error(`Failed to add credits: ${err.message}`);
339
+ process.exit(1);
340
+ }
341
+ }
342
+ function formatTimeAgo(dateStr) {
343
+ if (!dateStr)
344
+ return "never";
345
+ const diff = Date.now() - new Date(dateStr).getTime();
346
+ const mins = Math.floor(diff / 60000);
347
+ if (mins < 60)
348
+ return `${mins}m ago`;
349
+ const hours = Math.floor(mins / 60);
350
+ if (hours < 24)
351
+ return `${hours}h ago`;
352
+ const days = Math.floor(hours / 24);
353
+ return `${days}d ago`;
354
+ }
355
+ function displayAutoTopUpConfig(config) {
356
+ output.keyValue("Status", config.enabled ? "Enabled" : "Disabled");
357
+ output.keyValue("Amount", `$${config.amountUsd.toFixed(2)}`);
358
+ output.keyValue("Threshold", `$${config.thresholdUsd.toFixed(2)}`);
359
+ output.keyValue("Tokens", config.tokens.length > 0
360
+ ? config.tokens.map((t) => t.symbol).join(" → ")
361
+ : "none configured");
362
+ }
363
+ export async function creditsAutoCommand(opts) {
364
+ const apiKey = requireApiKey();
365
+ const apiUrl = getApiUrl();
366
+ const isUpdate = opts.enable || opts.disable || opts.amount || opts.threshold || opts.tokens;
367
+ if (!isUpdate) {
368
+ // GET current config
369
+ const spin = output.spinner("Fetching auto top-up config…");
370
+ try {
371
+ const res = await fetch(`${apiUrl}/llm/credits/auto-topup`, {
372
+ headers: {
373
+ "X-API-Key": apiKey,
374
+ "User-Agent": CLI_USER_AGENT,
375
+ },
376
+ signal: AbortSignal.timeout(10000),
377
+ });
378
+ spin.stop();
379
+ if (res.status === 403) {
380
+ output.error(ERR_LLM_NOT_ENABLED);
381
+ process.exit(1);
382
+ }
383
+ if (!res.ok) {
384
+ output.error(`Failed to fetch config (HTTP ${res.status})`);
385
+ process.exit(1);
386
+ }
387
+ const { config } = (await res.json());
388
+ output.brandBold("Bankr LLM Gateway — Auto Top-Up");
389
+ console.log();
390
+ displayAutoTopUpConfig(config);
391
+ output.keyValue("Last top-up", formatTimeAgo(config.lastTopUpAt));
392
+ if (config.lastError) {
393
+ output.keyValue("Last error", config.lastError.message);
394
+ }
395
+ console.log();
396
+ output.dim(" Update: bankr llm credits auto --amount 25 --tokens USDC");
397
+ }
398
+ catch (err) {
399
+ spin.stop();
400
+ output.error(`Failed to fetch config: ${err.message}`);
401
+ process.exit(1);
402
+ }
403
+ return;
404
+ }
405
+ // POST update config
406
+ if (opts.enable && opts.disable) {
407
+ output.error("Cannot use --enable and --disable together");
408
+ process.exit(1);
409
+ }
410
+ const body = {};
411
+ if (opts.disable) {
412
+ body.enabled = false;
413
+ }
414
+ else if (opts.enable) {
415
+ body.enabled = true;
416
+ }
417
+ else if (opts.amount || opts.threshold || opts.tokens) {
418
+ // Setting config values implicitly enables
419
+ body.enabled = true;
420
+ }
421
+ if (opts.amount) {
422
+ const amt = Number(opts.amount);
423
+ if (Number.isNaN(amt) || amt < 1 || amt > 1000) {
424
+ output.error("Amount must be between $1 and $1,000");
425
+ process.exit(1);
426
+ }
427
+ body.amountUsd = amt;
428
+ }
429
+ if (opts.threshold) {
430
+ const thr = Number(opts.threshold);
431
+ if (Number.isNaN(thr) || thr < 1 || thr > 500) {
432
+ output.error("Threshold must be between $1 and $500");
433
+ process.exit(1);
434
+ }
435
+ body.thresholdUsd = thr;
436
+ }
437
+ const missing = [];
438
+ if (opts.tokens) {
439
+ // Accepts symbols (USDC) or addresses (0x...), comma-separated
440
+ const inputs = opts.tokens
441
+ .split(",")
442
+ .map((s) => s.trim())
443
+ .filter(Boolean);
444
+ if (inputs.length === 0 || inputs.length > 3) {
445
+ output.error("Provide 1-3 comma-separated token symbols or addresses");
446
+ process.exit(1);
447
+ }
448
+ const resolved = [];
449
+ // Fetch balances to resolve both symbols and addresses
450
+ const spin = output.spinner("Resolving tokens…");
451
+ let baseTokens = [];
452
+ let hasNativeEth = false;
453
+ try {
454
+ const balData = await getBalances(["base"]);
455
+ const baseChain = balData.balances.base;
456
+ baseTokens = baseChain?.tokenBalances ?? [];
457
+ hasNativeEth = !!baseChain && parseFloat(baseChain.nativeBalance) > 0;
458
+ }
459
+ catch {
460
+ output.warn("Could not fetch balances for token resolution");
461
+ }
462
+ spin.stop();
463
+ for (const input of inputs) {
464
+ const isAddress = input.startsWith("0x");
465
+ const sym = isAddress ? null : input.toUpperCase();
466
+ // Native ETH
467
+ if (sym === "ETH" && hasNativeEth) {
468
+ resolved.push({
469
+ address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
470
+ chain: "base",
471
+ symbol: "ETH",
472
+ name: "Ethereum",
473
+ decimals: 18,
474
+ });
475
+ continue;
476
+ }
477
+ const tb = baseTokens.find((t) => isAddress
478
+ ? t.token.baseToken.address.toLowerCase() === input.toLowerCase()
479
+ : t.token.baseToken.symbol.toUpperCase() === sym);
480
+ if (tb) {
481
+ resolved.push({
482
+ address: tb.token.baseToken.address,
483
+ chain: "base",
484
+ symbol: tb.token.baseToken.symbol,
485
+ name: tb.token.baseToken.name,
486
+ decimals: tb.token.baseToken.decimals,
487
+ imageUrl: tb.token.baseToken.imgUrl,
488
+ });
489
+ }
490
+ else {
491
+ missing.push(input);
492
+ }
493
+ }
494
+ if (resolved.length === 0) {
495
+ output.error("No valid tokens resolved. Check your token symbols.");
496
+ process.exit(1);
497
+ }
498
+ body.tokens = resolved;
499
+ }
500
+ // Collect warnings to show after success output
501
+ const warnings = [];
502
+ if (missing.length > 0) {
503
+ warnings.push(`Token(s) not found in wallet: ${missing.join(", ")} — skipped`);
504
+ }
505
+ const spin = output.spinner("Updating auto top-up…");
506
+ try {
507
+ const res = await fetch(`${apiUrl}/llm/credits/auto-topup`, {
508
+ method: "POST",
509
+ headers: {
510
+ "X-API-Key": apiKey,
511
+ "Content-Type": "application/json",
512
+ "User-Agent": CLI_USER_AGENT,
513
+ },
514
+ body: JSON.stringify(body),
515
+ signal: AbortSignal.timeout(10000),
516
+ });
517
+ spin.stop();
518
+ if (res.status === 403) {
519
+ output.error(ERR_LLM_NOT_ENABLED);
520
+ process.exit(1);
521
+ }
522
+ if (!res.ok) {
523
+ const errBody = (await res.json().catch(() => ({})));
524
+ output.error(errBody.error ?? `Failed to update config (HTTP ${res.status})`);
525
+ process.exit(1);
526
+ }
527
+ output.success(opts.disable ? "Auto top-up disabled" : "Auto top-up settings updated");
528
+ // Show config from POST response (avoids extra GET round-trip)
529
+ const resBody = (await res.json());
530
+ if (resBody.config) {
531
+ console.log();
532
+ displayAutoTopUpConfig(resBody.config);
533
+ }
534
+ if (warnings.length > 0) {
535
+ console.log();
536
+ for (const w of warnings) {
537
+ output.warn(w);
538
+ }
539
+ }
540
+ }
541
+ catch (err) {
542
+ spin.stop();
543
+ output.error(`Failed to update config: ${err.message}`);
544
+ process.exit(1);
545
+ }
546
+ }
231
547
  /* ──────────────────────── bankr llm setup openclaw ────────────────────────── */
232
548
  export async function setupOpenclawCommand(opts) {
233
549
  const llmKey = getLlmKey();
@@ -1,7 +1,16 @@
1
1
  export declare function loginCommand(opts: {
2
2
  apiUrl?: string;
3
3
  apiKey?: string;
4
+ email?: string;
5
+ code?: string;
6
+ acceptTerms?: boolean;
7
+ keyName?: string;
8
+ readWrite?: boolean;
9
+ llm?: boolean;
4
10
  llmKey?: string;
5
11
  url?: boolean;
12
+ siwe?: boolean;
13
+ privateKey?: string;
14
+ partnerKey?: string;
6
15
  }): Promise<void>;
7
16
  //# sourceMappingURL=login.d.ts.map