@bankofai/x402-cli 1.0.0-beta.8 → 1.0.0-beta.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/cli.js +92 -47
- package/dist/x402.js +8 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -12,6 +12,8 @@ import { createPaymentPayload, decodeRequired, decodeResponse, decodeSignature,
|
|
|
12
12
|
import { assertRawAmount, findTokenByAddress, getToken, normalizeNetwork, toSmallestUnit } from "./tokens.js";
|
|
13
13
|
const BOOLEAN_FLAGS = new Set(["daemon", "dry-run", "force", "help", "human", "include-blocked", "json", "raw", "version"]);
|
|
14
14
|
const require = createRequire(import.meta.url);
|
|
15
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
16
|
+
const CATALOG_UPDATE_RETRIES = 3;
|
|
15
17
|
class CliError extends Error {
|
|
16
18
|
code;
|
|
17
19
|
hint;
|
|
@@ -263,7 +265,7 @@ function classify(error) {
|
|
|
263
265
|
hint: "Increase the max amount flag only if this provider price is expected.",
|
|
264
266
|
};
|
|
265
267
|
}
|
|
266
|
-
if (lower.includes("failed to fetch") || lower.includes("fetch failed") || lower.includes("econnrefused")) {
|
|
268
|
+
if (lower.includes("failed to fetch") || lower.includes("fetch failed") || lower.includes("econnrefused") || lower.includes("timed out")) {
|
|
267
269
|
return {
|
|
268
270
|
code: "NETWORK_ERROR",
|
|
269
271
|
message,
|
|
@@ -318,6 +320,7 @@ Options:
|
|
|
318
320
|
--dry-run Read requirements but do not sign or pay
|
|
319
321
|
--private-key <hex> Explicit payer private key (or PRIVATE_KEY/TRON_PRIVATE_KEY/EVM_PRIVATE_KEY)
|
|
320
322
|
--rpc-url <url> Explicit network RPC URL
|
|
323
|
+
--timeout-ms <ms> Network timeout in milliseconds (default: 30000)
|
|
321
324
|
--json Print JSON envelope
|
|
322
325
|
|
|
323
326
|
Examples:
|
|
@@ -339,6 +342,7 @@ Options:
|
|
|
339
342
|
--port <port> Bind port (default: 4020)
|
|
340
343
|
--resource-url <url> URL advertised in payment requirements
|
|
341
344
|
--facilitator-url <url> Facilitator base URL
|
|
345
|
+
--timeout-ms <ms> Facilitator timeout in milliseconds (default: 30000)
|
|
342
346
|
--daemon Run in background and print the child pid
|
|
343
347
|
--json Print JSON envelope
|
|
344
348
|
|
|
@@ -385,6 +389,7 @@ Options:
|
|
|
385
389
|
--provider <fqn> Provider FQN for export-gateway
|
|
386
390
|
--output-dir <dir> Output directory for generated files
|
|
387
391
|
-n, --limit <count> Search result limit
|
|
392
|
+
--timeout-ms <ms> Network timeout in milliseconds (default: 30000)
|
|
388
393
|
--include-blocked Include blocked providers in search
|
|
389
394
|
--json Print JSON envelope
|
|
390
395
|
`,
|
|
@@ -394,6 +399,7 @@ Options:
|
|
|
394
399
|
Options:
|
|
395
400
|
--catalog <source> catalog.json path or URL
|
|
396
401
|
-n, --limit <count> Search result limit
|
|
402
|
+
--timeout-ms <ms> Network timeout in milliseconds (default: 30000)
|
|
397
403
|
--include-blocked Include blocked providers in search
|
|
398
404
|
--json Print JSON envelope
|
|
399
405
|
`,
|
|
@@ -402,6 +408,7 @@ Options:
|
|
|
402
408
|
|
|
403
409
|
Options:
|
|
404
410
|
--catalog <source> catalog.json path or URL
|
|
411
|
+
--timeout-ms <ms> Network timeout in milliseconds (default: 30000)
|
|
405
412
|
--json Print JSON envelope
|
|
406
413
|
`,
|
|
407
414
|
"catalog-pay-json": `Usage:
|
|
@@ -409,6 +416,7 @@ Options:
|
|
|
409
416
|
|
|
410
417
|
Options:
|
|
411
418
|
--catalog <source> catalog.json path or URL
|
|
419
|
+
--timeout-ms <ms> Network timeout in milliseconds (default: 30000)
|
|
412
420
|
--raw Print raw pay payload instead of JSON envelope
|
|
413
421
|
--json Print JSON envelope
|
|
414
422
|
`,
|
|
@@ -417,6 +425,7 @@ Options:
|
|
|
417
425
|
|
|
418
426
|
Options:
|
|
419
427
|
--catalog <source> catalog.json path or URL
|
|
428
|
+
--timeout-ms <ms> Network timeout in milliseconds (default: 30000)
|
|
420
429
|
--json Print JSON envelope
|
|
421
430
|
`,
|
|
422
431
|
"catalog-export-gateway": `Usage:
|
|
@@ -607,8 +616,8 @@ function scoreFields(terms, fields) {
|
|
|
607
616
|
}
|
|
608
617
|
return { score, matchedFields };
|
|
609
618
|
}
|
|
610
|
-
async function readCatalog(source) {
|
|
611
|
-
const text = await readText(source);
|
|
619
|
+
async function readCatalog(source, options) {
|
|
620
|
+
const text = await readText(source, options);
|
|
612
621
|
const parsed = JSON.parse(text);
|
|
613
622
|
if (Array.isArray(parsed))
|
|
614
623
|
return parsed;
|
|
@@ -618,24 +627,24 @@ async function readCatalog(source) {
|
|
|
618
627
|
return parsed.items;
|
|
619
628
|
return [];
|
|
620
629
|
}
|
|
621
|
-
async function readCatalogObject(source) {
|
|
622
|
-
const parsed = JSON.parse(await readText(source));
|
|
630
|
+
async function readCatalogObject(source, options) {
|
|
631
|
+
const parsed = JSON.parse(await readText(source, options));
|
|
623
632
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
624
633
|
throw new Error(`expected JSON object from ${source}`);
|
|
625
634
|
}
|
|
626
635
|
return parsed;
|
|
627
636
|
}
|
|
628
|
-
async function readText(source) {
|
|
637
|
+
async function readText(source, options) {
|
|
629
638
|
if (!source.startsWith("http://") && !source.startsWith("https://")) {
|
|
630
639
|
return fs.readFileSync(source, "utf8");
|
|
631
640
|
}
|
|
632
|
-
const response = await
|
|
641
|
+
const response = await fetchWithTimeout(source, {}, timeoutMs(options), `fetch ${source}`);
|
|
633
642
|
if (!response.ok)
|
|
634
643
|
throw new Error(`failed to fetch ${source}: ${response.status}`);
|
|
635
644
|
return response.text();
|
|
636
645
|
}
|
|
637
|
-
async function readJson(source) {
|
|
638
|
-
return JSON.parse(await readText(source));
|
|
646
|
+
async function readJson(source, options) {
|
|
647
|
+
return JSON.parse(await readText(source, options));
|
|
639
648
|
}
|
|
640
649
|
function writeJson(file, value) {
|
|
641
650
|
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
@@ -713,11 +722,29 @@ function positiveIntegerOption(options, key, fallback) {
|
|
|
713
722
|
throw new CliError("INVALID_ARGUMENT", `--${key} must be a positive integer`, `Pass --${key} with a value greater than zero.`, 2);
|
|
714
723
|
return parsed;
|
|
715
724
|
}
|
|
725
|
+
function timeoutMs(options) {
|
|
726
|
+
return options ? positiveIntegerOption(options, "timeout-ms", DEFAULT_TIMEOUT_MS) : DEFAULT_TIMEOUT_MS;
|
|
727
|
+
}
|
|
728
|
+
async function fetchWithTimeout(input, init = {}, timeout = DEFAULT_TIMEOUT_MS, label = "request") {
|
|
729
|
+
const controller = new AbortController();
|
|
730
|
+
const timer = setTimeout(() => controller.abort(), timeout);
|
|
731
|
+
try {
|
|
732
|
+
return await fetch(input, { ...init, signal: controller.signal });
|
|
733
|
+
}
|
|
734
|
+
catch (error) {
|
|
735
|
+
if (error?.name === "AbortError")
|
|
736
|
+
throw new Error(`${label} timed out after ${timeout}ms`);
|
|
737
|
+
throw error;
|
|
738
|
+
}
|
|
739
|
+
finally {
|
|
740
|
+
clearTimeout(timer);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
716
743
|
function remoteBaseFromCatalogPayload(payload) {
|
|
717
744
|
const base = payload.base_url ?? payload.baseUrl;
|
|
718
745
|
return typeof base === "string" && /^https?:\/\//.test(base) ? `${base.replace(/\/+$/, "")}/` : undefined;
|
|
719
746
|
}
|
|
720
|
-
async function remoteBaseFromSource(source, payload) {
|
|
747
|
+
async function remoteBaseFromSource(source, payload, options) {
|
|
721
748
|
const fromPayload = payload ? remoteBaseFromCatalogPayload(payload) : undefined;
|
|
722
749
|
if (fromPayload)
|
|
723
750
|
return fromPayload;
|
|
@@ -725,7 +752,7 @@ async function remoteBaseFromSource(source, payload) {
|
|
|
725
752
|
return `${source.slice(0, source.lastIndexOf("/") + 1)}`;
|
|
726
753
|
}
|
|
727
754
|
try {
|
|
728
|
-
return remoteBaseFromCatalogPayload(await readCatalogObject(source));
|
|
755
|
+
return remoteBaseFromCatalogPayload(await readCatalogObject(source, options));
|
|
729
756
|
}
|
|
730
757
|
catch {
|
|
731
758
|
return undefined;
|
|
@@ -751,36 +778,37 @@ function catalogDetailSource(source, section, name) {
|
|
|
751
778
|
return direct;
|
|
752
779
|
return path.join(root, section, providerFilename(name));
|
|
753
780
|
}
|
|
754
|
-
async function readCatalogProvider(source, name) {
|
|
755
|
-
const providers = await readCatalog(source);
|
|
781
|
+
async function readCatalogProvider(source, name, options) {
|
|
782
|
+
const providers = await readCatalog(source, options);
|
|
756
783
|
const summary = providers.find((item) => item.name === name || item.fqn === name);
|
|
757
784
|
if (!summary)
|
|
758
785
|
throw new Error(`provider not found: ${name}`);
|
|
759
786
|
const fqn = summary.fqn ?? summary.name ?? name;
|
|
760
787
|
try {
|
|
761
|
-
return await readJson(catalogDetailSource(source, "providers", fqn));
|
|
788
|
+
return await readJson(catalogDetailSource(source, "providers", fqn), options);
|
|
762
789
|
}
|
|
763
790
|
catch {
|
|
764
791
|
return summary;
|
|
765
792
|
}
|
|
766
793
|
}
|
|
767
|
-
async function readCatalogPayProvider(source, name) {
|
|
768
|
-
const providers = await readCatalog(source);
|
|
794
|
+
async function readCatalogPayProvider(source, name, options) {
|
|
795
|
+
const providers = await readCatalog(source, options);
|
|
769
796
|
const summary = providers.find((item) => item.name === name || item.fqn === name);
|
|
770
797
|
const fqn = summary?.fqn ?? summary?.name ?? name;
|
|
771
798
|
try {
|
|
772
|
-
return await readJson(catalogDetailSource(source, "pay", fqn));
|
|
799
|
+
return await readJson(catalogDetailSource(source, "pay", fqn), options);
|
|
773
800
|
}
|
|
774
801
|
catch {
|
|
775
802
|
if (summary)
|
|
776
|
-
return readCatalogProvider(source, name);
|
|
803
|
+
return readCatalogProvider(source, name, options);
|
|
777
804
|
throw new Error(`provider not found: ${name}`);
|
|
778
805
|
}
|
|
779
806
|
}
|
|
780
|
-
async function cacheProviderAssets(source, catalogPayload) {
|
|
781
|
-
const base = await remoteBaseFromSource(source, catalogPayload);
|
|
807
|
+
async function cacheProviderAssets(source, catalogPayload, options) {
|
|
808
|
+
const base = await remoteBaseFromSource(source, catalogPayload, options);
|
|
809
|
+
const warnings = [];
|
|
782
810
|
if (!base)
|
|
783
|
-
return { detailCount: 0, payCount: 0 };
|
|
811
|
+
return { detailCount: 0, payCount: 0, warnings };
|
|
784
812
|
let detailCount = 0;
|
|
785
813
|
let payCount = 0;
|
|
786
814
|
for (const provider of catalogPayload.providers ?? []) {
|
|
@@ -789,34 +817,51 @@ async function cacheProviderAssets(source, catalogPayload) {
|
|
|
789
817
|
continue;
|
|
790
818
|
const filename = providerFilename(fqn);
|
|
791
819
|
try {
|
|
792
|
-
const detail = await readJson(new URL(`providers/${filename}`, base).toString());
|
|
820
|
+
const detail = await readJson(new URL(`providers/${filename}`, base).toString(), options);
|
|
793
821
|
writeJson(path.join(cacheDir(), "providers", filename), detail);
|
|
794
822
|
detailCount += 1;
|
|
795
823
|
}
|
|
796
|
-
catch {
|
|
797
|
-
|
|
824
|
+
catch (error) {
|
|
825
|
+
warnings.push(`failed to cache provider detail ${fqn}: ${error instanceof Error ? error.message : String(error)}`);
|
|
798
826
|
}
|
|
799
827
|
try {
|
|
800
|
-
const pay = await readJson(new URL(`pay/${filename}`, base).toString());
|
|
828
|
+
const pay = await readJson(new URL(`pay/${filename}`, base).toString(), options);
|
|
801
829
|
writeJson(path.join(cacheDir(), "pay", filename), pay);
|
|
802
830
|
payCount += 1;
|
|
803
831
|
}
|
|
804
|
-
catch {
|
|
805
|
-
|
|
832
|
+
catch (error) {
|
|
833
|
+
warnings.push(`failed to cache pay JSON ${fqn}: ${error instanceof Error ? error.message : String(error)}`);
|
|
806
834
|
}
|
|
807
835
|
}
|
|
808
|
-
return { detailCount, payCount };
|
|
836
|
+
return { detailCount, payCount, warnings };
|
|
809
837
|
}
|
|
810
838
|
async function catalogUpdate(source, options) {
|
|
811
|
-
|
|
839
|
+
let payload;
|
|
840
|
+
const warnings = [];
|
|
841
|
+
for (let attempt = 1; attempt <= CATALOG_UPDATE_RETRIES; attempt += 1) {
|
|
842
|
+
try {
|
|
843
|
+
payload = await readCatalogObject(source, options);
|
|
844
|
+
break;
|
|
845
|
+
}
|
|
846
|
+
catch (error) {
|
|
847
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
848
|
+
if (attempt === CATALOG_UPDATE_RETRIES)
|
|
849
|
+
throw error;
|
|
850
|
+
warnings.push(`catalog update attempt ${attempt} failed: ${message}`);
|
|
851
|
+
await delay(250 * attempt);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
if (!payload)
|
|
855
|
+
throw new Error(`failed to read catalog from ${source}`);
|
|
812
856
|
writeJson(cachedCatalogPath(), payload);
|
|
813
|
-
const cached = await cacheProviderAssets(source, payload);
|
|
857
|
+
const cached = await cacheProviderAssets(source, payload, options);
|
|
814
858
|
const result = {
|
|
815
859
|
source,
|
|
816
860
|
path: cachedCatalogPath(),
|
|
817
861
|
providerCount: payload.provider_count ?? payload.providerCount ?? (payload.providers ?? []).length,
|
|
818
862
|
detailCount: cached.detailCount,
|
|
819
863
|
payCount: cached.payCount,
|
|
864
|
+
warnings: [...warnings, ...cached.warnings],
|
|
820
865
|
};
|
|
821
866
|
emit({ command: "catalog update", mode: outputMode(options), result });
|
|
822
867
|
}
|
|
@@ -903,7 +948,7 @@ async function catalogExportGateway(gatewayUrl, options) {
|
|
|
903
948
|
const providerFqn = requireArgument(opt(options, "provider"), "--provider", "x402-cli catalog export-gateway <gateway-url> --provider <fqn> [options]");
|
|
904
949
|
sanitizeProviderName(providerFqn);
|
|
905
950
|
const base = gatewayUrl.replace(/\/+$/, "");
|
|
906
|
-
const detail = await readJson(`${base}/__402/catalog/providers/${providerFilename(providerFqn)}
|
|
951
|
+
const detail = await readJson(`${base}/__402/catalog/providers/${providerFilename(providerFqn)}`, options);
|
|
907
952
|
const outputRoot = opt(options, "output-dir", "providers");
|
|
908
953
|
const target = opt(options, "output-dir")
|
|
909
954
|
? path.resolve(outputRoot)
|
|
@@ -950,12 +995,12 @@ function buildRequirement(options) {
|
|
|
950
995
|
extra: assetTransferMethod ? { assetTransferMethod } : {},
|
|
951
996
|
};
|
|
952
997
|
}
|
|
953
|
-
async function facilitatorPost(baseUrl, path, body) {
|
|
954
|
-
const response = await
|
|
998
|
+
async function facilitatorPost(baseUrl, path, body, options) {
|
|
999
|
+
const response = await fetchWithTimeout(new URL(path, baseUrl), {
|
|
955
1000
|
method: "POST",
|
|
956
1001
|
headers: { "content-type": "application/json" },
|
|
957
1002
|
body: JSON.stringify(body),
|
|
958
|
-
});
|
|
1003
|
+
}, timeoutMs(options), `facilitator ${path}`);
|
|
959
1004
|
const text = await response.text();
|
|
960
1005
|
const data = text ? JSON.parse(text) : {};
|
|
961
1006
|
if (!response.ok)
|
|
@@ -1075,7 +1120,7 @@ async function serve(options) {
|
|
|
1075
1120
|
const verify = await facilitatorPost(facilitatorUrl, "/verify", {
|
|
1076
1121
|
paymentPayload: payload,
|
|
1077
1122
|
paymentRequirements: requirement,
|
|
1078
|
-
});
|
|
1123
|
+
}, options);
|
|
1079
1124
|
if (!(verify?.valid === true || verify?.isValid === true)) {
|
|
1080
1125
|
response.writeHead(400, { "content-type": "application/json" });
|
|
1081
1126
|
response.end(JSON.stringify({ error: "payment verification failed" }));
|
|
@@ -1084,7 +1129,7 @@ async function serve(options) {
|
|
|
1084
1129
|
const settle = await facilitatorPost(facilitatorUrl, "/settle", {
|
|
1085
1130
|
paymentPayload: payload,
|
|
1086
1131
|
paymentRequirements: requirement,
|
|
1087
|
-
});
|
|
1132
|
+
}, options);
|
|
1088
1133
|
if (!(settle?.success === true || settle?.settled === true || typeof settle?.transaction === "string" || typeof settle?.txHash === "string")) {
|
|
1089
1134
|
response.writeHead(502, { "content-type": "application/json" });
|
|
1090
1135
|
response.end(JSON.stringify({ error: "settlement failed" }));
|
|
@@ -1140,11 +1185,11 @@ async function pay(url, options) {
|
|
|
1140
1185
|
requireArgument(url, "URL", "x402-cli pay <url> [options]");
|
|
1141
1186
|
const method = opt(options, "method", "GET");
|
|
1142
1187
|
const baseHeaders = requestHeaders(options);
|
|
1143
|
-
const probe = await
|
|
1188
|
+
const probe = await fetchWithTimeout(url, {
|
|
1144
1189
|
method,
|
|
1145
1190
|
headers: baseHeaders,
|
|
1146
1191
|
body: ["GET", "HEAD"].includes(method.toUpperCase()) ? undefined : opt(options, "body"),
|
|
1147
|
-
});
|
|
1192
|
+
}, timeoutMs(options), `fetch ${url}`);
|
|
1148
1193
|
if (probe.status !== 402) {
|
|
1149
1194
|
emit({
|
|
1150
1195
|
command: "client",
|
|
@@ -1188,11 +1233,11 @@ async function pay(url, options) {
|
|
|
1188
1233
|
}));
|
|
1189
1234
|
const retryHeaders = new Headers(baseHeaders);
|
|
1190
1235
|
retryHeaders.set(headers.signature, encodeSignature(payload));
|
|
1191
|
-
const paid = await
|
|
1236
|
+
const paid = await fetchWithTimeout(url, {
|
|
1192
1237
|
method,
|
|
1193
1238
|
headers: retryHeaders,
|
|
1194
1239
|
body: ["GET", "HEAD"].includes(method.toUpperCase()) ? undefined : opt(options, "body"),
|
|
1195
|
-
});
|
|
1240
|
+
}, timeoutMs(options), `fetch ${url}`);
|
|
1196
1241
|
const body = await responsePayload(paid);
|
|
1197
1242
|
const paymentResponse = paid.headers.get(headers.response);
|
|
1198
1243
|
const result = {
|
|
@@ -1372,16 +1417,16 @@ function catalogPayAssets(target, options) {
|
|
|
1372
1417
|
result: { count: rows.length, assets: rows },
|
|
1373
1418
|
});
|
|
1374
1419
|
}
|
|
1375
|
-
async function readProviderDetailForSearch(source, fqn) {
|
|
1420
|
+
async function readProviderDetailForSearch(source, fqn, options) {
|
|
1376
1421
|
try {
|
|
1377
|
-
return await readJson(catalogDetailSource(source, "providers", fqn));
|
|
1422
|
+
return await readJson(catalogDetailSource(source, "providers", fqn), options);
|
|
1378
1423
|
}
|
|
1379
1424
|
catch {
|
|
1380
1425
|
return {};
|
|
1381
1426
|
}
|
|
1382
1427
|
}
|
|
1383
1428
|
async function searchCatalog(source, query, options) {
|
|
1384
|
-
const providers = await readCatalog(source);
|
|
1429
|
+
const providers = await readCatalog(source, options);
|
|
1385
1430
|
const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
1386
1431
|
if (!terms.length)
|
|
1387
1432
|
return [];
|
|
@@ -1393,7 +1438,7 @@ async function searchCatalog(source, query, options) {
|
|
|
1393
1438
|
const fqn = String(provider.fqn ?? provider.name ?? "");
|
|
1394
1439
|
if (!fqn)
|
|
1395
1440
|
continue;
|
|
1396
|
-
const detail = await readProviderDetailForSearch(source, fqn);
|
|
1441
|
+
const detail = await readProviderDetailForSearch(source, fqn, options);
|
|
1397
1442
|
const tags = stringList(detail.featured_tags ?? provider.featured_tags ?? detail.tags ?? provider.tags);
|
|
1398
1443
|
const endpoints = Array.isArray(detail.endpoints) ? detail.endpoints : Array.isArray(provider.endpoints) ? provider.endpoints : [];
|
|
1399
1444
|
const categoryMeta = detail.category_meta ?? provider.category_meta;
|
|
@@ -1504,7 +1549,7 @@ async function catalogSearch(source, query, options) {
|
|
|
1504
1549
|
}
|
|
1505
1550
|
async function catalogShow(source, name, options) {
|
|
1506
1551
|
requireArgument(name, "provider", "x402-cli catalog show <provider> [--catalog <source>]");
|
|
1507
|
-
const provider = await readCatalogProvider(source, name);
|
|
1552
|
+
const provider = await readCatalogProvider(source, name, options);
|
|
1508
1553
|
if (outputMode(options) === "json") {
|
|
1509
1554
|
emit({ command: "catalog show", mode: "json", result: provider });
|
|
1510
1555
|
return;
|
|
@@ -1519,7 +1564,7 @@ async function catalogShow(source, name, options) {
|
|
|
1519
1564
|
}
|
|
1520
1565
|
async function catalogEndpoints(source, name, options) {
|
|
1521
1566
|
requireArgument(name, "provider", "x402-cli catalog endpoints <provider> [--catalog <source>]");
|
|
1522
|
-
const provider = await readCatalogProvider(source, name);
|
|
1567
|
+
const provider = await readCatalogProvider(source, name, options);
|
|
1523
1568
|
const endpoints = provider.endpoints ?? [];
|
|
1524
1569
|
if (outputMode(options) === "json") {
|
|
1525
1570
|
emit({ command: "catalog endpoints", mode: "json", result: { provider: provider.fqn ?? provider.name, endpoints } });
|
|
@@ -1533,7 +1578,7 @@ async function catalogEndpoints(source, name, options) {
|
|
|
1533
1578
|
}
|
|
1534
1579
|
async function catalogPayJson(source, name, options) {
|
|
1535
1580
|
requireArgument(name, "provider", "x402-cli catalog pay-json <provider> [--catalog <source>]");
|
|
1536
|
-
const provider = await readCatalogPayProvider(source, name);
|
|
1581
|
+
const provider = await readCatalogPayProvider(source, name, options);
|
|
1537
1582
|
const endpoint = (provider.endpoints ?? []).find((item) => item.paid || item.x402_routes?.length || item.x402Routes?.length) ?? provider.endpoints?.[0];
|
|
1538
1583
|
if (!endpoint)
|
|
1539
1584
|
throw new Error(`provider has no endpoints: ${name}`);
|
package/dist/x402.js
CHANGED
|
@@ -112,7 +112,7 @@ async function createTronWallet(privateKey) {
|
|
|
112
112
|
return {
|
|
113
113
|
getAddress: () => address,
|
|
114
114
|
async signTypedData(args) {
|
|
115
|
-
const signature = await tronWeb
|
|
115
|
+
const signature = await signTronTypedData(tronWeb, args, rawKey);
|
|
116
116
|
return signature.startsWith("0x") ? signature : `0x${signature}`;
|
|
117
117
|
},
|
|
118
118
|
async signTransaction(tx) {
|
|
@@ -120,6 +120,13 @@ async function createTronWallet(privateKey) {
|
|
|
120
120
|
},
|
|
121
121
|
};
|
|
122
122
|
}
|
|
123
|
+
export async function signTronTypedData(tronWeb, args, rawPrivateKey) {
|
|
124
|
+
const trx = tronWeb.trx;
|
|
125
|
+
const signer = typeof trx.signTypedData === "function" ? trx.signTypedData.bind(trx) : trx._signTypedData?.bind(trx);
|
|
126
|
+
if (!signer)
|
|
127
|
+
throw new Error("tronweb typed-data signing is not available");
|
|
128
|
+
return signer(args.domain, args.types, args.message, rawPrivateKey);
|
|
129
|
+
}
|
|
123
130
|
export async function createPaymentPayload(args) {
|
|
124
131
|
const selected = ensurePermit2(args.selected);
|
|
125
132
|
const required = paymentRequired(selected, args.resource, args.extensions);
|