@agent-score/commerce 2.0.1 → 2.1.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 +26 -11
- package/dist/_core-kI7FRAiZ.d.mts +10 -0
- package/dist/_core-kI7FRAiZ.d.ts +10 -0
- package/dist/challenge/index.d.mts +3 -3
- package/dist/challenge/index.d.ts +3 -3
- package/dist/challenge/index.js +21 -14
- package/dist/challenge/index.js.map +1 -1
- package/dist/challenge/index.mjs +21 -14
- package/dist/challenge/index.mjs.map +1 -1
- package/dist/{checkout-B1JuEcbx.d.ts → checkout-BH-I_Ns8.d.ts} +19 -12
- package/dist/{checkout-BN5i1Fi7.d.mts → checkout-Bd_4aQ6c.d.mts} +19 -12
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/dist/core.mjs +1 -1
- package/dist/core.mjs.map +1 -1
- package/dist/default_rails-BWAquZeu.d.mts +188 -0
- package/dist/default_rails-BxBzcCA1.d.ts +188 -0
- package/dist/discovery/index.d.mts +5 -5
- package/dist/discovery/index.d.ts +5 -5
- package/dist/discovery/index.js +14 -1
- package/dist/discovery/index.js.map +1 -1
- package/dist/discovery/index.mjs +14 -1
- package/dist/discovery/index.mjs.map +1 -1
- package/dist/identity/express.d.mts +7 -3
- package/dist/identity/express.d.ts +7 -3
- package/dist/identity/express.js +39 -96
- package/dist/identity/express.js.map +1 -1
- package/dist/identity/express.mjs +37 -87
- package/dist/identity/express.mjs.map +1 -1
- package/dist/identity/fastify.d.mts +4 -4
- package/dist/identity/fastify.d.ts +4 -4
- package/dist/identity/fastify.js +60 -96
- package/dist/identity/fastify.js.map +1 -1
- package/dist/identity/fastify.mjs +58 -87
- package/dist/identity/fastify.mjs.map +1 -1
- package/dist/identity/hono.d.mts +11 -3
- package/dist/identity/hono.d.ts +11 -3
- package/dist/identity/hono.js +39 -93
- package/dist/identity/hono.js.map +1 -1
- package/dist/identity/hono.mjs +37 -84
- package/dist/identity/hono.mjs.map +1 -1
- package/dist/identity/nextjs.d.mts +10 -3
- package/dist/identity/nextjs.d.ts +10 -3
- package/dist/identity/nextjs.js +49 -93
- package/dist/identity/nextjs.js.map +1 -1
- package/dist/identity/nextjs.mjs +46 -84
- package/dist/identity/nextjs.mjs.map +1 -1
- package/dist/identity/policy.js +220 -129
- package/dist/identity/policy.js.map +1 -1
- package/dist/identity/policy.mjs +222 -131
- package/dist/identity/policy.mjs.map +1 -1
- package/dist/identity/web.d.mts +9 -3
- package/dist/identity/web.d.ts +9 -3
- package/dist/identity/web.js +45 -93
- package/dist/identity/web.js.map +1 -1
- package/dist/identity/web.mjs +42 -84
- package/dist/identity/web.mjs.map +1 -1
- package/dist/index.d.mts +554 -90
- package/dist/index.d.ts +554 -90
- package/dist/index.js +951 -152
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +939 -152
- package/dist/index.mjs.map +1 -1
- package/dist/middleware/express.d.mts +10 -0
- package/dist/middleware/express.d.ts +10 -0
- package/dist/middleware/express.js +128 -0
- package/dist/middleware/express.js.map +1 -0
- package/dist/middleware/express.mjs +91 -0
- package/dist/middleware/express.mjs.map +1 -0
- package/dist/middleware/fastify.d.mts +10 -0
- package/dist/middleware/fastify.d.ts +10 -0
- package/dist/middleware/fastify.js +127 -0
- package/dist/middleware/fastify.js.map +1 -0
- package/dist/middleware/fastify.mjs +90 -0
- package/dist/middleware/fastify.mjs.map +1 -0
- package/dist/middleware/hono.d.mts +10 -0
- package/dist/middleware/hono.d.ts +10 -0
- package/dist/middleware/hono.js +122 -0
- package/dist/middleware/hono.js.map +1 -0
- package/dist/middleware/hono.mjs +85 -0
- package/dist/middleware/hono.mjs.map +1 -0
- package/dist/middleware/nextjs.d.mts +22 -0
- package/dist/middleware/nextjs.d.ts +22 -0
- package/dist/middleware/nextjs.js +143 -0
- package/dist/middleware/nextjs.js.map +1 -0
- package/dist/middleware/nextjs.mjs +105 -0
- package/dist/middleware/nextjs.mjs.map +1 -0
- package/dist/middleware/web.d.mts +25 -0
- package/dist/middleware/web.d.ts +25 -0
- package/dist/middleware/web.js +128 -0
- package/dist/middleware/web.js.map +1 -0
- package/dist/middleware/web.mjs +91 -0
- package/dist/middleware/web.mjs.map +1 -0
- package/dist/payment/index.d.mts +21 -6
- package/dist/payment/index.d.ts +21 -6
- package/dist/payment/index.js +136 -9
- package/dist/payment/index.js.map +1 -1
- package/dist/payment/index.mjs +127 -9
- package/dist/payment/index.mjs.map +1 -1
- package/dist/{pricing-CxzwyiO6.d.mts → pricing-4n5Ota0D.d.mts} +14 -4
- package/dist/{pricing-CQ9DIFaw.d.ts → pricing-DHfH3ogG.d.ts} +14 -4
- package/dist/{rail_spec-XP0wKgJV.d.mts → rail_spec-D6qzh3J0.d.mts} +1 -1
- package/dist/{rail_spec-XP0wKgJV.d.ts → rail_spec-D6qzh3J0.d.ts} +1 -1
- package/dist/stripe-multichain/index.d.mts +150 -47
- package/dist/stripe-multichain/index.d.ts +150 -47
- package/dist/stripe-multichain/index.js +19749 -42
- package/dist/stripe-multichain/index.js.map +1 -1
- package/dist/stripe-multichain/index.mjs +19758 -27
- package/dist/stripe-multichain/index.mjs.map +1 -1
- package/dist/{x402_server-hgQzWQwB.d.mts → x402_server-Ciz2mls2.d.mts} +1 -1
- package/dist/{x402_server-hgQzWQwB.d.ts → x402_server-Ciz2mls2.d.ts} +1 -1
- package/package.json +43 -5
- package/dist/_response-BFYN3b6i.d.mts +0 -142
- package/dist/_response-_iPD5AIj.d.ts +0 -142
- package/dist/solana-Cds87OTu.d.mts +0 -67
- package/dist/solana-Cds87OTu.d.ts +0 -67
package/dist/index.mjs
CHANGED
|
@@ -31,6 +31,27 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
31
31
|
mod
|
|
32
32
|
));
|
|
33
33
|
|
|
34
|
+
// src/payment/network_kind.ts
|
|
35
|
+
function readNetwork(input) {
|
|
36
|
+
if (typeof input === "string") return input;
|
|
37
|
+
if (input && typeof input === "object") {
|
|
38
|
+
const network = input.network;
|
|
39
|
+
return typeof network === "string" ? network : "";
|
|
40
|
+
}
|
|
41
|
+
return "";
|
|
42
|
+
}
|
|
43
|
+
function isEvmNetwork(input) {
|
|
44
|
+
return readNetwork(input).startsWith("eip155:");
|
|
45
|
+
}
|
|
46
|
+
function isSolanaNetwork(input) {
|
|
47
|
+
return readNetwork(input).startsWith("solana:");
|
|
48
|
+
}
|
|
49
|
+
var init_network_kind = __esm({
|
|
50
|
+
"src/payment/network_kind.ts"() {
|
|
51
|
+
"use strict";
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
34
55
|
// src/identity/ucp.ts
|
|
35
56
|
function ucpSigningKeyFromJWKImpl(jwk) {
|
|
36
57
|
if (!jwk || typeof jwk !== "object") {
|
|
@@ -160,7 +181,7 @@ function isTempoSessionRailSpec(s) {
|
|
|
160
181
|
}
|
|
161
182
|
function mppRailToNetworkEntry(spec) {
|
|
162
183
|
if (isTempoSessionRailSpec(spec)) return tempoSessionToNetworkEntry(spec);
|
|
163
|
-
if ("rpcUrl" in spec || "tokenProgram" in spec || (spec
|
|
184
|
+
if ("rpcUrl" in spec || "tokenProgram" in spec || isSolanaNetwork(spec)) {
|
|
164
185
|
return solanaMppToNetworkEntry(spec);
|
|
165
186
|
}
|
|
166
187
|
if (isTempoRailSpec(spec)) return tempoToNetworkEntry(spec);
|
|
@@ -217,6 +238,7 @@ var UCPSigningKey, DEFAULT_VERSION, AGENTSCORE_CAPABILITY_NAME, AGENTSCORE_CAPAB
|
|
|
217
238
|
var init_ucp = __esm({
|
|
218
239
|
"src/identity/ucp.ts"() {
|
|
219
240
|
"use strict";
|
|
241
|
+
init_network_kind();
|
|
220
242
|
UCPSigningKey = {
|
|
221
243
|
fromJWK: ucpSigningKeyFromJWKImpl
|
|
222
244
|
};
|
|
@@ -636,64 +658,6 @@ var init_ucp_jwks = __esm({
|
|
|
636
658
|
}
|
|
637
659
|
});
|
|
638
660
|
|
|
639
|
-
// src/payment/usdc.ts
|
|
640
|
-
var USDC;
|
|
641
|
-
var init_usdc = __esm({
|
|
642
|
-
"src/payment/usdc.ts"() {
|
|
643
|
-
"use strict";
|
|
644
|
-
USDC = {
|
|
645
|
-
base: {
|
|
646
|
-
mainnet: { address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", decimals: 6 },
|
|
647
|
-
sepolia: { address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", decimals: 6 }
|
|
648
|
-
},
|
|
649
|
-
solana: {
|
|
650
|
-
mainnet: { mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", decimals: 6 },
|
|
651
|
-
devnet: { mint: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU", decimals: 6 }
|
|
652
|
-
},
|
|
653
|
-
tempo: {
|
|
654
|
-
mainnet: { address: "0x20C000000000000000000000b9537d11c60E8b50", decimals: 6 },
|
|
655
|
-
testnet: { address: "0x20c0000000000000000000000000000000000000", decimals: 6 }
|
|
656
|
-
}
|
|
657
|
-
};
|
|
658
|
-
}
|
|
659
|
-
});
|
|
660
|
-
|
|
661
|
-
// src/payment/wwwauthenticate.ts
|
|
662
|
-
function paymentRequiredHeader({
|
|
663
|
-
x402Version,
|
|
664
|
-
accepts,
|
|
665
|
-
resource
|
|
666
|
-
}) {
|
|
667
|
-
return Buffer.from(JSON.stringify({ x402Version, accepts, ...resource ? { resource } : {} })).toString("base64");
|
|
668
|
-
}
|
|
669
|
-
var init_wwwauthenticate = __esm({
|
|
670
|
-
"src/payment/wwwauthenticate.ts"() {
|
|
671
|
-
"use strict";
|
|
672
|
-
}
|
|
673
|
-
});
|
|
674
|
-
|
|
675
|
-
// src/payment/networks.ts
|
|
676
|
-
var networks;
|
|
677
|
-
var init_networks = __esm({
|
|
678
|
-
"src/payment/networks.ts"() {
|
|
679
|
-
"use strict";
|
|
680
|
-
networks = {
|
|
681
|
-
base: {
|
|
682
|
-
mainnet: { caip2: "eip155:8453", chainId: 8453 },
|
|
683
|
-
sepolia: { caip2: "eip155:84532", chainId: 84532 }
|
|
684
|
-
},
|
|
685
|
-
solana: {
|
|
686
|
-
mainnet: { caip2: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" },
|
|
687
|
-
devnet: { caip2: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1" }
|
|
688
|
-
},
|
|
689
|
-
tempo: {
|
|
690
|
-
mainnet: { caip2: "eip155:4217", chainId: 4217 },
|
|
691
|
-
testnet: { caip2: "eip155:42431", chainId: 42431 }
|
|
692
|
-
}
|
|
693
|
-
};
|
|
694
|
-
}
|
|
695
|
-
});
|
|
696
|
-
|
|
697
661
|
// node_modules/ox/_esm/core/Abi.js
|
|
698
662
|
var init_Abi = __esm({
|
|
699
663
|
"node_modules/ox/_esm/core/Abi.js"() {
|
|
@@ -19692,7 +19656,7 @@ function deserialize3(value) {
|
|
|
19692
19656
|
try {
|
|
19693
19657
|
const json2 = Base64_exports.toString(prefixMatch[1]);
|
|
19694
19658
|
const parsed = JSON.parse(json2);
|
|
19695
|
-
const { opaque: challengeOpaque, request, ...challengeFields } = parsed.challenge;
|
|
19659
|
+
const { opaque: challengeOpaque, request, meta: _meta, ...challengeFields } = parsed.challenge;
|
|
19696
19660
|
const { meta: meta4, opaque } = normalizeCredentialOpaque(challengeOpaque);
|
|
19697
19661
|
const challenge = Schema.parse({
|
|
19698
19662
|
...challengeFields,
|
|
@@ -20305,6 +20269,64 @@ var init_dist2 = __esm({
|
|
|
20305
20269
|
}
|
|
20306
20270
|
});
|
|
20307
20271
|
|
|
20272
|
+
// src/payment/usdc.ts
|
|
20273
|
+
var USDC;
|
|
20274
|
+
var init_usdc = __esm({
|
|
20275
|
+
"src/payment/usdc.ts"() {
|
|
20276
|
+
"use strict";
|
|
20277
|
+
USDC = {
|
|
20278
|
+
base: {
|
|
20279
|
+
mainnet: { address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", decimals: 6 },
|
|
20280
|
+
sepolia: { address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", decimals: 6 }
|
|
20281
|
+
},
|
|
20282
|
+
solana: {
|
|
20283
|
+
mainnet: { mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", decimals: 6 },
|
|
20284
|
+
devnet: { mint: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU", decimals: 6 }
|
|
20285
|
+
},
|
|
20286
|
+
tempo: {
|
|
20287
|
+
mainnet: { address: "0x20C000000000000000000000b9537d11c60E8b50", decimals: 6 },
|
|
20288
|
+
testnet: { address: "0x20c0000000000000000000000000000000000000", decimals: 6 }
|
|
20289
|
+
}
|
|
20290
|
+
};
|
|
20291
|
+
}
|
|
20292
|
+
});
|
|
20293
|
+
|
|
20294
|
+
// src/payment/wwwauthenticate.ts
|
|
20295
|
+
function paymentRequiredHeader({
|
|
20296
|
+
x402Version,
|
|
20297
|
+
accepts,
|
|
20298
|
+
resource
|
|
20299
|
+
}) {
|
|
20300
|
+
return Buffer.from(JSON.stringify({ x402Version, accepts, ...resource ? { resource } : {} })).toString("base64");
|
|
20301
|
+
}
|
|
20302
|
+
var init_wwwauthenticate = __esm({
|
|
20303
|
+
"src/payment/wwwauthenticate.ts"() {
|
|
20304
|
+
"use strict";
|
|
20305
|
+
}
|
|
20306
|
+
});
|
|
20307
|
+
|
|
20308
|
+
// src/payment/networks.ts
|
|
20309
|
+
var networks;
|
|
20310
|
+
var init_networks = __esm({
|
|
20311
|
+
"src/payment/networks.ts"() {
|
|
20312
|
+
"use strict";
|
|
20313
|
+
networks = {
|
|
20314
|
+
base: {
|
|
20315
|
+
mainnet: { caip2: "eip155:8453", chainId: 8453 },
|
|
20316
|
+
sepolia: { caip2: "eip155:84532", chainId: 84532 }
|
|
20317
|
+
},
|
|
20318
|
+
solana: {
|
|
20319
|
+
mainnet: { caip2: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" },
|
|
20320
|
+
devnet: { caip2: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1" }
|
|
20321
|
+
},
|
|
20322
|
+
tempo: {
|
|
20323
|
+
mainnet: { caip2: "eip155:4217", chainId: 4217 },
|
|
20324
|
+
testnet: { caip2: "eip155:42431", chainId: 42431 }
|
|
20325
|
+
}
|
|
20326
|
+
};
|
|
20327
|
+
}
|
|
20328
|
+
});
|
|
20329
|
+
|
|
20308
20330
|
// src/payment/rails.ts
|
|
20309
20331
|
function lookupRail(name) {
|
|
20310
20332
|
return rails[name];
|
|
@@ -21125,7 +21147,7 @@ function createAgentScoreCore(options) {
|
|
|
21125
21147
|
} = options;
|
|
21126
21148
|
const baseUrl = stripTrailingSlashes(rawBaseUrl);
|
|
21127
21149
|
const agentMemoryHint = buildAgentMemoryHint();
|
|
21128
|
-
const defaultUa = `@agent-score/commerce@${"2.0
|
|
21150
|
+
const defaultUa = `@agent-score/commerce@${"2.1.0"}`;
|
|
21129
21151
|
const userAgentHeader = userAgent ? `${userAgent} (${defaultUa})` : defaultUa;
|
|
21130
21152
|
const sdk = new AgentScore({ apiKey, baseUrl, userAgent: userAgentHeader });
|
|
21131
21153
|
const sessionSdkCache = /* @__PURE__ */ new Map();
|
|
@@ -21417,6 +21439,13 @@ function createAgentScoreCore(options) {
|
|
|
21417
21439
|
return { evaluate, captureWallet, getSignerVerdict };
|
|
21418
21440
|
}
|
|
21419
21441
|
|
|
21442
|
+
// src/_headers.ts
|
|
21443
|
+
function normalizeHeadersToLowercase(headers) {
|
|
21444
|
+
const out = {};
|
|
21445
|
+
for (const [k, v] of Object.entries(headers)) out[k.toLowerCase()] = v;
|
|
21446
|
+
return out;
|
|
21447
|
+
}
|
|
21448
|
+
|
|
21420
21449
|
// src/signer.ts
|
|
21421
21450
|
var TOKEN_PROGRAM = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
|
|
21422
21451
|
var TOKEN_2022_PROGRAM = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb";
|
|
@@ -21499,13 +21528,8 @@ async function extractPaymentSignerFromAuth(authHeader, x402PaymentHeader) {
|
|
|
21499
21528
|
function readX402PaymentHeader(request) {
|
|
21500
21529
|
return request.headers.get("payment-signature") ?? request.headers.get("x-payment") ?? void 0;
|
|
21501
21530
|
}
|
|
21502
|
-
function lowerHeaders(headers) {
|
|
21503
|
-
const out = {};
|
|
21504
|
-
for (const [k, v] of Object.entries(headers)) out[k.toLowerCase()] = v;
|
|
21505
|
-
return out;
|
|
21506
|
-
}
|
|
21507
21531
|
async function extractSignerForPrecheck(headers) {
|
|
21508
|
-
const lower =
|
|
21532
|
+
const lower = normalizeHeadersToLowercase(headers);
|
|
21509
21533
|
const x402 = lower["payment-signature"] ?? lower["x-payment"];
|
|
21510
21534
|
if (x402) {
|
|
21511
21535
|
const signer = await extractPaymentSignerFromAuth(void 0, x402);
|
|
@@ -21520,7 +21544,7 @@ async function extractSignerForPrecheck(headers) {
|
|
|
21520
21544
|
|
|
21521
21545
|
// src/identity/a2a.ts
|
|
21522
21546
|
var PROTOCOL_VERSION = "1.0";
|
|
21523
|
-
var
|
|
21547
|
+
var DEFAULT_TRANSPORT = "JSONRPC";
|
|
21524
21548
|
var DEFAULT_INPUT_MODE = "application/json";
|
|
21525
21549
|
var DEFAULT_OUTPUT_MODE = "application/json";
|
|
21526
21550
|
var UCP_A2A_EXTENSION_URI = "https://ucp.dev/2026-04-08/specification/reference";
|
|
@@ -21540,30 +21564,33 @@ function buildA2AAgentCard(input) {
|
|
|
21540
21564
|
}
|
|
21541
21565
|
const capabilities = {};
|
|
21542
21566
|
if (input.streaming !== void 0) capabilities.streaming = input.streaming;
|
|
21543
|
-
if (input.
|
|
21567
|
+
if (input.pushNotifications !== void 0) capabilities.pushNotifications = input.pushNotifications;
|
|
21568
|
+
if (input.stateTransitionHistory !== void 0) capabilities.stateTransitionHistory = input.stateTransitionHistory;
|
|
21544
21569
|
if (input.extensions && input.extensions.length > 0) capabilities.extensions = input.extensions;
|
|
21545
|
-
if (input.extended_agent_card !== void 0) capabilities.extended_agent_card = input.extended_agent_card;
|
|
21546
|
-
const primaryInterface = {
|
|
21547
|
-
url: input.url,
|
|
21548
|
-
protocol_binding: input.protocol_binding ?? DEFAULT_PROTOCOL_BINDING,
|
|
21549
|
-
protocol_version: input.a2a_protocol_version ?? PROTOCOL_VERSION
|
|
21550
|
-
};
|
|
21551
21570
|
const card = {
|
|
21552
21571
|
name: input.name,
|
|
21553
21572
|
description: input.description,
|
|
21554
|
-
|
|
21573
|
+
url: input.url,
|
|
21574
|
+
preferredTransport: input.preferredTransport ?? "HTTP+JSON",
|
|
21575
|
+
protocolVersion: input.protocolVersion ?? PROTOCOL_VERSION,
|
|
21555
21576
|
version: input.version ?? "1.0.0",
|
|
21556
21577
|
capabilities,
|
|
21557
|
-
|
|
21558
|
-
|
|
21578
|
+
defaultInputModes: input.defaultInputModes ?? [DEFAULT_INPUT_MODE],
|
|
21579
|
+
defaultOutputModes: input.defaultOutputModes ?? [DEFAULT_OUTPUT_MODE],
|
|
21559
21580
|
skills: input.skills
|
|
21560
21581
|
};
|
|
21582
|
+
if (input.additionalInterfaces !== void 0 && input.additionalInterfaces.length > 0) {
|
|
21583
|
+
card.additionalInterfaces = input.additionalInterfaces;
|
|
21584
|
+
}
|
|
21561
21585
|
if (input.provider !== void 0) card.provider = input.provider;
|
|
21562
|
-
if (input.
|
|
21563
|
-
if (input.
|
|
21586
|
+
if (input.documentationUrl !== void 0) card.documentationUrl = input.documentationUrl;
|
|
21587
|
+
if (input.iconUrl !== void 0) card.iconUrl = input.iconUrl;
|
|
21588
|
+
if (input.supportsAuthenticatedExtendedCard !== void 0) {
|
|
21589
|
+
card.supportsAuthenticatedExtendedCard = input.supportsAuthenticatedExtendedCard;
|
|
21590
|
+
}
|
|
21564
21591
|
if (input.signatures !== void 0 && input.signatures.length > 0) card.signatures = input.signatures;
|
|
21565
|
-
if (input.
|
|
21566
|
-
if (input.
|
|
21592
|
+
if (input.security !== void 0) card.security = input.security;
|
|
21593
|
+
if (input.securitySchemes !== void 0) card.securitySchemes = input.securitySchemes;
|
|
21567
21594
|
if (input.extras) {
|
|
21568
21595
|
for (const [k, v] of Object.entries(input.extras)) {
|
|
21569
21596
|
card[k] = v;
|
|
@@ -21571,6 +21598,8 @@ function buildA2AAgentCard(input) {
|
|
|
21571
21598
|
}
|
|
21572
21599
|
return card;
|
|
21573
21600
|
}
|
|
21601
|
+
var A2A_PROTOCOL_VERSION = PROTOCOL_VERSION;
|
|
21602
|
+
var A2A_DEFAULT_TRANSPORT = DEFAULT_TRANSPORT;
|
|
21574
21603
|
|
|
21575
21604
|
// src/index.ts
|
|
21576
21605
|
init_ucp();
|
|
@@ -21579,6 +21608,34 @@ init_ucp_jwks();
|
|
|
21579
21608
|
// src/checkout.ts
|
|
21580
21609
|
import { randomUUID } from "crypto";
|
|
21581
21610
|
|
|
21611
|
+
// src/_mppx_receipt.ts
|
|
21612
|
+
function extractMppxReceiptHeaderFromRaw(raw) {
|
|
21613
|
+
if (!raw || typeof raw !== "object" || !("withReceipt" in raw)) return null;
|
|
21614
|
+
const fn = raw.withReceipt;
|
|
21615
|
+
if (typeof fn !== "function") return null;
|
|
21616
|
+
try {
|
|
21617
|
+
const wrapped = fn.call(raw, new Response());
|
|
21618
|
+
return wrapped.headers.get("Payment-Receipt");
|
|
21619
|
+
} catch {
|
|
21620
|
+
return null;
|
|
21621
|
+
}
|
|
21622
|
+
}
|
|
21623
|
+
async function extractMppxReceiptMethod(header) {
|
|
21624
|
+
try {
|
|
21625
|
+
const { Receipt } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
|
|
21626
|
+
return Receipt.deserialize(header).method;
|
|
21627
|
+
} catch {
|
|
21628
|
+
return void 0;
|
|
21629
|
+
}
|
|
21630
|
+
}
|
|
21631
|
+
async function deriveMppxReceiptMethod(raw) {
|
|
21632
|
+
const direct = raw?.receipt?.method;
|
|
21633
|
+
if (direct) return direct;
|
|
21634
|
+
const header = extractMppxReceiptHeaderFromRaw(raw);
|
|
21635
|
+
if (!header) return void 0;
|
|
21636
|
+
return extractMppxReceiptMethod(header);
|
|
21637
|
+
}
|
|
21638
|
+
|
|
21582
21639
|
// src/payment/rail_spec.ts
|
|
21583
21640
|
init_usdc();
|
|
21584
21641
|
async function resolveRecipient(r) {
|
|
@@ -21803,10 +21860,13 @@ function buildHowToPay({
|
|
|
21803
21860
|
totalUsd,
|
|
21804
21861
|
rails: rails2,
|
|
21805
21862
|
opTokenPlaceholder,
|
|
21806
|
-
maxSpend
|
|
21863
|
+
maxSpend,
|
|
21864
|
+
decimals
|
|
21807
21865
|
}) {
|
|
21808
21866
|
const totalNum = typeof totalUsd === "string" ? Number(totalUsd) : totalUsd;
|
|
21809
|
-
const
|
|
21867
|
+
const d = decimals ?? 2;
|
|
21868
|
+
const defaultMaxSpend = totalNum >= 1 ? (Math.ceil(totalNum) + 1).toFixed(d) : totalNum.toFixed(d);
|
|
21869
|
+
const maxSpendStr = String(maxSpend ?? defaultMaxSpend);
|
|
21810
21870
|
const opToken = opTokenPlaceholder ?? "<your_opc_token>";
|
|
21811
21871
|
const block = {};
|
|
21812
21872
|
if (rails2.tempo) {
|
|
@@ -21899,26 +21959,26 @@ function buildPricingBlock({
|
|
|
21899
21959
|
totalCents,
|
|
21900
21960
|
taxRate,
|
|
21901
21961
|
taxState,
|
|
21902
|
-
currency
|
|
21962
|
+
currency,
|
|
21963
|
+
decimals
|
|
21903
21964
|
}) {
|
|
21904
21965
|
const shipping = shippingCents ?? 0;
|
|
21905
21966
|
const discount = discountCents ?? 0;
|
|
21906
21967
|
const total = totalCents ?? Math.max(0, subtotalCents + taxCents + shipping - discount);
|
|
21968
|
+
const d = decimals ?? 2;
|
|
21969
|
+
const fmt = (cents) => (cents / 100).toFixed(d);
|
|
21907
21970
|
const block = {
|
|
21908
|
-
subtotal:
|
|
21909
|
-
tax:
|
|
21910
|
-
total:
|
|
21971
|
+
subtotal: fmt(subtotalCents),
|
|
21972
|
+
tax: fmt(taxCents),
|
|
21973
|
+
total: fmt(total)
|
|
21911
21974
|
};
|
|
21912
|
-
if (shippingCents !== void 0) block.shipping =
|
|
21913
|
-
if (discountCents !== void 0) block.discount =
|
|
21975
|
+
if (shippingCents !== void 0) block.shipping = fmt(shipping);
|
|
21976
|
+
if (discountCents !== void 0) block.discount = fmt(discount);
|
|
21914
21977
|
if (taxRate !== void 0) block.tax_rate = taxRate;
|
|
21915
21978
|
if (taxState !== void 0) block.tax_state = taxState;
|
|
21916
21979
|
if (currency !== void 0) block.currency = currency;
|
|
21917
21980
|
return block;
|
|
21918
21981
|
}
|
|
21919
|
-
function formatCents(cents) {
|
|
21920
|
-
return (cents / 100).toFixed(2);
|
|
21921
|
-
}
|
|
21922
21982
|
|
|
21923
21983
|
// src/challenge/respond_402.ts
|
|
21924
21984
|
init_wwwauthenticate();
|
|
@@ -21927,10 +21987,7 @@ function respond402({
|
|
|
21927
21987
|
body,
|
|
21928
21988
|
x402
|
|
21929
21989
|
}) {
|
|
21930
|
-
const headers =
|
|
21931
|
-
for (const [k, v] of Object.entries(mppxChallengeHeaders)) {
|
|
21932
|
-
headers[k.toLowerCase()] = v;
|
|
21933
|
-
}
|
|
21990
|
+
const headers = normalizeHeadersToLowercase(mppxChallengeHeaders);
|
|
21934
21991
|
headers["content-type"] = "application/json";
|
|
21935
21992
|
if (x402) {
|
|
21936
21993
|
headers["payment-required"] = paymentRequiredHeader(x402);
|
|
@@ -21993,7 +22050,8 @@ function isSolanaMppRailSpec(s) {
|
|
|
21993
22050
|
return s.network?.startsWith("solana:") ?? false;
|
|
21994
22051
|
}
|
|
21995
22052
|
function solanaNetworkFromCAIP2(caip2) {
|
|
21996
|
-
if (caip2 === networks.solana.devnet.caip2) return "devnet";
|
|
22053
|
+
if (caip2 === "devnet" || caip2 === networks.solana.devnet.caip2) return "devnet";
|
|
22054
|
+
if (caip2 === "localnet") return "localnet";
|
|
21997
22055
|
return "mainnet-beta";
|
|
21998
22056
|
}
|
|
21999
22057
|
function solanaDefaultRpcUrl(network) {
|
|
@@ -22277,6 +22335,41 @@ function lazyMppxServer(opts) {
|
|
|
22277
22335
|
};
|
|
22278
22336
|
}
|
|
22279
22337
|
|
|
22338
|
+
// src/checkout.ts
|
|
22339
|
+
init_network_kind();
|
|
22340
|
+
|
|
22341
|
+
// src/payment/payment_header.ts
|
|
22342
|
+
function toTitleCase(name) {
|
|
22343
|
+
return name.replace(/(^|-)([a-z])/g, (_m, sep, c) => sep + c.toUpperCase());
|
|
22344
|
+
}
|
|
22345
|
+
function readHeader(headers, name) {
|
|
22346
|
+
if (typeof headers.get === "function") {
|
|
22347
|
+
return headers.get(name);
|
|
22348
|
+
}
|
|
22349
|
+
const rec = headers;
|
|
22350
|
+
const v = rec[name] ?? rec[name.toLowerCase()] ?? rec[toTitleCase(name)];
|
|
22351
|
+
if (typeof v === "string") return v;
|
|
22352
|
+
if (Array.isArray(v) && typeof v[0] === "string") return v[0];
|
|
22353
|
+
return null;
|
|
22354
|
+
}
|
|
22355
|
+
function asHeaders(input) {
|
|
22356
|
+
return typeof input.headers === "object" && input instanceof Request ? input.headers : input;
|
|
22357
|
+
}
|
|
22358
|
+
function hasPaymentHeader(input) {
|
|
22359
|
+
const headers = asHeaders(input);
|
|
22360
|
+
return Boolean(
|
|
22361
|
+
readHeader(headers, "payment-signature") || readHeader(headers, "x-payment") || readHeader(headers, "authorization")?.startsWith("Payment ")
|
|
22362
|
+
);
|
|
22363
|
+
}
|
|
22364
|
+
function hasX402Header(input) {
|
|
22365
|
+
const headers = asHeaders(input);
|
|
22366
|
+
return Boolean(readHeader(headers, "payment-signature") || readHeader(headers, "x-payment"));
|
|
22367
|
+
}
|
|
22368
|
+
function hasMppxHeader(input) {
|
|
22369
|
+
const headers = asHeaders(input);
|
|
22370
|
+
return Boolean(readHeader(headers, "authorization")?.startsWith("Payment "));
|
|
22371
|
+
}
|
|
22372
|
+
|
|
22280
22373
|
// src/payment/x402_settle.ts
|
|
22281
22374
|
function classifyX402SettleResult(result) {
|
|
22282
22375
|
if (result.success) return null;
|
|
@@ -22568,12 +22661,14 @@ function pricingResult(opts) {
|
|
|
22568
22661
|
...opts.discountCents !== void 0 && { discountCents: opts.discountCents },
|
|
22569
22662
|
...opts.taxRate !== void 0 && { taxRate: opts.taxRate },
|
|
22570
22663
|
...opts.taxState !== void 0 && { taxState: opts.taxState },
|
|
22571
|
-
currency
|
|
22664
|
+
currency,
|
|
22665
|
+
...opts.decimals !== void 0 && { decimals: opts.decimals }
|
|
22572
22666
|
});
|
|
22573
22667
|
return {
|
|
22574
22668
|
amountUsd: derivedAmount,
|
|
22575
22669
|
currency,
|
|
22576
22670
|
block,
|
|
22671
|
+
...opts.decimals !== void 0 && { decimals: opts.decimals },
|
|
22577
22672
|
...opts.product !== void 0 && { product: opts.product },
|
|
22578
22673
|
...opts.bodyExtras !== void 0 && { bodyExtras: opts.bodyExtras }
|
|
22579
22674
|
};
|
|
@@ -22584,6 +22679,7 @@ function pricingResult(opts) {
|
|
|
22584
22679
|
return {
|
|
22585
22680
|
amountUsd: opts.amountUsd,
|
|
22586
22681
|
currency,
|
|
22682
|
+
...opts.decimals !== void 0 && { decimals: opts.decimals },
|
|
22587
22683
|
...opts.product !== void 0 && { product: opts.product },
|
|
22588
22684
|
...opts.bodyExtras !== void 0 && { bodyExtras: opts.bodyExtras }
|
|
22589
22685
|
};
|
|
@@ -22609,21 +22705,8 @@ var CheckoutValidationError = class extends Error {
|
|
|
22609
22705
|
this.extra = opts.extra;
|
|
22610
22706
|
}
|
|
22611
22707
|
};
|
|
22612
|
-
function lowerHeaders2(headers) {
|
|
22613
|
-
const out = {};
|
|
22614
|
-
for (const [k, v] of Object.entries(headers)) out[k.toLowerCase()] = v;
|
|
22615
|
-
return out;
|
|
22616
|
-
}
|
|
22617
|
-
function hasX402Header(headers) {
|
|
22618
|
-
const h = lowerHeaders2(headers);
|
|
22619
|
-
return Boolean(h["payment-signature"] ?? h["x-payment"]);
|
|
22620
|
-
}
|
|
22621
|
-
function hasMppxHeader(headers) {
|
|
22622
|
-
const h = lowerHeaders2(headers);
|
|
22623
|
-
return (h["authorization"] ?? "").startsWith("Payment ");
|
|
22624
|
-
}
|
|
22625
22708
|
function resolveIdentityMetadata(ctx) {
|
|
22626
|
-
const h =
|
|
22709
|
+
const h = normalizeHeadersToLowercase(ctx.request.headers);
|
|
22627
22710
|
const wallet = h["x-wallet-address"];
|
|
22628
22711
|
if (!wallet) return void 0;
|
|
22629
22712
|
let linkedWallets;
|
|
@@ -22652,26 +22735,24 @@ function isTempoSessionRailSpec3(s) {
|
|
|
22652
22735
|
function specRailKey(spec) {
|
|
22653
22736
|
if (isStripeRailSpec2(spec)) return "stripe";
|
|
22654
22737
|
if (isTempoSessionRailSpec3(spec)) return "tempo_mpp";
|
|
22655
|
-
|
|
22656
|
-
if (
|
|
22657
|
-
if (network.startsWith("solana:") || "rpcUrl" in spec) return "solana_mpp";
|
|
22738
|
+
if (isEvmNetwork(spec)) return "x402_base";
|
|
22739
|
+
if (isSolanaNetwork(spec) || "rpcUrl" in spec) return "solana_mpp";
|
|
22658
22740
|
return "tempo_mpp";
|
|
22659
22741
|
}
|
|
22660
22742
|
function specMethodName(spec) {
|
|
22661
22743
|
if (isStripeRailSpec2(spec)) return "stripe/spt";
|
|
22662
22744
|
if (isTempoSessionRailSpec3(spec)) return "tempo/charge";
|
|
22663
|
-
|
|
22664
|
-
if (
|
|
22665
|
-
if (network.startsWith("solana:") || "rpcUrl" in spec) return "solana/charge";
|
|
22745
|
+
if (isEvmNetwork(spec)) return "x402/exact (base)";
|
|
22746
|
+
if (isSolanaNetwork(spec) || "rpcUrl" in spec) return "solana/charge";
|
|
22666
22747
|
return "tempo/charge";
|
|
22667
22748
|
}
|
|
22668
22749
|
function makeMppxComposeHook(opts) {
|
|
22669
22750
|
return async (ctx) => {
|
|
22670
22751
|
if (ctx.pricing === null) return { status: 402 };
|
|
22671
22752
|
const mpp = await opts.serverGetter();
|
|
22672
|
-
const lower =
|
|
22753
|
+
const lower = normalizeHeadersToLowercase(ctx.request.headers);
|
|
22673
22754
|
const authorization = lower["authorization"];
|
|
22674
|
-
const amountStr = ctx.pricing.amountUsd.toFixed(2);
|
|
22755
|
+
const amountStr = ctx.pricing.amountUsd.toFixed(ctx.pricing.decimals ?? 2);
|
|
22675
22756
|
let result;
|
|
22676
22757
|
try {
|
|
22677
22758
|
result = await mpp.charge({ authorization, amount: amountStr });
|
|
@@ -22755,7 +22836,7 @@ var Checkout = class {
|
|
|
22755
22836
|
let x402ServerGetter;
|
|
22756
22837
|
if (x402Server === void 0) {
|
|
22757
22838
|
const baseSpec = Object.values(opts.rails).find(
|
|
22758
|
-
(s) => !isTempoSessionRailSpec3(s) && !isStripeRailSpec2(s) && "recipient" in s && (s
|
|
22839
|
+
(s) => !isTempoSessionRailSpec3(s) && !isStripeRailSpec2(s) && "recipient" in s && isEvmNetwork(s)
|
|
22759
22840
|
);
|
|
22760
22841
|
if (baseSpec !== void 0) {
|
|
22761
22842
|
x402ServerGetter = lazyX402Server({
|
|
@@ -22845,7 +22926,7 @@ var Checkout = class {
|
|
|
22845
22926
|
* `"x402_base"` when no match found. */
|
|
22846
22927
|
x402RailKey() {
|
|
22847
22928
|
for (const [k, v] of Object.entries(this.rails)) {
|
|
22848
|
-
if (!isStripeRailSpec2(v) && !isTempoSessionRailSpec3(v) && (v
|
|
22929
|
+
if (!isStripeRailSpec2(v) && !isTempoSessionRailSpec3(v) && isEvmNetwork(v)) {
|
|
22849
22930
|
return k;
|
|
22850
22931
|
}
|
|
22851
22932
|
}
|
|
@@ -22854,18 +22935,47 @@ var Checkout = class {
|
|
|
22854
22935
|
/** Return the rails-dict key for the primary MPP rail. */
|
|
22855
22936
|
mppRailKey() {
|
|
22856
22937
|
for (const [k, v] of Object.entries(this.rails)) {
|
|
22857
|
-
|
|
22858
|
-
if (!isStripeRailSpec2(v) && !network.startsWith("eip155:")) return k;
|
|
22938
|
+
if (!isStripeRailSpec2(v) && !isEvmNetwork(v)) return k;
|
|
22859
22939
|
}
|
|
22860
22940
|
return "tempo";
|
|
22861
22941
|
}
|
|
22942
|
+
/** Map an mppx credential `method` (`tempo` | `solana` | `stripe`) to the
|
|
22943
|
+
* merchant's rails-dict key. Used in handleMppx so onSettled outcomes
|
|
22944
|
+
* distinguish Solana from Tempo (both settle under `rail: 'mpp'`) and from
|
|
22945
|
+
* Stripe SPT. Returns the first matching key or `undefined` when no rail in
|
|
22946
|
+
* the merchant's config corresponds to that method. */
|
|
22947
|
+
railsKeyForMppxMethod(method) {
|
|
22948
|
+
if (method === "stripe") {
|
|
22949
|
+
for (const [k, v] of Object.entries(this.rails)) {
|
|
22950
|
+
if (isStripeRailSpec2(v)) return k;
|
|
22951
|
+
}
|
|
22952
|
+
return void 0;
|
|
22953
|
+
}
|
|
22954
|
+
if (method === "solana") {
|
|
22955
|
+
for (const [k, v] of Object.entries(this.rails)) {
|
|
22956
|
+
if (isStripeRailSpec2(v) || isTempoSessionRailSpec3(v)) continue;
|
|
22957
|
+
if (isSolanaNetwork(v) || "rpcUrl" in v || "tokenProgram" in v) return k;
|
|
22958
|
+
}
|
|
22959
|
+
return void 0;
|
|
22960
|
+
}
|
|
22961
|
+
if (method === "tempo") {
|
|
22962
|
+
for (const [k, v] of Object.entries(this.rails)) {
|
|
22963
|
+
if (isStripeRailSpec2(v)) continue;
|
|
22964
|
+
if (isSolanaNetwork(v) || "rpcUrl" in v || "tokenProgram" in v) continue;
|
|
22965
|
+
if (isEvmNetwork(v)) continue;
|
|
22966
|
+
return k;
|
|
22967
|
+
}
|
|
22968
|
+
return void 0;
|
|
22969
|
+
}
|
|
22970
|
+
return void 0;
|
|
22971
|
+
}
|
|
22862
22972
|
/** CAIP-2 read from `rails['x402_base'].network` (or its default).
|
|
22863
22973
|
* Defined only when an `X402BaseRailSpec` is present in rails AND a server
|
|
22864
22974
|
* is configured (explicit or auto-derived); otherwise `null`. */
|
|
22865
22975
|
get x402BaseNetwork() {
|
|
22866
22976
|
if (!this.x402ServerAvailable()) return null;
|
|
22867
22977
|
for (const spec of Object.values(this.rails)) {
|
|
22868
|
-
if (!isStripeRailSpec2(spec) && !isTempoSessionRailSpec3(spec) && (spec
|
|
22978
|
+
if (!isStripeRailSpec2(spec) && !isTempoSessionRailSpec3(spec) && isEvmNetwork(spec)) {
|
|
22869
22979
|
return spec.network ?? "eip155:8453";
|
|
22870
22980
|
}
|
|
22871
22981
|
}
|
|
@@ -22917,8 +23027,8 @@ var Checkout = class {
|
|
|
22917
23027
|
throw err;
|
|
22918
23028
|
}
|
|
22919
23029
|
}
|
|
22920
|
-
const
|
|
22921
|
-
if (this.gate !== void 0 &&
|
|
23030
|
+
const hasPaymentHeader2 = hasX402Header(request.headers) || hasMppxHeader(request.headers);
|
|
23031
|
+
if (this.gate !== void 0 && hasPaymentHeader2) {
|
|
22922
23032
|
const denial = await this.runGate(ctx);
|
|
22923
23033
|
if (denial !== null) {
|
|
22924
23034
|
return {
|
|
@@ -23008,7 +23118,7 @@ var Checkout = class {
|
|
|
23008
23118
|
...policyOverride ?? {}
|
|
23009
23119
|
};
|
|
23010
23120
|
const core = createAgentScoreCore(coreOpts);
|
|
23011
|
-
const headers =
|
|
23121
|
+
const headers = normalizeHeadersToLowercase(ctx.request.headers);
|
|
23012
23122
|
const walletAddress = headers["x-wallet-address"];
|
|
23013
23123
|
const operatorToken = headers["x-operator-token"];
|
|
23014
23124
|
const identity = walletAddress !== void 0 || operatorToken !== void 0 ? {
|
|
@@ -23070,7 +23180,7 @@ var Checkout = class {
|
|
|
23070
23180
|
if (!this.zeroSettleCarveOut || ctx.pricing === null) return null;
|
|
23071
23181
|
const cents = Math.round(ctx.pricing.amountUsd * 100);
|
|
23072
23182
|
if (cents !== 0) return null;
|
|
23073
|
-
const headers =
|
|
23183
|
+
const headers = normalizeHeadersToLowercase(ctx.request.headers);
|
|
23074
23184
|
let zero;
|
|
23075
23185
|
if (rail === "x402-base") {
|
|
23076
23186
|
const x402Header = headers["payment-signature"] ?? headers["x-payment"];
|
|
@@ -23144,7 +23254,7 @@ var Checkout = class {
|
|
|
23144
23254
|
resourceConfig: {
|
|
23145
23255
|
scheme: "exact",
|
|
23146
23256
|
network: verified.signedNetwork,
|
|
23147
|
-
price: `$${ctx.pricing.amountUsd.toFixed(2)}`,
|
|
23257
|
+
price: `$${ctx.pricing.amountUsd.toFixed(ctx.pricing.decimals ?? 2)}`,
|
|
23148
23258
|
payTo: verified.signedPayTo,
|
|
23149
23259
|
maxTimeoutSeconds: 300
|
|
23150
23260
|
},
|
|
@@ -23205,15 +23315,20 @@ var Checkout = class {
|
|
|
23205
23315
|
}
|
|
23206
23316
|
const composed = await this.composeMppx(ctx);
|
|
23207
23317
|
if (composed.status === 200) {
|
|
23318
|
+
const paymentReceiptHeader = composed.paymentReceiptHeader ?? extractMppxReceiptHeaderFromRaw(composed.raw);
|
|
23319
|
+
const directMethod = composed.raw?.receipt?.method;
|
|
23320
|
+
const headerMethod = paymentReceiptHeader ? await extractMppxReceiptMethod(paymentReceiptHeader) : void 0;
|
|
23321
|
+
const receiptMethod = directMethod ?? headerMethod;
|
|
23322
|
+
const derivedKey = typeof receiptMethod === "string" ? this.railsKeyForMppxMethod(receiptMethod) : void 0;
|
|
23208
23323
|
const outcome = {
|
|
23209
23324
|
rail: "mpp",
|
|
23210
23325
|
paymentResponseHeader: composed.paymentResponseHeader ?? null,
|
|
23211
|
-
paymentReceiptHeader
|
|
23326
|
+
paymentReceiptHeader,
|
|
23212
23327
|
raw: composed.raw,
|
|
23213
23328
|
txHash: composed.txHash ?? null,
|
|
23214
23329
|
signerAddress: composed.signerAddress ?? null,
|
|
23215
23330
|
signerNetwork: composed.signerNetwork ?? null,
|
|
23216
|
-
railKey: composed.railKey ?? this.mppRailKey()
|
|
23331
|
+
railKey: derivedKey ?? composed.railKey ?? this.mppRailKey()
|
|
23217
23332
|
};
|
|
23218
23333
|
return await this.buildSuccess(ctx, outcome);
|
|
23219
23334
|
}
|
|
@@ -23248,15 +23363,18 @@ var Checkout = class {
|
|
|
23248
23363
|
howToPayRails[k] = v;
|
|
23249
23364
|
}
|
|
23250
23365
|
}
|
|
23366
|
+
const pricingDecimals = ctx.pricing.decimals ?? 2;
|
|
23251
23367
|
const howToPay = buildHowToPay({
|
|
23252
23368
|
url: this.url,
|
|
23253
23369
|
retryBodyJson: JSON.stringify(ctx.request.body),
|
|
23254
|
-
totalUsd: ctx.pricing.amountUsd.toFixed(
|
|
23255
|
-
rails: howToPayRails
|
|
23370
|
+
totalUsd: ctx.pricing.amountUsd.toFixed(pricingDecimals),
|
|
23371
|
+
rails: howToPayRails,
|
|
23372
|
+
...ctx.pricing.decimals !== void 0 && { decimals: ctx.pricing.decimals }
|
|
23256
23373
|
});
|
|
23257
23374
|
const pricingBlock = ctx.pricing.block ?? buildPricingBlock({
|
|
23258
|
-
subtotalCents:
|
|
23259
|
-
currency: ctx.pricing.currency ?? "USD"
|
|
23375
|
+
subtotalCents: ctx.pricing.amountUsd * 100,
|
|
23376
|
+
currency: ctx.pricing.currency ?? "USD",
|
|
23377
|
+
...ctx.pricing.decimals !== void 0 && { decimals: ctx.pricing.decimals }
|
|
23260
23378
|
});
|
|
23261
23379
|
let x402Accepts = [];
|
|
23262
23380
|
let x402Resource;
|
|
@@ -23269,7 +23387,7 @@ var Checkout = class {
|
|
|
23269
23387
|
try {
|
|
23270
23388
|
x402Accepts = await buildX402AcceptsFor402(x402Server, {
|
|
23271
23389
|
network: baseNetwork,
|
|
23272
|
-
price: `$${ctx.pricing.amountUsd.toFixed(
|
|
23390
|
+
price: `$${ctx.pricing.amountUsd.toFixed(pricingDecimals)}`,
|
|
23273
23391
|
payTo: recipient,
|
|
23274
23392
|
maxTimeoutSeconds: 300
|
|
23275
23393
|
});
|
|
@@ -23285,7 +23403,7 @@ var Checkout = class {
|
|
|
23285
23403
|
agentInstructions: buildAgentInstructions({ howToPay }),
|
|
23286
23404
|
...identityMetadata !== void 0 ? { identityMetadata } : {},
|
|
23287
23405
|
pricing: pricingBlock,
|
|
23288
|
-
amountUsd: ctx.pricing.amountUsd.toFixed(
|
|
23406
|
+
amountUsd: ctx.pricing.amountUsd.toFixed(pricingDecimals),
|
|
23289
23407
|
retryBody: ctx.request.body,
|
|
23290
23408
|
agentMemory: firstEncounterAgentMemory({ firstEncounter: true }),
|
|
23291
23409
|
...ctx.pricing.product ? { product: ctx.pricing.product } : {},
|
|
@@ -23393,17 +23511,6 @@ function stripContentType(headers) {
|
|
|
23393
23511
|
}
|
|
23394
23512
|
return out;
|
|
23395
23513
|
}
|
|
23396
|
-
function extractMppxReceiptHeaderFromRaw(raw) {
|
|
23397
|
-
if (!raw || typeof raw !== "object" || !("withReceipt" in raw)) return null;
|
|
23398
|
-
const fn = raw.withReceipt;
|
|
23399
|
-
if (typeof fn !== "function") return null;
|
|
23400
|
-
try {
|
|
23401
|
-
const wrapped = fn.call(raw, new Response());
|
|
23402
|
-
return wrapped.headers.get("Payment-Receipt");
|
|
23403
|
-
} catch {
|
|
23404
|
-
return null;
|
|
23405
|
-
}
|
|
23406
|
-
}
|
|
23407
23514
|
function headersToRecord(h) {
|
|
23408
23515
|
if (h === void 0) return {};
|
|
23409
23516
|
if (h instanceof Headers) {
|
|
@@ -23717,6 +23824,15 @@ import { createHash } from "crypto";
|
|
|
23717
23824
|
function hashOperatorToken(plaintext) {
|
|
23718
23825
|
return createHash("sha256").update(plaintext, "utf8").digest("hex");
|
|
23719
23826
|
}
|
|
23827
|
+
function extractOwnerScope(input) {
|
|
23828
|
+
const headers = asHeaders(input);
|
|
23829
|
+
const walletAddress = readHeader(headers, "x-wallet-address");
|
|
23830
|
+
const operatorToken = readHeader(headers, "x-operator-token");
|
|
23831
|
+
return {
|
|
23832
|
+
...walletAddress ? { walletAddress } : {},
|
|
23833
|
+
...operatorToken ? { operatorTokenHash: hashOperatorToken(operatorToken) } : {}
|
|
23834
|
+
};
|
|
23835
|
+
}
|
|
23720
23836
|
|
|
23721
23837
|
// src/payment/index.ts
|
|
23722
23838
|
init_directive();
|
|
@@ -23730,8 +23846,45 @@ init_directive();
|
|
|
23730
23846
|
init_wwwauthenticate();
|
|
23731
23847
|
|
|
23732
23848
|
// src/payment/amounts.ts
|
|
23733
|
-
function
|
|
23734
|
-
|
|
23849
|
+
function usdToAtomic(usd, opts) {
|
|
23850
|
+
const { decimals } = opts;
|
|
23851
|
+
if (!Number.isInteger(decimals) || decimals < 0) {
|
|
23852
|
+
throw new RangeError(`decimals must be a non-negative integer, got ${decimals}`);
|
|
23853
|
+
}
|
|
23854
|
+
if (typeof usd === "number") {
|
|
23855
|
+
if (!Number.isFinite(usd)) {
|
|
23856
|
+
throw new RangeError(`usd must be finite, got ${usd}`);
|
|
23857
|
+
}
|
|
23858
|
+
if (usd < 0) {
|
|
23859
|
+
throw new RangeError(`usd must be non-negative, got ${usd}`);
|
|
23860
|
+
}
|
|
23861
|
+
}
|
|
23862
|
+
const s = (typeof usd === "number" ? usd.toString() : usd).trim();
|
|
23863
|
+
if (s.startsWith("-")) {
|
|
23864
|
+
throw new RangeError(`usd must be non-negative, got ${s}`);
|
|
23865
|
+
}
|
|
23866
|
+
if (s === "NaN" || s === "Infinity") {
|
|
23867
|
+
throw new RangeError(`usd must be finite, got ${s}`);
|
|
23868
|
+
}
|
|
23869
|
+
const match = /^(\d*)(?:\.(\d*))?$/.exec(s);
|
|
23870
|
+
if (!match || match[1] === "" && (match[2] === void 0 || match[2] === "")) {
|
|
23871
|
+
throw new SyntaxError(`invalid usd value: ${JSON.stringify(usd)}`);
|
|
23872
|
+
}
|
|
23873
|
+
const intPart = match[1] || "0";
|
|
23874
|
+
const fracPart = match[2] ?? "";
|
|
23875
|
+
if (fracPart.length <= decimals) {
|
|
23876
|
+
return BigInt(intPart + fracPart.padEnd(decimals, "0"));
|
|
23877
|
+
}
|
|
23878
|
+
const kept = fracPart.slice(0, decimals);
|
|
23879
|
+
const roundDigit = fracPart[decimals];
|
|
23880
|
+
let result = BigInt(intPart + kept);
|
|
23881
|
+
if (roundDigit >= "5") {
|
|
23882
|
+
result += 1n;
|
|
23883
|
+
}
|
|
23884
|
+
return result;
|
|
23885
|
+
}
|
|
23886
|
+
function formatUsdCents(cents, decimals = 2) {
|
|
23887
|
+
return (cents / 100).toFixed(decimals);
|
|
23735
23888
|
}
|
|
23736
23889
|
|
|
23737
23890
|
// src/payment/solana.ts
|
|
@@ -23754,7 +23907,631 @@ async function loadSolanaFeePayer(opts) {
|
|
|
23754
23907
|
}
|
|
23755
23908
|
return kit.createKeyPairSignerFromPrivateKeyBytes(bytes);
|
|
23756
23909
|
}
|
|
23910
|
+
|
|
23911
|
+
// src/payment/compose_rails.ts
|
|
23912
|
+
init_usdc();
|
|
23913
|
+
function buildMppxComposeRails(opts) {
|
|
23914
|
+
const rails2 = [];
|
|
23915
|
+
if (opts.tempoRecipient) {
|
|
23916
|
+
rails2.push(["tempo/charge", {
|
|
23917
|
+
amount: opts.amountUsd,
|
|
23918
|
+
currency: opts.tempoTokenAddress ?? USDC.tempo.mainnet.address,
|
|
23919
|
+
decimals: 6,
|
|
23920
|
+
recipient: opts.tempoRecipient
|
|
23921
|
+
}]);
|
|
23922
|
+
}
|
|
23923
|
+
if (opts.solanaRecipient) {
|
|
23924
|
+
const atomic = usdToAtomic(opts.amountUsd, { decimals: 6 });
|
|
23925
|
+
rails2.push(["solana/charge", {
|
|
23926
|
+
amount: atomic.toString(),
|
|
23927
|
+
currency: opts.solanaTokenMint ?? USDC.solana.mainnet.mint,
|
|
23928
|
+
decimals: 6,
|
|
23929
|
+
recipient: opts.solanaRecipient,
|
|
23930
|
+
network: opts.solanaNetwork ?? "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
|
|
23931
|
+
}]);
|
|
23932
|
+
}
|
|
23933
|
+
if (opts.includeStripe !== false) {
|
|
23934
|
+
rails2.push(["stripe/charge", { amount: opts.amountUsd, currency: "usd", decimals: 2 }]);
|
|
23935
|
+
}
|
|
23936
|
+
return rails2;
|
|
23937
|
+
}
|
|
23938
|
+
|
|
23939
|
+
// src/payment/default_rails.ts
|
|
23940
|
+
init_networks();
|
|
23941
|
+
init_usdc();
|
|
23942
|
+
function buildDefaultCheckoutRails(opts) {
|
|
23943
|
+
const out = {};
|
|
23944
|
+
if (opts.tempo) {
|
|
23945
|
+
out.tempo = { recipient: "", ...RAIL_SPEC_DEFAULTS.tempo, ...opts.tempo };
|
|
23946
|
+
}
|
|
23947
|
+
if (opts.x402Base) {
|
|
23948
|
+
const merged = { recipient: "", ...RAIL_SPEC_DEFAULTS.x402Base, ...opts.x402Base };
|
|
23949
|
+
if (merged.network === networks.base.sepolia.caip2) {
|
|
23950
|
+
if (opts.x402Base.chainId === void 0) merged.chainId = networks.base.sepolia.chainId;
|
|
23951
|
+
if (opts.x402Base.token === void 0) merged.token = USDC.base.sepolia.address;
|
|
23952
|
+
} else if (merged.network === networks.base.mainnet.caip2) {
|
|
23953
|
+
if (opts.x402Base.chainId === void 0) merged.chainId = networks.base.mainnet.chainId;
|
|
23954
|
+
if (opts.x402Base.token === void 0) merged.token = USDC.base.mainnet.address;
|
|
23955
|
+
}
|
|
23956
|
+
out.x402_base = merged;
|
|
23957
|
+
}
|
|
23958
|
+
if (opts.solanaMpp) {
|
|
23959
|
+
const merged = { recipient: "", ...RAIL_SPEC_DEFAULTS.solanaMpp, ...opts.solanaMpp };
|
|
23960
|
+
const isDevnet = merged.network === "devnet" || merged.network === networks.solana.devnet.caip2;
|
|
23961
|
+
if (isDevnet && opts.solanaMpp.token === void 0) {
|
|
23962
|
+
merged.token = USDC.solana.devnet.mint;
|
|
23963
|
+
}
|
|
23964
|
+
out.solana_mpp = merged;
|
|
23965
|
+
}
|
|
23966
|
+
if (opts.stripe) {
|
|
23967
|
+
out.stripe = { ...RAIL_SPEC_DEFAULTS.stripe, ...opts.stripe };
|
|
23968
|
+
}
|
|
23969
|
+
return out;
|
|
23970
|
+
}
|
|
23971
|
+
|
|
23972
|
+
// src/payment/index.ts
|
|
23973
|
+
init_network_kind();
|
|
23974
|
+
|
|
23975
|
+
// src/checkout_compute_first.ts
|
|
23976
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
23977
|
+
|
|
23978
|
+
// src/discovery/index.ts
|
|
23979
|
+
init_probe();
|
|
23980
|
+
|
|
23981
|
+
// src/discovery/agentscore_content.ts
|
|
23982
|
+
var PURCHASE_MODE_NOTES = Object.freeze({
|
|
23983
|
+
redemption_only: "Requires a single-use redemption code (printed on a mailer or other out-of-band delivery). Submit the code in the request body as `redemption_code`. Without a valid code the order is rejected.",
|
|
23984
|
+
coupon_applicable: "Codes are optional. Without one, settle at list price. With a valid code the discount is applied automatically (percent_off, fixed_off, or fixed_settle).",
|
|
23985
|
+
paid_only: "Codes are NOT accepted. Settle at the listed price. Submitting a `redemption_code` field returns 400 codes_not_accepted."
|
|
23986
|
+
});
|
|
23987
|
+
function buildSuccessNextSteps(opts) {
|
|
23988
|
+
const out = {
|
|
23989
|
+
action: "done",
|
|
23990
|
+
user_message: opts.userMessage ?? "Payment complete. Your AgentScore Passport is now active across every AgentScore-gated merchant."
|
|
23991
|
+
};
|
|
23992
|
+
if (opts.orderStatusUrl) out.order_status_url = opts.orderStatusUrl;
|
|
23993
|
+
if (opts.fulfillmentEta !== void 0) out.fulfillment_eta = opts.fulfillmentEta;
|
|
23994
|
+
return out;
|
|
23995
|
+
}
|
|
23996
|
+
|
|
23997
|
+
// src/discovery/index.ts
|
|
23998
|
+
init_well_known();
|
|
23999
|
+
|
|
24000
|
+
// src/quote_cache.ts
|
|
24001
|
+
import { createHash as createHash2 } from "crypto";
|
|
24002
|
+
|
|
24003
|
+
// src/_redis.ts
|
|
24004
|
+
async function tryCreateRedis(opts) {
|
|
24005
|
+
const url2 = opts.url ?? process.env.REDIS_URL;
|
|
24006
|
+
if (!url2) return null;
|
|
24007
|
+
try {
|
|
24008
|
+
const mod = await import("ioredis");
|
|
24009
|
+
const client = new mod.default(url2, {
|
|
24010
|
+
connectTimeout: opts.connectTimeout ?? 3e3,
|
|
24011
|
+
maxRetriesPerRequest: opts.maxRetriesPerRequest ?? 1,
|
|
24012
|
+
tls: url2.startsWith("rediss://") ? {} : void 0
|
|
24013
|
+
});
|
|
24014
|
+
client.on("error", (err) => console.error(`[${opts.label}] Redis error:`, err.message));
|
|
24015
|
+
return client;
|
|
24016
|
+
} catch {
|
|
24017
|
+
return null;
|
|
24018
|
+
}
|
|
24019
|
+
}
|
|
24020
|
+
function memoizedRedis(opts) {
|
|
24021
|
+
let promise2 = null;
|
|
24022
|
+
return () => {
|
|
24023
|
+
if (!promise2) promise2 = tryCreateRedis(opts);
|
|
24024
|
+
return promise2;
|
|
24025
|
+
};
|
|
24026
|
+
}
|
|
24027
|
+
|
|
24028
|
+
// src/quote_cache.ts
|
|
24029
|
+
function canonicalize2(value) {
|
|
24030
|
+
if (Array.isArray(value)) return value.map(canonicalize2);
|
|
24031
|
+
if (value && typeof value === "object") {
|
|
24032
|
+
const sorted = {};
|
|
24033
|
+
for (const key of Object.keys(value).sort()) {
|
|
24034
|
+
sorted[key] = canonicalize2(value[key]);
|
|
24035
|
+
}
|
|
24036
|
+
return sorted;
|
|
24037
|
+
}
|
|
24038
|
+
return value;
|
|
24039
|
+
}
|
|
24040
|
+
function createQuoteCache(opts = {}) {
|
|
24041
|
+
const ttlMs = opts.ttlMs ?? 5 * 6e4;
|
|
24042
|
+
const keyPrefix = opts.keyPrefix ?? "quote:";
|
|
24043
|
+
const memMap = /* @__PURE__ */ new Map();
|
|
24044
|
+
const getRedis = memoizedRedis({ url: opts.redisUrl, label: "quote-cache" });
|
|
24045
|
+
const evictExpired = () => {
|
|
24046
|
+
const now = Date.now();
|
|
24047
|
+
for (const [k, v] of memMap.entries()) {
|
|
24048
|
+
if (v.expiresAt <= now) memMap.delete(k);
|
|
24049
|
+
}
|
|
24050
|
+
};
|
|
24051
|
+
return {
|
|
24052
|
+
bodyHashKey(prefix, body) {
|
|
24053
|
+
const canonical = JSON.stringify(canonicalize2(body));
|
|
24054
|
+
const hash3 = createHash2("sha256").update(`${prefix}::${canonical}`).digest("hex").slice(0, 24);
|
|
24055
|
+
return `${prefix}::${hash3}`;
|
|
24056
|
+
},
|
|
24057
|
+
async read(key) {
|
|
24058
|
+
const r = await getRedis();
|
|
24059
|
+
if (r) {
|
|
24060
|
+
try {
|
|
24061
|
+
const raw = await r.get(`${keyPrefix}${key}`);
|
|
24062
|
+
if (!raw) return null;
|
|
24063
|
+
return JSON.parse(raw);
|
|
24064
|
+
} catch {
|
|
24065
|
+
}
|
|
24066
|
+
}
|
|
24067
|
+
evictExpired();
|
|
24068
|
+
const entry = memMap.get(key);
|
|
24069
|
+
return entry ? entry.entry : null;
|
|
24070
|
+
},
|
|
24071
|
+
async write(key, body, priceCents, recipients = {}) {
|
|
24072
|
+
const cached2 = { body, priceCents, recipients };
|
|
24073
|
+
const r = await getRedis();
|
|
24074
|
+
if (r) {
|
|
24075
|
+
try {
|
|
24076
|
+
await r.set(`${keyPrefix}${key}`, JSON.stringify(cached2), "PX", ttlMs);
|
|
24077
|
+
return;
|
|
24078
|
+
} catch {
|
|
24079
|
+
}
|
|
24080
|
+
}
|
|
24081
|
+
memMap.set(key, { entry: cached2, expiresAt: Date.now() + ttlMs });
|
|
24082
|
+
},
|
|
24083
|
+
async clear() {
|
|
24084
|
+
memMap.clear();
|
|
24085
|
+
const r = await getRedis();
|
|
24086
|
+
if (r) {
|
|
24087
|
+
try {
|
|
24088
|
+
await r.flushdb();
|
|
24089
|
+
} catch {
|
|
24090
|
+
}
|
|
24091
|
+
}
|
|
24092
|
+
}
|
|
24093
|
+
};
|
|
24094
|
+
}
|
|
24095
|
+
|
|
24096
|
+
// src/checkout_compute_first.ts
|
|
24097
|
+
var DEFAULT_TTL_MS = 5 * 6e4;
|
|
24098
|
+
function decimalsForUnit(unitPriceCents) {
|
|
24099
|
+
if (Number.isInteger(unitPriceCents)) return 2;
|
|
24100
|
+
const str = unitPriceCents.toString();
|
|
24101
|
+
const dotIdx = str.indexOf(".");
|
|
24102
|
+
const frac = dotIdx === -1 ? 0 : str.length - dotIdx - 1;
|
|
24103
|
+
return 2 + frac;
|
|
24104
|
+
}
|
|
24105
|
+
function computeFirstCheckout(opts) {
|
|
24106
|
+
const cache = opts.cache ?? createQuoteCache({ ttlMs: opts.cacheTtlMs ?? DEFAULT_TTL_MS });
|
|
24107
|
+
const decimals = opts.decimals ?? decimalsForUnit(opts.unitPriceCents);
|
|
24108
|
+
const appUrl = opts.appUrl ?? new URL(opts.url).origin;
|
|
24109
|
+
async function mintAndResolveRecipients(req, body, priceCents) {
|
|
24110
|
+
const minted = opts.mintRecipients ? await opts.mintRecipients({ request: req, body, priceCents }) : {};
|
|
24111
|
+
const out = {};
|
|
24112
|
+
const tempo = minted.tempo ?? (opts.rails.tempo ? await resolveRecipient(opts.rails.tempo.recipient) : void 0);
|
|
24113
|
+
const x402Base = minted.x402_base ?? (opts.rails.x402_base ? await resolveRecipient(opts.rails.x402_base.recipient) : void 0);
|
|
24114
|
+
const solana = minted.solana_mpp ?? (opts.rails.solana_mpp ? await resolveRecipient(opts.rails.solana_mpp.recipient) : void 0);
|
|
24115
|
+
if (tempo) out.tempo = tempo;
|
|
24116
|
+
if (x402Base) out.x402_base = x402Base;
|
|
24117
|
+
if (solana) out.solana_mpp = solana;
|
|
24118
|
+
return out;
|
|
24119
|
+
}
|
|
24120
|
+
async function emit402(req, body, priceCents, recipients) {
|
|
24121
|
+
const totalUsd = formatUsdCents(priceCents, decimals);
|
|
24122
|
+
const tempoRecipient = recipients.tempo;
|
|
24123
|
+
const x402BaseRecipient = recipients.x402_base;
|
|
24124
|
+
const solanaRecipient = recipients.solana_mpp;
|
|
24125
|
+
const accepted = await buildAcceptedMethods({
|
|
24126
|
+
...tempoRecipient && opts.rails.tempo && { tempo: { ...opts.rails.tempo, recipient: tempoRecipient } },
|
|
24127
|
+
...solanaRecipient && opts.rails.solana_mpp && { solana_mpp: { ...opts.rails.solana_mpp, recipient: solanaRecipient } },
|
|
24128
|
+
...opts.rails.stripe && { stripe: opts.rails.stripe }
|
|
24129
|
+
});
|
|
24130
|
+
if (x402BaseRecipient && opts.rails.x402_base) {
|
|
24131
|
+
try {
|
|
24132
|
+
const resolvedX402PayTo = await resolveRecipient(x402BaseRecipient);
|
|
24133
|
+
const x402Entries = await buildX402AcceptsFor402(opts.x402Server, {
|
|
24134
|
+
network: opts.rails.x402_base.network ?? "eip155:8453",
|
|
24135
|
+
price: `$${totalUsd}`,
|
|
24136
|
+
payTo: resolvedX402PayTo,
|
|
24137
|
+
maxTimeoutSeconds: 300
|
|
24138
|
+
});
|
|
24139
|
+
accepted.push(...x402Entries);
|
|
24140
|
+
} catch (err) {
|
|
24141
|
+
console.warn(
|
|
24142
|
+
`[${opts.name}.computeFirst] buildX402AcceptsFor402 failed; dropping x402 from accepts:`,
|
|
24143
|
+
err instanceof Error ? err.message : err
|
|
24144
|
+
);
|
|
24145
|
+
}
|
|
24146
|
+
}
|
|
24147
|
+
const howToPay = buildHowToPay({
|
|
24148
|
+
url: opts.url,
|
|
24149
|
+
retryBodyJson: JSON.stringify(body),
|
|
24150
|
+
totalUsd,
|
|
24151
|
+
decimals,
|
|
24152
|
+
rails: {
|
|
24153
|
+
...tempoRecipient && opts.rails.tempo && { tempo: { ...opts.rails.tempo, recipient: tempoRecipient } },
|
|
24154
|
+
...x402BaseRecipient && opts.rails.x402_base && { x402_base: { ...opts.rails.x402_base, recipient: x402BaseRecipient } },
|
|
24155
|
+
...solanaRecipient && opts.rails.solana_mpp && { solana_mpp: { ...opts.rails.solana_mpp, recipient: solanaRecipient } },
|
|
24156
|
+
...opts.rails.stripe && { stripe: opts.rails.stripe }
|
|
24157
|
+
}
|
|
24158
|
+
});
|
|
24159
|
+
const pricing = buildPricingBlock({ subtotalCents: priceCents, currency: "USD", decimals });
|
|
24160
|
+
const agentInstructions = buildAgentInstructions({
|
|
24161
|
+
howToPay,
|
|
24162
|
+
warnings: [
|
|
24163
|
+
"The quoted price is exact: it was derived from the actual number of results returned by the work on the probe leg.",
|
|
24164
|
+
"The merchant cached the result against a hash of this request body. Retry with the same body within the quote TTL (default 5 min) to settle and receive the cached results; if the quote expires, re-probe."
|
|
24165
|
+
]
|
|
24166
|
+
});
|
|
24167
|
+
let mppChallengeHeaders = {};
|
|
24168
|
+
if (opts.composeMppx) {
|
|
24169
|
+
try {
|
|
24170
|
+
const mppResult = await opts.composeMppx({
|
|
24171
|
+
request: req,
|
|
24172
|
+
cachedBody: body,
|
|
24173
|
+
priceCents,
|
|
24174
|
+
priceUsd: totalUsd,
|
|
24175
|
+
recipients
|
|
24176
|
+
});
|
|
24177
|
+
if (mppResult.status === 402 && mppResult.headers) {
|
|
24178
|
+
mppChallengeHeaders = mppResult.headers;
|
|
24179
|
+
}
|
|
24180
|
+
} catch (err) {
|
|
24181
|
+
console.warn(
|
|
24182
|
+
`[${opts.name}.computeFirst] composeMppx probe-leg failed; dropping MPP rails from 402 challenge:`,
|
|
24183
|
+
err instanceof Error ? err.message : err
|
|
24184
|
+
);
|
|
24185
|
+
}
|
|
24186
|
+
}
|
|
24187
|
+
const body402 = build402Body({
|
|
24188
|
+
product: { id: opts.name, name: opts.name },
|
|
24189
|
+
acceptedMethods: accepted,
|
|
24190
|
+
pricing,
|
|
24191
|
+
agentInstructions,
|
|
24192
|
+
amountUsd: totalUsd,
|
|
24193
|
+
currency: "USD",
|
|
24194
|
+
orderId: null,
|
|
24195
|
+
retryBody: body
|
|
24196
|
+
});
|
|
24197
|
+
const headers = new Headers({ "Content-Type": "application/json" });
|
|
24198
|
+
for (const [k, v] of Object.entries(mppChallengeHeaders)) headers.set(k, v);
|
|
24199
|
+
headers.set(
|
|
24200
|
+
"PAYMENT-REQUIRED",
|
|
24201
|
+
paymentRequiredHeader({ x402Version: 2, accepts: accepted, resource: { url: opts.url } })
|
|
24202
|
+
);
|
|
24203
|
+
return new Response(JSON.stringify(body402), { status: 402, headers });
|
|
24204
|
+
}
|
|
24205
|
+
async function handleX402Settle(req, referenceId, cachedBody, priceCents, recipients) {
|
|
24206
|
+
const verified = await verifyX402Request({
|
|
24207
|
+
request: req,
|
|
24208
|
+
isCachedAddress: async () => true,
|
|
24209
|
+
acceptedNetwork: opts.rails.x402_base?.network ?? "eip155:8453"
|
|
24210
|
+
});
|
|
24211
|
+
if (!verified.ok) {
|
|
24212
|
+
return new Response(JSON.stringify(verified.body), {
|
|
24213
|
+
status: verified.status,
|
|
24214
|
+
headers: { "Content-Type": "application/json" }
|
|
24215
|
+
});
|
|
24216
|
+
}
|
|
24217
|
+
const actualUsd = formatUsdCents(priceCents, decimals);
|
|
24218
|
+
const settle = await processX402Settle({
|
|
24219
|
+
x402Server: opts.x402Server,
|
|
24220
|
+
payload: verified.payload,
|
|
24221
|
+
resourceConfig: {
|
|
24222
|
+
scheme: "exact",
|
|
24223
|
+
network: verified.signedNetwork,
|
|
24224
|
+
price: `$${actualUsd}`,
|
|
24225
|
+
payTo: verified.signedPayTo,
|
|
24226
|
+
maxTimeoutSeconds: 300
|
|
24227
|
+
},
|
|
24228
|
+
resourceMeta: {
|
|
24229
|
+
url: req.url,
|
|
24230
|
+
description: `Agent purchase via x402-exact (${opts.name})`,
|
|
24231
|
+
mimeType: "application/json"
|
|
24232
|
+
}
|
|
24233
|
+
});
|
|
24234
|
+
if (!settle.success) {
|
|
24235
|
+
const detail = settle.error?.message ?? "unknown";
|
|
24236
|
+
return new Response(
|
|
24237
|
+
JSON.stringify({
|
|
24238
|
+
id: referenceId,
|
|
24239
|
+
endpoint: opts.name,
|
|
24240
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24241
|
+
payment_status: "failed",
|
|
24242
|
+
charged_usd: "0.00",
|
|
24243
|
+
rail: `x402-base (${verified.signedNetwork})`,
|
|
24244
|
+
error: {
|
|
24245
|
+
code: "settle_failed",
|
|
24246
|
+
message: "Facilitator rejected the exact settle; no on-chain capture occurred.",
|
|
24247
|
+
detail
|
|
24248
|
+
}
|
|
24249
|
+
}),
|
|
24250
|
+
{ status: 502, headers: { "Content-Type": "application/json" } }
|
|
24251
|
+
);
|
|
24252
|
+
}
|
|
24253
|
+
const signer = await extractPaymentSigner(req, readX402PaymentHeader(req));
|
|
24254
|
+
const signerInfo = signer ? { address: signer.address, network: signer.network } : void 0;
|
|
24255
|
+
const railLabel = `Base (${verified.signedNetwork})`;
|
|
24256
|
+
if (opts.onSettled) {
|
|
24257
|
+
try {
|
|
24258
|
+
await opts.onSettled({
|
|
24259
|
+
request: req,
|
|
24260
|
+
rail: "x402",
|
|
24261
|
+
cachedBody,
|
|
24262
|
+
priceCents,
|
|
24263
|
+
priceUsd: actualUsd,
|
|
24264
|
+
recipients,
|
|
24265
|
+
...signerInfo ? { signer: signerInfo } : {}
|
|
24266
|
+
});
|
|
24267
|
+
} catch (err) {
|
|
24268
|
+
console.warn(`[${opts.name}.computeFirst.onSettled] x402 side-effect failed:`, err instanceof Error ? err.message : err);
|
|
24269
|
+
}
|
|
24270
|
+
}
|
|
24271
|
+
const buildBody = opts.buildSuccessBody ?? defaultSuccessBody(appUrl);
|
|
24272
|
+
const body = buildBody({
|
|
24273
|
+
referenceId,
|
|
24274
|
+
endpoint: opts.name,
|
|
24275
|
+
chargedUsd: actualUsd,
|
|
24276
|
+
rail: railLabel,
|
|
24277
|
+
...signerInfo ? { signer: signerInfo } : {},
|
|
24278
|
+
cachedBody
|
|
24279
|
+
});
|
|
24280
|
+
return new Response(JSON.stringify(body), { status: 200, headers: { "Content-Type": "application/json" } });
|
|
24281
|
+
}
|
|
24282
|
+
function mppRailLabel(method) {
|
|
24283
|
+
const scheme = method?.split("/")[0];
|
|
24284
|
+
if (scheme === "tempo") {
|
|
24285
|
+
const networkName = opts.rails.tempo?.testnet ? "tempo-testnet" : opts.rails.tempo?.network ?? "tempo-mainnet";
|
|
24286
|
+
return `Tempo (${networkName})`;
|
|
24287
|
+
}
|
|
24288
|
+
if (scheme === "solana") {
|
|
24289
|
+
const networkName = opts.rails.solana_mpp?.network ?? "solana";
|
|
24290
|
+
return `Solana (${networkName})`;
|
|
24291
|
+
}
|
|
24292
|
+
if (scheme === "stripe") return "Stripe (card+link)";
|
|
24293
|
+
return "MPP";
|
|
24294
|
+
}
|
|
24295
|
+
async function handleMppSettle(req, referenceId, cachedBody, priceCents, recipients) {
|
|
24296
|
+
if (!opts.composeMppx) {
|
|
24297
|
+
return new Response(
|
|
24298
|
+
JSON.stringify({
|
|
24299
|
+
id: referenceId,
|
|
24300
|
+
endpoint: opts.name,
|
|
24301
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24302
|
+
payment_status: "failed",
|
|
24303
|
+
charged_usd: "0.00",
|
|
24304
|
+
error: { code: "mpp_unavailable", message: "MPP settle hook not configured on this endpoint." }
|
|
24305
|
+
}),
|
|
24306
|
+
{ status: 503, headers: { "Content-Type": "application/json" } }
|
|
24307
|
+
);
|
|
24308
|
+
}
|
|
24309
|
+
const priceUsd = formatUsdCents(priceCents, decimals);
|
|
24310
|
+
const result = await opts.composeMppx({ request: req, cachedBody, priceCents, priceUsd, recipients });
|
|
24311
|
+
if (result.status !== 200) {
|
|
24312
|
+
const headers = result.headers ?? {};
|
|
24313
|
+
return new Response(
|
|
24314
|
+
JSON.stringify({
|
|
24315
|
+
id: referenceId,
|
|
24316
|
+
endpoint: opts.name,
|
|
24317
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24318
|
+
payment_status: "failed",
|
|
24319
|
+
charged_usd: "0.00",
|
|
24320
|
+
error: { code: "mpp_settle_failed", message: "MPP compose did not return 200; credential rejected." }
|
|
24321
|
+
}),
|
|
24322
|
+
{ status: 400, headers: { "Content-Type": "application/json", ...headers } }
|
|
24323
|
+
);
|
|
24324
|
+
}
|
|
24325
|
+
const signer = result.signerAddress ? { address: result.signerAddress, network: result.signerNetwork ?? "evm" } : await extractPaymentSigner(req, readX402PaymentHeader(req)).then((s) => s ? { address: s.address, network: s.network } : void 0);
|
|
24326
|
+
const method = await deriveMppxReceiptMethod(result.raw);
|
|
24327
|
+
const railLabel = mppRailLabel(method);
|
|
24328
|
+
if (opts.onSettled) {
|
|
24329
|
+
try {
|
|
24330
|
+
await opts.onSettled({
|
|
24331
|
+
request: req,
|
|
24332
|
+
rail: "mpp",
|
|
24333
|
+
mppMethod: method,
|
|
24334
|
+
cachedBody,
|
|
24335
|
+
priceCents,
|
|
24336
|
+
priceUsd,
|
|
24337
|
+
recipients,
|
|
24338
|
+
...signer ? { signer } : {},
|
|
24339
|
+
...result.txHash ? { paymentIntentId: result.txHash } : {}
|
|
24340
|
+
});
|
|
24341
|
+
} catch (err) {
|
|
24342
|
+
console.warn(`[${opts.name}.computeFirst.onSettled] MPP side-effect failed:`, err instanceof Error ? err.message : err);
|
|
24343
|
+
}
|
|
24344
|
+
}
|
|
24345
|
+
const buildBody = opts.buildSuccessBody ?? defaultSuccessBody(appUrl);
|
|
24346
|
+
const body = buildBody({
|
|
24347
|
+
referenceId,
|
|
24348
|
+
endpoint: opts.name,
|
|
24349
|
+
chargedUsd: priceUsd,
|
|
24350
|
+
rail: railLabel,
|
|
24351
|
+
...result.txHash ? { paymentIntentId: result.txHash } : {},
|
|
24352
|
+
...signer ? { signer } : {},
|
|
24353
|
+
cachedBody
|
|
24354
|
+
});
|
|
24355
|
+
return new Response(JSON.stringify(body), { status: 200, headers: { "Content-Type": "application/json" } });
|
|
24356
|
+
}
|
|
24357
|
+
async function handle(req) {
|
|
24358
|
+
const referenceId = `${opts.name}_${randomUUID2()}`;
|
|
24359
|
+
let body;
|
|
24360
|
+
try {
|
|
24361
|
+
body = await req.clone().json();
|
|
24362
|
+
} catch {
|
|
24363
|
+
body = {};
|
|
24364
|
+
}
|
|
24365
|
+
try {
|
|
24366
|
+
opts.validateInput?.(body);
|
|
24367
|
+
} catch (err) {
|
|
24368
|
+
if (err instanceof CheckoutValidationError) {
|
|
24369
|
+
return new Response(
|
|
24370
|
+
JSON.stringify({
|
|
24371
|
+
error: { code: err.code, message: err.message },
|
|
24372
|
+
...err.action ? { next_steps: { action: err.action, user_message: err.message } } : {},
|
|
24373
|
+
...err.extra
|
|
24374
|
+
}),
|
|
24375
|
+
{ status: err.status, headers: { "Content-Type": "application/json" } }
|
|
24376
|
+
);
|
|
24377
|
+
}
|
|
24378
|
+
throw err;
|
|
24379
|
+
}
|
|
24380
|
+
const cacheKey2 = cache.bodyHashKey(opts.name, body);
|
|
24381
|
+
if (hasX402Header(req.headers) || hasMppxHeader(req.headers)) {
|
|
24382
|
+
const quote2 = await cache.read(cacheKey2);
|
|
24383
|
+
if (!quote2) {
|
|
24384
|
+
return new Response(
|
|
24385
|
+
JSON.stringify({
|
|
24386
|
+
id: referenceId,
|
|
24387
|
+
endpoint: opts.name,
|
|
24388
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24389
|
+
payment_status: "failed",
|
|
24390
|
+
charged_usd: "0.00",
|
|
24391
|
+
error: {
|
|
24392
|
+
code: "stale_quote",
|
|
24393
|
+
message: "No active quote for this request body. The quote may have expired or the body changed since the probe."
|
|
24394
|
+
},
|
|
24395
|
+
next_steps: {
|
|
24396
|
+
action: "re_probe",
|
|
24397
|
+
suggestion: "Send the same body without a payment header to get a fresh 402 quote, then retry with the payment credential."
|
|
24398
|
+
}
|
|
24399
|
+
}),
|
|
24400
|
+
{ status: 400, headers: { "Content-Type": "application/json" } }
|
|
24401
|
+
);
|
|
24402
|
+
}
|
|
24403
|
+
if (hasX402Header(req.headers)) return handleX402Settle(req, referenceId, quote2.body, quote2.priceCents, quote2.recipients);
|
|
24404
|
+
return handleMppSettle(req, referenceId, quote2.body, quote2.priceCents, quote2.recipients);
|
|
24405
|
+
}
|
|
24406
|
+
let quote = await cache.read(cacheKey2);
|
|
24407
|
+
if (!quote) {
|
|
24408
|
+
let outcome;
|
|
24409
|
+
try {
|
|
24410
|
+
outcome = await opts.runWork(body, { request: req });
|
|
24411
|
+
} catch {
|
|
24412
|
+
return new Response(
|
|
24413
|
+
JSON.stringify({
|
|
24414
|
+
id: referenceId,
|
|
24415
|
+
endpoint: opts.name,
|
|
24416
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24417
|
+
payment_status: "no_charge",
|
|
24418
|
+
charged_usd: "0.00",
|
|
24419
|
+
result: { matches: [], total: 0 },
|
|
24420
|
+
error: {
|
|
24421
|
+
code: "upstream_failed",
|
|
24422
|
+
message: "The wrapped endpoint failed; no charge was applied."
|
|
24423
|
+
}
|
|
24424
|
+
}),
|
|
24425
|
+
{ status: 200, headers: { "Content-Type": "application/json" } }
|
|
24426
|
+
);
|
|
24427
|
+
}
|
|
24428
|
+
if (outcome.resultCount === 0) {
|
|
24429
|
+
return new Response(
|
|
24430
|
+
JSON.stringify({
|
|
24431
|
+
id: referenceId,
|
|
24432
|
+
endpoint: opts.name,
|
|
24433
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24434
|
+
payment_status: "no_charge",
|
|
24435
|
+
charged_usd: "0.00",
|
|
24436
|
+
result: outcome.body
|
|
24437
|
+
}),
|
|
24438
|
+
{ status: 200, headers: { "Content-Type": "application/json" } }
|
|
24439
|
+
);
|
|
24440
|
+
}
|
|
24441
|
+
const priceCents = opts.unitPriceCents * outcome.resultCount;
|
|
24442
|
+
const recipients = await mintAndResolveRecipients(req, body, priceCents);
|
|
24443
|
+
await cache.write(cacheKey2, outcome.body, priceCents, recipients);
|
|
24444
|
+
quote = { body: outcome.body, priceCents, recipients };
|
|
24445
|
+
}
|
|
24446
|
+
return emit402(req, body, quote.priceCents, quote.recipients);
|
|
24447
|
+
}
|
|
24448
|
+
return {
|
|
24449
|
+
handleWeb: handle,
|
|
24450
|
+
async handleHono(c) {
|
|
24451
|
+
return handle(c.req.raw);
|
|
24452
|
+
}
|
|
24453
|
+
};
|
|
24454
|
+
}
|
|
24455
|
+
function defaultSuccessBody(appUrl) {
|
|
24456
|
+
return ({ referenceId, endpoint, chargedUsd, rail, paymentIntentId, signer, cachedBody }) => ({
|
|
24457
|
+
id: referenceId,
|
|
24458
|
+
endpoint,
|
|
24459
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24460
|
+
payment_status: "completed",
|
|
24461
|
+
charged_usd: chargedUsd,
|
|
24462
|
+
rail,
|
|
24463
|
+
...paymentIntentId ? { payment_intent_id: paymentIntentId } : {},
|
|
24464
|
+
...signer ? { signer } : {},
|
|
24465
|
+
result: cachedBody,
|
|
24466
|
+
next_steps: buildSuccessNextSteps({ orderStatusUrl: `${appUrl}/health` }),
|
|
24467
|
+
agent_memory: firstEncounterAgentMemory({ firstEncounter: true })
|
|
24468
|
+
});
|
|
24469
|
+
}
|
|
24470
|
+
|
|
24471
|
+
// src/identity/default_denied.ts
|
|
24472
|
+
function createDefaultOnDenied(opts) {
|
|
24473
|
+
const supportContext = opts.supportContext ?? "Contact support if you believe this denial is in error.";
|
|
24474
|
+
const paymentRequiredMessage = opts.paymentRequiredMessage ?? "AgentScore tier does not support assess. Contact support.";
|
|
24475
|
+
const walletNotTrustedMessage = opts.walletNotTrustedMessage ?? `Identity check did not satisfy policy for ${opts.merchantName}.`;
|
|
24476
|
+
return function defaultOnDenied(reason) {
|
|
24477
|
+
if (reason.code === "wallet_signer_mismatch" || reason.code === "wallet_auth_requires_wallet_signing") {
|
|
24478
|
+
const body = buildSignerMismatchBody({
|
|
24479
|
+
result: {
|
|
24480
|
+
kind: reason.code,
|
|
24481
|
+
claimedOperator: reason.claimed_operator ?? null,
|
|
24482
|
+
actualSignerOperator: reason.actual_signer_operator ?? null,
|
|
24483
|
+
expectedSigner: reason.expected_signer ?? "",
|
|
24484
|
+
actualSigner: reason.actual_signer ?? "",
|
|
24485
|
+
linkedWallets: reason.linked_wallets ?? [],
|
|
24486
|
+
agentInstructions: reason.agent_instructions ?? "",
|
|
24487
|
+
claimedWallet: reason.expected_signer ?? ""
|
|
24488
|
+
}
|
|
24489
|
+
});
|
|
24490
|
+
return { status: 403, body: body ?? denialReasonToBody(reason) };
|
|
24491
|
+
}
|
|
24492
|
+
if (reason.code === "wallet_not_trusted") {
|
|
24493
|
+
return {
|
|
24494
|
+
status: 403,
|
|
24495
|
+
body: {
|
|
24496
|
+
error: { code: "compliance_denied", message: walletNotTrustedMessage },
|
|
24497
|
+
reasons: reason.reasons ?? [],
|
|
24498
|
+
policy_result: reason.data?.policy_result,
|
|
24499
|
+
verify_url: reason.verify_url,
|
|
24500
|
+
next_steps: buildContactSupportNextSteps(opts.supportEmail, supportContext)
|
|
24501
|
+
}
|
|
24502
|
+
};
|
|
24503
|
+
}
|
|
24504
|
+
if (reason.code === "payment_required") {
|
|
24505
|
+
return {
|
|
24506
|
+
status: 403,
|
|
24507
|
+
body: {
|
|
24508
|
+
...denialReasonToBody(reason),
|
|
24509
|
+
error: { code: "compliance_error", message: paymentRequiredMessage }
|
|
24510
|
+
}
|
|
24511
|
+
};
|
|
24512
|
+
}
|
|
24513
|
+
const status = reason.code === "token_expired" || reason.code === "invalid_credential" ? 401 : reason.code === "api_error" ? 503 : 403;
|
|
24514
|
+
return {
|
|
24515
|
+
status,
|
|
24516
|
+
body: denialReasonToBody(reason),
|
|
24517
|
+
...status >= 500 && { headers: { "Cache-Control": "no-store" } }
|
|
24518
|
+
};
|
|
24519
|
+
};
|
|
24520
|
+
}
|
|
24521
|
+
function defaultReadOnlyOnDenied(reason) {
|
|
24522
|
+
const message = reason.code === "missing_identity" ? "X-Wallet-Address or X-Operator-Token header required" : "Invalid identity";
|
|
24523
|
+
return {
|
|
24524
|
+
status: 401,
|
|
24525
|
+
body: {
|
|
24526
|
+
...denialReasonToBody(reason),
|
|
24527
|
+
error: { code: "unauthorized", message }
|
|
24528
|
+
},
|
|
24529
|
+
headers: { "Cache-Control": "no-store" }
|
|
24530
|
+
};
|
|
24531
|
+
}
|
|
23757
24532
|
export {
|
|
24533
|
+
A2A_DEFAULT_TRANSPORT,
|
|
24534
|
+
A2A_PROTOCOL_VERSION,
|
|
23758
24535
|
AGENTSCORE_UCP_CAPABILITY,
|
|
23759
24536
|
Checkout,
|
|
23760
24537
|
CheckoutValidationError,
|
|
@@ -23765,18 +24542,28 @@ export {
|
|
|
23765
24542
|
buildA2AAgentCard,
|
|
23766
24543
|
buildAgentMemoryHint,
|
|
23767
24544
|
buildContactSupportNextSteps,
|
|
24545
|
+
buildDefaultCheckoutRails,
|
|
23768
24546
|
buildGateFromPolicy,
|
|
23769
24547
|
buildJWKSResponse,
|
|
24548
|
+
buildMppxComposeRails,
|
|
23770
24549
|
buildSignerMismatchBody,
|
|
23771
24550
|
buildUCPProfile,
|
|
24551
|
+
computeFirstCheckout,
|
|
24552
|
+
createDefaultOnDenied,
|
|
24553
|
+
createQuoteCache,
|
|
24554
|
+
defaultReadOnlyOnDenied,
|
|
23772
24555
|
denialReasonStatus,
|
|
23773
24556
|
denialReasonToBody,
|
|
24557
|
+
extractOwnerScope,
|
|
23774
24558
|
extractPaymentSigner,
|
|
23775
24559
|
extractPaymentSignerFromAuth,
|
|
23776
24560
|
extractSignerForPrecheck,
|
|
23777
24561
|
formatUsdCents,
|
|
23778
24562
|
generateUCPSigningKey,
|
|
23779
24563
|
getIdentityStatus,
|
|
24564
|
+
hasMppxHeader,
|
|
24565
|
+
hasPaymentHeader,
|
|
24566
|
+
hasX402Header,
|
|
23780
24567
|
hashOperatorToken,
|
|
23781
24568
|
isFixableDenial,
|
|
23782
24569
|
loadSolanaFeePayer,
|