@bankr/cli 0.3.23 → 0.3.32
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 +6 -0
- package/dist/cli.js +7 -12
- package/dist/commands/balances.js +1 -2
- package/dist/commands/cancel.js +1 -4
- package/dist/commands/club.js +6 -16
- package/dist/commands/config.js +1 -2
- package/dist/commands/fees.js +19 -29
- package/dist/commands/files.js +17 -39
- package/dist/commands/launch.js +15 -14
- package/dist/commands/llm.d.ts +8 -0
- package/dist/commands/llm.js +275 -66
- package/dist/commands/login.js +20 -31
- package/dist/commands/portfolio.js +1 -2
- package/dist/commands/prompt.js +25 -28
- package/dist/commands/sign.js +8 -16
- package/dist/commands/sounds.js +6 -16
- package/dist/commands/status.js +1 -4
- package/dist/commands/submit.js +12 -24
- package/dist/commands/swap.js +2 -4
- package/dist/commands/tokens.js +1 -2
- package/dist/commands/transfer.js +2 -4
- package/dist/commands/update.js +1 -2
- package/dist/commands/webhooks.js +21 -65
- package/dist/commands/whoami.js +1 -2
- package/dist/commands/x402.js +36 -100
- package/dist/lib/api.d.ts +4 -2
- package/dist/lib/api.js +2 -2
- package/dist/lib/explorer.js +1 -0
- package/dist/lib/output.d.ts +4 -0
- package/dist/lib/output.js +12 -0
- package/package.json +1 -1
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
17
17
|
import { join } from "node:path";
|
|
18
18
|
import { confirm } from "@inquirer/prompts";
|
|
19
|
+
import { authHeaders, handleResponse } from "../lib/api.js";
|
|
19
20
|
import * as output from "../lib/output.js";
|
|
20
|
-
import {
|
|
21
|
-
import { getApiUrl, requireApiKey, CLI_USER_AGENT } from "../lib/config.js";
|
|
21
|
+
import { getApiUrl } from "../lib/config.js";
|
|
22
22
|
// ── Config file ─────────────────────────────────────────────────────────
|
|
23
23
|
const CONFIG_FILENAME = "bankr.webhooks.json";
|
|
24
24
|
const WEBHOOKS_DIR = "webhooks";
|
|
@@ -36,8 +36,7 @@ function loadConfigFile(projectRoot) {
|
|
|
36
36
|
return JSON.parse(readFileSync(p, "utf-8"));
|
|
37
37
|
}
|
|
38
38
|
catch {
|
|
39
|
-
output.
|
|
40
|
-
process.exit(1);
|
|
39
|
+
output.fatal(`Failed to parse ${p}. Check that it is valid JSON.`);
|
|
41
40
|
}
|
|
42
41
|
}
|
|
43
42
|
}
|
|
@@ -46,23 +45,6 @@ function loadConfigFile(projectRoot) {
|
|
|
46
45
|
function saveConfigFile(projectRoot, config) {
|
|
47
46
|
writeFileSync(join(projectRoot, CONFIG_FILENAME), JSON.stringify(config, null, 2) + "\n");
|
|
48
47
|
}
|
|
49
|
-
function authHeaders() {
|
|
50
|
-
return {
|
|
51
|
-
"X-API-Key": requireApiKey(),
|
|
52
|
-
"Content-Type": "application/json",
|
|
53
|
-
"User-Agent": CLI_USER_AGENT,
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
async function handleResponse(res) {
|
|
57
|
-
if (!res.ok) {
|
|
58
|
-
const body = (await res
|
|
59
|
-
.json()
|
|
60
|
-
.catch(() => ({ message: res.statusText })));
|
|
61
|
-
const msg = body.message || body.error || res.statusText;
|
|
62
|
-
throw new Error(`API error (${res.status}): ${msg}`);
|
|
63
|
-
}
|
|
64
|
-
return res.json();
|
|
65
|
-
}
|
|
66
48
|
const MAX_WEBHOOK_NAME_LENGTH = 47;
|
|
67
49
|
const WEBHOOK_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
68
50
|
function validateWebhookName(name) {
|
|
@@ -326,8 +308,7 @@ export default async function handler(req: Request): Promise<Response> {
|
|
|
326
308
|
export async function webhooksAddCommand(name, options = {}) {
|
|
327
309
|
const err = validateWebhookName(name);
|
|
328
310
|
if (err) {
|
|
329
|
-
output.
|
|
330
|
-
process.exit(1);
|
|
311
|
+
output.fatal(err);
|
|
331
312
|
}
|
|
332
313
|
const providerInput = (options.provider ?? "generic").toLowerCase();
|
|
333
314
|
const validProviders = [
|
|
@@ -337,20 +318,17 @@ export async function webhooksAddCommand(name, options = {}) {
|
|
|
337
318
|
"generic",
|
|
338
319
|
];
|
|
339
320
|
if (!validProviders.includes(providerInput)) {
|
|
340
|
-
output.
|
|
341
|
-
process.exit(1);
|
|
321
|
+
output.fatal(`Invalid provider "${providerInput}". Valid: ${validProviders.join(", ")}.`);
|
|
342
322
|
}
|
|
343
323
|
const provider = providerInput;
|
|
344
324
|
const root = findProjectRoot();
|
|
345
325
|
const dir = join(root, WEBHOOKS_DIR);
|
|
346
326
|
if (!existsSync(dir)) {
|
|
347
|
-
output.
|
|
348
|
-
process.exit(1);
|
|
327
|
+
output.fatal(`No ${WEBHOOKS_DIR}/ directory found. Run 'bankr webhooks init' first.`);
|
|
349
328
|
}
|
|
350
329
|
const serviceDir = join(dir, name);
|
|
351
330
|
if (existsSync(serviceDir)) {
|
|
352
|
-
output.
|
|
353
|
-
process.exit(1);
|
|
331
|
+
output.fatal(`Webhook "${name}" already exists at ${WEBHOOKS_DIR}/${name}/`);
|
|
354
332
|
}
|
|
355
333
|
mkdirSync(serviceDir, { recursive: true });
|
|
356
334
|
const { source, envHint } = handlerTemplate(name, provider);
|
|
@@ -397,8 +375,7 @@ export async function webhooksDeployCommand(name) {
|
|
|
397
375
|
const root = findProjectRoot();
|
|
398
376
|
const dir = join(root, WEBHOOKS_DIR);
|
|
399
377
|
if (!existsSync(dir)) {
|
|
400
|
-
output.
|
|
401
|
-
process.exit(1);
|
|
378
|
+
output.fatal(`No ${WEBHOOKS_DIR}/ directory found. Run 'bankr webhooks init' first.`);
|
|
402
379
|
}
|
|
403
380
|
let config = loadConfigFile(root);
|
|
404
381
|
if (!config)
|
|
@@ -413,19 +390,16 @@ export async function webhooksDeployCommand(name) {
|
|
|
413
390
|
}
|
|
414
391
|
}
|
|
415
392
|
if (discovered.length === 0) {
|
|
416
|
-
output.
|
|
417
|
-
process.exit(1);
|
|
393
|
+
output.fatal("No webhooks found. Run 'bankr webhooks add <name>' first.");
|
|
418
394
|
}
|
|
419
395
|
const toDeploy = name ? discovered.filter((s) => s === name) : discovered;
|
|
420
396
|
if (name && toDeploy.length === 0) {
|
|
421
|
-
output.
|
|
422
|
-
process.exit(1);
|
|
397
|
+
output.fatal(`Webhook "${name}" not found in ${WEBHOOKS_DIR}/`);
|
|
423
398
|
}
|
|
424
399
|
for (const svc of toDeploy) {
|
|
425
400
|
const nameError = validateWebhookName(svc);
|
|
426
401
|
if (nameError) {
|
|
427
|
-
output.
|
|
428
|
-
process.exit(1);
|
|
402
|
+
output.fatal(nameError);
|
|
429
403
|
}
|
|
430
404
|
if (!config.webhooks[svc]) {
|
|
431
405
|
config.webhooks[svc] = {
|
|
@@ -487,9 +461,7 @@ export async function webhooksDeployCommand(name) {
|
|
|
487
461
|
output.info("Your handler code is responsible for verifying incoming signatures (Slack, GitHub, etc.). Provider-specific scaffolds include the verifier inline — `bankr webhooks add <name> --provider slack|github|stripe` to scaffold one.");
|
|
488
462
|
}
|
|
489
463
|
catch (err) {
|
|
490
|
-
|
|
491
|
-
output.error(getErrorMessage(err));
|
|
492
|
-
process.exit(1);
|
|
464
|
+
output.failWith(spin, "Deploy failed", err);
|
|
493
465
|
}
|
|
494
466
|
}
|
|
495
467
|
export async function webhooksListCommand() {
|
|
@@ -517,9 +489,7 @@ export async function webhooksListCommand() {
|
|
|
517
489
|
}
|
|
518
490
|
}
|
|
519
491
|
catch (err) {
|
|
520
|
-
|
|
521
|
-
output.error(getErrorMessage(err));
|
|
522
|
-
process.exit(1);
|
|
492
|
+
output.failWith(spin, "Failed to list webhooks", err);
|
|
523
493
|
}
|
|
524
494
|
}
|
|
525
495
|
export async function webhooksPauseResumeCommand(name, action) {
|
|
@@ -535,9 +505,7 @@ export async function webhooksPauseResumeCommand(name, action) {
|
|
|
535
505
|
spin.succeed(`${name} ${action === "pause" ? "paused" : "resumed"}`);
|
|
536
506
|
}
|
|
537
507
|
catch (err) {
|
|
538
|
-
|
|
539
|
-
output.error(getErrorMessage(err));
|
|
540
|
-
process.exit(1);
|
|
508
|
+
output.failWith(spin, `Failed to ${action} ${name}`, err);
|
|
541
509
|
}
|
|
542
510
|
}
|
|
543
511
|
export async function webhooksDeleteCommand(name) {
|
|
@@ -558,9 +526,7 @@ export async function webhooksDeleteCommand(name) {
|
|
|
558
526
|
spin.succeed(`${name} deleted`);
|
|
559
527
|
}
|
|
560
528
|
catch (err) {
|
|
561
|
-
|
|
562
|
-
output.error(getErrorMessage(err));
|
|
563
|
-
process.exit(1);
|
|
529
|
+
output.failWith(spin, `Failed to delete ${name}`, err);
|
|
564
530
|
}
|
|
565
531
|
}
|
|
566
532
|
export async function webhooksLogsCommand(name) {
|
|
@@ -586,23 +552,19 @@ export async function webhooksLogsCommand(name) {
|
|
|
586
552
|
}
|
|
587
553
|
}
|
|
588
554
|
catch (err) {
|
|
589
|
-
|
|
590
|
-
output.error(getErrorMessage(err));
|
|
591
|
-
process.exit(1);
|
|
555
|
+
output.failWith(spin, "Failed to fetch logs", err);
|
|
592
556
|
}
|
|
593
557
|
}
|
|
594
558
|
// ── Env vars ────────────────────────────────────────────────────────────
|
|
595
559
|
export async function webhooksEnvSetCommand(keyValue) {
|
|
596
560
|
const eqIdx = keyValue.indexOf("=");
|
|
597
561
|
if (eqIdx === -1) {
|
|
598
|
-
output.
|
|
599
|
-
process.exit(1);
|
|
562
|
+
output.fatal("Usage: bankr webhooks env set KEY=VALUE");
|
|
600
563
|
}
|
|
601
564
|
const key = keyValue.slice(0, eqIdx);
|
|
602
565
|
const value = keyValue.slice(eqIdx + 1);
|
|
603
566
|
if (!key) {
|
|
604
|
-
output.
|
|
605
|
-
process.exit(1);
|
|
567
|
+
output.fatal("Key cannot be empty");
|
|
606
568
|
}
|
|
607
569
|
const spin = output.spinner(`Setting ${key}...`);
|
|
608
570
|
try {
|
|
@@ -615,9 +577,7 @@ export async function webhooksEnvSetCommand(keyValue) {
|
|
|
615
577
|
spin.succeed(`Set ${key}`);
|
|
616
578
|
}
|
|
617
579
|
catch (err) {
|
|
618
|
-
|
|
619
|
-
output.error(getErrorMessage(err));
|
|
620
|
-
process.exit(1);
|
|
580
|
+
output.failWith(spin, `Failed to set ${key}`, err);
|
|
621
581
|
}
|
|
622
582
|
}
|
|
623
583
|
export async function webhooksEnvListCommand() {
|
|
@@ -636,9 +596,7 @@ export async function webhooksEnvListCommand() {
|
|
|
636
596
|
console.log(` ${n}`);
|
|
637
597
|
}
|
|
638
598
|
catch (err) {
|
|
639
|
-
|
|
640
|
-
output.error(getErrorMessage(err));
|
|
641
|
-
process.exit(1);
|
|
599
|
+
output.failWith(spin, "Failed to list env vars", err);
|
|
642
600
|
}
|
|
643
601
|
}
|
|
644
602
|
export async function webhooksEnvUnsetCommand(key) {
|
|
@@ -649,9 +607,7 @@ export async function webhooksEnvUnsetCommand(key) {
|
|
|
649
607
|
spin.succeed(`Removed ${key}`);
|
|
650
608
|
}
|
|
651
609
|
catch (err) {
|
|
652
|
-
|
|
653
|
-
output.error(getErrorMessage(err));
|
|
654
|
-
process.exit(1);
|
|
610
|
+
output.failWith(spin, `Failed to remove ${key}`, err);
|
|
655
611
|
}
|
|
656
612
|
}
|
|
657
613
|
//# sourceMappingURL=webhooks.js.map
|
package/dist/commands/whoami.js
CHANGED
|
@@ -8,8 +8,7 @@ export async function whoamiCommand() {
|
|
|
8
8
|
const apiUrl = getApiUrl();
|
|
9
9
|
const configPath = getConfigPath();
|
|
10
10
|
if (!apiKey) {
|
|
11
|
-
output.
|
|
12
|
-
process.exit(1);
|
|
11
|
+
output.fatal("Not authenticated. Run `bankr login` to set up your Bankr API key.");
|
|
13
12
|
}
|
|
14
13
|
const source = process.env.BANKR_API_KEY ? "env (BANKR_API_KEY)" : configPath;
|
|
15
14
|
output.label("Bankr API Key", output.maskApiKey(apiKey));
|
package/dist/commands/x402.js
CHANGED
|
@@ -19,9 +19,9 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
19
19
|
import { join } from "node:path";
|
|
20
20
|
import chalk from "chalk";
|
|
21
21
|
import { input, select, confirm } from "@inquirer/prompts";
|
|
22
|
+
import { authHeaders, handleResponse } from "../lib/api.js";
|
|
22
23
|
import * as output from "../lib/output.js";
|
|
23
|
-
import {
|
|
24
|
-
import { getApiUrl, requireApiKey, CLI_USER_AGENT } from "../lib/config.js";
|
|
24
|
+
import { getApiUrl } from "../lib/config.js";
|
|
25
25
|
// ── Config file helpers ─────────────────────────────────────────────────
|
|
26
26
|
const CONFIG_FILENAME = "bankr.x402.json";
|
|
27
27
|
function findProjectRoot() {
|
|
@@ -44,8 +44,7 @@ function loadConfigFile(projectRoot) {
|
|
|
44
44
|
return JSON.parse(readFileSync(p, "utf-8"));
|
|
45
45
|
}
|
|
46
46
|
catch {
|
|
47
|
-
output.
|
|
48
|
-
process.exit(1);
|
|
47
|
+
output.fatal(`Failed to parse ${p}. Check that it is valid JSON.`);
|
|
49
48
|
}
|
|
50
49
|
}
|
|
51
50
|
}
|
|
@@ -55,24 +54,6 @@ function saveConfigFile(projectRoot, config) {
|
|
|
55
54
|
const configPath = join(projectRoot, CONFIG_FILENAME);
|
|
56
55
|
writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
57
56
|
}
|
|
58
|
-
// ── API helpers ─────────────────────────────────────────────────────────
|
|
59
|
-
function authHeaders() {
|
|
60
|
-
return {
|
|
61
|
-
"X-API-Key": requireApiKey(),
|
|
62
|
-
"Content-Type": "application/json",
|
|
63
|
-
"User-Agent": CLI_USER_AGENT,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
async function handleResponse(res) {
|
|
67
|
-
if (!res.ok) {
|
|
68
|
-
const body = (await res
|
|
69
|
-
.json()
|
|
70
|
-
.catch(() => ({ message: res.statusText })));
|
|
71
|
-
const msg = body.message || body.error || res.statusText;
|
|
72
|
-
throw new Error(`API error (${res.status}): ${msg}`);
|
|
73
|
-
}
|
|
74
|
-
return res.json();
|
|
75
|
-
}
|
|
76
57
|
// ── Default handler template ────────────────────────────────────────────
|
|
77
58
|
const HANDLER_TEMPLATE = `/**
|
|
78
59
|
* x402 service handler.
|
|
@@ -144,19 +125,16 @@ function validateServiceName(name) {
|
|
|
144
125
|
export async function x402AddCommand(name) {
|
|
145
126
|
const nameError = validateServiceName(name);
|
|
146
127
|
if (nameError) {
|
|
147
|
-
output.
|
|
148
|
-
process.exit(1);
|
|
128
|
+
output.fatal(nameError);
|
|
149
129
|
}
|
|
150
130
|
const root = findProjectRoot();
|
|
151
131
|
const x402Dir = join(root, "x402");
|
|
152
132
|
if (!existsSync(x402Dir)) {
|
|
153
|
-
output.
|
|
154
|
-
process.exit(1);
|
|
133
|
+
output.fatal("No x402/ directory found. Run 'bankr x402 init' first.");
|
|
155
134
|
}
|
|
156
135
|
const serviceDir = join(x402Dir, name);
|
|
157
136
|
if (existsSync(serviceDir)) {
|
|
158
|
-
output.
|
|
159
|
-
process.exit(1);
|
|
137
|
+
output.fatal(`Service "${name}" already exists at x402/${name}/`);
|
|
160
138
|
}
|
|
161
139
|
// Ask for method
|
|
162
140
|
const method = await select({
|
|
@@ -327,8 +305,7 @@ export async function x402DeployCommand(name) {
|
|
|
327
305
|
const root = findProjectRoot();
|
|
328
306
|
const x402Dir = join(root, "x402");
|
|
329
307
|
if (!existsSync(x402Dir)) {
|
|
330
|
-
output.
|
|
331
|
-
process.exit(1);
|
|
308
|
+
output.fatal("No x402/ directory found. Run 'bankr x402 init' first.");
|
|
332
309
|
}
|
|
333
310
|
// Load or bootstrap config
|
|
334
311
|
let config = loadConfigFile(root);
|
|
@@ -345,21 +322,18 @@ export async function x402DeployCommand(name) {
|
|
|
345
322
|
}
|
|
346
323
|
}
|
|
347
324
|
if (services.length === 0) {
|
|
348
|
-
output.
|
|
349
|
-
process.exit(1);
|
|
325
|
+
output.fatal("No services found. Run 'bankr x402 add <name>' first.");
|
|
350
326
|
}
|
|
351
327
|
// Filter to single service if name provided
|
|
352
328
|
const toDeploy = name ? services.filter((s) => s === name) : services;
|
|
353
329
|
if (name && toDeploy.length === 0) {
|
|
354
|
-
output.
|
|
355
|
-
process.exit(1);
|
|
330
|
+
output.fatal(`Service "${name}" not found in x402/`);
|
|
356
331
|
}
|
|
357
332
|
// Validate service names and ensure config entries
|
|
358
333
|
for (const svc of toDeploy) {
|
|
359
334
|
const nameError = validateServiceName(svc);
|
|
360
335
|
if (nameError) {
|
|
361
|
-
output.
|
|
362
|
-
process.exit(1);
|
|
336
|
+
output.fatal(nameError);
|
|
363
337
|
}
|
|
364
338
|
if (!config.services[svc]) {
|
|
365
339
|
config.services[svc] = {
|
|
@@ -424,9 +398,7 @@ export async function x402DeployCommand(name) {
|
|
|
424
398
|
}
|
|
425
399
|
}
|
|
426
400
|
catch (err) {
|
|
427
|
-
|
|
428
|
-
output.error(getErrorMessage(err));
|
|
429
|
-
process.exit(1);
|
|
401
|
+
output.failWith(spin, "Deploy failed", err);
|
|
430
402
|
}
|
|
431
403
|
}
|
|
432
404
|
/**
|
|
@@ -454,9 +426,7 @@ export async function x402ListCommand() {
|
|
|
454
426
|
}
|
|
455
427
|
}
|
|
456
428
|
catch (err) {
|
|
457
|
-
|
|
458
|
-
output.error(getErrorMessage(err));
|
|
459
|
-
process.exit(1);
|
|
429
|
+
output.failWith(spin, "Failed to list endpoints", err);
|
|
460
430
|
}
|
|
461
431
|
}
|
|
462
432
|
/**
|
|
@@ -475,9 +445,7 @@ export async function x402PauseResumeCommand(name, action) {
|
|
|
475
445
|
spin.succeed(`${name} ${action === "pause" ? "paused" : "resumed"}`);
|
|
476
446
|
}
|
|
477
447
|
catch (err) {
|
|
478
|
-
|
|
479
|
-
output.error(getErrorMessage(err));
|
|
480
|
-
process.exit(1);
|
|
448
|
+
output.failWith(spin, `Failed to ${action} ${name}`, err);
|
|
481
449
|
}
|
|
482
450
|
}
|
|
483
451
|
/**
|
|
@@ -501,9 +469,7 @@ export async function x402DeleteCommand(name) {
|
|
|
501
469
|
spin.succeed(`${name} deleted`);
|
|
502
470
|
}
|
|
503
471
|
catch (err) {
|
|
504
|
-
|
|
505
|
-
output.error(getErrorMessage(err));
|
|
506
|
-
process.exit(1);
|
|
472
|
+
output.failWith(spin, `Failed to delete ${name}`, err);
|
|
507
473
|
}
|
|
508
474
|
}
|
|
509
475
|
/**
|
|
@@ -535,9 +501,7 @@ export async function x402RevenueCommand(name) {
|
|
|
535
501
|
console.log();
|
|
536
502
|
}
|
|
537
503
|
catch (err) {
|
|
538
|
-
|
|
539
|
-
output.error(getErrorMessage(err));
|
|
540
|
-
process.exit(1);
|
|
504
|
+
output.failWith(spin, "Failed to fetch revenue", err);
|
|
541
505
|
}
|
|
542
506
|
}
|
|
543
507
|
/**
|
|
@@ -546,14 +510,12 @@ export async function x402RevenueCommand(name) {
|
|
|
546
510
|
export async function x402EnvSetCommand(keyValue) {
|
|
547
511
|
const eqIdx = keyValue.indexOf("=");
|
|
548
512
|
if (eqIdx === -1) {
|
|
549
|
-
output.
|
|
550
|
-
process.exit(1);
|
|
513
|
+
output.fatal("Usage: bankr x402 env set KEY=VALUE");
|
|
551
514
|
}
|
|
552
515
|
const key = keyValue.slice(0, eqIdx);
|
|
553
516
|
const value = keyValue.slice(eqIdx + 1);
|
|
554
517
|
if (!key) {
|
|
555
|
-
output.
|
|
556
|
-
process.exit(1);
|
|
518
|
+
output.fatal("Key cannot be empty");
|
|
557
519
|
}
|
|
558
520
|
const spin = output.spinner(`Setting ${key}...`);
|
|
559
521
|
try {
|
|
@@ -566,9 +528,7 @@ export async function x402EnvSetCommand(keyValue) {
|
|
|
566
528
|
spin.succeed(`Set ${key}`);
|
|
567
529
|
}
|
|
568
530
|
catch (err) {
|
|
569
|
-
|
|
570
|
-
output.error(getErrorMessage(err));
|
|
571
|
-
process.exit(1);
|
|
531
|
+
output.failWith(spin, `Failed to set ${key}`, err);
|
|
572
532
|
}
|
|
573
533
|
}
|
|
574
534
|
/**
|
|
@@ -591,9 +551,7 @@ export async function x402EnvListCommand() {
|
|
|
591
551
|
}
|
|
592
552
|
}
|
|
593
553
|
catch (err) {
|
|
594
|
-
|
|
595
|
-
output.error(getErrorMessage(err));
|
|
596
|
-
process.exit(1);
|
|
554
|
+
output.failWith(spin, "Failed to list env vars", err);
|
|
597
555
|
}
|
|
598
556
|
}
|
|
599
557
|
/**
|
|
@@ -610,9 +568,7 @@ export async function x402EnvUnsetCommand(key) {
|
|
|
610
568
|
spin.succeed(`Removed ${key}`);
|
|
611
569
|
}
|
|
612
570
|
catch (err) {
|
|
613
|
-
|
|
614
|
-
output.error(getErrorMessage(err));
|
|
615
|
-
process.exit(1);
|
|
571
|
+
output.failWith(spin, `Failed to remove ${key}`, err);
|
|
616
572
|
}
|
|
617
573
|
}
|
|
618
574
|
// ── Schema display helpers ──────────────────────────────────────────────
|
|
@@ -768,34 +724,28 @@ function printServiceFormatted(svc, rank, total) {
|
|
|
768
724
|
// ── Schema ────────────────────────────────────────────────────────────
|
|
769
725
|
export async function x402SchemaCommand(url, opts = {}) {
|
|
770
726
|
if (!url) {
|
|
771
|
-
output.
|
|
772
|
-
process.exit(1);
|
|
727
|
+
output.fatal("Usage: bankr x402 schema <url>\n Example: bankr x402 schema https://x402.bankr.bot/0xabc.../my-service");
|
|
773
728
|
}
|
|
774
729
|
let parsed;
|
|
775
730
|
try {
|
|
776
731
|
parsed = new URL(url);
|
|
777
732
|
}
|
|
778
733
|
catch {
|
|
779
|
-
output.
|
|
780
|
-
process.exit(1);
|
|
781
|
-
return; // unreachable but makes TS happy
|
|
734
|
+
output.fatal("Invalid URL");
|
|
782
735
|
}
|
|
783
736
|
if (!parsed.hostname.endsWith("x402.bankr.bot")) {
|
|
784
|
-
output.
|
|
785
|
-
process.exit(1);
|
|
737
|
+
output.fatal("Schema lookup is only available for Bankr-hosted endpoints (x402.bankr.bot).");
|
|
786
738
|
}
|
|
787
739
|
const parts = parsed.pathname.split("/").filter(Boolean);
|
|
788
740
|
if (parts.length < 2) {
|
|
789
|
-
output.
|
|
790
|
-
process.exit(1);
|
|
741
|
+
output.fatal("Invalid Bankr x402 URL. Expected: https://x402.bankr.bot/<address>/<service>");
|
|
791
742
|
}
|
|
792
743
|
const spin = output.spinner("Fetching endpoint schema...");
|
|
793
744
|
try {
|
|
794
745
|
const res = await fetch(`${getApiUrl()}/x402/endpoints/schema/${parts[0]}/${parts[1]}`);
|
|
795
746
|
if (res.status === 404) {
|
|
796
747
|
spin.fail("Endpoint not found");
|
|
797
|
-
output.
|
|
798
|
-
process.exit(1);
|
|
748
|
+
output.fatal(`No active endpoint found for ${parts[0]}/${parts[1]}`);
|
|
799
749
|
}
|
|
800
750
|
const result = await handleResponse(res);
|
|
801
751
|
spin.stop();
|
|
@@ -877,9 +827,7 @@ export async function x402SchemaCommand(url, opts = {}) {
|
|
|
877
827
|
console.log();
|
|
878
828
|
}
|
|
879
829
|
catch (err) {
|
|
880
|
-
|
|
881
|
-
output.error(getErrorMessage(err));
|
|
882
|
-
process.exit(1);
|
|
830
|
+
output.failWith(spin, "Schema lookup failed", err);
|
|
883
831
|
}
|
|
884
832
|
}
|
|
885
833
|
async function fetchSchemaForInteractive(url) {
|
|
@@ -1029,15 +977,13 @@ export function outboundMaxPayment(callerCapUsd, advertisedUsd) {
|
|
|
1029
977
|
}
|
|
1030
978
|
export async function x402CallCommand(url, opts = {}) {
|
|
1031
979
|
if (!url) {
|
|
1032
|
-
output.
|
|
1033
|
-
process.exit(1);
|
|
980
|
+
output.fatal("Usage: bankr x402 call <url> [--method POST] [--body '{}']");
|
|
1034
981
|
}
|
|
1035
982
|
let method = opts.method?.toUpperCase() ?? "GET";
|
|
1036
983
|
const maxPaymentUsd = opts.maxPayment ? parseFloat(opts.maxPayment) : 1;
|
|
1037
984
|
let requestBody = opts.body;
|
|
1038
985
|
if (isNaN(maxPaymentUsd) || maxPaymentUsd <= 0 || maxPaymentUsd > 10) {
|
|
1039
|
-
output.
|
|
1040
|
-
process.exit(1);
|
|
986
|
+
output.fatal("--max-payment must be between 0 and 10 (USD)");
|
|
1041
987
|
}
|
|
1042
988
|
// Endpoint-advertised price. Shown at confirm time; the outbound cap is
|
|
1043
989
|
// clamped to min(advertised, caller's maxPaymentUsd) — see outboundMaxPayment.
|
|
@@ -1057,8 +1003,7 @@ export async function x402CallCommand(url, opts = {}) {
|
|
|
1057
1003
|
resolvedPrice = parseAdvertisedPrice(schema.price, schema.currency);
|
|
1058
1004
|
const capError = checkAdvertisedPrice(resolvedPrice, maxPaymentUsd);
|
|
1059
1005
|
if (capError) {
|
|
1060
|
-
output.
|
|
1061
|
-
process.exit(1);
|
|
1006
|
+
output.fatal(capError);
|
|
1062
1007
|
}
|
|
1063
1008
|
if (schema.methods.length > 0) {
|
|
1064
1009
|
method = schema.methods.includes("POST") ? "POST" : schema.methods[0];
|
|
@@ -1100,8 +1045,7 @@ export async function x402CallCommand(url, opts = {}) {
|
|
|
1100
1045
|
if (typedProp.type === "number" || typedProp.type === "integer") {
|
|
1101
1046
|
const num = Number(answer);
|
|
1102
1047
|
if (isNaN(num)) {
|
|
1103
|
-
output.
|
|
1104
|
-
process.exit(1);
|
|
1048
|
+
output.fatal(`Invalid number for ${key}: "${answer}"`);
|
|
1105
1049
|
}
|
|
1106
1050
|
values[key] = num;
|
|
1107
1051
|
}
|
|
@@ -1155,8 +1099,7 @@ export async function x402CallCommand(url, opts = {}) {
|
|
|
1155
1099
|
requestBody = bodyInput;
|
|
1156
1100
|
}
|
|
1157
1101
|
catch {
|
|
1158
|
-
output.
|
|
1159
|
-
process.exit(1);
|
|
1102
|
+
output.fatal("Invalid JSON body");
|
|
1160
1103
|
}
|
|
1161
1104
|
}
|
|
1162
1105
|
}
|
|
@@ -1192,8 +1135,7 @@ export async function x402CallCommand(url, opts = {}) {
|
|
|
1192
1135
|
resolvedPrice = parseAdvertisedPrice(schema.price, schema.currency);
|
|
1193
1136
|
const capError = checkAdvertisedPrice(resolvedPrice, maxPaymentUsd);
|
|
1194
1137
|
if (capError) {
|
|
1195
|
-
output.
|
|
1196
|
-
process.exit(1);
|
|
1138
|
+
output.fatal(capError);
|
|
1197
1139
|
}
|
|
1198
1140
|
}
|
|
1199
1141
|
}
|
|
@@ -1239,8 +1181,7 @@ export async function x402CallCommand(url, opts = {}) {
|
|
|
1239
1181
|
return;
|
|
1240
1182
|
}
|
|
1241
1183
|
if (!result.success) {
|
|
1242
|
-
output.
|
|
1243
|
-
process.exit(1);
|
|
1184
|
+
output.fatal(result.error ?? "Call failed");
|
|
1244
1185
|
}
|
|
1245
1186
|
// Show endpoint schema info (Bankr-hosted endpoints only)
|
|
1246
1187
|
if (result.endpointSchema) {
|
|
@@ -1273,17 +1214,14 @@ export async function x402CallCommand(url, opts = {}) {
|
|
|
1273
1214
|
console.log();
|
|
1274
1215
|
}
|
|
1275
1216
|
catch (err) {
|
|
1276
|
-
|
|
1277
|
-
output.error(getErrorMessage(err));
|
|
1278
|
-
process.exit(1);
|
|
1217
|
+
output.failWith(spin, "Call failed", err);
|
|
1279
1218
|
}
|
|
1280
1219
|
}
|
|
1281
1220
|
// ── Search ────────────────────────────────────────────────────────────
|
|
1282
1221
|
export async function x402SearchCommand(queryParts, opts = {}) {
|
|
1283
1222
|
const query = queryParts.join(" ").trim();
|
|
1284
1223
|
if (!query) {
|
|
1285
|
-
output.
|
|
1286
|
-
process.exit(1);
|
|
1224
|
+
output.fatal("Usage: bankr x402 search <query>");
|
|
1287
1225
|
}
|
|
1288
1226
|
const spin = output.spinner("Searching services...");
|
|
1289
1227
|
try {
|
|
@@ -1320,9 +1258,7 @@ export async function x402SearchCommand(queryParts, opts = {}) {
|
|
|
1320
1258
|
}
|
|
1321
1259
|
}
|
|
1322
1260
|
catch (err) {
|
|
1323
|
-
|
|
1324
|
-
output.error(getErrorMessage(err));
|
|
1325
|
-
process.exit(1);
|
|
1261
|
+
output.failWith(spin, "Search failed", err);
|
|
1326
1262
|
}
|
|
1327
1263
|
}
|
|
1328
1264
|
//# sourceMappingURL=x402.js.map
|
package/dist/lib/api.d.ts
CHANGED
|
@@ -43,6 +43,8 @@ export interface JobStatusResponse {
|
|
|
43
43
|
richData?: unknown[];
|
|
44
44
|
cancellable?: boolean;
|
|
45
45
|
}
|
|
46
|
+
export declare function authHeaders(): Record<string, string>;
|
|
47
|
+
export declare function handleResponse<T>(res: Response): Promise<T>;
|
|
46
48
|
export interface ApiErrorBody {
|
|
47
49
|
error: string;
|
|
48
50
|
message: string;
|
|
@@ -196,7 +198,7 @@ export interface SubmitResponse {
|
|
|
196
198
|
export declare function submit(request: SubmitRequest): Promise<SubmitResponse>;
|
|
197
199
|
export type FeeRecipientType = "wallet" | "x" | "farcaster" | "ens";
|
|
198
200
|
/** Chains the deploy endpoint accepts (mirrors the API's zod enum). */
|
|
199
|
-
export type LaunchChain = "base" | "robinhood";
|
|
201
|
+
export type LaunchChain = "base" | "robinhood" | "arbitrum";
|
|
200
202
|
export interface DeployTokenRequest {
|
|
201
203
|
tokenName: string;
|
|
202
204
|
tokenSymbol?: string;
|
|
@@ -234,7 +236,7 @@ export interface CreatorFeesTokenResult {
|
|
|
234
236
|
tokenAddress: string;
|
|
235
237
|
name: string;
|
|
236
238
|
symbol: string;
|
|
237
|
-
/** Launch chain ("base" | "robinhood"); absent on older API versions → base. */
|
|
239
|
+
/** Launch chain ("base" | "robinhood" | "arbitrum"); absent on older API versions → base. */
|
|
238
240
|
chain?: string;
|
|
239
241
|
poolId: string;
|
|
240
242
|
initializer?: string;
|
package/dist/lib/api.js
CHANGED
|
@@ -7,14 +7,14 @@ const TERMINAL_STATUSES = [
|
|
|
7
7
|
function isTerminalStatus(status) {
|
|
8
8
|
return TERMINAL_STATUSES.includes(status);
|
|
9
9
|
}
|
|
10
|
-
function authHeaders() {
|
|
10
|
+
export function authHeaders() {
|
|
11
11
|
return {
|
|
12
12
|
"X-API-Key": requireApiKey(),
|
|
13
13
|
"Content-Type": "application/json",
|
|
14
14
|
"User-Agent": CLI_USER_AGENT,
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
|
-
async function handleResponse(res) {
|
|
17
|
+
export async function handleResponse(res) {
|
|
18
18
|
if (!res.ok) {
|
|
19
19
|
const body = (await res
|
|
20
20
|
.json()
|
package/dist/lib/explorer.js
CHANGED
|
@@ -5,6 +5,7 @@ const EXPLORERS = {
|
|
|
5
5
|
name: "Blockscout",
|
|
6
6
|
baseUrl: "https://robinhoodchain.blockscout.com",
|
|
7
7
|
},
|
|
8
|
+
42161: { name: "Arbiscan", baseUrl: "https://arbiscan.io" },
|
|
8
9
|
};
|
|
9
10
|
/** Unknown chain ids fall back to Basescan (pre-multichain behavior). */
|
|
10
11
|
export function txExplorer(chainId, txHash) {
|
package/dist/lib/output.d.ts
CHANGED
|
@@ -22,6 +22,10 @@ export declare function brand(msg: string): void;
|
|
|
22
22
|
export declare function brandBold(msg: string): void;
|
|
23
23
|
export declare function success(msg: string): void;
|
|
24
24
|
export declare function error(msg: string): void;
|
|
25
|
+
/** Collapses the error-then-exit epilogue every command repeats. */
|
|
26
|
+
export declare function fatal(message: string): never;
|
|
27
|
+
/** Same epilogue, for the spinner-driven variant that reports a caught error. */
|
|
28
|
+
export declare function failWith(spinner: Ora, label: string, err: unknown): never;
|
|
25
29
|
export declare function warn(msg: string): void;
|
|
26
30
|
export declare function info(msg: string): void;
|
|
27
31
|
export declare function blank(): void;
|
package/dist/lib/output.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import ora from "ora";
|
|
3
|
+
import { getErrorMessage } from "./errors.js";
|
|
3
4
|
const BRAND_HEX = "#FF613D";
|
|
4
5
|
const brandColor = chalk.hex(BRAND_HEX);
|
|
5
6
|
const brandColorBold = brandColor.bold;
|
|
@@ -39,6 +40,17 @@ export function success(msg) {
|
|
|
39
40
|
export function error(msg) {
|
|
40
41
|
console.error(chalk.red(`✗ ${msg}`));
|
|
41
42
|
}
|
|
43
|
+
/** Collapses the error-then-exit epilogue every command repeats. */
|
|
44
|
+
export function fatal(message) {
|
|
45
|
+
error(message);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
/** Same epilogue, for the spinner-driven variant that reports a caught error. */
|
|
49
|
+
export function failWith(spinner, label, err) {
|
|
50
|
+
spinner.fail(label);
|
|
51
|
+
error(getErrorMessage(err));
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
42
54
|
export function warn(msg) {
|
|
43
55
|
console.log(chalk.yellow(`⚠ ${msg}`));
|
|
44
56
|
}
|