@bankr/cli 0.2.15 → 0.3.8
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 +1 -1
- package/dist/cli.js +129 -81
- package/dist/commands/club.d.ts +1 -0
- package/dist/commands/club.js +47 -5
- package/dist/commands/fees.js +41 -47
- package/dist/commands/launch.js +16 -23
- package/dist/commands/llm.js +176 -41
- package/dist/commands/login.d.ts +0 -1
- package/dist/commands/login.js +28 -23
- package/dist/commands/prompt.js +6 -0
- package/dist/commands/swap.d.ts +8 -0
- package/dist/commands/swap.js +107 -0
- package/dist/commands/transfer.js +38 -25
- package/dist/commands/webhooks.js +2 -7
- package/dist/commands/x402.js +57 -41
- package/dist/lib/api.d.ts +69 -3
- package/dist/lib/api.js +52 -10
- package/dist/lib/config.d.ts +0 -1
- package/dist/lib/output.d.ts +1 -0
- package/dist/lib/output.js +3 -0
- package/dist/lib/tokens.d.ts +21 -0
- package/dist/lib/tokens.js +40 -0
- package/package.json +6 -6
|
@@ -1,28 +1,38 @@
|
|
|
1
|
-
import { transfer,
|
|
1
|
+
import { transfer, resolveRecipient } from "../lib/api.js";
|
|
2
2
|
import * as output from "../lib/output.js";
|
|
3
|
-
import { NATIVE_SYMBOLS
|
|
3
|
+
import { NATIVE_SYMBOLS } from "../lib/chains.js";
|
|
4
4
|
import { isAddress } from "viem";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
import { ZERO_ADDRESS, resolveTokenSymbol } from "../lib/tokens.js";
|
|
6
|
+
function looksLikeEnsName(value) {
|
|
7
|
+
const v = value.trim().toLowerCase();
|
|
8
|
+
return v.endsWith(".eth") || v.endsWith(".cb.id");
|
|
9
|
+
}
|
|
10
|
+
async function resolveTransferRecipient(raw) {
|
|
11
|
+
const value = raw.trim();
|
|
12
|
+
if (isAddress(value)) {
|
|
13
|
+
return { address: value, label: value };
|
|
14
|
+
}
|
|
15
|
+
if (!looksLikeEnsName(value)) {
|
|
16
|
+
output.error(`Invalid recipient "${value}". Expected a 0x address or an ENS name (e.g. vitalik.eth, name.base.eth, name.cb.id).`);
|
|
17
|
+
process.exit(1);
|
|
12
18
|
}
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
.
|
|
23
|
-
|
|
19
|
+
const spin = output.spinner(`Resolving ENS name "${value}"...`);
|
|
20
|
+
try {
|
|
21
|
+
const resolved = await resolveRecipient(value, "ens");
|
|
22
|
+
if (!resolved.resolved || !resolved.address) {
|
|
23
|
+
spin.fail(`Could not resolve "${value}": ${resolved.error ?? "unknown error"}`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
spin.succeed(`Resolved ${value} → ${resolved.address}`);
|
|
27
|
+
return {
|
|
28
|
+
address: resolved.address,
|
|
29
|
+
label: `${value} (${resolved.address})`,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
spin.fail(`ENS resolution failed for "${value}": ${err.message}`);
|
|
34
|
+
process.exit(1);
|
|
24
35
|
}
|
|
25
|
-
return { address: exactMatch.address, symbol: exactMatch.symbol };
|
|
26
36
|
}
|
|
27
37
|
export async function transferCommand(opts) {
|
|
28
38
|
const isNative = opts.native ?? false;
|
|
@@ -31,16 +41,19 @@ export async function transferCommand(opts) {
|
|
|
31
41
|
output.error("Token required for ERC20 transfers. Use --token <symbol or address> or --native.");
|
|
32
42
|
process.exit(1);
|
|
33
43
|
}
|
|
44
|
+
const recipient = await resolveTransferRecipient(opts.to);
|
|
45
|
+
const recipientAddress = recipient.address;
|
|
46
|
+
const recipientLabel = recipient.label;
|
|
34
47
|
let tokenAddress;
|
|
35
48
|
let tokenLabel;
|
|
36
49
|
if (isNative) {
|
|
37
|
-
tokenAddress =
|
|
50
|
+
tokenAddress = ZERO_ADDRESS;
|
|
38
51
|
tokenLabel = NATIVE_SYMBOLS[chain] ?? "ETH";
|
|
39
52
|
}
|
|
40
53
|
else {
|
|
41
54
|
const spin = output.spinner(`Resolving token "${opts.token}"...`);
|
|
42
55
|
try {
|
|
43
|
-
const resolved = await
|
|
56
|
+
const resolved = await resolveTokenSymbol(opts.token, chain);
|
|
44
57
|
tokenAddress = resolved.address;
|
|
45
58
|
tokenLabel = resolved.symbol;
|
|
46
59
|
if (tokenAddress !== opts.token) {
|
|
@@ -56,11 +69,11 @@ export async function transferCommand(opts) {
|
|
|
56
69
|
}
|
|
57
70
|
}
|
|
58
71
|
const chainLabel = chain !== "base" ? ` on ${chain}` : "";
|
|
59
|
-
const spin = output.spinner(`Transferring ${opts.amount} ${tokenLabel} to ${
|
|
72
|
+
const spin = output.spinner(`Transferring ${opts.amount} ${tokenLabel} to ${recipientLabel}${chainLabel}...`);
|
|
60
73
|
try {
|
|
61
74
|
const result = await transfer({
|
|
62
75
|
tokenAddress,
|
|
63
|
-
recipientAddress
|
|
76
|
+
recipientAddress,
|
|
64
77
|
amount: opts.amount,
|
|
65
78
|
isNativeToken: isNative,
|
|
66
79
|
chain,
|
|
@@ -17,7 +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 { getApiUrl, requireApiKey,
|
|
20
|
+
import { getApiUrl, requireApiKey, CLI_USER_AGENT } from "../lib/config.js";
|
|
21
21
|
// ── Config file ─────────────────────────────────────────────────────────
|
|
22
22
|
const CONFIG_FILENAME = "bankr.webhooks.json";
|
|
23
23
|
const WEBHOOKS_DIR = "webhooks";
|
|
@@ -46,16 +46,11 @@ function saveConfigFile(projectRoot, config) {
|
|
|
46
46
|
writeFileSync(join(projectRoot, CONFIG_FILENAME), JSON.stringify(config, null, 2) + "\n");
|
|
47
47
|
}
|
|
48
48
|
function authHeaders() {
|
|
49
|
-
|
|
49
|
+
return {
|
|
50
50
|
"X-API-Key": requireApiKey(),
|
|
51
51
|
"Content-Type": "application/json",
|
|
52
52
|
"User-Agent": CLI_USER_AGENT,
|
|
53
53
|
};
|
|
54
|
-
const config = readConfig();
|
|
55
|
-
if (config.partnerKey) {
|
|
56
|
-
headers["X-Partner-Key"] = config.partnerKey;
|
|
57
|
-
}
|
|
58
|
-
return headers;
|
|
59
54
|
}
|
|
60
55
|
async function handleResponse(res) {
|
|
61
56
|
if (!res.ok) {
|
package/dist/commands/x402.js
CHANGED
|
@@ -20,7 +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 { getApiUrl, requireApiKey,
|
|
23
|
+
import { getApiUrl, requireApiKey, CLI_USER_AGENT } from "../lib/config.js";
|
|
24
24
|
// ── Config file helpers ─────────────────────────────────────────────────
|
|
25
25
|
const CONFIG_FILENAME = "bankr.x402.json";
|
|
26
26
|
function findProjectRoot() {
|
|
@@ -50,16 +50,11 @@ function saveConfigFile(projectRoot, config) {
|
|
|
50
50
|
}
|
|
51
51
|
// ── API helpers ─────────────────────────────────────────────────────────
|
|
52
52
|
function authHeaders() {
|
|
53
|
-
|
|
53
|
+
return {
|
|
54
54
|
"X-API-Key": requireApiKey(),
|
|
55
55
|
"Content-Type": "application/json",
|
|
56
56
|
"User-Agent": CLI_USER_AGENT,
|
|
57
57
|
};
|
|
58
|
-
const config = readConfig();
|
|
59
|
-
if (config.partnerKey) {
|
|
60
|
-
headers["X-Partner-Key"] = config.partnerKey;
|
|
61
|
-
}
|
|
62
|
-
return headers;
|
|
63
58
|
}
|
|
64
59
|
async function handleResponse(res) {
|
|
65
60
|
if (!res.ok) {
|
|
@@ -279,10 +274,7 @@ export async function x402ConfigureCommand(name) {
|
|
|
279
274
|
const currency = "USDC";
|
|
280
275
|
const network = await select({
|
|
281
276
|
message: "Network:",
|
|
282
|
-
choices: [
|
|
283
|
-
{ name: "Base", value: "base" },
|
|
284
|
-
{ name: "Base Sepolia (testnet)", value: "base-sepolia" },
|
|
285
|
-
],
|
|
277
|
+
choices: [{ name: "Base", value: "base" }],
|
|
286
278
|
default: existing.network ?? "base",
|
|
287
279
|
theme: output.bankrTheme,
|
|
288
280
|
});
|
|
@@ -697,62 +689,78 @@ function resolveSchemas(schema) {
|
|
|
697
689
|
const outputSchema = schema.output;
|
|
698
690
|
return { input: inputSchema, output: outputSchema };
|
|
699
691
|
}
|
|
700
|
-
|
|
692
|
+
/**
|
|
693
|
+
* Builds the verbose multi-line card for a service. Returns the rendered
|
|
694
|
+
* string. Pass `rank` and `total` to render a `#N of M` badge in the header
|
|
695
|
+
* (used by the search command so reading top-to-bottom shows ascending rank
|
|
696
|
+
* with the top match at the bottom).
|
|
697
|
+
*/
|
|
698
|
+
function formatServiceCard(svc, rank, total) {
|
|
701
699
|
const route = svc.routes[0];
|
|
702
700
|
const methods = route?.methods?.filter((m) => m !== "*").join(", ") || "ANY";
|
|
703
701
|
const url = svc.url ?? `https://x402.bankr.bot/${svc.slug}`;
|
|
704
702
|
const isGet = methods === "GET";
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
703
|
+
const lines = [];
|
|
704
|
+
// ── Header (with rank badge) ──
|
|
705
|
+
const rankBadge = rank !== undefined
|
|
706
|
+
? `${chalk.bold(`#${rank}${total ? ` of ${total}` : ""}`)} `
|
|
707
|
+
: "";
|
|
708
|
+
const scoreBadge = svc.score !== undefined
|
|
709
|
+
? ` ${chalk.dim(`(score ${svc.score.toFixed(2)})`)}`
|
|
710
|
+
: "";
|
|
711
|
+
lines.push(` ${rankBadge}${output.fmt.brandBold(svc.name)}${scoreBadge}`);
|
|
712
|
+
if (svc.description)
|
|
713
|
+
lines.push(` ${chalk.dim(svc.description)}`);
|
|
714
|
+
lines.push("");
|
|
711
715
|
// ── Metadata ──
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
+
lines.push(` ${chalk.dim("URL")} ${url}`);
|
|
717
|
+
lines.push(` ${chalk.dim("Method")} ${chalk.bold(methods)}`);
|
|
718
|
+
lines.push(` ${chalk.dim("Price")} ${chalk.green(`$${route?.price ?? "?"} ${route?.currency ?? "USDC"}`)}`);
|
|
719
|
+
lines.push(` ${chalk.dim("Network")} ${route?.network ?? "base"}`);
|
|
716
720
|
// ── Schema ──
|
|
717
721
|
const { input: inputSchema, output: outputSchema } = resolveSchemas(route?.schema);
|
|
718
722
|
if (inputSchema || outputSchema) {
|
|
719
|
-
|
|
723
|
+
lines.push("");
|
|
720
724
|
if (inputSchema) {
|
|
721
725
|
const label = isGet ? "Input (query params)" : "Input (JSON body)";
|
|
722
|
-
|
|
726
|
+
lines.push(` ${chalk.bold(label)}`);
|
|
723
727
|
if (isJsonSchema(inputSchema)) {
|
|
724
728
|
for (const line of renderJsonSchemaProps(inputSchema)) {
|
|
725
|
-
|
|
729
|
+
lines.push(line);
|
|
726
730
|
}
|
|
727
731
|
}
|
|
728
732
|
else if (typeof inputSchema === "object" && inputSchema !== null) {
|
|
729
733
|
for (const line of renderLegacySchema(inputSchema)) {
|
|
730
|
-
|
|
734
|
+
lines.push(line);
|
|
731
735
|
}
|
|
732
736
|
}
|
|
733
737
|
}
|
|
734
738
|
if (outputSchema) {
|
|
735
|
-
|
|
736
|
-
|
|
739
|
+
lines.push("");
|
|
740
|
+
lines.push(` ${chalk.bold("Output")}`);
|
|
737
741
|
if (isJsonSchema(outputSchema)) {
|
|
738
742
|
for (const line of renderJsonSchemaProps(outputSchema)) {
|
|
739
|
-
|
|
743
|
+
lines.push(line);
|
|
740
744
|
}
|
|
741
745
|
}
|
|
742
746
|
else if (typeof outputSchema === "object" && outputSchema !== null) {
|
|
743
747
|
for (const line of renderLegacySchema(outputSchema)) {
|
|
744
|
-
|
|
748
|
+
lines.push(line);
|
|
745
749
|
}
|
|
746
750
|
}
|
|
747
751
|
}
|
|
748
752
|
}
|
|
749
753
|
// ── Tags ──
|
|
750
754
|
if (svc.tags?.length) {
|
|
751
|
-
|
|
752
|
-
|
|
755
|
+
lines.push("");
|
|
756
|
+
lines.push(` ${svc.tags.map((t) => chalk.dim(`#${t}`)).join(" ")}`);
|
|
753
757
|
}
|
|
754
|
-
|
|
755
|
-
|
|
758
|
+
lines.push(` ${chalk.dim("─".repeat(60))}`);
|
|
759
|
+
lines.push("");
|
|
760
|
+
return lines.join("\n");
|
|
761
|
+
}
|
|
762
|
+
function printServiceFormatted(svc, rank, total) {
|
|
763
|
+
console.log(formatServiceCard(svc, rank, total));
|
|
756
764
|
}
|
|
757
765
|
// ── Schema ────────────────────────────────────────────────────────────
|
|
758
766
|
export async function x402SchemaCommand(url, opts = {}) {
|
|
@@ -1144,8 +1152,7 @@ export async function x402CallCommand(url, opts = {}) {
|
|
|
1144
1152
|
resolvedPrice = parseFloat(schema.price);
|
|
1145
1153
|
}
|
|
1146
1154
|
}
|
|
1147
|
-
|
|
1148
|
-
if (!opts.yes && !opts.interactive) {
|
|
1155
|
+
if (!opts.yes && !opts.interactive && !output.isNonInteractive()) {
|
|
1149
1156
|
const priceDisplay = resolvedPrice !== null
|
|
1150
1157
|
? chalk.green(`$${resolvedPrice} USDC`)
|
|
1151
1158
|
: chalk.green(`up to $${maxPaymentUsd} USDC`);
|
|
@@ -1235,7 +1242,7 @@ export async function x402SearchCommand(queryParts, opts = {}) {
|
|
|
1235
1242
|
}
|
|
1236
1243
|
const spin = output.spinner("Searching services...");
|
|
1237
1244
|
try {
|
|
1238
|
-
const params = new URLSearchParams({ q: query, limit: "
|
|
1245
|
+
const params = new URLSearchParams({ q: query, limit: "50" });
|
|
1239
1246
|
const res = await fetch(`${getApiUrl()}/x402/endpoints/discover?${params}`);
|
|
1240
1247
|
const result = await handleResponse(res);
|
|
1241
1248
|
spin.stop();
|
|
@@ -1246,16 +1253,25 @@ export async function x402SearchCommand(queryParts, opts = {}) {
|
|
|
1246
1253
|
output.info(`No services found for "${query}"`);
|
|
1247
1254
|
return;
|
|
1248
1255
|
}
|
|
1249
|
-
// Raw mode: dump JSON and exit
|
|
1256
|
+
// Raw mode: dump JSON and exit (preserves natural rank order for AI
|
|
1257
|
+
// agents and pipelines — most relevant first).
|
|
1250
1258
|
if (opts.raw) {
|
|
1251
1259
|
console.log(JSON.stringify(services, null, 2));
|
|
1252
1260
|
return;
|
|
1253
1261
|
}
|
|
1262
|
+
// Print results in REVERSE rank order so the cursor parks on the most
|
|
1263
|
+
// relevant result (rank #1) at the bottom of the buffer. Each card has
|
|
1264
|
+
// a `#N of M` badge so the rank is always visible regardless of which
|
|
1265
|
+
// direction you read.
|
|
1254
1266
|
console.log();
|
|
1255
|
-
console.log(` ${chalk.dim(`Found ${services.length} service(s) for`)} "${query}"`);
|
|
1267
|
+
console.log(` ${chalk.dim(`Found ${services.length} service(s) for`)} "${query}" ${chalk.dim("(scrolling order: lowest rank first, top match at the bottom)")}`);
|
|
1256
1268
|
console.log(` ${chalk.dim("─".repeat(60))}`);
|
|
1257
|
-
|
|
1258
|
-
|
|
1269
|
+
console.log();
|
|
1270
|
+
const total = services.length;
|
|
1271
|
+
// Iterate in reverse: start with the lowest-ranked result, end on rank #1.
|
|
1272
|
+
for (let i = total - 1; i >= 0; i--) {
|
|
1273
|
+
const svc = services[i];
|
|
1274
|
+
printServiceFormatted(svc, i + 1, total);
|
|
1259
1275
|
}
|
|
1260
1276
|
}
|
|
1261
1277
|
catch (err) {
|
package/dist/lib/api.d.ts
CHANGED
|
@@ -209,7 +209,6 @@ export interface DeployTokenResponse {
|
|
|
209
209
|
tokenAddress: string;
|
|
210
210
|
poolId: string;
|
|
211
211
|
txHash?: string;
|
|
212
|
-
activityId: string;
|
|
213
212
|
chain: string;
|
|
214
213
|
simulated?: boolean;
|
|
215
214
|
feeDistribution: Record<string, {
|
|
@@ -292,15 +291,39 @@ export interface StreamProgress {
|
|
|
292
291
|
*/
|
|
293
292
|
export declare function getBeneficiaryFeesStreaming(address: string, onProgress: (progress: StreamProgress) => void): Promise<BeneficiaryFeesResponse>;
|
|
294
293
|
/**
|
|
295
|
-
* Fetch creator fee data for a specific token address. Unauthenticated
|
|
296
|
-
*
|
|
294
|
+
* Fetch creator fee data for a specific token address. Unauthenticated.
|
|
295
|
+
*
|
|
296
|
+
* Uses the unified `/token-launches/:addr/fees` endpoint (added as part of
|
|
297
|
+
* the token-launches API consolidation epic). The legacy alias
|
|
298
|
+
* `GET /public/doppler/token-fees/:addr` still works but emits `Deprecation`
|
|
299
|
+
* and `Sunset` headers.
|
|
297
300
|
*/
|
|
298
301
|
export declare function getTokenCreatorFees(tokenAddress: string, days?: number): Promise<CreatorFeesResponse>;
|
|
299
302
|
/**
|
|
300
303
|
* Build a Doppler fee claim transaction. Requires authentication.
|
|
301
304
|
* The returned transaction data should be submitted via `submit()`.
|
|
305
|
+
*
|
|
306
|
+
* @deprecated Use `claimTokenLaunchFees` instead — it builds, signs, and
|
|
307
|
+
* broadcasts in a single HTTP call. Kept here so older CLI scripts continue
|
|
308
|
+
* to work through the deprecation window.
|
|
302
309
|
*/
|
|
303
310
|
export declare function buildDopplerClaimTx(tokenAddress: string): Promise<DopplerClaimTxResponse>;
|
|
311
|
+
export interface ClaimTokenLaunchFeesResponse {
|
|
312
|
+
transactionHash?: string;
|
|
313
|
+
status?: string;
|
|
314
|
+
signer?: string;
|
|
315
|
+
chainId: number;
|
|
316
|
+
description: string;
|
|
317
|
+
blockNumber?: string;
|
|
318
|
+
gasUsed?: string;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Claim trading fees for a Bankr-launched token. Auto-detects Doppler vs
|
|
322
|
+
* Clanker and executes (build + sign + broadcast) in a single call.
|
|
323
|
+
*
|
|
324
|
+
* Replaces the two-step `buildDopplerClaimTx` + `submit` flow.
|
|
325
|
+
*/
|
|
326
|
+
export declare function claimTokenLaunchFees(tokenAddress: string): Promise<ClaimTokenLaunchFeesResponse>;
|
|
304
327
|
export interface BuildClaimTx {
|
|
305
328
|
tokenAddress: string;
|
|
306
329
|
tokenName: string;
|
|
@@ -399,6 +422,49 @@ export interface TransferResponse {
|
|
|
399
422
|
error?: string;
|
|
400
423
|
}
|
|
401
424
|
export declare function transfer(request: TransferRequest): Promise<TransferResponse>;
|
|
425
|
+
export interface SwapQuoteRequest {
|
|
426
|
+
fromChain: string;
|
|
427
|
+
fromToken: string;
|
|
428
|
+
toChain: string;
|
|
429
|
+
toToken: string;
|
|
430
|
+
amount: string;
|
|
431
|
+
}
|
|
432
|
+
export interface SwapQuoteSide {
|
|
433
|
+
chain: string;
|
|
434
|
+
token: string;
|
|
435
|
+
amount: string;
|
|
436
|
+
formattedAmount: string;
|
|
437
|
+
symbol: string;
|
|
438
|
+
decimals: number;
|
|
439
|
+
usdValue: string;
|
|
440
|
+
}
|
|
441
|
+
export interface SwapQuoteResponse {
|
|
442
|
+
from: SwapQuoteSide;
|
|
443
|
+
to: SwapQuoteSide;
|
|
444
|
+
minBuyAmount: string;
|
|
445
|
+
}
|
|
446
|
+
export interface SwapExecuteRequest extends SwapQuoteRequest {
|
|
447
|
+
minBuyAmount: string;
|
|
448
|
+
}
|
|
449
|
+
export interface SwapExecuteResponse {
|
|
450
|
+
success: boolean;
|
|
451
|
+
hash?: string;
|
|
452
|
+
error?: string;
|
|
453
|
+
amountReceived?: number;
|
|
454
|
+
amountReceivedRaw?: string;
|
|
455
|
+
amountSold?: number;
|
|
456
|
+
amountSoldRaw?: string;
|
|
457
|
+
}
|
|
458
|
+
export declare function getSwapQuote(request: SwapQuoteRequest): Promise<SwapQuoteResponse>;
|
|
459
|
+
export declare function executeSwap(request: SwapExecuteRequest): Promise<SwapExecuteResponse>;
|
|
460
|
+
export type RecipientType = "address" | "ens" | "twitter" | "farcaster";
|
|
461
|
+
export interface ResolveRecipientResponse {
|
|
462
|
+
resolved: boolean;
|
|
463
|
+
address?: string;
|
|
464
|
+
displayName?: string;
|
|
465
|
+
error?: string;
|
|
466
|
+
}
|
|
467
|
+
export declare function resolveRecipient(value: string, type: RecipientType): Promise<ResolveRecipientResponse>;
|
|
402
468
|
export interface X402PayRequest {
|
|
403
469
|
url: string;
|
|
404
470
|
method?: string;
|
package/dist/lib/api.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CLI_USER_AGENT, getApiUrl,
|
|
1
|
+
import { CLI_USER_AGENT, getApiUrl, requireApiKey } from "./config.js";
|
|
2
2
|
const TERMINAL_STATUSES = [
|
|
3
3
|
"completed",
|
|
4
4
|
"failed",
|
|
@@ -8,16 +8,11 @@ function isTerminalStatus(status) {
|
|
|
8
8
|
return TERMINAL_STATUSES.includes(status);
|
|
9
9
|
}
|
|
10
10
|
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
|
-
const config = readConfig();
|
|
17
|
-
if (config.partnerKey) {
|
|
18
|
-
headers["X-Partner-Key"] = config.partnerKey;
|
|
19
|
-
}
|
|
20
|
-
return headers;
|
|
21
16
|
}
|
|
22
17
|
async function handleResponse(res) {
|
|
23
18
|
if (!res.ok) {
|
|
@@ -219,12 +214,16 @@ export async function getBeneficiaryFeesStreaming(address, onProgress) {
|
|
|
219
214
|
return result;
|
|
220
215
|
}
|
|
221
216
|
/**
|
|
222
|
-
* Fetch creator fee data for a specific token address. Unauthenticated
|
|
223
|
-
*
|
|
217
|
+
* Fetch creator fee data for a specific token address. Unauthenticated.
|
|
218
|
+
*
|
|
219
|
+
* Uses the unified `/token-launches/:addr/fees` endpoint (added as part of
|
|
220
|
+
* the token-launches API consolidation epic). The legacy alias
|
|
221
|
+
* `GET /public/doppler/token-fees/:addr` still works but emits `Deprecation`
|
|
222
|
+
* and `Sunset` headers.
|
|
224
223
|
*/
|
|
225
224
|
export async function getTokenCreatorFees(tokenAddress, days) {
|
|
226
225
|
const params = days ? `?days=${days}` : "";
|
|
227
|
-
const res = await fetch(`${getApiUrl()}/
|
|
226
|
+
const res = await fetch(`${getApiUrl()}/token-launches/${tokenAddress}/fees${params}`, {
|
|
228
227
|
headers: {
|
|
229
228
|
"User-Agent": CLI_USER_AGENT,
|
|
230
229
|
},
|
|
@@ -234,6 +233,10 @@ export async function getTokenCreatorFees(tokenAddress, days) {
|
|
|
234
233
|
/**
|
|
235
234
|
* Build a Doppler fee claim transaction. Requires authentication.
|
|
236
235
|
* The returned transaction data should be submitted via `submit()`.
|
|
236
|
+
*
|
|
237
|
+
* @deprecated Use `claimTokenLaunchFees` instead — it builds, signs, and
|
|
238
|
+
* broadcasts in a single HTTP call. Kept here so older CLI scripts continue
|
|
239
|
+
* to work through the deprecation window.
|
|
237
240
|
*/
|
|
238
241
|
export async function buildDopplerClaimTx(tokenAddress) {
|
|
239
242
|
const res = await fetch(`${getApiUrl()}/agent/doppler/claim`, {
|
|
@@ -243,6 +246,20 @@ export async function buildDopplerClaimTx(tokenAddress) {
|
|
|
243
246
|
});
|
|
244
247
|
return handleResponse(res);
|
|
245
248
|
}
|
|
249
|
+
/**
|
|
250
|
+
* Claim trading fees for a Bankr-launched token. Auto-detects Doppler vs
|
|
251
|
+
* Clanker and executes (build + sign + broadcast) in a single call.
|
|
252
|
+
*
|
|
253
|
+
* Replaces the two-step `buildDopplerClaimTx` + `submit` flow.
|
|
254
|
+
*/
|
|
255
|
+
export async function claimTokenLaunchFees(tokenAddress) {
|
|
256
|
+
const res = await fetch(`${getApiUrl()}/token-launches/${tokenAddress}/fees/claim`, {
|
|
257
|
+
method: "POST",
|
|
258
|
+
headers: authHeaders(),
|
|
259
|
+
body: JSON.stringify({}),
|
|
260
|
+
});
|
|
261
|
+
return handleResponse(res);
|
|
262
|
+
}
|
|
246
263
|
export async function getOwnProfile() {
|
|
247
264
|
const res = await fetch(`${getApiUrl()}/agent/profile`, {
|
|
248
265
|
headers: authHeaders(),
|
|
@@ -299,6 +316,31 @@ export async function transfer(request) {
|
|
|
299
316
|
});
|
|
300
317
|
return handleResponse(res);
|
|
301
318
|
}
|
|
319
|
+
export async function getSwapQuote(request) {
|
|
320
|
+
const res = await fetch(`${getApiUrl()}/wallet/swap-quote`, {
|
|
321
|
+
method: "POST",
|
|
322
|
+
headers: authHeaders(),
|
|
323
|
+
body: JSON.stringify(request),
|
|
324
|
+
});
|
|
325
|
+
return handleResponse(res);
|
|
326
|
+
}
|
|
327
|
+
export async function executeSwap(request) {
|
|
328
|
+
const res = await fetch(`${getApiUrl()}/wallet/swap`, {
|
|
329
|
+
method: "POST",
|
|
330
|
+
headers: authHeaders(),
|
|
331
|
+
body: JSON.stringify(request),
|
|
332
|
+
});
|
|
333
|
+
return handleResponse(res);
|
|
334
|
+
}
|
|
335
|
+
export async function resolveRecipient(value, type) {
|
|
336
|
+
const params = new URLSearchParams({ value, type });
|
|
337
|
+
const res = await fetch(`${getApiUrl()}/addresses/resolve?${params}`, {
|
|
338
|
+
headers: {
|
|
339
|
+
"User-Agent": CLI_USER_AGENT,
|
|
340
|
+
},
|
|
341
|
+
});
|
|
342
|
+
return handleResponse(res);
|
|
343
|
+
}
|
|
302
344
|
export async function x402Pay(request) {
|
|
303
345
|
const res = await fetch(`${getApiUrl()}/wallet/x402-pay`, {
|
|
304
346
|
method: "POST",
|
package/dist/lib/config.d.ts
CHANGED
package/dist/lib/output.d.ts
CHANGED
|
@@ -44,5 +44,6 @@ export interface RemediationStep {
|
|
|
44
44
|
* Used when the API returns a `remediation` array in error responses.
|
|
45
45
|
*/
|
|
46
46
|
export declare function remediation(steps: RemediationStep[]): void;
|
|
47
|
+
export declare function isNonInteractive(): boolean;
|
|
47
48
|
export declare function formatStatus(status: string): string;
|
|
48
49
|
//# sourceMappingURL=output.d.ts.map
|
package/dist/lib/output.js
CHANGED
|
@@ -105,6 +105,9 @@ export function remediation(steps) {
|
|
|
105
105
|
}
|
|
106
106
|
console.log();
|
|
107
107
|
}
|
|
108
|
+
export function isNonInteractive() {
|
|
109
|
+
return process.env.BANKR_NOT_INTERACTIVE === "1";
|
|
110
|
+
}
|
|
108
111
|
export function formatStatus(status) {
|
|
109
112
|
switch (status) {
|
|
110
113
|
case "completed":
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native-token sentinel (zero address). The API detects + sanitizes native
|
|
3
|
+
* tokens from this, so callers send it instead of a real contract address.
|
|
4
|
+
*/
|
|
5
|
+
export declare const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
6
|
+
/** Shorten an address for display, e.g. `0x8335…2913`. */
|
|
7
|
+
export declare function shortenAddress(address: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Resolve a token symbol or 0x address to `{ address, symbol }` on a chain:
|
|
10
|
+
* - a valid 0x address is used as-is (symbol shown shortened for display),
|
|
11
|
+
* - otherwise an exact, case-insensitive symbol match is looked up via
|
|
12
|
+
* `/tokens/search`, throwing a "Did you mean" suggestion list on no match.
|
|
13
|
+
*
|
|
14
|
+
* Native-token handling is caller-specific (a `--native` flag for transfer, a
|
|
15
|
+
* native-ticker/zero-address short-circuit for swap), so it lives in the command.
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveTokenSymbol(tokenInput: string, chain: string): Promise<{
|
|
18
|
+
address: string;
|
|
19
|
+
symbol: string;
|
|
20
|
+
}>;
|
|
21
|
+
//# sourceMappingURL=tokens.d.ts.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { isAddress } from "viem";
|
|
2
|
+
import { searchTokens } from "./api.js";
|
|
3
|
+
import { CHAIN_IDS } from "./chains.js";
|
|
4
|
+
/**
|
|
5
|
+
* Native-token sentinel (zero address). The API detects + sanitizes native
|
|
6
|
+
* tokens from this, so callers send it instead of a real contract address.
|
|
7
|
+
*/
|
|
8
|
+
export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
9
|
+
/** Shorten an address for display, e.g. `0x8335…2913`. */
|
|
10
|
+
export function shortenAddress(address) {
|
|
11
|
+
return `${address.slice(0, 6)}…${address.slice(-4)}`;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Resolve a token symbol or 0x address to `{ address, symbol }` on a chain:
|
|
15
|
+
* - a valid 0x address is used as-is (symbol shown shortened for display),
|
|
16
|
+
* - otherwise an exact, case-insensitive symbol match is looked up via
|
|
17
|
+
* `/tokens/search`, throwing a "Did you mean" suggestion list on no match.
|
|
18
|
+
*
|
|
19
|
+
* Native-token handling is caller-specific (a `--native` flag for transfer, a
|
|
20
|
+
* native-ticker/zero-address short-circuit for swap), so it lives in the command.
|
|
21
|
+
*/
|
|
22
|
+
export async function resolveTokenSymbol(tokenInput, chain) {
|
|
23
|
+
const input = tokenInput.trim();
|
|
24
|
+
if (isAddress(input)) {
|
|
25
|
+
return { address: input, symbol: shortenAddress(input) };
|
|
26
|
+
}
|
|
27
|
+
const chainId = CHAIN_IDS[chain];
|
|
28
|
+
const res = await searchTokens(input, chainId);
|
|
29
|
+
const inputUpper = input.toUpperCase();
|
|
30
|
+
const exactMatch = res.tokens.find((t) => t.symbol.toUpperCase() === inputUpper);
|
|
31
|
+
if (!exactMatch) {
|
|
32
|
+
const available = res.tokens
|
|
33
|
+
.slice(0, 5)
|
|
34
|
+
.map((t) => `${t.symbol} (${t.address})`)
|
|
35
|
+
.join(", ");
|
|
36
|
+
throw new Error(`No exact match for "${input}" on ${chain}. Did you mean: ${available || "no results"}`);
|
|
37
|
+
}
|
|
38
|
+
return { address: exactMatch.address, symbol: exactMatch.symbol };
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=tokens.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bankr/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.8",
|
|
4
4
|
"description": "Official CLI for the Bankr AI agent platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -40,11 +40,11 @@
|
|
|
40
40
|
"url": "https://discord.gg/bankr"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@inquirer/prompts": "^8.2
|
|
44
|
-
"chalk": "^5.
|
|
45
|
-
"commander": "^
|
|
46
|
-
"open": "^
|
|
47
|
-
"ora": "^
|
|
43
|
+
"@inquirer/prompts": "^8.4.2",
|
|
44
|
+
"chalk": "^5.6.2",
|
|
45
|
+
"commander": "^14.0.3",
|
|
46
|
+
"open": "^11.0.0",
|
|
47
|
+
"ora": "^9.4.0",
|
|
48
48
|
"viem": "^2.37.2"
|
|
49
49
|
}
|
|
50
50
|
}
|