@devlab.group/agent-commerce 0.1.0-alpha.0 → 0.2.0-beta.0
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 +41 -22
- package/dist/{chunk-CZ6ZDAYD.js → chunk-ASK67X56.js} +9 -7
- package/dist/chunk-ASK67X56.js.map +1 -0
- package/dist/chunk-MQMKQGAB.js +199 -0
- package/dist/chunk-MQMKQGAB.js.map +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +253 -49
- package/dist/cli/index.js.map +1 -1
- package/dist/guardrails-Di_yI_DW.d.ts +25 -0
- package/dist/index.d.ts +36 -18
- package/dist/index.js +74 -33
- package/dist/index.js.map +1 -1
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +2 -2
- package/dist/mcp.js.map +1 -1
- package/dist/{protocol-adapter-C0goMgLK.d.ts → protocol-adapter-CtB0sOnV.d.ts} +2 -3
- package/dist/{runtime-LCk2TzGN.d.ts → runtime-Bie-9FAM.d.ts} +15 -3
- package/dist/x402.d.ts +69 -17
- package/dist/x402.js +265 -216
- package/dist/x402.js.map +1 -1
- package/package.json +13 -7
- package/dist/chunk-CZ6ZDAYD.js.map +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -267,6 +267,54 @@ var init_core = __esm({
|
|
|
267
267
|
}
|
|
268
268
|
});
|
|
269
269
|
|
|
270
|
+
// src/payments/x402/networks.ts
|
|
271
|
+
function findNetworkProfile(id) {
|
|
272
|
+
return BY_ID.get(id);
|
|
273
|
+
}
|
|
274
|
+
function requireNetworkProfile(id, path2) {
|
|
275
|
+
const profile = BY_ID.get(id);
|
|
276
|
+
if (!profile) {
|
|
277
|
+
throw new CommerceError(
|
|
278
|
+
"CONFIG_INVALID",
|
|
279
|
+
`${path2}: "${id}" is not a supported network. Supported CAIP-2 identifiers: ${SUPPORTED_NETWORK_IDS.join(", ")}`,
|
|
280
|
+
{ details: { path: path2, network: id } }
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
return profile;
|
|
284
|
+
}
|
|
285
|
+
function resolveDeploymentMode(profile, facilitatorMode) {
|
|
286
|
+
if (facilitatorMode === "local") return "local";
|
|
287
|
+
return profile.kind;
|
|
288
|
+
}
|
|
289
|
+
function describeDeploymentMode(mode) {
|
|
290
|
+
return mode === "mainnet" ? LIVE_MAINNET_BANNER : mode.toUpperCase();
|
|
291
|
+
}
|
|
292
|
+
var PROFILES, BY_ID, SUPPORTED_NETWORK_IDS, LIVE_MAINNET_BANNER;
|
|
293
|
+
var init_networks = __esm({
|
|
294
|
+
"src/payments/x402/networks.ts"() {
|
|
295
|
+
init_core();
|
|
296
|
+
PROFILES = [
|
|
297
|
+
{
|
|
298
|
+
id: "eip155:84532",
|
|
299
|
+
chainId: 84532,
|
|
300
|
+
displayName: "Base Sepolia",
|
|
301
|
+
kind: "testnet",
|
|
302
|
+
canonicalAsset: { symbol: "USDC", address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e" }
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
id: "eip155:8453",
|
|
306
|
+
chainId: 8453,
|
|
307
|
+
displayName: "Base",
|
|
308
|
+
kind: "mainnet",
|
|
309
|
+
canonicalAsset: { symbol: "USDC", address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" }
|
|
310
|
+
}
|
|
311
|
+
];
|
|
312
|
+
BY_ID = new Map(PROFILES.map((profile) => [profile.id, profile]));
|
|
313
|
+
SUPPORTED_NETWORK_IDS = PROFILES.map((p) => p.id);
|
|
314
|
+
LIVE_MAINNET_BANNER = "LIVE MAINNET MODE \u2014 REAL FUNDS";
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
|
|
270
318
|
// src/config/env.ts
|
|
271
319
|
function substituteEnv(value, env, path2 = "$") {
|
|
272
320
|
if (typeof value === "string") {
|
|
@@ -329,6 +377,142 @@ var init_env = __esm({
|
|
|
329
377
|
PLACEHOLDER_PATTERN = /\$\{([A-Za-z_][A-Za-z0-9_]*)(:-([^}]*))?\}/g;
|
|
330
378
|
}
|
|
331
379
|
});
|
|
380
|
+
|
|
381
|
+
// src/payments/x402/local-chain/accounts.ts
|
|
382
|
+
var ANVIL_WELL_KNOWN_ACCOUNTS;
|
|
383
|
+
var init_accounts = __esm({
|
|
384
|
+
"src/payments/x402/local-chain/accounts.ts"() {
|
|
385
|
+
ANVIL_WELL_KNOWN_ACCOUNTS = [
|
|
386
|
+
{
|
|
387
|
+
address: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
|
|
388
|
+
privateKey: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
address: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
|
|
392
|
+
privateKey: "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
address: "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
|
|
396
|
+
privateKey: "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a"
|
|
397
|
+
}
|
|
398
|
+
];
|
|
399
|
+
ANVIL_WELL_KNOWN_ACCOUNTS[0];
|
|
400
|
+
ANVIL_WELL_KNOWN_ACCOUNTS[1];
|
|
401
|
+
ANVIL_WELL_KNOWN_ACCOUNTS[2];
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
// src/payments/x402/dev-key-guard.ts
|
|
406
|
+
function isWellKnownDevAddress(address) {
|
|
407
|
+
return WELL_KNOWN_DEV_ADDRESSES.has(address.toLowerCase());
|
|
408
|
+
}
|
|
409
|
+
function isLikelyLocalOrPrivateHost(hostname) {
|
|
410
|
+
const h = hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
411
|
+
if (h === "localhost" || h === "127.0.0.1" || h === "::1") return true;
|
|
412
|
+
if (/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(h)) return true;
|
|
413
|
+
if (/^10\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(h)) return true;
|
|
414
|
+
if (/^192\.168\.\d{1,3}\.\d{1,3}$/.test(h)) return true;
|
|
415
|
+
if (/^172\.(1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}$/.test(h)) return true;
|
|
416
|
+
if (!h.includes(".") && !h.includes(":")) return true;
|
|
417
|
+
return false;
|
|
418
|
+
}
|
|
419
|
+
var WELL_KNOWN_DEV_ADDRESSES;
|
|
420
|
+
var init_dev_key_guard = __esm({
|
|
421
|
+
"src/payments/x402/dev-key-guard.ts"() {
|
|
422
|
+
init_core();
|
|
423
|
+
init_accounts();
|
|
424
|
+
new Set(
|
|
425
|
+
ANVIL_WELL_KNOWN_ACCOUNTS.map((a) => a.privateKey.toLowerCase())
|
|
426
|
+
);
|
|
427
|
+
WELL_KNOWN_DEV_ADDRESSES = new Set(
|
|
428
|
+
ANVIL_WELL_KNOWN_ACCOUNTS.map((a) => a.address.toLowerCase())
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
// src/payments/x402/guardrails.ts
|
|
434
|
+
function invalid(message, path2) {
|
|
435
|
+
return new CommerceError("CONFIG_INVALID", message, { details: { path: path2 } });
|
|
436
|
+
}
|
|
437
|
+
function resolveX402Deployment(input) {
|
|
438
|
+
const profile = requireNetworkProfile(input.network, "payments.x402.network");
|
|
439
|
+
const mode = resolveDeploymentMode(profile, input.facilitator.mode);
|
|
440
|
+
if (profile.kind === "mainnet" && input.facilitator.mode === "local") {
|
|
441
|
+
throw invalid(
|
|
442
|
+
`payments.x402: network "${profile.id}" (${profile.displayName}) is a mainnet and cannot be served by facilitator.mode "local". A mainnet deployment must settle through a remote facilitator.`,
|
|
443
|
+
"payments.x402.facilitator.mode"
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
if (mode === "mainnet" && input.allowMainnet !== true) {
|
|
447
|
+
throw invalid(
|
|
448
|
+
`payments.x402: network "${profile.id}" (${profile.displayName}) settles real funds. Set payments.x402.allowMainnet: true to acknowledge this explicitly \u2014 it is never the default.`,
|
|
449
|
+
"payments.x402.allowMainnet"
|
|
450
|
+
);
|
|
451
|
+
}
|
|
452
|
+
if (input.facilitator.mode === "remote") {
|
|
453
|
+
assertFacilitatorUrlIsSafe(input.facilitator.url, mode);
|
|
454
|
+
if (mode === "mainnet" && input.facilitator.auth.type === "none") {
|
|
455
|
+
throw invalid(
|
|
456
|
+
"payments.x402: a mainnet facilitator must be authenticated. Set payments.x402.facilitator.auth to a supported type \u2014 an unauthenticated production facilitator is refused.",
|
|
457
|
+
"payments.x402.facilitator.auth"
|
|
458
|
+
);
|
|
459
|
+
}
|
|
460
|
+
if (input.facilitator.auth.type === "bearer" && input.facilitator.auth.token.trim() === "") {
|
|
461
|
+
throw invalid(
|
|
462
|
+
'payments.x402: facilitator.auth.type is "bearer" but the token is empty. An empty credential is refused rather than sent.',
|
|
463
|
+
"payments.x402.facilitator.auth.token"
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
if (mode !== "local" && isWellKnownDevAddress(input.payTo)) {
|
|
468
|
+
throw invalid(
|
|
469
|
+
`payments.x402: "payTo" (${input.payTo}) is a well-known Anvil development address and this is a ${mode} deployment. Anyone can spend what settles there. Set payTo to your own merchant wallet.`,
|
|
470
|
+
"payments.x402.payTo"
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
const canonical = profile.canonicalAsset;
|
|
474
|
+
if (mode === "mainnet" && canonical && !sameAddress(input.asset, canonical.address)) {
|
|
475
|
+
throw invalid(
|
|
476
|
+
`payments.x402: asset ${input.asset} is not ${canonical.symbol} on ${profile.displayName} (expected ${canonical.address}). Settling a mainnet payment in an unintended token is refused.`,
|
|
477
|
+
"payments.x402.asset"
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
return { profile, mode };
|
|
481
|
+
}
|
|
482
|
+
function assertFacilitatorUrlIsSafe(url, mode) {
|
|
483
|
+
let parsed;
|
|
484
|
+
try {
|
|
485
|
+
parsed = new URL(url);
|
|
486
|
+
} catch (cause) {
|
|
487
|
+
throw new CommerceError(
|
|
488
|
+
"CONFIG_INVALID",
|
|
489
|
+
`payments.x402: facilitator.url "${url}" is not a valid URL`,
|
|
490
|
+
{ cause, details: { path: "payments.x402.facilitator.url" } }
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
if (parsed.protocol === "https:") return;
|
|
494
|
+
if (parsed.protocol !== "http:") {
|
|
495
|
+
throw invalid(
|
|
496
|
+
`payments.x402: facilitator.url must be https (or http on a local/private host); got "${parsed.protocol}//"`,
|
|
497
|
+
"payments.x402.facilitator.url"
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
if (mode !== "mainnet" && isLikelyLocalOrPrivateHost(parsed.hostname)) return;
|
|
501
|
+
throw invalid(
|
|
502
|
+
`payments.x402: facilitator.url "${url}" uses plain HTTP. Payment authorisations and settlement results would travel unencrypted. Use https, or point at a local/private host on a non-mainnet deployment.`,
|
|
503
|
+
"payments.x402.facilitator.url"
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
function sameAddress(a, b) {
|
|
507
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
508
|
+
}
|
|
509
|
+
var init_guardrails = __esm({
|
|
510
|
+
"src/payments/x402/guardrails.ts"() {
|
|
511
|
+
init_core();
|
|
512
|
+
init_dev_key_guard();
|
|
513
|
+
init_networks();
|
|
514
|
+
}
|
|
515
|
+
});
|
|
332
516
|
function parseConfig(raw, env) {
|
|
333
517
|
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
334
518
|
throw new CommerceError(
|
|
@@ -435,14 +619,12 @@ function normalise(raw) {
|
|
|
435
619
|
}
|
|
436
620
|
};
|
|
437
621
|
const x402Raw = raw.payments.x402;
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
}
|
|
445
|
-
const x402 = x402Raw ? {
|
|
622
|
+
const facilitator = x402Raw === void 0 ? void 0 : x402Raw.facilitator.mode === "local" ? { mode: "local", signerPrivateKey: x402Raw.facilitator.signerPrivateKey } : {
|
|
623
|
+
mode: "remote",
|
|
624
|
+
url: x402Raw.facilitator.url,
|
|
625
|
+
auth: x402Raw.facilitator.auth ?? { type: "none" }
|
|
626
|
+
};
|
|
627
|
+
const x402 = x402Raw && facilitator ? {
|
|
446
628
|
enabled: toBoolean(x402Raw.enabled, "payments.x402.enabled"),
|
|
447
629
|
network: x402Raw.network,
|
|
448
630
|
rpcUrl: x402Raw.rpcUrl,
|
|
@@ -454,18 +636,26 @@ function normalise(raw) {
|
|
|
454
636
|
max: 36
|
|
455
637
|
}),
|
|
456
638
|
payTo: x402Raw.payTo,
|
|
457
|
-
maxTimeoutSeconds: toNumber(
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
639
|
+
maxTimeoutSeconds: toNumber(
|
|
640
|
+
x402Raw.maxTimeoutSeconds,
|
|
641
|
+
"payments.x402.maxTimeoutSeconds",
|
|
642
|
+
{
|
|
643
|
+
min: 1
|
|
644
|
+
}
|
|
645
|
+
),
|
|
646
|
+
facilitator,
|
|
647
|
+
...x402Raw.allowMainnet !== void 0 ? { allowMainnet: toBoolean(x402Raw.allowMainnet, "payments.x402.allowMainnet") } : {}
|
|
465
648
|
} : void 0;
|
|
466
649
|
if (x402) {
|
|
467
650
|
validateAddress("payments.x402.payTo", x402.payTo);
|
|
468
651
|
validateAddress("payments.x402.asset", x402.asset);
|
|
652
|
+
resolveX402Deployment({
|
|
653
|
+
network: x402.network,
|
|
654
|
+
payTo: x402.payTo,
|
|
655
|
+
asset: x402.asset,
|
|
656
|
+
facilitator: x402.facilitator,
|
|
657
|
+
...x402.allowMainnet !== void 0 ? { allowMainnet: x402.allowMainnet } : {}
|
|
658
|
+
});
|
|
469
659
|
}
|
|
470
660
|
const resources = Object.entries(raw.resources).map(
|
|
471
661
|
([id, entry]) => normaliseResource(id, entry, protocols, x402)
|
|
@@ -510,7 +700,7 @@ function normaliseResource(id, entry, protocols, x402) {
|
|
|
510
700
|
}
|
|
511
701
|
for (const protocol of entry.expose) {
|
|
512
702
|
if (!SUPPORTED_PROTOCOLS.has(protocol)) {
|
|
513
|
-
const hint = protocol === "ucp" ? " (UCP is planned, not supported in
|
|
703
|
+
const hint = protocol === "ucp" ? " (UCP is planned, not supported in this release)" : "";
|
|
514
704
|
throw new CommerceError(
|
|
515
705
|
"CONFIG_INVALID",
|
|
516
706
|
`Resource "${id}" exposes unsupported protocol "${protocol}"${hint}. Supported: http, mcp.`,
|
|
@@ -546,7 +736,7 @@ function normaliseResource(id, entry, protocols, x402) {
|
|
|
546
736
|
if (entry.pricing.type === "dynamic") {
|
|
547
737
|
throw new CommerceError(
|
|
548
738
|
"CONFIG_INVALID",
|
|
549
|
-
`Resource "${id}" uses pricing.type "dynamic", which is not supported in
|
|
739
|
+
`Resource "${id}" uses pricing.type "dynamic", which is not supported in this release`,
|
|
550
740
|
{ details: { path: `resources.${id}.pricing.type`, resourceId: id } }
|
|
551
741
|
);
|
|
552
742
|
}
|
|
@@ -778,11 +968,12 @@ function validateAddress(path2, value) {
|
|
|
778
968
|
);
|
|
779
969
|
}
|
|
780
970
|
}
|
|
781
|
-
var SUPPORTED_CONFIG_VERSION, ADDRESS_PATTERN, ZERO_ADDRESS_PATTERN, MCP_TOOL_NAME_PATTERN, NumberOrString, BooleanOrString, MerchantSchema, ServerSchema, StorageSchema, ProtocolsSchema, BackendMethodSchema, BackendHandlerSchema, PricingSchema, JsonSchemaValueSchema, ResourceEntrySchema, ResourcesMapSchema, FacilitatorSchema, X402Schema, PaymentsSchema, RawConfigSchema, SUPPORTED_PROTOCOLS, SUPPORTED_PAYMENT_METHODS, EMPTY_CLOSED_OBJECT_SCHEMA, UNSUPPORTED_SCHEMA_KEYWORDS, PRICING_AMOUNT_PATTERN, ZERO_AMOUNT_PATTERN;
|
|
971
|
+
var SUPPORTED_CONFIG_VERSION, ADDRESS_PATTERN, ZERO_ADDRESS_PATTERN, MCP_TOOL_NAME_PATTERN, NumberOrString, BooleanOrString, MerchantSchema, ServerSchema, StorageSchema, ProtocolsSchema, BackendMethodSchema, BackendHandlerSchema, PricingSchema, JsonSchemaValueSchema, ResourceEntrySchema, ResourcesMapSchema, FacilitatorAuthSchema, FacilitatorSchema, X402Schema, PaymentsSchema, RawConfigSchema, SUPPORTED_PROTOCOLS, SUPPORTED_PAYMENT_METHODS, EMPTY_CLOSED_OBJECT_SCHEMA, UNSUPPORTED_SCHEMA_KEYWORDS, PRICING_AMOUNT_PATTERN, ZERO_AMOUNT_PATTERN;
|
|
782
972
|
var init_schema = __esm({
|
|
783
973
|
"src/config/schema.ts"() {
|
|
784
974
|
init_execution();
|
|
785
975
|
init_core();
|
|
976
|
+
init_guardrails();
|
|
786
977
|
init_env();
|
|
787
978
|
SUPPORTED_CONFIG_VERSION = 1;
|
|
788
979
|
ADDRESS_PATTERN = /^0x[0-9a-fA-F]{40}$/;
|
|
@@ -859,6 +1050,10 @@ var init_schema = __esm({
|
|
|
859
1050
|
payments: z.array(z.string().min(1)).optional()
|
|
860
1051
|
}).strict();
|
|
861
1052
|
ResourcesMapSchema = z.record(z.string().min(1), ResourceEntrySchema);
|
|
1053
|
+
FacilitatorAuthSchema = z.discriminatedUnion("type", [
|
|
1054
|
+
z.object({ type: z.literal("none") }).strict(),
|
|
1055
|
+
z.object({ type: z.literal("bearer"), token: z.string().min(1) }).strict()
|
|
1056
|
+
]);
|
|
862
1057
|
FacilitatorSchema = z.discriminatedUnion("mode", [
|
|
863
1058
|
z.object({
|
|
864
1059
|
mode: z.literal("local"),
|
|
@@ -866,7 +1061,12 @@ var init_schema = __esm({
|
|
|
866
1061
|
}).strict(),
|
|
867
1062
|
z.object({
|
|
868
1063
|
mode: z.literal("remote"),
|
|
869
|
-
url: z.string().min(1)
|
|
1064
|
+
url: z.string().min(1),
|
|
1065
|
+
// Absent means "this facilitator takes no credential" — an explicit
|
|
1066
|
+
// statement, normalised to `{ type: 'none' }` below. On a mainnet that
|
|
1067
|
+
// combination is refused outright, so the default can never quietly
|
|
1068
|
+
// become an unauthenticated production facilitator.
|
|
1069
|
+
auth: FacilitatorAuthSchema.optional()
|
|
870
1070
|
}).strict()
|
|
871
1071
|
]);
|
|
872
1072
|
X402Schema = z.object({
|
|
@@ -879,7 +1079,9 @@ var init_schema = __esm({
|
|
|
879
1079
|
assetDecimals: NumberOrString,
|
|
880
1080
|
payTo: z.string().min(1),
|
|
881
1081
|
maxTimeoutSeconds: NumberOrString,
|
|
882
|
-
facilitator: FacilitatorSchema
|
|
1082
|
+
facilitator: FacilitatorSchema,
|
|
1083
|
+
/** Real funds. Never defaulted — see src/payments/x402/guardrails.ts. */
|
|
1084
|
+
allowMainnet: BooleanOrString.optional()
|
|
883
1085
|
}).strict();
|
|
884
1086
|
PaymentsSchema = z.object({
|
|
885
1087
|
x402: X402Schema.optional()
|
|
@@ -1080,10 +1282,11 @@ async function execCommand(command, args) {
|
|
|
1080
1282
|
// src/cli/commands/doctor.ts
|
|
1081
1283
|
init_execution();
|
|
1082
1284
|
init_core();
|
|
1285
|
+
init_networks();
|
|
1083
1286
|
|
|
1084
1287
|
// src/storage/receipts/store.ts
|
|
1085
1288
|
init_core();
|
|
1086
|
-
var PACKAGE_VERSION = "0.
|
|
1289
|
+
var PACKAGE_VERSION = "0.2.0-beta.0" ;
|
|
1087
1290
|
|
|
1088
1291
|
// src/storage/receipts/redact.ts
|
|
1089
1292
|
var SECRET_KEY_PATTERN = /private[-_ ]?key|secret|password|mnemonic|seed[-_ ]?phrase|api[-_ ]?key|authoriz(e|ation)|^auth$|auth[-_]?header|payment[-_ ]?proof|^proof$|x-payment|signature|signed[-_ ]?message|token|bearer|credential|cookie|session|jwt/i;
|
|
@@ -1598,23 +1801,8 @@ async function fetchJson(fetchImpl, url, timeoutMs = 1500) {
|
|
|
1598
1801
|
}
|
|
1599
1802
|
}
|
|
1600
1803
|
|
|
1601
|
-
// src/payments/x402/local-chain/accounts.ts
|
|
1602
|
-
var ANVIL_WELL_KNOWN_ACCOUNTS = [
|
|
1603
|
-
{
|
|
1604
|
-
address: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
|
|
1605
|
-
privateKey: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
|
|
1606
|
-
},
|
|
1607
|
-
{
|
|
1608
|
-
address: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
|
|
1609
|
-
privateKey: "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"
|
|
1610
|
-
},
|
|
1611
|
-
{
|
|
1612
|
-
address: "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
|
|
1613
|
-
privateKey: "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a"
|
|
1614
|
-
}
|
|
1615
|
-
];
|
|
1616
|
-
|
|
1617
1804
|
// src/cli/lib/init-config.ts
|
|
1805
|
+
init_accounts();
|
|
1618
1806
|
var LOCAL_DEV_MERCHANT_ADDRESS = ANVIL_WELL_KNOWN_ACCOUNTS[1].address;
|
|
1619
1807
|
var LOCAL_DEV_FACILITATOR_PRIVATE_KEY = ANVIL_WELL_KNOWN_ACCOUNTS[0].privateKey;
|
|
1620
1808
|
var PLACEHOLDER_ASSET_ADDRESS = "0x000000000000000000000000000000000000dEaD";
|
|
@@ -1692,7 +1880,7 @@ function buildInitConfigObject(answers) {
|
|
|
1692
1880
|
payments: answers.x402Enabled ? {
|
|
1693
1881
|
x402: {
|
|
1694
1882
|
enabled: true,
|
|
1695
|
-
network: "
|
|
1883
|
+
network: "eip155:84532",
|
|
1696
1884
|
rpcUrl: "http://127.0.0.1:8545",
|
|
1697
1885
|
asset: PLACEHOLDER_ASSET_ADDRESS,
|
|
1698
1886
|
assetName: "MockUSDC",
|
|
@@ -1845,7 +2033,7 @@ function maskMiddle(value, keep = 6) {
|
|
|
1845
2033
|
}
|
|
1846
2034
|
createRequire(import.meta.url);
|
|
1847
2035
|
function readVersionReport() {
|
|
1848
|
-
const injected = '{"cliVersion":"0.
|
|
2036
|
+
const injected = '{"cliVersion":"0.2.0-beta.0","pinned":[{"name":"@modelcontextprotocol/sdk","version":"1.30.0","via":"@devlab.group/agent-commerce"},{"name":"@x402/core","version":"2.23.0","via":"@devlab.group/agent-commerce"},{"name":"@x402/evm","version":"2.23.0","via":"@devlab.group/agent-commerce"},{"name":"viem","version":"2.55.18","via":"@devlab.group/agent-commerce"},{"name":"better-sqlite3","version":"13.0.3","via":"@devlab.group/agent-commerce"},{"name":"fastify","version":"5.12.0","via":"@devlab.group/agent-commerce"},{"name":"pino","version":"10.3.1","via":"@devlab.group/agent-commerce"},{"name":"zod","version":"3.25.76","via":"@devlab.group/agent-commerce"}]}' ;
|
|
1849
2037
|
{
|
|
1850
2038
|
return JSON.parse(injected);
|
|
1851
2039
|
}
|
|
@@ -1884,12 +2072,12 @@ function extractWellKnownX402(body) {
|
|
|
1884
2072
|
}
|
|
1885
2073
|
return { asset, network, payTo };
|
|
1886
2074
|
}
|
|
1887
|
-
function
|
|
2075
|
+
function sameAddress2(a, b) {
|
|
1888
2076
|
return a.toLowerCase() === b.toLowerCase();
|
|
1889
2077
|
}
|
|
1890
2078
|
function findX402Mismatch(configured, live) {
|
|
1891
2079
|
const diffs = [];
|
|
1892
|
-
if (!
|
|
2080
|
+
if (!sameAddress2(configured.asset, live.asset)) {
|
|
1893
2081
|
diffs.push(
|
|
1894
2082
|
`asset: gateway is using ${live.asset} but local config resolves to ${configured.asset}`
|
|
1895
2083
|
);
|
|
@@ -1899,7 +2087,7 @@ function findX402Mismatch(configured, live) {
|
|
|
1899
2087
|
`network: gateway is using "${live.network}" but local config resolves to "${configured.network}"`
|
|
1900
2088
|
);
|
|
1901
2089
|
}
|
|
1902
|
-
if (!
|
|
2090
|
+
if (!sameAddress2(configured.payTo, live.payTo)) {
|
|
1903
2091
|
diffs.push(
|
|
1904
2092
|
`payTo: gateway is using ${live.payTo} but local config resolves to ${configured.payTo}`
|
|
1905
2093
|
);
|
|
@@ -1994,9 +2182,13 @@ async function runDoctor(options, deps = {}) {
|
|
|
1994
2182
|
if (x402 === void 0 || !x402.enabled) {
|
|
1995
2183
|
checks.push({ name: "Payments", status: "INFO", detail: "x402 not configured" });
|
|
1996
2184
|
} else {
|
|
1997
|
-
const
|
|
2185
|
+
const profile = findNetworkProfile(x402.network);
|
|
2186
|
+
const mode = profile ? resolveDeploymentMode(profile, x402.facilitator.mode) : void 0;
|
|
2187
|
+
const where = profile === void 0 || mode === void 0 ? `unknown network ${x402.network}` : mode === "local" ? `LOCAL dev chain (${x402.network}, chain id shared with ${profile.displayName})` : `${describeDeploymentMode(mode)} on ${profile.displayName} (${x402.network})`;
|
|
2188
|
+
const facilitatorDetail = x402.facilitator.mode === "local" ? "local" : `remote (auth=${x402.facilitator.auth.type})`;
|
|
2189
|
+
const summary = `x402 v2 (scheme=exact) enabled \u2014 ${where}, destination=${maskMiddle(x402.payTo)}, facilitator=${facilitatorDetail}`;
|
|
1998
2190
|
const live = wellKnown?.ok ? extractWellKnownX402(wellKnown.body) : void 0;
|
|
1999
|
-
if (
|
|
2191
|
+
if (sameAddress2(x402.asset, PLACEHOLDER_ASSET_ADDRESS)) {
|
|
2000
2192
|
checks.push({
|
|
2001
2193
|
name: "Payments",
|
|
2002
2194
|
status: "WARN",
|
|
@@ -2020,11 +2212,18 @@ async function runDoctor(options, deps = {}) {
|
|
|
2020
2212
|
mismatch === void 0 ? { name: "Payments", status: "PASS", detail: summary } : { name: "Payments", status: "FAIL", detail: mismatch }
|
|
2021
2213
|
);
|
|
2022
2214
|
}
|
|
2215
|
+
if (mode === "mainnet") {
|
|
2216
|
+
checks.push({
|
|
2217
|
+
name: "Mainnet safety",
|
|
2218
|
+
status: "INFO",
|
|
2219
|
+
detail: `${describeDeploymentMode("mainnet")} \u2014 enforced at config load: explicit allowMainnet opt-in, remote facilitator over HTTPS with a credential, non-development payTo, and the canonical asset for this network. Payments are fail-closed.`
|
|
2220
|
+
});
|
|
2221
|
+
}
|
|
2023
2222
|
}
|
|
2024
2223
|
checks.push({
|
|
2025
2224
|
name: "Payments (MPP)",
|
|
2026
2225
|
status: "INFO",
|
|
2027
|
-
detail: "planned \u2014 not implemented in
|
|
2226
|
+
detail: "planned \u2014 not implemented in this release"
|
|
2028
2227
|
});
|
|
2029
2228
|
if (config === void 0) {
|
|
2030
2229
|
checks.push({ name: "Storage", status: "WARN", detail: "skipped \u2014 config invalid" });
|
|
@@ -2034,9 +2233,8 @@ async function runDoctor(options, deps = {}) {
|
|
|
2034
2233
|
// from the host) silently produces a fresh empty database and a false
|
|
2035
2234
|
// "healthy, receipts=0" PASS — a read-only command must not have this
|
|
2036
2235
|
// side effect, and it shadows the real store's real receipts entirely.
|
|
2037
|
-
|
|
2038
|
-
//
|
|
2039
|
-
// branch below, same as today.
|
|
2236
|
+
// `:memory:` never exists on disk by definition, so it always falls
|
|
2237
|
+
// through to the real open/health/count branch below, same as today.
|
|
2040
2238
|
config.storage.receipts.path !== ":memory:" && !existsSync(config.storage.receipts.path)
|
|
2041
2239
|
) {
|
|
2042
2240
|
checks.push({
|
|
@@ -2379,6 +2577,12 @@ function buildProgram(io = processIo) {
|
|
|
2379
2577
|
}
|
|
2380
2578
|
|
|
2381
2579
|
// src/cli/index.ts
|
|
2580
|
+
for (const stream of [process.stdout, process.stderr]) {
|
|
2581
|
+
stream.on("error", (err) => {
|
|
2582
|
+
if (err.code === "EPIPE") process.exit(0);
|
|
2583
|
+
throw err;
|
|
2584
|
+
});
|
|
2585
|
+
}
|
|
2382
2586
|
async function main() {
|
|
2383
2587
|
const program = buildProgram();
|
|
2384
2588
|
try {
|