@bankr/cli 0.2.8 → 0.2.9
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/dist/commands/x402.js +40 -7
- package/dist/lib/output.js +7 -0
- package/package.json +1 -1
package/dist/commands/x402.js
CHANGED
|
@@ -925,23 +925,44 @@ async function fetchSchemaForInteractive(url) {
|
|
|
925
925
|
// Fall through to next strategy
|
|
926
926
|
}
|
|
927
927
|
}
|
|
928
|
-
// Strategy 3: Probe endpoint for 402 response to get price info
|
|
928
|
+
// Strategy 3: Probe endpoint for 402 response to get price info.
|
|
929
|
+
// Checks header first (Bankr endpoints), then falls back to response
|
|
930
|
+
// body (Coinbase x402 standard used by external endpoints).
|
|
929
931
|
try {
|
|
930
932
|
const probeRes = await fetch(url, { method: "GET" });
|
|
931
933
|
if (probeRes.status === 402) {
|
|
932
934
|
const paymentHeader = probeRes.headers.get("payment-required") ??
|
|
933
935
|
probeRes.headers.get("x-payment-required");
|
|
936
|
+
let accept = null;
|
|
934
937
|
if (paymentHeader) {
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
938
|
+
try {
|
|
939
|
+
const decoded = Buffer.from(paymentHeader, "base64").toString("utf-8");
|
|
940
|
+
const requirements = JSON.parse(decoded);
|
|
941
|
+
accept = requirements.accepts?.[0] ?? requirements;
|
|
942
|
+
}
|
|
943
|
+
catch {
|
|
944
|
+
// Header parse failed, try body
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
if (!accept) {
|
|
948
|
+
try {
|
|
949
|
+
const bodyText = await probeRes.text();
|
|
950
|
+
const bodyJson = JSON.parse(bodyText);
|
|
951
|
+
accept = bodyJson.accepts?.[0] ?? null;
|
|
952
|
+
}
|
|
953
|
+
catch {
|
|
954
|
+
// Body parse failed too
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
const acceptAmount = accept?.maxAmountRequired ?? accept?.amount;
|
|
958
|
+
if (acceptAmount) {
|
|
959
|
+
const amountAtomic = BigInt(acceptAmount);
|
|
939
960
|
const amountUsd = Number(amountAtomic) / 1000000;
|
|
940
961
|
// Extract service name from URL path
|
|
941
962
|
const serviceName = parts[parts.length - 1] ?? "endpoint";
|
|
942
963
|
return {
|
|
943
964
|
name: serviceName,
|
|
944
|
-
description: "",
|
|
965
|
+
description: accept?.description ?? "",
|
|
945
966
|
methods: ["GET"],
|
|
946
967
|
price: amountUsd.toFixed(6),
|
|
947
968
|
currency: "USDC",
|
|
@@ -1101,10 +1122,22 @@ export async function x402CallCommand(url, opts = {}) {
|
|
|
1101
1122
|
}
|
|
1102
1123
|
console.log();
|
|
1103
1124
|
}
|
|
1125
|
+
// Non-interactive: probe the endpoint to show the actual price before confirming
|
|
1126
|
+
if (!opts.interactive && !opts.yes && resolvedPrice === null) {
|
|
1127
|
+
const spin = output.spinner("Checking endpoint price...");
|
|
1128
|
+
const schema = await fetchSchemaForInteractive(url);
|
|
1129
|
+
spin.stop();
|
|
1130
|
+
if (schema) {
|
|
1131
|
+
resolvedPrice = parseFloat(schema.price);
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1104
1134
|
// Confirm payment unless --yes
|
|
1105
1135
|
if (!opts.yes && !opts.interactive) {
|
|
1136
|
+
const priceDisplay = resolvedPrice !== null
|
|
1137
|
+
? chalk.green(`$${resolvedPrice} USDC`)
|
|
1138
|
+
: chalk.green(`up to $${maxPaymentUsd} USDC`);
|
|
1106
1139
|
const confirmed = await confirm({
|
|
1107
|
-
message: `Call ${chalk.bold(url)} with
|
|
1140
|
+
message: `Call ${chalk.bold(url)} with ${priceDisplay} payment?`,
|
|
1108
1141
|
default: true,
|
|
1109
1142
|
});
|
|
1110
1143
|
if (!confirmed) {
|
package/dist/lib/output.js
CHANGED
|
@@ -61,6 +61,13 @@ export function spinner(text) {
|
|
|
61
61
|
export function maskApiKey(key) {
|
|
62
62
|
if (key.length <= 8)
|
|
63
63
|
return "****";
|
|
64
|
+
// New prefixed keys: bk_usr_{keyId}_{secret} → bk_usr_{keyId}_*****
|
|
65
|
+
const parts = key.split("_");
|
|
66
|
+
if (parts.length === 4 &&
|
|
67
|
+
parts[0] === "bk" &&
|
|
68
|
+
(parts[1] === "usr" || parts[1] === "ptr")) {
|
|
69
|
+
return `${parts[0]}_${parts[1]}_${parts[2]}_*****`;
|
|
70
|
+
}
|
|
64
71
|
return key.slice(0, 6) + "..." + key.slice(-4);
|
|
65
72
|
}
|
|
66
73
|
export function formatDuration(ms) {
|