@bankr/cli 0.3.12 → 0.3.23
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 +28 -10
- package/dist/cli.js +31 -8
- package/dist/commands/balances.js +2 -1
- package/dist/commands/cancel.js +2 -1
- package/dist/commands/club.js +4 -3
- package/dist/commands/fees.js +83 -45
- package/dist/commands/files.js +14 -13
- package/dist/commands/launch.d.ts +5 -0
- package/dist/commands/launch.js +76 -7
- package/dist/commands/llm.d.ts +2 -0
- package/dist/commands/llm.js +264 -44
- package/dist/commands/login.d.ts +14 -0
- package/dist/commands/login.js +41 -30
- package/dist/commands/portfolio.js +3 -2
- package/dist/commands/profile.js +6 -5
- package/dist/commands/prompt.js +19 -6
- package/dist/commands/sign.js +2 -1
- package/dist/commands/sounds.js +4 -3
- package/dist/commands/status.js +3 -2
- package/dist/commands/submit.js +3 -2
- package/dist/commands/swap.js +9 -7
- package/dist/commands/tokens.js +3 -2
- package/dist/commands/transfer.js +8 -6
- package/dist/commands/update.js +2 -1
- package/dist/commands/webhooks.js +15 -10
- package/dist/commands/whoami.js +3 -2
- package/dist/commands/x402.d.ts +3 -0
- package/dist/commands/x402.js +75 -30
- package/dist/lib/api.d.ts +18 -1
- package/dist/lib/api.js +32 -41
- package/dist/lib/errors.d.ts +7 -0
- package/dist/lib/errors.js +9 -0
- package/dist/lib/explorer.d.ts +7 -0
- package/dist/lib/explorer.js +14 -0
- package/dist/lib/output.d.ts +1 -0
- package/dist/lib/output.js +6 -0
- package/dist/lib/passthrough.d.ts +21 -0
- package/dist/lib/passthrough.js +26 -0
- package/dist/lib/tokens.d.ts +0 -5
- package/dist/lib/tokens.js +0 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -108,26 +108,44 @@ bankr agent cancel job_ABC123DEF456
|
|
|
108
108
|
Launch Claude Code / OpenCode routed through the Bankr gateway:
|
|
109
109
|
|
|
110
110
|
```bash
|
|
111
|
-
# Claude Code
|
|
112
|
-
|
|
111
|
+
# Claude Code — `bankr claude` is a top-level alias for `bankr llm claude`
|
|
112
|
+
# (auto-translates dotted model IDs to the Anthropic wire format)
|
|
113
|
+
bankr claude --model claude-opus-5
|
|
113
114
|
|
|
114
|
-
# Or use dotted form — bankr
|
|
115
|
-
bankr
|
|
115
|
+
# Or use dotted form — bankr claude rewrites it to claude-opus-4-8
|
|
116
|
+
bankr claude --model claude-opus-4.8
|
|
117
|
+
|
|
118
|
+
# The [1m] suffix is optional via the gateway, but MUST be quoted if used
|
|
119
|
+
# (zsh reads [1m] as a glob)
|
|
120
|
+
bankr claude --model "claude-opus-5[1m]"
|
|
116
121
|
|
|
117
122
|
# OpenCode (use the bankr/ prefix with the gateway-canonical dotted form)
|
|
118
123
|
bankr llm opencode -m bankr/claude-opus-4.8
|
|
119
124
|
```
|
|
120
125
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
`
|
|
124
|
-
|
|
125
|
-
|
|
126
|
+
Because `claude` is a command, it shadows the default prompt fallthrough:
|
|
127
|
+
`bankr claude ...` launches Claude Code rather than prompting the agent. Use
|
|
128
|
+
`bankr agent "..."` to send the agent a prompt starting with that word.
|
|
129
|
+
|
|
130
|
+
**Claude Code model format**: Claude Code's `--model` flag expects Anthropic
|
|
131
|
+
wire IDs, which use dashes rather than dots in the version (`claude-opus-5`,
|
|
132
|
+
`claude-sonnet-5`, `claude-opus-4-8`, `claude-haiku-4-5`). If you pass the
|
|
133
|
+
gateway-canonical dotted form (`claude-opus-4.8`), Claude Code silently falls
|
|
134
|
+
back to its default — the flag appears honored but the real request is a
|
|
135
|
+
different model.
|
|
126
136
|
|
|
127
|
-
`bankr
|
|
137
|
+
`bankr claude` translates dotted → dashed for you. If you use older
|
|
128
138
|
versions of the CLI (or invoke `claude` directly via `ANTHROPIC_BASE_URL`),
|
|
129
139
|
pass the dashed form explicitly.
|
|
130
140
|
|
|
141
|
+
**1M context tier**: the gateway strips Claude Code's `[1m]` suffix and enables
|
|
142
|
+
the 1M beta from the model's own context window, so it's **optional here** —
|
|
143
|
+
`claude-opus-5` and `claude-opus-5[1m]` send an identical upstream request. If
|
|
144
|
+
you do use it, **quote it**: in zsh (the macOS default) `[1m]` is a glob
|
|
145
|
+
character class, so an unquoted id aborts with `zsh: no matches found:
|
|
146
|
+
claude-opus-5[1m]` before the CLI ever runs. Bash passes it through literally,
|
|
147
|
+
so the same command can work on one machine and fail on another.
|
|
148
|
+
|
|
131
149
|
### Configuration
|
|
132
150
|
|
|
133
151
|
```bash
|
package/dist/cli.js
CHANGED
|
@@ -10,6 +10,8 @@ import { skillsCommand } from "./commands/capabilities.js";
|
|
|
10
10
|
import { cancelCommand } from "./commands/cancel.js";
|
|
11
11
|
import { configGetCommand, configSetCommand } from "./commands/config.js";
|
|
12
12
|
import { setConfigPath } from "./lib/config.js";
|
|
13
|
+
import { getErrorMessage } from "./lib/errors.js";
|
|
14
|
+
import { passthroughArgs } from "./lib/passthrough.js";
|
|
13
15
|
import { claudeCommand, creditsCommand, creditsAddCommand, creditsAutoCommand, modelsCommand, opencodeCommand, setupClaudeCodeCommand, setupCursorCommand, setupOpenclawCommand, setupOpenCodeCommand, } from "./commands/llm.js";
|
|
14
16
|
import { feesCommand, feesClaimCommand, feesClaimWalletCommand, } from "./commands/fees.js";
|
|
15
17
|
import { launchCommand } from "./commands/launch.js";
|
|
@@ -340,17 +342,20 @@ agentCmd
|
|
|
340
342
|
program.commandsGroup("Tokens");
|
|
341
343
|
program
|
|
342
344
|
.command("launch")
|
|
343
|
-
.description("Launch a token on Base (interactive wizard)")
|
|
345
|
+
.description("Launch a token on Base or Robinhood Chain (interactive wizard)")
|
|
344
346
|
.optionsGroup("Token")
|
|
345
347
|
.option("--name <name>", "Token name")
|
|
346
348
|
.option("--symbol <symbol>", "Token symbol (default: auto-generated from name)")
|
|
347
349
|
.option("--image <url>", "Token image URL")
|
|
350
|
+
.option("--chain <chain>", "Chain to launch on: base, robinhood (default: base)")
|
|
351
|
+
.option("--no-vesting", "Turn off the default 15% creator vesting (sell 100% of supply into the pool)")
|
|
348
352
|
.optionsGroup("Links")
|
|
349
353
|
.option("--tweet <url>", "Associated tweet URL")
|
|
350
354
|
.option("--website <url>", "Project website URL")
|
|
351
355
|
.optionsGroup("Fees")
|
|
352
356
|
.option("--fee <recipient>", "Fee recipient (username, ENS, or address)")
|
|
353
357
|
.option("--fee-type <type>", "Fee recipient type: x, farcaster, ens, wallet (default: x)")
|
|
358
|
+
.option("--quote-only-fees", "Collect all creator fees in the pool's quote token (e.g. WETH) instead of a mix of your token and the quote token")
|
|
354
359
|
.optionsGroup("")
|
|
355
360
|
.option("-y, --yes", "Skip confirmation prompt")
|
|
356
361
|
.option("--simulate", "Simulate the deploy without broadcasting a transaction")
|
|
@@ -359,10 +364,13 @@ program
|
|
|
359
364
|
name: opts.name,
|
|
360
365
|
symbol: opts.symbol,
|
|
361
366
|
image: opts.image,
|
|
367
|
+
chain: opts.chain,
|
|
368
|
+
vesting: opts.vesting,
|
|
362
369
|
tweet: opts.tweet,
|
|
363
370
|
website: opts.website,
|
|
364
371
|
fee: opts.fee,
|
|
365
372
|
feeType: opts.feeType,
|
|
373
|
+
quoteOnlyFees: opts.quoteOnlyFees,
|
|
366
374
|
yes: opts.yes,
|
|
367
375
|
simulate: opts.simulate,
|
|
368
376
|
});
|
|
@@ -469,6 +477,7 @@ llmCmd
|
|
|
469
477
|
.command("models")
|
|
470
478
|
.description("List available models")
|
|
471
479
|
.option("--private", "Show only models that support private (:private) inference")
|
|
480
|
+
.option("--zdr", "Show only models that support zero data retention (:zdr)")
|
|
472
481
|
.action(modelsCommand);
|
|
473
482
|
const llmCreditsCmd = llmCmd
|
|
474
483
|
.command("credits")
|
|
@@ -496,6 +505,7 @@ llmSetupCmd
|
|
|
496
505
|
.command("openclaw")
|
|
497
506
|
.description("OpenClaw config")
|
|
498
507
|
.option("--install", "Write config to ~/.openclaw/openclaw.json")
|
|
508
|
+
.option("--images", "Also route image generation (gpt-image-2) through the gateway — takes over OpenClaw's 'openai' provider slot")
|
|
499
509
|
.action(setupOpenclawCommand);
|
|
500
510
|
llmSetupCmd
|
|
501
511
|
.command("opencode")
|
|
@@ -510,25 +520,38 @@ llmSetupCmd
|
|
|
510
520
|
.command("claude")
|
|
511
521
|
.description("Claude Code config")
|
|
512
522
|
.action(setupClaudeCodeCommand);
|
|
523
|
+
// `helpOption(false)` forwards `-h`/`--help` to the spawned tool instead of
|
|
524
|
+
// letting commander print ours — on a pure passthrough launcher the user
|
|
525
|
+
// almost always wants the tool's help. Use `bankr llm --help` for ours.
|
|
513
526
|
llmCmd
|
|
514
527
|
.command("claude")
|
|
515
528
|
.description("Run Claude Code via gateway")
|
|
516
529
|
.allowUnknownOption()
|
|
517
530
|
.allowExcessArguments()
|
|
531
|
+
.helpOption(false)
|
|
518
532
|
.action(async () => {
|
|
519
|
-
|
|
520
|
-
const args = idx >= 0 ? process.argv.slice(idx + 1) : [];
|
|
521
|
-
await claudeCommand(args);
|
|
533
|
+
await claudeCommand(passthroughArgs("claude"));
|
|
522
534
|
});
|
|
523
535
|
llmCmd
|
|
524
536
|
.command("opencode")
|
|
525
537
|
.description("Run OpenCode via gateway")
|
|
526
538
|
.allowUnknownOption()
|
|
527
539
|
.allowExcessArguments()
|
|
540
|
+
.helpOption(false)
|
|
541
|
+
.action(async () => {
|
|
542
|
+
await opencodeCommand(passthroughArgs("opencode"));
|
|
543
|
+
});
|
|
544
|
+
// Top-level shorthand for the most-used launcher. This shadows the default
|
|
545
|
+
// prompt fallthrough, so `bankr claude ...` launches Claude Code rather than
|
|
546
|
+
// prompting the agent about Claude — ask the agent via `bankr agent "..."`.
|
|
547
|
+
program
|
|
548
|
+
.command("claude")
|
|
549
|
+
.description("Run Claude Code via gateway (alias for `bankr llm claude`)")
|
|
550
|
+
.allowUnknownOption()
|
|
551
|
+
.allowExcessArguments()
|
|
552
|
+
.helpOption(false)
|
|
528
553
|
.action(async () => {
|
|
529
|
-
|
|
530
|
-
const args = idx >= 0 ? process.argv.slice(idx + 1) : [];
|
|
531
|
-
await opencodeCommand(args);
|
|
554
|
+
await claudeCommand(passthroughArgs("claude"));
|
|
532
555
|
});
|
|
533
556
|
// Token search and info
|
|
534
557
|
program.commandsGroup("Tokens");
|
|
@@ -1046,7 +1069,7 @@ async function main() {
|
|
|
1046
1069
|
console.log();
|
|
1047
1070
|
process.exit(0);
|
|
1048
1071
|
}
|
|
1049
|
-
output.error(err
|
|
1072
|
+
output.error(getErrorMessage(err));
|
|
1050
1073
|
process.exit(1);
|
|
1051
1074
|
}
|
|
1052
1075
|
await checkForUpdate(pkg.version);
|
|
@@ -2,6 +2,7 @@ import chalk from "chalk";
|
|
|
2
2
|
import { getBalances, } from "../lib/api.js";
|
|
3
3
|
import * as output from "../lib/output.js";
|
|
4
4
|
import { formatUsd, formatBalance } from "../lib/output.js";
|
|
5
|
+
import { getErrorMessage } from "../lib/errors.js";
|
|
5
6
|
import { CHAIN_LABELS, VALID_CHAINS } from "../lib/chains.js";
|
|
6
7
|
const BRAND = chalk.hex("#FF613D");
|
|
7
8
|
const DIM = chalk.dim;
|
|
@@ -53,7 +54,7 @@ export async function balancesCommand(opts) {
|
|
|
53
54
|
spin.succeed("Balances loaded");
|
|
54
55
|
}
|
|
55
56
|
catch (err) {
|
|
56
|
-
spin.fail(`Failed to fetch balances: ${err
|
|
57
|
+
spin.fail(`Failed to fetch balances: ${getErrorMessage(err)}`);
|
|
57
58
|
process.exit(1);
|
|
58
59
|
}
|
|
59
60
|
// JSON output mode
|
package/dist/commands/cancel.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { cancelJob } from "../lib/api.js";
|
|
2
2
|
import { requireApiKey } from "../lib/config.js";
|
|
3
3
|
import * as output from "../lib/output.js";
|
|
4
|
+
import { getErrorMessage } from "../lib/errors.js";
|
|
4
5
|
export async function cancelCommand(jobId) {
|
|
5
6
|
requireApiKey();
|
|
6
7
|
const spin = output.spinner("Cancelling job...");
|
|
@@ -18,7 +19,7 @@ export async function cancelCommand(jobId) {
|
|
|
18
19
|
}
|
|
19
20
|
catch (err) {
|
|
20
21
|
spin.fail("Failed to cancel job");
|
|
21
|
-
output.error(err
|
|
22
|
+
output.error(getErrorMessage(err));
|
|
22
23
|
process.exit(1);
|
|
23
24
|
}
|
|
24
25
|
}
|
package/dist/commands/club.js
CHANGED
|
@@ -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(
|
|
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(
|
|
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(
|
|
190
|
+
output.error(getErrorMessage(err));
|
|
190
191
|
process.exit(1);
|
|
191
192
|
}
|
|
192
193
|
}
|
package/dist/commands/fees.js
CHANGED
|
@@ -4,7 +4,9 @@ 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";
|
|
9
|
+
import { getErrorMessage } from "../lib/errors.js";
|
|
8
10
|
// ---------------------------------------------------------------------------
|
|
9
11
|
// Constants
|
|
10
12
|
// ---------------------------------------------------------------------------
|
|
@@ -212,7 +214,11 @@ function renderDashboard(data) {
|
|
|
212
214
|
console.log(` ${l}`);
|
|
213
215
|
}
|
|
214
216
|
console.log(`${DIM(` Wallet: ${data.address}`)}`);
|
|
215
|
-
|
|
217
|
+
// Tokens can span launch chains ("chain" absent on pre-multichain rows).
|
|
218
|
+
const chainNames = [
|
|
219
|
+
...new Set(data.tokens.map((t) => (t.chain ?? "base") === "robinhood" ? "Robinhood" : "Base")),
|
|
220
|
+
].join(" + ") || "Base";
|
|
221
|
+
console.log(`${DIM(` Chain: ${chainNames} \u00b7 Tokens: ${data.tokens.length} \u00b7 Period: ${data.days} days`)}`);
|
|
216
222
|
if (data.tokens.length === 0) {
|
|
217
223
|
console.log(`\n ${DIM("No tokens found where this wallet is a creator beneficiary.")}`);
|
|
218
224
|
console.log("");
|
|
@@ -278,28 +284,33 @@ function renderDashboard(data) {
|
|
|
278
284
|
console.log(` ${BRAND_BOLD("\u2550".repeat(62))}`);
|
|
279
285
|
console.log("");
|
|
280
286
|
for (const token of data.tokens) {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
287
|
+
// Numeraire leg = the side whose label differs from the launched token's
|
|
288
|
+
// symbol \u2014 stock-paired launches label it with the stock ticker, not WETH.
|
|
289
|
+
const tokenIsToken0 = token.token0Label === token.symbol;
|
|
290
|
+
const numeraireLabel = tokenIsToken0
|
|
291
|
+
? token.token1Label
|
|
292
|
+
: token.token0Label;
|
|
293
|
+
const claimableNumeraire = tokenIsToken0
|
|
286
294
|
? token.claimable.token1
|
|
287
295
|
: token.claimable.token0;
|
|
288
|
-
const
|
|
289
|
-
? token.
|
|
290
|
-
: token.
|
|
291
|
-
const
|
|
296
|
+
const claimableToken = tokenIsToken0
|
|
297
|
+
? token.claimable.token0
|
|
298
|
+
: token.claimable.token1;
|
|
299
|
+
const claimedNumeraire = tokenIsToken0
|
|
292
300
|
? token.claimed.token1
|
|
293
301
|
: token.claimed.token0;
|
|
294
|
-
const
|
|
302
|
+
const claimedToken = tokenIsToken0
|
|
303
|
+
? token.claimed.token0
|
|
304
|
+
: token.claimed.token1;
|
|
305
|
+
const tokenSymbol = tokenIsToken0 ? token.token0Label : token.token1Label;
|
|
295
306
|
const sourceLabel = token.source === "clanker" ? DIM(" [Clanker]") : DIM(" [Doppler]");
|
|
296
307
|
console.log(` ${BOLD(WHITE(token.name))} ${DIM("($" + token.symbol + ")")}${sourceLabel}`);
|
|
297
308
|
const shareInfo = token.source === "clanker"
|
|
298
309
|
? `${DIM("Creator")} ${DIM("\u00b7 Token:")} ${DIM(token.tokenAddress)}`
|
|
299
310
|
: `${DIM("Share:")} ${token.share} ${DIM("\u00b7 Token:")} ${DIM(token.tokenAddress)}`;
|
|
300
311
|
console.log(` ${shareInfo}`);
|
|
301
|
-
console.log(` ${DIM("Claimable:")} ${BRIGHT_GREEN(
|
|
302
|
-
console.log(` ${DIM("Claimed:")} ${WHITE(
|
|
312
|
+
console.log(` ${DIM("Claimable:")} ${BRIGHT_GREEN(claimableNumeraire.padStart(12))} ${numeraireLabel} ${DIM("|")} ${BRIGHT_GREEN(claimableToken.padStart(18))} ${tokenSymbol}`);
|
|
313
|
+
console.log(` ${DIM("Claimed:")} ${WHITE(claimedNumeraire.padStart(12))} ${numeraireLabel} ${DIM("|")} ${WHITE(claimedToken.padStart(18))} ${tokenSymbol} ${DIM(`(${token.claimed.count} claims)`)}`);
|
|
303
314
|
console.log("");
|
|
304
315
|
}
|
|
305
316
|
console.log(` ${BRAND_BOLD("\u2550".repeat(62))}`);
|
|
@@ -338,7 +349,7 @@ export async function feesCommand(address, opts) {
|
|
|
338
349
|
catch (err) {
|
|
339
350
|
spin.fail("Failed to fetch token fee data");
|
|
340
351
|
emitCESP("task.error");
|
|
341
|
-
output.error(err
|
|
352
|
+
output.error(getErrorMessage(err));
|
|
342
353
|
process.exit(1);
|
|
343
354
|
}
|
|
344
355
|
return;
|
|
@@ -360,7 +371,7 @@ export async function feesCommand(address, opts) {
|
|
|
360
371
|
}
|
|
361
372
|
catch (err) {
|
|
362
373
|
spin.fail("Failed to fetch wallet info");
|
|
363
|
-
output.error(err
|
|
374
|
+
output.error(getErrorMessage(err));
|
|
364
375
|
process.exit(1);
|
|
365
376
|
}
|
|
366
377
|
}
|
|
@@ -379,7 +390,7 @@ export async function feesCommand(address, opts) {
|
|
|
379
390
|
catch (err) {
|
|
380
391
|
spin.fail("Failed to fetch fee data");
|
|
381
392
|
emitCESP("task.error");
|
|
382
|
-
output.error(err
|
|
393
|
+
output.error(getErrorMessage(err));
|
|
383
394
|
process.exit(1);
|
|
384
395
|
}
|
|
385
396
|
}
|
|
@@ -430,7 +441,8 @@ export async function feesClaimCommand(tokenAddress, opts) {
|
|
|
430
441
|
}
|
|
431
442
|
console.log();
|
|
432
443
|
if (result.transactionHash) {
|
|
433
|
-
|
|
444
|
+
const explorer = txExplorer(result.chainId, result.transactionHash);
|
|
445
|
+
output.dim(`View on ${explorer.name}: ${explorer.url}`);
|
|
434
446
|
}
|
|
435
447
|
if (!ok) {
|
|
436
448
|
process.exit(1);
|
|
@@ -439,7 +451,7 @@ export async function feesClaimCommand(tokenAddress, opts) {
|
|
|
439
451
|
catch (err) {
|
|
440
452
|
spin.fail("Claim submission failed");
|
|
441
453
|
emitCESP("task.error");
|
|
442
|
-
output.error(err
|
|
454
|
+
output.error(getErrorMessage(err));
|
|
443
455
|
process.exit(1);
|
|
444
456
|
}
|
|
445
457
|
}
|
|
@@ -544,42 +556,64 @@ export async function feesClaimWalletCommand(address, opts) {
|
|
|
544
556
|
const result = await getBeneficiaryFeesStreaming(address, (progress) => {
|
|
545
557
|
fetchSpin.text = `Scanning pools... ${progress.scanned}/${progress.total} (${progress.found ?? 0} with claimable fees)`;
|
|
546
558
|
});
|
|
547
|
-
|
|
559
|
+
// A time-budget stop leaves `scanned` below `totalLaunches`; report the
|
|
560
|
+
// number actually scanned so this line can't contradict the warning below.
|
|
561
|
+
const scanned = result.scanned ?? result.totalLaunches;
|
|
562
|
+
fetchSpin.succeed(`Scanned ${scanned} launches — ${result.poolsWithShares} pools with shares, ${result.tokens.length} with claimable fees`);
|
|
563
|
+
if (result.truncated) {
|
|
564
|
+
output.warn(`Scan stopped early at ${scanned} launches — this wallet has more than the server scans in one request. Claimable fees beyond that are not listed.`);
|
|
565
|
+
}
|
|
548
566
|
allTokens = result.tokens;
|
|
549
567
|
}
|
|
550
568
|
catch (err) {
|
|
551
569
|
fetchSpin.fail("Failed to fetch fee data");
|
|
552
|
-
output.error(err
|
|
570
|
+
output.error(getErrorMessage(err));
|
|
553
571
|
process.exit(1);
|
|
554
572
|
}
|
|
555
573
|
// Step 5: Filter to tokens with claimable fees (API already filters, but
|
|
556
574
|
// double-check for any rounding edge cases)
|
|
557
575
|
const parseAmount = (s) => parseFloat(s.replace(/^[<>]/, "")) || 0;
|
|
576
|
+
// Numeraire leg = the side whose label differs from the launched token's
|
|
577
|
+
// symbol — stock-paired launches label it with the stock ticker, not WETH.
|
|
578
|
+
const numeraireLegOf = (token) => {
|
|
579
|
+
const tokenIsToken0 = token.token0Label === token.symbol;
|
|
580
|
+
return {
|
|
581
|
+
label: tokenIsToken0 ? token.token1Label : token.token0Label,
|
|
582
|
+
claimable: tokenIsToken0
|
|
583
|
+
? token.claimable.token1
|
|
584
|
+
: token.claimable.token0,
|
|
585
|
+
tokenClaimable: tokenIsToken0
|
|
586
|
+
? token.claimable.token0
|
|
587
|
+
: token.claimable.token1,
|
|
588
|
+
};
|
|
589
|
+
};
|
|
558
590
|
const claimableTokens = allTokens.filter((token) => {
|
|
559
|
-
const
|
|
560
|
-
|
|
561
|
-
? token.claimable.token0
|
|
562
|
-
: token.claimable.token1;
|
|
563
|
-
const claimableToken = wethIsToken0
|
|
564
|
-
? token.claimable.token1
|
|
565
|
-
: token.claimable.token0;
|
|
566
|
-
return parseAmount(claimableWeth) > 0 || parseAmount(claimableToken) > 0;
|
|
591
|
+
const leg = numeraireLegOf(token);
|
|
592
|
+
return (parseAmount(leg.claimable) > 0 || parseAmount(leg.tokenClaimable) > 0);
|
|
567
593
|
});
|
|
568
594
|
if (claimableTokens.length === 0) {
|
|
569
595
|
console.log();
|
|
570
596
|
output.dim("No claimable fees found for this wallet.");
|
|
571
597
|
return;
|
|
572
598
|
}
|
|
573
|
-
// Show total claimable WETH
|
|
599
|
+
// Show total claimable WETH — WETH legs only; stock-paired numeraires are a
|
|
600
|
+
// different unit and get their own per-ticker lines.
|
|
574
601
|
const totalWeth = claimableTokens.reduce((sum, token) => {
|
|
575
|
-
const
|
|
576
|
-
|
|
577
|
-
? token.claimable.token0
|
|
578
|
-
: token.claimable.token1;
|
|
579
|
-
return sum + parseAmount(wethStr);
|
|
602
|
+
const leg = numeraireLegOf(token);
|
|
603
|
+
return leg.label === "WETH" ? sum + parseAmount(leg.claimable) : sum;
|
|
580
604
|
}, 0);
|
|
605
|
+
const nonWethTotals = new Map();
|
|
606
|
+
for (const token of claimableTokens) {
|
|
607
|
+
const leg = numeraireLegOf(token);
|
|
608
|
+
if (leg.label !== "WETH" && parseAmount(leg.claimable) > 0) {
|
|
609
|
+
nonWethTotals.set(leg.label, (nonWethTotals.get(leg.label) ?? 0) + parseAmount(leg.claimable));
|
|
610
|
+
}
|
|
611
|
+
}
|
|
581
612
|
console.log();
|
|
582
613
|
output.keyValue("Total claimable", `${totalWeth.toFixed(6)} WETH across ${claimableTokens.length} token${claimableTokens.length !== 1 ? "s" : ""}`);
|
|
614
|
+
for (const [label, amount] of nonWethTotals) {
|
|
615
|
+
output.keyValue("", `${amount.toFixed(6)} ${label} (stock-paired)`);
|
|
616
|
+
}
|
|
583
617
|
// Step 6: Select tokens
|
|
584
618
|
let selectedTokens;
|
|
585
619
|
if (opts.all) {
|
|
@@ -587,12 +621,9 @@ export async function feesClaimWalletCommand(address, opts) {
|
|
|
587
621
|
}
|
|
588
622
|
else {
|
|
589
623
|
const choices = claimableTokens.map((token) => {
|
|
590
|
-
const
|
|
591
|
-
const claimableWeth = wethIsToken0
|
|
592
|
-
? token.claimable.token0
|
|
593
|
-
: token.claimable.token1;
|
|
624
|
+
const leg = numeraireLegOf(token);
|
|
594
625
|
return {
|
|
595
|
-
name: `${token.name} ($${token.symbol}) - ${
|
|
626
|
+
name: `${token.name} ($${token.symbol}) - ${leg.claimable} ${leg.label}`,
|
|
596
627
|
value: token.tokenAddress,
|
|
597
628
|
checked: true,
|
|
598
629
|
};
|
|
@@ -631,10 +662,17 @@ export async function feesClaimWalletCommand(address, opts) {
|
|
|
631
662
|
],
|
|
632
663
|
},
|
|
633
664
|
];
|
|
665
|
+
// Robinhood-chain launches can't be claimed here: this flow signs and
|
|
666
|
+
// broadcasts on Base only, and a Base tx to a robinhood initializer is a
|
|
667
|
+
// gas-burning no-op. Skip them loudly.
|
|
668
|
+
const baseChainTokens = selectedTokens.filter((t) => (t.chain ?? "base") === "base");
|
|
669
|
+
if (baseChainTokens.length < selectedTokens.length) {
|
|
670
|
+
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.`);
|
|
671
|
+
}
|
|
634
672
|
// Filter to tokens with initializer (required for local tx building)
|
|
635
|
-
const buildableTokens =
|
|
636
|
-
if (buildableTokens.length <
|
|
637
|
-
output.warn(`${
|
|
673
|
+
const buildableTokens = baseChainTokens.filter((t) => t.initializer);
|
|
674
|
+
if (buildableTokens.length < baseChainTokens.length) {
|
|
675
|
+
output.warn(`${baseChainTokens.length - buildableTokens.length} token(s) missing initializer data — skipped`);
|
|
638
676
|
}
|
|
639
677
|
if (buildableTokens.length === 0) {
|
|
640
678
|
output.error("No transactions could be built");
|
|
@@ -663,7 +701,7 @@ export async function feesClaimWalletCommand(address, opts) {
|
|
|
663
701
|
return (gas * GAS_BUFFER) / 100n;
|
|
664
702
|
}
|
|
665
703
|
catch (err) {
|
|
666
|
-
output.warn(`${token.symbol}: gas estimate failed — ${err
|
|
704
|
+
output.warn(`${token.symbol}: gas estimate failed — ${getErrorMessage(err)}`);
|
|
667
705
|
return null;
|
|
668
706
|
}
|
|
669
707
|
}));
|
|
@@ -724,7 +762,7 @@ export async function feesClaimWalletCommand(address, opts) {
|
|
|
724
762
|
pendingTxs.push({ token: tx.token, hash });
|
|
725
763
|
}
|
|
726
764
|
catch (err) {
|
|
727
|
-
sendSpin.fail(`${tx.token.symbol}: Send failed — ${err
|
|
765
|
+
sendSpin.fail(`${tx.token.symbol}: Send failed — ${getErrorMessage(err)}`);
|
|
728
766
|
emitCESP("task.error");
|
|
729
767
|
failCount++;
|
|
730
768
|
if (readyTxs.indexOf(tx) < readyTxs.length - 1) {
|
|
@@ -754,7 +792,7 @@ export async function feesClaimWalletCommand(address, opts) {
|
|
|
754
792
|
token,
|
|
755
793
|
hash,
|
|
756
794
|
status: "failed",
|
|
757
|
-
error: err
|
|
795
|
+
error: getErrorMessage(err),
|
|
758
796
|
};
|
|
759
797
|
}
|
|
760
798
|
}));
|
package/dist/commands/files.js
CHANGED
|
@@ -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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
459
|
+
output.error(getErrorMessage(err));
|
|
459
460
|
process.exit(1);
|
|
460
461
|
}
|
|
461
462
|
}
|
|
@@ -2,10 +2,15 @@ export interface LaunchOptions {
|
|
|
2
2
|
name?: string;
|
|
3
3
|
symbol?: string;
|
|
4
4
|
image?: string;
|
|
5
|
+
chain?: string;
|
|
6
|
+
/** Commander --no-vesting flag: false = vesting explicitly turned off. */
|
|
7
|
+
vesting?: boolean;
|
|
5
8
|
tweet?: string;
|
|
6
9
|
website?: string;
|
|
7
10
|
fee?: string;
|
|
8
11
|
feeType?: string;
|
|
12
|
+
/** --quote-only-fees flag: collect all creator fees in the quote token. */
|
|
13
|
+
quoteOnlyFees?: boolean;
|
|
9
14
|
yes?: boolean;
|
|
10
15
|
simulate?: boolean;
|
|
11
16
|
}
|