@agent-score/commerce 2.0.2 → 2.1.1
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-jNUIql6D.d.mts → checkout-BRw_caGr.d.mts} +13 -33
- package/dist/{checkout-DhSj_h94.d.ts → checkout-CuSNUJFX.d.ts} +13 -33
- 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-C5gKZJMI.d.ts +198 -0
- package/dist/default_rails-XFCuRddA.d.mts +198 -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 +22 -23317
- package/dist/identity/policy.js.map +1 -1
- package/dist/identity/policy.mjs +1 -23320
- 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 +621 -90
- package/dist/index.d.ts +621 -90
- package/dist/index.js +1202 -328
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1188 -327
- 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 +32 -21
- package/dist/payment/index.d.ts +32 -21
- package/dist/payment/index.js +215 -12
- package/dist/payment/index.js.map +1 -1
- package/dist/payment/index.mjs +205 -12
- 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 +19799 -43
- package/dist/stripe-multichain/index.js.map +1 -1
- package/dist/stripe-multichain/index.mjs +19808 -28
- 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.js
CHANGED
|
@@ -33,6 +33,27 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
33
33
|
));
|
|
34
34
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
35
35
|
|
|
36
|
+
// src/payment/network_kind.ts
|
|
37
|
+
function readNetwork(input) {
|
|
38
|
+
if (typeof input === "string") return input;
|
|
39
|
+
if (input && typeof input === "object") {
|
|
40
|
+
const network = input.network;
|
|
41
|
+
return typeof network === "string" ? network : "";
|
|
42
|
+
}
|
|
43
|
+
return "";
|
|
44
|
+
}
|
|
45
|
+
function isEvmNetwork(input) {
|
|
46
|
+
return readNetwork(input).startsWith("eip155:");
|
|
47
|
+
}
|
|
48
|
+
function isSolanaNetwork(input) {
|
|
49
|
+
return readNetwork(input).startsWith("solana:");
|
|
50
|
+
}
|
|
51
|
+
var init_network_kind = __esm({
|
|
52
|
+
"src/payment/network_kind.ts"() {
|
|
53
|
+
"use strict";
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
36
57
|
// src/identity/ucp.ts
|
|
37
58
|
function ucpSigningKeyFromJWKImpl(jwk) {
|
|
38
59
|
if (!jwk || typeof jwk !== "object") {
|
|
@@ -162,7 +183,7 @@ function isTempoSessionRailSpec(s) {
|
|
|
162
183
|
}
|
|
163
184
|
function mppRailToNetworkEntry(spec) {
|
|
164
185
|
if (isTempoSessionRailSpec(spec)) return tempoSessionToNetworkEntry(spec);
|
|
165
|
-
if ("rpcUrl" in spec || "tokenProgram" in spec || (spec
|
|
186
|
+
if ("rpcUrl" in spec || "tokenProgram" in spec || isSolanaNetwork(spec)) {
|
|
166
187
|
return solanaMppToNetworkEntry(spec);
|
|
167
188
|
}
|
|
168
189
|
if (isTempoRailSpec(spec)) return tempoToNetworkEntry(spec);
|
|
@@ -219,6 +240,7 @@ var UCPSigningKey, DEFAULT_VERSION, AGENTSCORE_CAPABILITY_NAME, AGENTSCORE_CAPAB
|
|
|
219
240
|
var init_ucp = __esm({
|
|
220
241
|
"src/identity/ucp.ts"() {
|
|
221
242
|
"use strict";
|
|
243
|
+
init_network_kind();
|
|
222
244
|
UCPSigningKey = {
|
|
223
245
|
fromJWK: ucpSigningKeyFromJWKImpl
|
|
224
246
|
};
|
|
@@ -638,64 +660,6 @@ var init_ucp_jwks = __esm({
|
|
|
638
660
|
}
|
|
639
661
|
});
|
|
640
662
|
|
|
641
|
-
// src/payment/usdc.ts
|
|
642
|
-
var USDC;
|
|
643
|
-
var init_usdc = __esm({
|
|
644
|
-
"src/payment/usdc.ts"() {
|
|
645
|
-
"use strict";
|
|
646
|
-
USDC = {
|
|
647
|
-
base: {
|
|
648
|
-
mainnet: { address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", decimals: 6 },
|
|
649
|
-
sepolia: { address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", decimals: 6 }
|
|
650
|
-
},
|
|
651
|
-
solana: {
|
|
652
|
-
mainnet: { mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", decimals: 6 },
|
|
653
|
-
devnet: { mint: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU", decimals: 6 }
|
|
654
|
-
},
|
|
655
|
-
tempo: {
|
|
656
|
-
mainnet: { address: "0x20C000000000000000000000b9537d11c60E8b50", decimals: 6 },
|
|
657
|
-
testnet: { address: "0x20c0000000000000000000000000000000000000", decimals: 6 }
|
|
658
|
-
}
|
|
659
|
-
};
|
|
660
|
-
}
|
|
661
|
-
});
|
|
662
|
-
|
|
663
|
-
// src/payment/wwwauthenticate.ts
|
|
664
|
-
function paymentRequiredHeader({
|
|
665
|
-
x402Version,
|
|
666
|
-
accepts,
|
|
667
|
-
resource
|
|
668
|
-
}) {
|
|
669
|
-
return Buffer.from(JSON.stringify({ x402Version, accepts, ...resource ? { resource } : {} })).toString("base64");
|
|
670
|
-
}
|
|
671
|
-
var init_wwwauthenticate = __esm({
|
|
672
|
-
"src/payment/wwwauthenticate.ts"() {
|
|
673
|
-
"use strict";
|
|
674
|
-
}
|
|
675
|
-
});
|
|
676
|
-
|
|
677
|
-
// src/payment/networks.ts
|
|
678
|
-
var networks;
|
|
679
|
-
var init_networks = __esm({
|
|
680
|
-
"src/payment/networks.ts"() {
|
|
681
|
-
"use strict";
|
|
682
|
-
networks = {
|
|
683
|
-
base: {
|
|
684
|
-
mainnet: { caip2: "eip155:8453", chainId: 8453 },
|
|
685
|
-
sepolia: { caip2: "eip155:84532", chainId: 84532 }
|
|
686
|
-
},
|
|
687
|
-
solana: {
|
|
688
|
-
mainnet: { caip2: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" },
|
|
689
|
-
devnet: { caip2: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1" }
|
|
690
|
-
},
|
|
691
|
-
tempo: {
|
|
692
|
-
mainnet: { caip2: "eip155:4217", chainId: 4217 },
|
|
693
|
-
testnet: { caip2: "eip155:42431", chainId: 42431 }
|
|
694
|
-
}
|
|
695
|
-
};
|
|
696
|
-
}
|
|
697
|
-
});
|
|
698
|
-
|
|
699
663
|
// node_modules/ox/_esm/core/Abi.js
|
|
700
664
|
var init_Abi = __esm({
|
|
701
665
|
"node_modules/ox/_esm/core/Abi.js"() {
|
|
@@ -20307,6 +20271,64 @@ var init_dist2 = __esm({
|
|
|
20307
20271
|
}
|
|
20308
20272
|
});
|
|
20309
20273
|
|
|
20274
|
+
// src/payment/usdc.ts
|
|
20275
|
+
var USDC;
|
|
20276
|
+
var init_usdc = __esm({
|
|
20277
|
+
"src/payment/usdc.ts"() {
|
|
20278
|
+
"use strict";
|
|
20279
|
+
USDC = {
|
|
20280
|
+
base: {
|
|
20281
|
+
mainnet: { address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", decimals: 6 },
|
|
20282
|
+
sepolia: { address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", decimals: 6 }
|
|
20283
|
+
},
|
|
20284
|
+
solana: {
|
|
20285
|
+
mainnet: { mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", decimals: 6 },
|
|
20286
|
+
devnet: { mint: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU", decimals: 6 }
|
|
20287
|
+
},
|
|
20288
|
+
tempo: {
|
|
20289
|
+
mainnet: { address: "0x20C000000000000000000000b9537d11c60E8b50", decimals: 6 },
|
|
20290
|
+
testnet: { address: "0x20c0000000000000000000000000000000000000", decimals: 6 }
|
|
20291
|
+
}
|
|
20292
|
+
};
|
|
20293
|
+
}
|
|
20294
|
+
});
|
|
20295
|
+
|
|
20296
|
+
// src/payment/wwwauthenticate.ts
|
|
20297
|
+
function paymentRequiredHeader({
|
|
20298
|
+
x402Version,
|
|
20299
|
+
accepts,
|
|
20300
|
+
resource
|
|
20301
|
+
}) {
|
|
20302
|
+
return Buffer.from(JSON.stringify({ x402Version, accepts, ...resource ? { resource } : {} })).toString("base64");
|
|
20303
|
+
}
|
|
20304
|
+
var init_wwwauthenticate = __esm({
|
|
20305
|
+
"src/payment/wwwauthenticate.ts"() {
|
|
20306
|
+
"use strict";
|
|
20307
|
+
}
|
|
20308
|
+
});
|
|
20309
|
+
|
|
20310
|
+
// src/payment/networks.ts
|
|
20311
|
+
var networks;
|
|
20312
|
+
var init_networks = __esm({
|
|
20313
|
+
"src/payment/networks.ts"() {
|
|
20314
|
+
"use strict";
|
|
20315
|
+
networks = {
|
|
20316
|
+
base: {
|
|
20317
|
+
mainnet: { caip2: "eip155:8453", chainId: 8453 },
|
|
20318
|
+
sepolia: { caip2: "eip155:84532", chainId: 84532 }
|
|
20319
|
+
},
|
|
20320
|
+
solana: {
|
|
20321
|
+
mainnet: { caip2: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" },
|
|
20322
|
+
devnet: { caip2: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1" }
|
|
20323
|
+
},
|
|
20324
|
+
tempo: {
|
|
20325
|
+
mainnet: { caip2: "eip155:4217", chainId: 4217 },
|
|
20326
|
+
testnet: { caip2: "eip155:42431", chainId: 42431 }
|
|
20327
|
+
}
|
|
20328
|
+
};
|
|
20329
|
+
}
|
|
20330
|
+
});
|
|
20331
|
+
|
|
20310
20332
|
// src/payment/rails.ts
|
|
20311
20333
|
function lookupRail(name) {
|
|
20312
20334
|
return rails[name];
|
|
@@ -20785,6 +20807,8 @@ var init_well_known = __esm({
|
|
|
20785
20807
|
// src/index.ts
|
|
20786
20808
|
var index_exports = {};
|
|
20787
20809
|
__export(index_exports, {
|
|
20810
|
+
A2A_DEFAULT_TRANSPORT: () => A2A_DEFAULT_TRANSPORT,
|
|
20811
|
+
A2A_PROTOCOL_VERSION: () => A2A_PROTOCOL_VERSION,
|
|
20788
20812
|
AGENTSCORE_UCP_CAPABILITY: () => AGENTSCORE_UCP_CAPABILITY,
|
|
20789
20813
|
Checkout: () => Checkout,
|
|
20790
20814
|
CheckoutValidationError: () => CheckoutValidationError,
|
|
@@ -20795,18 +20819,29 @@ __export(index_exports, {
|
|
|
20795
20819
|
buildA2AAgentCard: () => buildA2AAgentCard,
|
|
20796
20820
|
buildAgentMemoryHint: () => buildAgentMemoryHint,
|
|
20797
20821
|
buildContactSupportNextSteps: () => buildContactSupportNextSteps,
|
|
20822
|
+
buildDefaultCheckoutRails: () => buildDefaultCheckoutRails,
|
|
20798
20823
|
buildGateFromPolicy: () => buildGateFromPolicy,
|
|
20799
20824
|
buildJWKSResponse: () => buildJWKSResponse,
|
|
20825
|
+
buildMppxComposeRails: () => buildMppxComposeRails,
|
|
20800
20826
|
buildSignerMismatchBody: () => buildSignerMismatchBody,
|
|
20801
20827
|
buildUCPProfile: () => buildUCPProfile,
|
|
20828
|
+
buildVerificationRequiredBody: () => buildVerificationRequiredBody,
|
|
20829
|
+
computeFirstCheckout: () => computeFirstCheckout,
|
|
20830
|
+
createDefaultOnDenied: () => createDefaultOnDenied,
|
|
20831
|
+
createQuoteCache: () => createQuoteCache,
|
|
20832
|
+
defaultReadOnlyOnDenied: () => defaultReadOnlyOnDenied,
|
|
20802
20833
|
denialReasonStatus: () => denialReasonStatus,
|
|
20803
20834
|
denialReasonToBody: () => denialReasonToBody,
|
|
20835
|
+
extractOwnerScope: () => extractOwnerScope,
|
|
20804
20836
|
extractPaymentSigner: () => extractPaymentSigner,
|
|
20805
20837
|
extractPaymentSignerFromAuth: () => extractPaymentSignerFromAuth,
|
|
20806
20838
|
extractSignerForPrecheck: () => extractSignerForPrecheck,
|
|
20807
20839
|
formatUsdCents: () => formatUsdCents,
|
|
20808
20840
|
generateUCPSigningKey: () => generateUCPSigningKey,
|
|
20809
20841
|
getIdentityStatus: () => getIdentityStatus,
|
|
20842
|
+
hasMppxHeader: () => hasMppxHeader,
|
|
20843
|
+
hasPaymentHeader: () => hasPaymentHeader,
|
|
20844
|
+
hasX402Header: () => hasX402Header,
|
|
20810
20845
|
hashOperatorToken: () => hashOperatorToken,
|
|
20811
20846
|
isFixableDenial: () => isFixableDenial,
|
|
20812
20847
|
loadSolanaFeePayer: () => loadSolanaFeePayer,
|
|
@@ -21015,6 +21050,20 @@ var RESERVED_FIELDS = /* @__PURE__ */ new Set([
|
|
|
21015
21050
|
"actual_signer",
|
|
21016
21051
|
"linked_wallets"
|
|
21017
21052
|
]);
|
|
21053
|
+
function buildVerificationRequiredBody(reason, opts = {}) {
|
|
21054
|
+
const body = denialReasonToBody(reason);
|
|
21055
|
+
body.error = {
|
|
21056
|
+
code: "operator_verification_required",
|
|
21057
|
+
message: opts.message ?? "Identity verification is required."
|
|
21058
|
+
};
|
|
21059
|
+
if (opts.agentInstructions !== void 0) {
|
|
21060
|
+
body.agent_instructions = opts.agentInstructions;
|
|
21061
|
+
}
|
|
21062
|
+
if (opts.extra) {
|
|
21063
|
+
for (const [k, v] of Object.entries(opts.extra)) body[k] = v;
|
|
21064
|
+
}
|
|
21065
|
+
return body;
|
|
21066
|
+
}
|
|
21018
21067
|
function denialReasonToBody(reason) {
|
|
21019
21068
|
const message = reason.message ?? DEFAULT_MESSAGES[reason.code];
|
|
21020
21069
|
const body = { error: { code: reason.code, message } };
|
|
@@ -21172,7 +21221,7 @@ function createAgentScoreCore(options) {
|
|
|
21172
21221
|
} = options;
|
|
21173
21222
|
const baseUrl = stripTrailingSlashes(rawBaseUrl);
|
|
21174
21223
|
const agentMemoryHint = buildAgentMemoryHint();
|
|
21175
|
-
const defaultUa = `@agent-score/commerce@${"2.
|
|
21224
|
+
const defaultUa = `@agent-score/commerce@${"2.1.1"}`;
|
|
21176
21225
|
const userAgentHeader = userAgent ? `${userAgent} (${defaultUa})` : defaultUa;
|
|
21177
21226
|
const sdk = new import_sdk.AgentScore({ apiKey, baseUrl, userAgent: userAgentHeader });
|
|
21178
21227
|
const sessionSdkCache = /* @__PURE__ */ new Map();
|
|
@@ -21464,6 +21513,13 @@ function createAgentScoreCore(options) {
|
|
|
21464
21513
|
return { evaluate, captureWallet, getSignerVerdict };
|
|
21465
21514
|
}
|
|
21466
21515
|
|
|
21516
|
+
// src/_headers.ts
|
|
21517
|
+
function normalizeHeadersToLowercase(headers) {
|
|
21518
|
+
const out = {};
|
|
21519
|
+
for (const [k, v] of Object.entries(headers)) out[k.toLowerCase()] = v;
|
|
21520
|
+
return out;
|
|
21521
|
+
}
|
|
21522
|
+
|
|
21467
21523
|
// src/signer.ts
|
|
21468
21524
|
var TOKEN_PROGRAM = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
|
|
21469
21525
|
var TOKEN_2022_PROGRAM = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb";
|
|
@@ -21546,13 +21602,8 @@ async function extractPaymentSignerFromAuth(authHeader, x402PaymentHeader) {
|
|
|
21546
21602
|
function readX402PaymentHeader(request) {
|
|
21547
21603
|
return request.headers.get("payment-signature") ?? request.headers.get("x-payment") ?? void 0;
|
|
21548
21604
|
}
|
|
21549
|
-
function lowerHeaders(headers) {
|
|
21550
|
-
const out = {};
|
|
21551
|
-
for (const [k, v] of Object.entries(headers)) out[k.toLowerCase()] = v;
|
|
21552
|
-
return out;
|
|
21553
|
-
}
|
|
21554
21605
|
async function extractSignerForPrecheck(headers) {
|
|
21555
|
-
const lower =
|
|
21606
|
+
const lower = normalizeHeadersToLowercase(headers);
|
|
21556
21607
|
const x402 = lower["payment-signature"] ?? lower["x-payment"];
|
|
21557
21608
|
if (x402) {
|
|
21558
21609
|
const signer = await extractPaymentSignerFromAuth(void 0, x402);
|
|
@@ -21567,7 +21618,7 @@ async function extractSignerForPrecheck(headers) {
|
|
|
21567
21618
|
|
|
21568
21619
|
// src/identity/a2a.ts
|
|
21569
21620
|
var PROTOCOL_VERSION = "1.0";
|
|
21570
|
-
var
|
|
21621
|
+
var DEFAULT_TRANSPORT = "JSONRPC";
|
|
21571
21622
|
var DEFAULT_INPUT_MODE = "application/json";
|
|
21572
21623
|
var DEFAULT_OUTPUT_MODE = "application/json";
|
|
21573
21624
|
var UCP_A2A_EXTENSION_URI = "https://ucp.dev/2026-04-08/specification/reference";
|
|
@@ -21587,30 +21638,33 @@ function buildA2AAgentCard(input) {
|
|
|
21587
21638
|
}
|
|
21588
21639
|
const capabilities = {};
|
|
21589
21640
|
if (input.streaming !== void 0) capabilities.streaming = input.streaming;
|
|
21590
|
-
if (input.
|
|
21641
|
+
if (input.pushNotifications !== void 0) capabilities.pushNotifications = input.pushNotifications;
|
|
21642
|
+
if (input.stateTransitionHistory !== void 0) capabilities.stateTransitionHistory = input.stateTransitionHistory;
|
|
21591
21643
|
if (input.extensions && input.extensions.length > 0) capabilities.extensions = input.extensions;
|
|
21592
|
-
if (input.extended_agent_card !== void 0) capabilities.extended_agent_card = input.extended_agent_card;
|
|
21593
|
-
const primaryInterface = {
|
|
21594
|
-
url: input.url,
|
|
21595
|
-
protocol_binding: input.protocol_binding ?? DEFAULT_PROTOCOL_BINDING,
|
|
21596
|
-
protocol_version: input.a2a_protocol_version ?? PROTOCOL_VERSION
|
|
21597
|
-
};
|
|
21598
21644
|
const card = {
|
|
21599
21645
|
name: input.name,
|
|
21600
21646
|
description: input.description,
|
|
21601
|
-
|
|
21647
|
+
url: input.url,
|
|
21648
|
+
preferredTransport: input.preferredTransport ?? "HTTP+JSON",
|
|
21649
|
+
protocolVersion: input.protocolVersion ?? PROTOCOL_VERSION,
|
|
21602
21650
|
version: input.version ?? "1.0.0",
|
|
21603
21651
|
capabilities,
|
|
21604
|
-
|
|
21605
|
-
|
|
21652
|
+
defaultInputModes: input.defaultInputModes ?? [DEFAULT_INPUT_MODE],
|
|
21653
|
+
defaultOutputModes: input.defaultOutputModes ?? [DEFAULT_OUTPUT_MODE],
|
|
21606
21654
|
skills: input.skills
|
|
21607
21655
|
};
|
|
21656
|
+
if (input.additionalInterfaces !== void 0 && input.additionalInterfaces.length > 0) {
|
|
21657
|
+
card.additionalInterfaces = input.additionalInterfaces;
|
|
21658
|
+
}
|
|
21608
21659
|
if (input.provider !== void 0) card.provider = input.provider;
|
|
21609
|
-
if (input.
|
|
21610
|
-
if (input.
|
|
21660
|
+
if (input.documentationUrl !== void 0) card.documentationUrl = input.documentationUrl;
|
|
21661
|
+
if (input.iconUrl !== void 0) card.iconUrl = input.iconUrl;
|
|
21662
|
+
if (input.supportsAuthenticatedExtendedCard !== void 0) {
|
|
21663
|
+
card.supportsAuthenticatedExtendedCard = input.supportsAuthenticatedExtendedCard;
|
|
21664
|
+
}
|
|
21611
21665
|
if (input.signatures !== void 0 && input.signatures.length > 0) card.signatures = input.signatures;
|
|
21612
|
-
if (input.
|
|
21613
|
-
if (input.
|
|
21666
|
+
if (input.security !== void 0) card.security = input.security;
|
|
21667
|
+
if (input.securitySchemes !== void 0) card.securitySchemes = input.securitySchemes;
|
|
21614
21668
|
if (input.extras) {
|
|
21615
21669
|
for (const [k, v] of Object.entries(input.extras)) {
|
|
21616
21670
|
card[k] = v;
|
|
@@ -21618,89 +21672,250 @@ function buildA2AAgentCard(input) {
|
|
|
21618
21672
|
}
|
|
21619
21673
|
return card;
|
|
21620
21674
|
}
|
|
21675
|
+
var A2A_PROTOCOL_VERSION = PROTOCOL_VERSION;
|
|
21676
|
+
var A2A_DEFAULT_TRANSPORT = DEFAULT_TRANSPORT;
|
|
21621
21677
|
|
|
21622
21678
|
// src/index.ts
|
|
21623
21679
|
init_ucp();
|
|
21624
21680
|
init_ucp_jwks();
|
|
21625
21681
|
|
|
21626
|
-
// src/
|
|
21627
|
-
var
|
|
21628
|
-
|
|
21629
|
-
|
|
21630
|
-
|
|
21631
|
-
|
|
21632
|
-
|
|
21633
|
-
|
|
21634
|
-
|
|
21635
|
-
|
|
21636
|
-
|
|
21637
|
-
|
|
21638
|
-
|
|
21639
|
-
token: USDC.tempo.mainnet.address,
|
|
21640
|
-
symbol: "USDC.e",
|
|
21641
|
-
decimals: 6,
|
|
21642
|
-
testnet: false,
|
|
21643
|
-
recommend: "both"
|
|
21644
|
-
},
|
|
21645
|
-
x402Base: {
|
|
21646
|
-
network: "eip155:8453",
|
|
21647
|
-
chainId: 8453,
|
|
21648
|
-
token: USDC.base.mainnet.address,
|
|
21649
|
-
symbol: "USDC",
|
|
21650
|
-
decimals: 6,
|
|
21651
|
-
mode: "exact"
|
|
21652
|
-
},
|
|
21653
|
-
solanaMpp: {
|
|
21654
|
-
network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
|
|
21655
|
-
token: USDC.solana.mainnet.mint,
|
|
21656
|
-
symbol: "USDC",
|
|
21657
|
-
decimals: 6
|
|
21658
|
-
},
|
|
21659
|
-
stripe: {
|
|
21660
|
-
rails: ["card", "link", "shared_payment_token"]
|
|
21661
|
-
},
|
|
21662
|
-
tempoSession: {
|
|
21663
|
-
currency: USDC.tempo.mainnet.address,
|
|
21664
|
-
testnet: false
|
|
21682
|
+
// src/errors.ts
|
|
21683
|
+
var CheckoutValidationError = class extends Error {
|
|
21684
|
+
code;
|
|
21685
|
+
action;
|
|
21686
|
+
status;
|
|
21687
|
+
extra;
|
|
21688
|
+
constructor(opts) {
|
|
21689
|
+
super(opts.message);
|
|
21690
|
+
this.name = "CheckoutValidationError";
|
|
21691
|
+
this.code = opts.code;
|
|
21692
|
+
this.action = opts.action ?? "fix_request";
|
|
21693
|
+
this.status = opts.status ?? 400;
|
|
21694
|
+
this.extra = opts.extra;
|
|
21665
21695
|
}
|
|
21666
21696
|
};
|
|
21667
21697
|
|
|
21668
|
-
// src/
|
|
21669
|
-
|
|
21670
|
-
|
|
21671
|
-
|
|
21672
|
-
|
|
21673
|
-
|
|
21674
|
-
|
|
21675
|
-
|
|
21676
|
-
|
|
21677
|
-
|
|
21678
|
-
|
|
21679
|
-
|
|
21680
|
-
|
|
21681
|
-
|
|
21682
|
-
|
|
21683
|
-
|
|
21684
|
-
|
|
21685
|
-
|
|
21686
|
-
|
|
21687
|
-
if (
|
|
21688
|
-
|
|
21689
|
-
|
|
21690
|
-
|
|
21691
|
-
|
|
21692
|
-
|
|
21693
|
-
|
|
21694
|
-
|
|
21695
|
-
pay_to: await resolveRecipient(x402_base.recipient)
|
|
21696
|
-
});
|
|
21698
|
+
// src/identity/policy.ts
|
|
21699
|
+
function buildGateFromPolicy(policy, base) {
|
|
21700
|
+
if (!policy || !policy.enforcement) return null;
|
|
21701
|
+
return {
|
|
21702
|
+
apiKey: base.apiKey,
|
|
21703
|
+
...base.baseUrl !== void 0 && { baseUrl: base.baseUrl },
|
|
21704
|
+
...policy.requireKyc !== void 0 && { requireKyc: policy.requireKyc },
|
|
21705
|
+
...policy.requireSanctionsClear !== void 0 && {
|
|
21706
|
+
requireSanctionsClear: policy.requireSanctionsClear
|
|
21707
|
+
},
|
|
21708
|
+
...policy.minAge !== void 0 && { minAge: policy.minAge },
|
|
21709
|
+
...policy.allowedJurisdictions !== void 0 && {
|
|
21710
|
+
allowedJurisdictions: [...policy.allowedJurisdictions]
|
|
21711
|
+
}
|
|
21712
|
+
};
|
|
21713
|
+
}
|
|
21714
|
+
async function runGateWithEnforcement(enforcement, runGate) {
|
|
21715
|
+
if (!runGate || !enforcement) return { status: "anonymous" };
|
|
21716
|
+
const outcome = await runGate();
|
|
21717
|
+
if (outcome.ok) return { status: "verified" };
|
|
21718
|
+
if (enforcement === "hard") {
|
|
21719
|
+
return {
|
|
21720
|
+
status: "denied",
|
|
21721
|
+
denialStatus: outcome.status,
|
|
21722
|
+
denialBody: outcome.body,
|
|
21723
|
+
...outcome.reason !== void 0 && { denialReason: outcome.reason }
|
|
21724
|
+
};
|
|
21697
21725
|
}
|
|
21698
|
-
|
|
21699
|
-
|
|
21700
|
-
|
|
21701
|
-
|
|
21702
|
-
|
|
21703
|
-
|
|
21726
|
+
return {
|
|
21727
|
+
status: "unverified",
|
|
21728
|
+
denialStatus: outcome.status,
|
|
21729
|
+
denialBody: outcome.body,
|
|
21730
|
+
...outcome.reason !== void 0 && { denialReason: outcome.reason }
|
|
21731
|
+
};
|
|
21732
|
+
}
|
|
21733
|
+
function shippingCountryAllowed(country, policy) {
|
|
21734
|
+
if (!policy?.allowedShippingCountries || policy.allowedShippingCountries.length === 0) return true;
|
|
21735
|
+
const allowed = new Set(policy.allowedShippingCountries.map((c) => c.toUpperCase()));
|
|
21736
|
+
return allowed.has(country.toUpperCase());
|
|
21737
|
+
}
|
|
21738
|
+
function shippingStateAllowed(state, country, policy) {
|
|
21739
|
+
if (!policy?.allowedShippingStates || policy.allowedShippingStates.length === 0) return true;
|
|
21740
|
+
if (country.toUpperCase() !== "US") return true;
|
|
21741
|
+
const allowed = new Set(policy.allowedShippingStates.map((s) => s.toUpperCase()));
|
|
21742
|
+
return allowed.has(state.toUpperCase());
|
|
21743
|
+
}
|
|
21744
|
+
function validateShippingAgainstPolicy(opts) {
|
|
21745
|
+
const code = opts.errorCode ?? "unsupported_jurisdiction";
|
|
21746
|
+
const action = opts.errorAction ?? "change_shipping_state";
|
|
21747
|
+
const item = opts.productName ? `'${opts.productName}'` : "this item";
|
|
21748
|
+
if (!shippingCountryAllowed(opts.country, opts.policy)) {
|
|
21749
|
+
throw new CheckoutValidationError({
|
|
21750
|
+
code,
|
|
21751
|
+
message: opts.countryMessage ?? `We can't ship ${item} to ${opts.country.toUpperCase() || "<unset>"}.`,
|
|
21752
|
+
action
|
|
21753
|
+
});
|
|
21754
|
+
}
|
|
21755
|
+
if (!shippingStateAllowed(opts.state, opts.country, opts.policy)) {
|
|
21756
|
+
throw new CheckoutValidationError({
|
|
21757
|
+
code,
|
|
21758
|
+
message: opts.stateMessage ?? `We can't ship ${item} to ${opts.state.toUpperCase() || "<unset>"}.`,
|
|
21759
|
+
action
|
|
21760
|
+
});
|
|
21761
|
+
}
|
|
21762
|
+
}
|
|
21763
|
+
|
|
21764
|
+
// src/identity/tokens.ts
|
|
21765
|
+
var import_node_crypto = require("crypto");
|
|
21766
|
+
|
|
21767
|
+
// src/payment/payment_header.ts
|
|
21768
|
+
function toTitleCase(name) {
|
|
21769
|
+
return name.replace(/(^|-)([a-z])/g, (_m, sep, c) => sep + c.toUpperCase());
|
|
21770
|
+
}
|
|
21771
|
+
function readHeader(headers, name) {
|
|
21772
|
+
if (typeof headers.get === "function") {
|
|
21773
|
+
return headers.get(name);
|
|
21774
|
+
}
|
|
21775
|
+
const rec = headers;
|
|
21776
|
+
const v = rec[name] ?? rec[name.toLowerCase()] ?? rec[toTitleCase(name)];
|
|
21777
|
+
if (typeof v === "string") return v;
|
|
21778
|
+
if (Array.isArray(v) && typeof v[0] === "string") return v[0];
|
|
21779
|
+
return null;
|
|
21780
|
+
}
|
|
21781
|
+
function asHeaders(input) {
|
|
21782
|
+
return typeof input.headers === "object" && input instanceof Request ? input.headers : input;
|
|
21783
|
+
}
|
|
21784
|
+
function hasPaymentHeader(input) {
|
|
21785
|
+
const headers = asHeaders(input);
|
|
21786
|
+
return Boolean(
|
|
21787
|
+
readHeader(headers, "payment-signature") || readHeader(headers, "x-payment") || readHeader(headers, "authorization")?.startsWith("Payment ")
|
|
21788
|
+
);
|
|
21789
|
+
}
|
|
21790
|
+
function hasX402Header(input) {
|
|
21791
|
+
const headers = asHeaders(input);
|
|
21792
|
+
return Boolean(readHeader(headers, "payment-signature") || readHeader(headers, "x-payment"));
|
|
21793
|
+
}
|
|
21794
|
+
function hasMppxHeader(input) {
|
|
21795
|
+
const headers = asHeaders(input);
|
|
21796
|
+
return Boolean(readHeader(headers, "authorization")?.startsWith("Payment "));
|
|
21797
|
+
}
|
|
21798
|
+
|
|
21799
|
+
// src/identity/tokens.ts
|
|
21800
|
+
function hashOperatorToken(plaintext) {
|
|
21801
|
+
return (0, import_node_crypto.createHash)("sha256").update(plaintext, "utf8").digest("hex");
|
|
21802
|
+
}
|
|
21803
|
+
function extractOwnerScope(input) {
|
|
21804
|
+
const headers = asHeaders(input);
|
|
21805
|
+
const walletAddress = readHeader(headers, "x-wallet-address");
|
|
21806
|
+
const operatorToken = readHeader(headers, "x-operator-token");
|
|
21807
|
+
return {
|
|
21808
|
+
...walletAddress ? { walletAddress } : {},
|
|
21809
|
+
...operatorToken ? { operatorTokenHash: hashOperatorToken(operatorToken) } : {}
|
|
21810
|
+
};
|
|
21811
|
+
}
|
|
21812
|
+
|
|
21813
|
+
// src/checkout.ts
|
|
21814
|
+
var import_node_crypto2 = require("crypto");
|
|
21815
|
+
|
|
21816
|
+
// src/_mppx_receipt.ts
|
|
21817
|
+
function extractMppxReceiptHeaderFromRaw(raw) {
|
|
21818
|
+
if (!raw || typeof raw !== "object" || !("withReceipt" in raw)) return null;
|
|
21819
|
+
const fn = raw.withReceipt;
|
|
21820
|
+
if (typeof fn !== "function") return null;
|
|
21821
|
+
try {
|
|
21822
|
+
const wrapped = fn.call(raw, new Response());
|
|
21823
|
+
return wrapped.headers.get("Payment-Receipt");
|
|
21824
|
+
} catch {
|
|
21825
|
+
return null;
|
|
21826
|
+
}
|
|
21827
|
+
}
|
|
21828
|
+
async function extractMppxReceiptMethod(header) {
|
|
21829
|
+
try {
|
|
21830
|
+
const { Receipt } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
|
|
21831
|
+
return Receipt.deserialize(header).method;
|
|
21832
|
+
} catch {
|
|
21833
|
+
return void 0;
|
|
21834
|
+
}
|
|
21835
|
+
}
|
|
21836
|
+
async function deriveMppxReceiptMethod(raw) {
|
|
21837
|
+
const direct = raw?.receipt?.method;
|
|
21838
|
+
if (direct) return direct;
|
|
21839
|
+
const header = extractMppxReceiptHeaderFromRaw(raw);
|
|
21840
|
+
if (!header) return void 0;
|
|
21841
|
+
return extractMppxReceiptMethod(header);
|
|
21842
|
+
}
|
|
21843
|
+
|
|
21844
|
+
// src/payment/rail_spec.ts
|
|
21845
|
+
init_usdc();
|
|
21846
|
+
async function resolveRecipient(r) {
|
|
21847
|
+
if (typeof r === "string") return r;
|
|
21848
|
+
return Promise.resolve(r());
|
|
21849
|
+
}
|
|
21850
|
+
var RAIL_SPEC_DEFAULTS = {
|
|
21851
|
+
tempo: {
|
|
21852
|
+
network: "tempo-mainnet",
|
|
21853
|
+
chainId: 4217,
|
|
21854
|
+
token: USDC.tempo.mainnet.address,
|
|
21855
|
+
symbol: "USDC.e",
|
|
21856
|
+
decimals: 6,
|
|
21857
|
+
testnet: false,
|
|
21858
|
+
recommend: "both"
|
|
21859
|
+
},
|
|
21860
|
+
x402Base: {
|
|
21861
|
+
network: "eip155:8453",
|
|
21862
|
+
chainId: 8453,
|
|
21863
|
+
token: USDC.base.mainnet.address,
|
|
21864
|
+
symbol: "USDC",
|
|
21865
|
+
decimals: 6,
|
|
21866
|
+
mode: "exact"
|
|
21867
|
+
},
|
|
21868
|
+
solanaMpp: {
|
|
21869
|
+
network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
|
|
21870
|
+
token: USDC.solana.mainnet.mint,
|
|
21871
|
+
symbol: "USDC",
|
|
21872
|
+
decimals: 6
|
|
21873
|
+
},
|
|
21874
|
+
stripe: {
|
|
21875
|
+
rails: ["card", "link", "shared_payment_token"]
|
|
21876
|
+
},
|
|
21877
|
+
tempoSession: {
|
|
21878
|
+
currency: USDC.tempo.mainnet.address,
|
|
21879
|
+
testnet: false
|
|
21880
|
+
}
|
|
21881
|
+
};
|
|
21882
|
+
|
|
21883
|
+
// src/challenge/accepted_methods.ts
|
|
21884
|
+
async function buildAcceptedMethods({
|
|
21885
|
+
tempo,
|
|
21886
|
+
x402_base,
|
|
21887
|
+
solana_mpp,
|
|
21888
|
+
stripe
|
|
21889
|
+
}) {
|
|
21890
|
+
const out = [];
|
|
21891
|
+
if (tempo) {
|
|
21892
|
+
out.push({
|
|
21893
|
+
method: "tempo/charge",
|
|
21894
|
+
network: tempo.network ?? RAIL_SPEC_DEFAULTS.tempo.network,
|
|
21895
|
+
chain_id: tempo.chainId ?? RAIL_SPEC_DEFAULTS.tempo.chainId,
|
|
21896
|
+
token: tempo.token ?? RAIL_SPEC_DEFAULTS.tempo.token,
|
|
21897
|
+
symbol: tempo.symbol ?? RAIL_SPEC_DEFAULTS.tempo.symbol,
|
|
21898
|
+
decimals: tempo.decimals ?? RAIL_SPEC_DEFAULTS.tempo.decimals,
|
|
21899
|
+
pay_to: await resolveRecipient(tempo.recipient)
|
|
21900
|
+
});
|
|
21901
|
+
}
|
|
21902
|
+
if (x402_base) {
|
|
21903
|
+
out.push({
|
|
21904
|
+
method: "x402/exact",
|
|
21905
|
+
network: x402_base.network ?? RAIL_SPEC_DEFAULTS.x402Base.network,
|
|
21906
|
+
chain_id: x402_base.chainId ?? RAIL_SPEC_DEFAULTS.x402Base.chainId,
|
|
21907
|
+
token: x402_base.token ?? RAIL_SPEC_DEFAULTS.x402Base.token,
|
|
21908
|
+
symbol: x402_base.symbol ?? RAIL_SPEC_DEFAULTS.x402Base.symbol,
|
|
21909
|
+
decimals: x402_base.decimals ?? RAIL_SPEC_DEFAULTS.x402Base.decimals,
|
|
21910
|
+
pay_to: await resolveRecipient(x402_base.recipient)
|
|
21911
|
+
});
|
|
21912
|
+
}
|
|
21913
|
+
if (solana_mpp) {
|
|
21914
|
+
out.push({
|
|
21915
|
+
method: "solana/charge",
|
|
21916
|
+
network: solana_mpp.network ?? RAIL_SPEC_DEFAULTS.solanaMpp.network,
|
|
21917
|
+
token: solana_mpp.token ?? RAIL_SPEC_DEFAULTS.solanaMpp.token,
|
|
21918
|
+
symbol: solana_mpp.symbol ?? RAIL_SPEC_DEFAULTS.solanaMpp.symbol,
|
|
21704
21919
|
decimals: solana_mpp.decimals ?? RAIL_SPEC_DEFAULTS.solanaMpp.decimals,
|
|
21705
21920
|
pay_to: await resolveRecipient(solana_mpp.recipient)
|
|
21706
21921
|
});
|
|
@@ -21850,10 +22065,13 @@ function buildHowToPay({
|
|
|
21850
22065
|
totalUsd,
|
|
21851
22066
|
rails: rails2,
|
|
21852
22067
|
opTokenPlaceholder,
|
|
21853
|
-
maxSpend
|
|
22068
|
+
maxSpend,
|
|
22069
|
+
decimals
|
|
21854
22070
|
}) {
|
|
21855
22071
|
const totalNum = typeof totalUsd === "string" ? Number(totalUsd) : totalUsd;
|
|
21856
|
-
const
|
|
22072
|
+
const d = decimals ?? 2;
|
|
22073
|
+
const defaultMaxSpend = totalNum >= 1 ? (Math.ceil(totalNum) + 1).toFixed(d) : totalNum.toFixed(d);
|
|
22074
|
+
const maxSpendStr = String(maxSpend ?? defaultMaxSpend);
|
|
21857
22075
|
const opToken = opTokenPlaceholder ?? "<your_opc_token>";
|
|
21858
22076
|
const block = {};
|
|
21859
22077
|
if (rails2.tempo) {
|
|
@@ -21946,26 +22164,26 @@ function buildPricingBlock({
|
|
|
21946
22164
|
totalCents,
|
|
21947
22165
|
taxRate,
|
|
21948
22166
|
taxState,
|
|
21949
|
-
currency
|
|
22167
|
+
currency,
|
|
22168
|
+
decimals
|
|
21950
22169
|
}) {
|
|
21951
22170
|
const shipping = shippingCents ?? 0;
|
|
21952
22171
|
const discount = discountCents ?? 0;
|
|
21953
22172
|
const total = totalCents ?? Math.max(0, subtotalCents + taxCents + shipping - discount);
|
|
22173
|
+
const d = decimals ?? 2;
|
|
22174
|
+
const fmt = (cents) => (cents / 100).toFixed(d);
|
|
21954
22175
|
const block = {
|
|
21955
|
-
subtotal:
|
|
21956
|
-
tax:
|
|
21957
|
-
total:
|
|
22176
|
+
subtotal: fmt(subtotalCents),
|
|
22177
|
+
tax: fmt(taxCents),
|
|
22178
|
+
total: fmt(total)
|
|
21958
22179
|
};
|
|
21959
|
-
if (shippingCents !== void 0) block.shipping =
|
|
21960
|
-
if (discountCents !== void 0) block.discount =
|
|
22180
|
+
if (shippingCents !== void 0) block.shipping = fmt(shipping);
|
|
22181
|
+
if (discountCents !== void 0) block.discount = fmt(discount);
|
|
21961
22182
|
if (taxRate !== void 0) block.tax_rate = taxRate;
|
|
21962
22183
|
if (taxState !== void 0) block.tax_state = taxState;
|
|
21963
22184
|
if (currency !== void 0) block.currency = currency;
|
|
21964
22185
|
return block;
|
|
21965
22186
|
}
|
|
21966
|
-
function formatCents(cents) {
|
|
21967
|
-
return (cents / 100).toFixed(2);
|
|
21968
|
-
}
|
|
21969
22187
|
|
|
21970
22188
|
// src/challenge/respond_402.ts
|
|
21971
22189
|
init_wwwauthenticate();
|
|
@@ -21974,10 +22192,7 @@ function respond402({
|
|
|
21974
22192
|
body,
|
|
21975
22193
|
x402
|
|
21976
22194
|
}) {
|
|
21977
|
-
const headers =
|
|
21978
|
-
for (const [k, v] of Object.entries(mppxChallengeHeaders)) {
|
|
21979
|
-
headers[k.toLowerCase()] = v;
|
|
21980
|
-
}
|
|
22195
|
+
const headers = normalizeHeadersToLowercase(mppxChallengeHeaders);
|
|
21981
22196
|
headers["content-type"] = "application/json";
|
|
21982
22197
|
if (x402) {
|
|
21983
22198
|
headers["payment-required"] = paymentRequiredHeader(x402);
|
|
@@ -22004,6 +22219,12 @@ function buildValidationError({
|
|
|
22004
22219
|
return body;
|
|
22005
22220
|
}
|
|
22006
22221
|
|
|
22222
|
+
// src/payment/constants.ts
|
|
22223
|
+
var STRIPE_MIN_CHARGE_USD = 0.5;
|
|
22224
|
+
|
|
22225
|
+
// src/payment/mppx_server.ts
|
|
22226
|
+
var import_node_async_hooks = require("async_hooks");
|
|
22227
|
+
|
|
22007
22228
|
// src/stripe-multichain/mppx_stripe.ts
|
|
22008
22229
|
async function createMppxStripe({
|
|
22009
22230
|
profileId,
|
|
@@ -22040,7 +22261,8 @@ function isSolanaMppRailSpec(s) {
|
|
|
22040
22261
|
return s.network?.startsWith("solana:") ?? false;
|
|
22041
22262
|
}
|
|
22042
22263
|
function solanaNetworkFromCAIP2(caip2) {
|
|
22043
|
-
if (caip2 === networks.solana.devnet.caip2) return "devnet";
|
|
22264
|
+
if (caip2 === "devnet" || caip2 === networks.solana.devnet.caip2) return "devnet";
|
|
22265
|
+
if (caip2 === "localnet") return "localnet";
|
|
22044
22266
|
return "mainnet-beta";
|
|
22045
22267
|
}
|
|
22046
22268
|
function solanaDefaultRpcUrl(network) {
|
|
@@ -22183,6 +22405,31 @@ function wrapSolanaChargeWithFinalizedBlockhash(baseMethod, rpcUrl) {
|
|
|
22183
22405
|
}
|
|
22184
22406
|
};
|
|
22185
22407
|
}
|
|
22408
|
+
var mppxCapture = new import_node_async_hooks.AsyncLocalStorage();
|
|
22409
|
+
var consoleErrorPatched = false;
|
|
22410
|
+
function ensureConsoleErrorPatch() {
|
|
22411
|
+
if (consoleErrorPatched) return;
|
|
22412
|
+
consoleErrorPatched = true;
|
|
22413
|
+
const original = console.error.bind(console);
|
|
22414
|
+
console.error = function captureMppxInternal(...args) {
|
|
22415
|
+
if (args[0] === "mppx: internal verification error" && args[1] !== void 0) {
|
|
22416
|
+
const ctx = mppxCapture.getStore();
|
|
22417
|
+
if (ctx) {
|
|
22418
|
+
const e = args[1];
|
|
22419
|
+
const reason = typeof e?.shortMessage === "string" ? e.shortMessage : typeof e?.message === "string" ? e.message : String(args[1]);
|
|
22420
|
+
const details = e?.details;
|
|
22421
|
+
ctx.reason = typeof details === "string" && details.length > 0 ? `${reason} (${details})` : reason;
|
|
22422
|
+
}
|
|
22423
|
+
}
|
|
22424
|
+
return original(...args);
|
|
22425
|
+
};
|
|
22426
|
+
}
|
|
22427
|
+
async function runWithMppxFailureCapture(fn) {
|
|
22428
|
+
ensureConsoleErrorPatch();
|
|
22429
|
+
const ctx = { reason: null };
|
|
22430
|
+
const result = await mppxCapture.run(ctx, fn);
|
|
22431
|
+
return { result, failureReason: ctx.reason };
|
|
22432
|
+
}
|
|
22186
22433
|
|
|
22187
22434
|
// src/payment/x402_server.ts
|
|
22188
22435
|
init_networks();
|
|
@@ -22324,6 +22571,29 @@ function lazyMppxServer(opts) {
|
|
|
22324
22571
|
};
|
|
22325
22572
|
}
|
|
22326
22573
|
|
|
22574
|
+
// src/payment/mppx_failures.ts
|
|
22575
|
+
var TEMPO_KEY_NOT_REGISTERED = {
|
|
22576
|
+
code: "tempo_key_not_registered",
|
|
22577
|
+
status: 401,
|
|
22578
|
+
message: "Tempo rejected the transaction: signer wallet is not registered with Tempo's keychain.",
|
|
22579
|
+
nextSteps: {
|
|
22580
|
+
action: "register_tempo_key",
|
|
22581
|
+
user_message: "Your wallet is not enrolled with Tempo. Run `tempo wallet login` to complete the one-time WebAuthn enrollment (or use `tempo request` directly), then retry. To skip enrollment, switch to the Base or Solana rail on this 402."
|
|
22582
|
+
},
|
|
22583
|
+
extra: { upstream_error: "KeyNotFound", chain: "tempo" }
|
|
22584
|
+
};
|
|
22585
|
+
function classifyMppxFailure(reason) {
|
|
22586
|
+
if (!reason) return null;
|
|
22587
|
+
const lower = reason.toLowerCase();
|
|
22588
|
+
if (lower.includes("keychain validation failed") || lower.includes("keynotfound")) {
|
|
22589
|
+
return TEMPO_KEY_NOT_REGISTERED;
|
|
22590
|
+
}
|
|
22591
|
+
return null;
|
|
22592
|
+
}
|
|
22593
|
+
|
|
22594
|
+
// src/checkout.ts
|
|
22595
|
+
init_network_kind();
|
|
22596
|
+
|
|
22327
22597
|
// src/payment/x402_settle.ts
|
|
22328
22598
|
function classifyX402SettleResult(result) {
|
|
22329
22599
|
if (result.success) return null;
|
|
@@ -22615,12 +22885,14 @@ function pricingResult(opts) {
|
|
|
22615
22885
|
...opts.discountCents !== void 0 && { discountCents: opts.discountCents },
|
|
22616
22886
|
...opts.taxRate !== void 0 && { taxRate: opts.taxRate },
|
|
22617
22887
|
...opts.taxState !== void 0 && { taxState: opts.taxState },
|
|
22618
|
-
currency
|
|
22888
|
+
currency,
|
|
22889
|
+
...opts.decimals !== void 0 && { decimals: opts.decimals }
|
|
22619
22890
|
});
|
|
22620
22891
|
return {
|
|
22621
22892
|
amountUsd: derivedAmount,
|
|
22622
22893
|
currency,
|
|
22623
22894
|
block,
|
|
22895
|
+
...opts.decimals !== void 0 && { decimals: opts.decimals },
|
|
22624
22896
|
...opts.product !== void 0 && { product: opts.product },
|
|
22625
22897
|
...opts.bodyExtras !== void 0 && { bodyExtras: opts.bodyExtras }
|
|
22626
22898
|
};
|
|
@@ -22631,6 +22903,7 @@ function pricingResult(opts) {
|
|
|
22631
22903
|
return {
|
|
22632
22904
|
amountUsd: opts.amountUsd,
|
|
22633
22905
|
currency,
|
|
22906
|
+
...opts.decimals !== void 0 && { decimals: opts.decimals },
|
|
22634
22907
|
...opts.product !== void 0 && { product: opts.product },
|
|
22635
22908
|
...opts.bodyExtras !== void 0 && { bodyExtras: opts.bodyExtras }
|
|
22636
22909
|
};
|
|
@@ -22642,35 +22915,8 @@ function getIdentityStatus(ctx) {
|
|
|
22642
22915
|
if (decision === "allow") return "verified";
|
|
22643
22916
|
return "unverified";
|
|
22644
22917
|
}
|
|
22645
|
-
var CheckoutValidationError = class extends Error {
|
|
22646
|
-
code;
|
|
22647
|
-
action;
|
|
22648
|
-
status;
|
|
22649
|
-
extra;
|
|
22650
|
-
constructor(opts) {
|
|
22651
|
-
super(opts.message);
|
|
22652
|
-
this.name = "CheckoutValidationError";
|
|
22653
|
-
this.code = opts.code;
|
|
22654
|
-
this.action = opts.action ?? "fix_request";
|
|
22655
|
-
this.status = opts.status ?? 400;
|
|
22656
|
-
this.extra = opts.extra;
|
|
22657
|
-
}
|
|
22658
|
-
};
|
|
22659
|
-
function lowerHeaders2(headers) {
|
|
22660
|
-
const out = {};
|
|
22661
|
-
for (const [k, v] of Object.entries(headers)) out[k.toLowerCase()] = v;
|
|
22662
|
-
return out;
|
|
22663
|
-
}
|
|
22664
|
-
function hasX402Header(headers) {
|
|
22665
|
-
const h = lowerHeaders2(headers);
|
|
22666
|
-
return Boolean(h["payment-signature"] ?? h["x-payment"]);
|
|
22667
|
-
}
|
|
22668
|
-
function hasMppxHeader(headers) {
|
|
22669
|
-
const h = lowerHeaders2(headers);
|
|
22670
|
-
return (h["authorization"] ?? "").startsWith("Payment ");
|
|
22671
|
-
}
|
|
22672
22918
|
function resolveIdentityMetadata(ctx) {
|
|
22673
|
-
const h =
|
|
22919
|
+
const h = normalizeHeadersToLowercase(ctx.request.headers);
|
|
22674
22920
|
const wallet = h["x-wallet-address"];
|
|
22675
22921
|
if (!wallet) return void 0;
|
|
22676
22922
|
let linkedWallets;
|
|
@@ -22699,26 +22945,24 @@ function isTempoSessionRailSpec3(s) {
|
|
|
22699
22945
|
function specRailKey(spec) {
|
|
22700
22946
|
if (isStripeRailSpec2(spec)) return "stripe";
|
|
22701
22947
|
if (isTempoSessionRailSpec3(spec)) return "tempo_mpp";
|
|
22702
|
-
|
|
22703
|
-
if (
|
|
22704
|
-
if (network.startsWith("solana:") || "rpcUrl" in spec) return "solana_mpp";
|
|
22948
|
+
if (isEvmNetwork(spec)) return "x402_base";
|
|
22949
|
+
if (isSolanaNetwork(spec) || "rpcUrl" in spec) return "solana_mpp";
|
|
22705
22950
|
return "tempo_mpp";
|
|
22706
22951
|
}
|
|
22707
22952
|
function specMethodName(spec) {
|
|
22708
22953
|
if (isStripeRailSpec2(spec)) return "stripe/spt";
|
|
22709
22954
|
if (isTempoSessionRailSpec3(spec)) return "tempo/charge";
|
|
22710
|
-
|
|
22711
|
-
if (
|
|
22712
|
-
if (network.startsWith("solana:") || "rpcUrl" in spec) return "solana/charge";
|
|
22955
|
+
if (isEvmNetwork(spec)) return "x402/exact (base)";
|
|
22956
|
+
if (isSolanaNetwork(spec) || "rpcUrl" in spec) return "solana/charge";
|
|
22713
22957
|
return "tempo/charge";
|
|
22714
22958
|
}
|
|
22715
22959
|
function makeMppxComposeHook(opts) {
|
|
22716
22960
|
return async (ctx) => {
|
|
22717
22961
|
if (ctx.pricing === null) return { status: 402 };
|
|
22718
22962
|
const mpp = await opts.serverGetter();
|
|
22719
|
-
const lower =
|
|
22963
|
+
const lower = normalizeHeadersToLowercase(ctx.request.headers);
|
|
22720
22964
|
const authorization = lower["authorization"];
|
|
22721
|
-
const amountStr = ctx.pricing.amountUsd.toFixed(2);
|
|
22965
|
+
const amountStr = ctx.pricing.amountUsd.toFixed(ctx.pricing.decimals ?? 2);
|
|
22722
22966
|
let result;
|
|
22723
22967
|
try {
|
|
22724
22968
|
result = await mpp.charge({ authorization, amount: amountStr });
|
|
@@ -22802,7 +23046,7 @@ var Checkout = class {
|
|
|
22802
23046
|
let x402ServerGetter;
|
|
22803
23047
|
if (x402Server === void 0) {
|
|
22804
23048
|
const baseSpec = Object.values(opts.rails).find(
|
|
22805
|
-
(s) => !isTempoSessionRailSpec3(s) && !isStripeRailSpec2(s) && "recipient" in s && (s
|
|
23049
|
+
(s) => !isTempoSessionRailSpec3(s) && !isStripeRailSpec2(s) && "recipient" in s && isEvmNetwork(s)
|
|
22806
23050
|
);
|
|
22807
23051
|
if (baseSpec !== void 0) {
|
|
22808
23052
|
x402ServerGetter = lazyX402Server({
|
|
@@ -22892,7 +23136,7 @@ var Checkout = class {
|
|
|
22892
23136
|
* `"x402_base"` when no match found. */
|
|
22893
23137
|
x402RailKey() {
|
|
22894
23138
|
for (const [k, v] of Object.entries(this.rails)) {
|
|
22895
|
-
if (!isStripeRailSpec2(v) && !isTempoSessionRailSpec3(v) && (v
|
|
23139
|
+
if (!isStripeRailSpec2(v) && !isTempoSessionRailSpec3(v) && isEvmNetwork(v)) {
|
|
22896
23140
|
return k;
|
|
22897
23141
|
}
|
|
22898
23142
|
}
|
|
@@ -22901,8 +23145,7 @@ var Checkout = class {
|
|
|
22901
23145
|
/** Return the rails-dict key for the primary MPP rail. */
|
|
22902
23146
|
mppRailKey() {
|
|
22903
23147
|
for (const [k, v] of Object.entries(this.rails)) {
|
|
22904
|
-
|
|
22905
|
-
if (!isStripeRailSpec2(v) && !network.startsWith("eip155:")) return k;
|
|
23148
|
+
if (!isStripeRailSpec2(v) && !isEvmNetwork(v)) return k;
|
|
22906
23149
|
}
|
|
22907
23150
|
return "tempo";
|
|
22908
23151
|
}
|
|
@@ -22921,17 +23164,15 @@ var Checkout = class {
|
|
|
22921
23164
|
if (method === "solana") {
|
|
22922
23165
|
for (const [k, v] of Object.entries(this.rails)) {
|
|
22923
23166
|
if (isStripeRailSpec2(v) || isTempoSessionRailSpec3(v)) continue;
|
|
22924
|
-
|
|
22925
|
-
if (network.startsWith("solana:") || "rpcUrl" in v || "tokenProgram" in v) return k;
|
|
23167
|
+
if (isSolanaNetwork(v) || "rpcUrl" in v || "tokenProgram" in v) return k;
|
|
22926
23168
|
}
|
|
22927
23169
|
return void 0;
|
|
22928
23170
|
}
|
|
22929
23171
|
if (method === "tempo") {
|
|
22930
23172
|
for (const [k, v] of Object.entries(this.rails)) {
|
|
22931
23173
|
if (isStripeRailSpec2(v)) continue;
|
|
22932
|
-
|
|
22933
|
-
if (
|
|
22934
|
-
if (network.startsWith("eip155:")) continue;
|
|
23174
|
+
if (isSolanaNetwork(v) || "rpcUrl" in v || "tokenProgram" in v) continue;
|
|
23175
|
+
if (isEvmNetwork(v)) continue;
|
|
22935
23176
|
return k;
|
|
22936
23177
|
}
|
|
22937
23178
|
return void 0;
|
|
@@ -22944,7 +23185,7 @@ var Checkout = class {
|
|
|
22944
23185
|
get x402BaseNetwork() {
|
|
22945
23186
|
if (!this.x402ServerAvailable()) return null;
|
|
22946
23187
|
for (const spec of Object.values(this.rails)) {
|
|
22947
|
-
if (!isStripeRailSpec2(spec) && !isTempoSessionRailSpec3(spec) && (spec
|
|
23188
|
+
if (!isStripeRailSpec2(spec) && !isTempoSessionRailSpec3(spec) && isEvmNetwork(spec)) {
|
|
22948
23189
|
return spec.network ?? "eip155:8453";
|
|
22949
23190
|
}
|
|
22950
23191
|
}
|
|
@@ -22996,8 +23237,8 @@ var Checkout = class {
|
|
|
22996
23237
|
throw err;
|
|
22997
23238
|
}
|
|
22998
23239
|
}
|
|
22999
|
-
const
|
|
23000
|
-
if (this.gate !== void 0 &&
|
|
23240
|
+
const hasPaymentHeader2 = hasX402Header(request.headers) || hasMppxHeader(request.headers);
|
|
23241
|
+
if (this.gate !== void 0 && hasPaymentHeader2) {
|
|
23001
23242
|
const denial = await this.runGate(ctx);
|
|
23002
23243
|
if (denial !== null) {
|
|
23003
23244
|
return {
|
|
@@ -23010,7 +23251,14 @@ var Checkout = class {
|
|
|
23010
23251
|
}
|
|
23011
23252
|
}
|
|
23012
23253
|
ctx.pricing = await this.computePricing(ctx);
|
|
23013
|
-
|
|
23254
|
+
try {
|
|
23255
|
+
await this.resolveRecipientsForCtx(ctx);
|
|
23256
|
+
} catch (err) {
|
|
23257
|
+
if (err instanceof Error && err.name === "CheckoutValidationError") {
|
|
23258
|
+
return this.validationErrorResult(ctx, err);
|
|
23259
|
+
}
|
|
23260
|
+
throw err;
|
|
23261
|
+
}
|
|
23014
23262
|
const x402ServerOk = this.x402ServerAvailable() && this.x402BaseNetwork !== null;
|
|
23015
23263
|
if (hasX402Header(request.headers) && x402ServerOk) {
|
|
23016
23264
|
const zero = await this.handleZeroSettle(ctx, "x402-base");
|
|
@@ -23081,13 +23329,21 @@ var Checkout = class {
|
|
|
23081
23329
|
...gate.failOpen !== void 0 && { failOpen: gate.failOpen },
|
|
23082
23330
|
...gate.cacheSeconds !== void 0 && { cacheSeconds: gate.cacheSeconds },
|
|
23083
23331
|
...gate.chain !== void 0 && { chain: gate.chain },
|
|
23084
|
-
|
|
23085
|
-
|
|
23332
|
+
// Auto-default `createSessionOnMissing` from gate config when the merchant
|
|
23333
|
+
// didn't supply one. Matches python-commerce's behavior — every gated route
|
|
23334
|
+
// gets the bootstrap session-mint UX out of the box. Merchants who need
|
|
23335
|
+
// custom session context or onBeforeSession side effects (goods merchants
|
|
23336
|
+
// pre-minting an order_id) supply their own config instead.
|
|
23337
|
+
createSessionOnMissing: gate.createSessionOnMissing ?? {
|
|
23338
|
+
apiKey: gate.apiKey,
|
|
23339
|
+
...gate.baseUrl !== void 0 && { baseUrl: gate.baseUrl },
|
|
23340
|
+
...gate.context !== void 0 && { context: gate.context },
|
|
23341
|
+
...gate.merchantName !== void 0 && { productName: gate.merchantName }
|
|
23086
23342
|
},
|
|
23087
23343
|
...policyOverride ?? {}
|
|
23088
23344
|
};
|
|
23089
23345
|
const core = createAgentScoreCore(coreOpts);
|
|
23090
|
-
const headers =
|
|
23346
|
+
const headers = normalizeHeadersToLowercase(ctx.request.headers);
|
|
23091
23347
|
const walletAddress = headers["x-wallet-address"];
|
|
23092
23348
|
const operatorToken = headers["x-operator-token"];
|
|
23093
23349
|
const identity = walletAddress !== void 0 || operatorToken !== void 0 ? {
|
|
@@ -23149,7 +23405,7 @@ var Checkout = class {
|
|
|
23149
23405
|
if (!this.zeroSettleCarveOut || ctx.pricing === null) return null;
|
|
23150
23406
|
const cents = Math.round(ctx.pricing.amountUsd * 100);
|
|
23151
23407
|
if (cents !== 0) return null;
|
|
23152
|
-
const headers =
|
|
23408
|
+
const headers = normalizeHeadersToLowercase(ctx.request.headers);
|
|
23153
23409
|
let zero;
|
|
23154
23410
|
if (rail === "x402-base") {
|
|
23155
23411
|
const x402Header = headers["payment-signature"] ?? headers["x-payment"];
|
|
@@ -23179,7 +23435,7 @@ var Checkout = class {
|
|
|
23179
23435
|
return await this.buildSuccess(ctx, outcome);
|
|
23180
23436
|
}
|
|
23181
23437
|
async mintRefId(request) {
|
|
23182
|
-
if (this.mintReferenceId === void 0) return (0,
|
|
23438
|
+
if (this.mintReferenceId === void 0) return (0, import_node_crypto2.randomUUID)();
|
|
23183
23439
|
const seedCtx = { request, referenceId: "", pricing: null, recipients: {}, state: {} };
|
|
23184
23440
|
return await this.mintReferenceId(seedCtx);
|
|
23185
23441
|
}
|
|
@@ -23223,7 +23479,7 @@ var Checkout = class {
|
|
|
23223
23479
|
resourceConfig: {
|
|
23224
23480
|
scheme: "exact",
|
|
23225
23481
|
network: verified.signedNetwork,
|
|
23226
|
-
price: `$${ctx.pricing.amountUsd.toFixed(2)}`,
|
|
23482
|
+
price: `$${ctx.pricing.amountUsd.toFixed(ctx.pricing.decimals ?? 2)}`,
|
|
23227
23483
|
payTo: verified.signedPayTo,
|
|
23228
23484
|
maxTimeoutSeconds: 300
|
|
23229
23485
|
},
|
|
@@ -23282,7 +23538,9 @@ var Checkout = class {
|
|
|
23282
23538
|
if (this.composeMppx === void 0) {
|
|
23283
23539
|
throw new Error("Checkout.handleMppx: composeMppx hook not configured");
|
|
23284
23540
|
}
|
|
23285
|
-
const composed = await
|
|
23541
|
+
const { result: composed, failureReason } = await runWithMppxFailureCapture(
|
|
23542
|
+
async () => this.composeMppx(ctx)
|
|
23543
|
+
);
|
|
23286
23544
|
if (composed.status === 200) {
|
|
23287
23545
|
const paymentReceiptHeader = composed.paymentReceiptHeader ?? extractMppxReceiptHeaderFromRaw(composed.raw);
|
|
23288
23546
|
const directMethod = composed.raw?.receipt?.method;
|
|
@@ -23301,6 +23559,22 @@ var Checkout = class {
|
|
|
23301
23559
|
};
|
|
23302
23560
|
return await this.buildSuccess(ctx, outcome);
|
|
23303
23561
|
}
|
|
23562
|
+
const classified = classifyMppxFailure(failureReason);
|
|
23563
|
+
if (classified !== null) {
|
|
23564
|
+
return {
|
|
23565
|
+
status: classified.status,
|
|
23566
|
+
body: buildValidationError({
|
|
23567
|
+
code: classified.code,
|
|
23568
|
+
message: classified.message,
|
|
23569
|
+
nextSteps: classified.nextSteps,
|
|
23570
|
+
...classified.extra && { extra: classified.extra }
|
|
23571
|
+
}),
|
|
23572
|
+
headers: { ...composed.headers ?? {} },
|
|
23573
|
+
referenceId: ctx.referenceId,
|
|
23574
|
+
settled: false,
|
|
23575
|
+
settlePhase: "verify_failed"
|
|
23576
|
+
};
|
|
23577
|
+
}
|
|
23304
23578
|
return {
|
|
23305
23579
|
status: 400,
|
|
23306
23580
|
body: buildValidationError({
|
|
@@ -23319,7 +23593,11 @@ var Checkout = class {
|
|
|
23319
23593
|
throw new Error("Checkout.emit402: pricing not computed");
|
|
23320
23594
|
}
|
|
23321
23595
|
await this.resolveRecipientsForCtx(ctx);
|
|
23322
|
-
|
|
23596
|
+
let emitRails = applyRecipientOverrides(this.rails, ctx.recipients);
|
|
23597
|
+
if (ctx.pricing.amountUsd < STRIPE_MIN_CHARGE_USD && emitRails.stripe !== void 0) {
|
|
23598
|
+
const { stripe: _stripe, ...rest } = emitRails;
|
|
23599
|
+
emitRails = rest;
|
|
23600
|
+
}
|
|
23323
23601
|
const accepted = await buildAcceptedMethods({
|
|
23324
23602
|
tempo: pickRail(emitRails, "tempo"),
|
|
23325
23603
|
x402_base: pickRail(emitRails, "x402_base"),
|
|
@@ -23332,15 +23610,18 @@ var Checkout = class {
|
|
|
23332
23610
|
howToPayRails[k] = v;
|
|
23333
23611
|
}
|
|
23334
23612
|
}
|
|
23613
|
+
const pricingDecimals = ctx.pricing.decimals ?? 2;
|
|
23335
23614
|
const howToPay = buildHowToPay({
|
|
23336
23615
|
url: this.url,
|
|
23337
23616
|
retryBodyJson: JSON.stringify(ctx.request.body),
|
|
23338
|
-
totalUsd: ctx.pricing.amountUsd.toFixed(
|
|
23339
|
-
rails: howToPayRails
|
|
23617
|
+
totalUsd: ctx.pricing.amountUsd.toFixed(pricingDecimals),
|
|
23618
|
+
rails: howToPayRails,
|
|
23619
|
+
...ctx.pricing.decimals !== void 0 && { decimals: ctx.pricing.decimals }
|
|
23340
23620
|
});
|
|
23341
23621
|
const pricingBlock = ctx.pricing.block ?? buildPricingBlock({
|
|
23342
|
-
subtotalCents:
|
|
23343
|
-
currency: ctx.pricing.currency ?? "USD"
|
|
23622
|
+
subtotalCents: ctx.pricing.amountUsd * 100,
|
|
23623
|
+
currency: ctx.pricing.currency ?? "USD",
|
|
23624
|
+
...ctx.pricing.decimals !== void 0 && { decimals: ctx.pricing.decimals }
|
|
23344
23625
|
});
|
|
23345
23626
|
let x402Accepts = [];
|
|
23346
23627
|
let x402Resource;
|
|
@@ -23353,7 +23634,7 @@ var Checkout = class {
|
|
|
23353
23634
|
try {
|
|
23354
23635
|
x402Accepts = await buildX402AcceptsFor402(x402Server, {
|
|
23355
23636
|
network: baseNetwork,
|
|
23356
|
-
price: `$${ctx.pricing.amountUsd.toFixed(
|
|
23637
|
+
price: `$${ctx.pricing.amountUsd.toFixed(pricingDecimals)}`,
|
|
23357
23638
|
payTo: recipient,
|
|
23358
23639
|
maxTimeoutSeconds: 300
|
|
23359
23640
|
});
|
|
@@ -23369,7 +23650,7 @@ var Checkout = class {
|
|
|
23369
23650
|
agentInstructions: buildAgentInstructions({ howToPay }),
|
|
23370
23651
|
...identityMetadata !== void 0 ? { identityMetadata } : {},
|
|
23371
23652
|
pricing: pricingBlock,
|
|
23372
|
-
amountUsd: ctx.pricing.amountUsd.toFixed(
|
|
23653
|
+
amountUsd: ctx.pricing.amountUsd.toFixed(pricingDecimals),
|
|
23373
23654
|
retryBody: ctx.request.body,
|
|
23374
23655
|
agentMemory: firstEncounterAgentMemory({ firstEncounter: true }),
|
|
23375
23656
|
...ctx.pricing.product ? { product: ctx.pricing.product } : {},
|
|
@@ -23477,25 +23758,6 @@ function stripContentType(headers) {
|
|
|
23477
23758
|
}
|
|
23478
23759
|
return out;
|
|
23479
23760
|
}
|
|
23480
|
-
function extractMppxReceiptHeaderFromRaw(raw) {
|
|
23481
|
-
if (!raw || typeof raw !== "object" || !("withReceipt" in raw)) return null;
|
|
23482
|
-
const fn = raw.withReceipt;
|
|
23483
|
-
if (typeof fn !== "function") return null;
|
|
23484
|
-
try {
|
|
23485
|
-
const wrapped = fn.call(raw, new Response());
|
|
23486
|
-
return wrapped.headers.get("Payment-Receipt");
|
|
23487
|
-
} catch {
|
|
23488
|
-
return null;
|
|
23489
|
-
}
|
|
23490
|
-
}
|
|
23491
|
-
async function extractMppxReceiptMethod(header) {
|
|
23492
|
-
try {
|
|
23493
|
-
const { Receipt } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
|
|
23494
|
-
return Receipt.deserialize(header).method;
|
|
23495
|
-
} catch {
|
|
23496
|
-
return void 0;
|
|
23497
|
-
}
|
|
23498
|
-
}
|
|
23499
23761
|
function headersToRecord(h) {
|
|
23500
23762
|
if (h === void 0) return {};
|
|
23501
23763
|
if (h instanceof Headers) {
|
|
@@ -23738,78 +24000,6 @@ Checkout.prototype.mountUcpRoutesFastify = function(app, opts) {
|
|
|
23738
24000
|
app.options(jwksPath, preflight);
|
|
23739
24001
|
};
|
|
23740
24002
|
|
|
23741
|
-
// src/identity/policy.ts
|
|
23742
|
-
function buildGateFromPolicy(policy, base) {
|
|
23743
|
-
if (!policy || !policy.enforcement) return null;
|
|
23744
|
-
return {
|
|
23745
|
-
apiKey: base.apiKey,
|
|
23746
|
-
...base.baseUrl !== void 0 && { baseUrl: base.baseUrl },
|
|
23747
|
-
...policy.requireKyc !== void 0 && { requireKyc: policy.requireKyc },
|
|
23748
|
-
...policy.requireSanctionsClear !== void 0 && {
|
|
23749
|
-
requireSanctionsClear: policy.requireSanctionsClear
|
|
23750
|
-
},
|
|
23751
|
-
...policy.minAge !== void 0 && { minAge: policy.minAge },
|
|
23752
|
-
...policy.allowedJurisdictions !== void 0 && {
|
|
23753
|
-
allowedJurisdictions: [...policy.allowedJurisdictions]
|
|
23754
|
-
}
|
|
23755
|
-
};
|
|
23756
|
-
}
|
|
23757
|
-
async function runGateWithEnforcement(enforcement, runGate) {
|
|
23758
|
-
if (!runGate || !enforcement) return { status: "anonymous" };
|
|
23759
|
-
const outcome = await runGate();
|
|
23760
|
-
if (outcome.ok) return { status: "verified" };
|
|
23761
|
-
if (enforcement === "hard") {
|
|
23762
|
-
return {
|
|
23763
|
-
status: "denied",
|
|
23764
|
-
denialStatus: outcome.status,
|
|
23765
|
-
denialBody: outcome.body,
|
|
23766
|
-
...outcome.reason !== void 0 && { denialReason: outcome.reason }
|
|
23767
|
-
};
|
|
23768
|
-
}
|
|
23769
|
-
return {
|
|
23770
|
-
status: "unverified",
|
|
23771
|
-
denialStatus: outcome.status,
|
|
23772
|
-
denialBody: outcome.body,
|
|
23773
|
-
...outcome.reason !== void 0 && { denialReason: outcome.reason }
|
|
23774
|
-
};
|
|
23775
|
-
}
|
|
23776
|
-
function shippingCountryAllowed(country, policy) {
|
|
23777
|
-
if (!policy?.allowedShippingCountries || policy.allowedShippingCountries.length === 0) return true;
|
|
23778
|
-
const allowed = new Set(policy.allowedShippingCountries.map((c) => c.toUpperCase()));
|
|
23779
|
-
return allowed.has(country.toUpperCase());
|
|
23780
|
-
}
|
|
23781
|
-
function shippingStateAllowed(state, country, policy) {
|
|
23782
|
-
if (!policy?.allowedShippingStates || policy.allowedShippingStates.length === 0) return true;
|
|
23783
|
-
if (country.toUpperCase() !== "US") return true;
|
|
23784
|
-
const allowed = new Set(policy.allowedShippingStates.map((s) => s.toUpperCase()));
|
|
23785
|
-
return allowed.has(state.toUpperCase());
|
|
23786
|
-
}
|
|
23787
|
-
function validateShippingAgainstPolicy(opts) {
|
|
23788
|
-
const code = opts.errorCode ?? "unsupported_jurisdiction";
|
|
23789
|
-
const action = opts.errorAction ?? "change_shipping_state";
|
|
23790
|
-
const item = opts.productName ? `'${opts.productName}'` : "this item";
|
|
23791
|
-
if (!shippingCountryAllowed(opts.country, opts.policy)) {
|
|
23792
|
-
throw new CheckoutValidationError({
|
|
23793
|
-
code,
|
|
23794
|
-
message: opts.countryMessage ?? `We can't ship ${item} to ${opts.country.toUpperCase() || "<unset>"}.`,
|
|
23795
|
-
action
|
|
23796
|
-
});
|
|
23797
|
-
}
|
|
23798
|
-
if (!shippingStateAllowed(opts.state, opts.country, opts.policy)) {
|
|
23799
|
-
throw new CheckoutValidationError({
|
|
23800
|
-
code,
|
|
23801
|
-
message: opts.stateMessage ?? `We can't ship ${item} to ${opts.state.toUpperCase() || "<unset>"}.`,
|
|
23802
|
-
action
|
|
23803
|
-
});
|
|
23804
|
-
}
|
|
23805
|
-
}
|
|
23806
|
-
|
|
23807
|
-
// src/identity/tokens.ts
|
|
23808
|
-
var import_node_crypto2 = require("crypto");
|
|
23809
|
-
function hashOperatorToken(plaintext) {
|
|
23810
|
-
return (0, import_node_crypto2.createHash)("sha256").update(plaintext, "utf8").digest("hex");
|
|
23811
|
-
}
|
|
23812
|
-
|
|
23813
24003
|
// src/payment/index.ts
|
|
23814
24004
|
init_directive();
|
|
23815
24005
|
init_networks();
|
|
@@ -23822,8 +24012,45 @@ init_directive();
|
|
|
23822
24012
|
init_wwwauthenticate();
|
|
23823
24013
|
|
|
23824
24014
|
// src/payment/amounts.ts
|
|
23825
|
-
function
|
|
23826
|
-
|
|
24015
|
+
function usdToAtomic(usd, opts) {
|
|
24016
|
+
const { decimals } = opts;
|
|
24017
|
+
if (!Number.isInteger(decimals) || decimals < 0) {
|
|
24018
|
+
throw new RangeError(`decimals must be a non-negative integer, got ${decimals}`);
|
|
24019
|
+
}
|
|
24020
|
+
if (typeof usd === "number") {
|
|
24021
|
+
if (!Number.isFinite(usd)) {
|
|
24022
|
+
throw new RangeError(`usd must be finite, got ${usd}`);
|
|
24023
|
+
}
|
|
24024
|
+
if (usd < 0) {
|
|
24025
|
+
throw new RangeError(`usd must be non-negative, got ${usd}`);
|
|
24026
|
+
}
|
|
24027
|
+
}
|
|
24028
|
+
const s = (typeof usd === "number" ? usd.toString() : usd).trim();
|
|
24029
|
+
if (s.startsWith("-")) {
|
|
24030
|
+
throw new RangeError(`usd must be non-negative, got ${s}`);
|
|
24031
|
+
}
|
|
24032
|
+
if (s === "NaN" || s === "Infinity") {
|
|
24033
|
+
throw new RangeError(`usd must be finite, got ${s}`);
|
|
24034
|
+
}
|
|
24035
|
+
const match = /^(\d*)(?:\.(\d*))?$/.exec(s);
|
|
24036
|
+
if (!match || match[1] === "" && (match[2] === void 0 || match[2] === "")) {
|
|
24037
|
+
throw new SyntaxError(`invalid usd value: ${JSON.stringify(usd)}`);
|
|
24038
|
+
}
|
|
24039
|
+
const intPart = match[1] || "0";
|
|
24040
|
+
const fracPart = match[2] ?? "";
|
|
24041
|
+
if (fracPart.length <= decimals) {
|
|
24042
|
+
return BigInt(intPart + fracPart.padEnd(decimals, "0"));
|
|
24043
|
+
}
|
|
24044
|
+
const kept = fracPart.slice(0, decimals);
|
|
24045
|
+
const roundDigit = fracPart[decimals];
|
|
24046
|
+
let result = BigInt(intPart + kept);
|
|
24047
|
+
if (roundDigit >= "5") {
|
|
24048
|
+
result += 1n;
|
|
24049
|
+
}
|
|
24050
|
+
return result;
|
|
24051
|
+
}
|
|
24052
|
+
function formatUsdCents(cents, decimals = 2) {
|
|
24053
|
+
return (cents / 100).toFixed(decimals);
|
|
23827
24054
|
}
|
|
23828
24055
|
|
|
23829
24056
|
// src/payment/solana.ts
|
|
@@ -23846,8 +24073,644 @@ async function loadSolanaFeePayer(opts) {
|
|
|
23846
24073
|
}
|
|
23847
24074
|
return kit.createKeyPairSignerFromPrivateKeyBytes(bytes);
|
|
23848
24075
|
}
|
|
24076
|
+
|
|
24077
|
+
// src/payment/compose_rails.ts
|
|
24078
|
+
init_usdc();
|
|
24079
|
+
var warnedStripeBelowMinimum = false;
|
|
24080
|
+
function buildMppxComposeRails(opts) {
|
|
24081
|
+
const rails2 = [];
|
|
24082
|
+
if (opts.tempoRecipient) {
|
|
24083
|
+
rails2.push(["tempo/charge", {
|
|
24084
|
+
amount: opts.amountUsd,
|
|
24085
|
+
currency: opts.tempoTokenAddress ?? USDC.tempo.mainnet.address,
|
|
24086
|
+
decimals: 6,
|
|
24087
|
+
recipient: opts.tempoRecipient
|
|
24088
|
+
}]);
|
|
24089
|
+
}
|
|
24090
|
+
if (opts.solanaRecipient) {
|
|
24091
|
+
const atomic = usdToAtomic(opts.amountUsd, { decimals: 6 });
|
|
24092
|
+
rails2.push(["solana/charge", {
|
|
24093
|
+
amount: atomic.toString(),
|
|
24094
|
+
currency: opts.solanaTokenMint ?? USDC.solana.mainnet.mint,
|
|
24095
|
+
decimals: 6,
|
|
24096
|
+
recipient: opts.solanaRecipient,
|
|
24097
|
+
network: opts.solanaNetwork ?? "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
|
|
24098
|
+
}]);
|
|
24099
|
+
}
|
|
24100
|
+
if (opts.includeStripe !== false) {
|
|
24101
|
+
const amountUsdNumeric = Number(opts.amountUsd);
|
|
24102
|
+
if (Number.isFinite(amountUsdNumeric) && amountUsdNumeric < STRIPE_MIN_CHARGE_USD) {
|
|
24103
|
+
if (!warnedStripeBelowMinimum) {
|
|
24104
|
+
warnedStripeBelowMinimum = true;
|
|
24105
|
+
console.warn(
|
|
24106
|
+
`[buildMppxComposeRails] Dropping stripe/charge rail: amountUsd=${opts.amountUsd} is below Stripe's $${STRIPE_MIN_CHARGE_USD.toFixed(2)} USD minimum. Stripe's fixed ~$0.30 fee makes sub-50-cent charges unprofitable (and many accounts reject PI creation with amount_too_small below this floor). Pass includeStripe: false to suppress this warning.`
|
|
24107
|
+
);
|
|
24108
|
+
}
|
|
24109
|
+
} else {
|
|
24110
|
+
rails2.push(["stripe/charge", { amount: opts.amountUsd, currency: "usd", decimals: 2 }]);
|
|
24111
|
+
}
|
|
24112
|
+
}
|
|
24113
|
+
return rails2;
|
|
24114
|
+
}
|
|
24115
|
+
|
|
24116
|
+
// src/payment/default_rails.ts
|
|
24117
|
+
init_networks();
|
|
24118
|
+
init_usdc();
|
|
24119
|
+
function buildDefaultCheckoutRails(opts) {
|
|
24120
|
+
const out = {};
|
|
24121
|
+
if (opts.tempo) {
|
|
24122
|
+
out.tempo = { recipient: "", ...RAIL_SPEC_DEFAULTS.tempo, ...opts.tempo };
|
|
24123
|
+
}
|
|
24124
|
+
if (opts.x402Base) {
|
|
24125
|
+
const merged = { recipient: "", ...RAIL_SPEC_DEFAULTS.x402Base, ...opts.x402Base };
|
|
24126
|
+
if (merged.network === networks.base.sepolia.caip2) {
|
|
24127
|
+
if (opts.x402Base.chainId === void 0) merged.chainId = networks.base.sepolia.chainId;
|
|
24128
|
+
if (opts.x402Base.token === void 0) merged.token = USDC.base.sepolia.address;
|
|
24129
|
+
} else if (merged.network === networks.base.mainnet.caip2) {
|
|
24130
|
+
if (opts.x402Base.chainId === void 0) merged.chainId = networks.base.mainnet.chainId;
|
|
24131
|
+
if (opts.x402Base.token === void 0) merged.token = USDC.base.mainnet.address;
|
|
24132
|
+
}
|
|
24133
|
+
out.x402_base = merged;
|
|
24134
|
+
}
|
|
24135
|
+
if (opts.solanaMpp) {
|
|
24136
|
+
const merged = { recipient: "", ...RAIL_SPEC_DEFAULTS.solanaMpp, ...opts.solanaMpp };
|
|
24137
|
+
const isDevnet = merged.network === "devnet" || merged.network === networks.solana.devnet.caip2;
|
|
24138
|
+
if (isDevnet && opts.solanaMpp.token === void 0) {
|
|
24139
|
+
merged.token = USDC.solana.devnet.mint;
|
|
24140
|
+
}
|
|
24141
|
+
out.solana_mpp = merged;
|
|
24142
|
+
}
|
|
24143
|
+
if (opts.stripe) {
|
|
24144
|
+
out.stripe = { ...RAIL_SPEC_DEFAULTS.stripe, ...opts.stripe };
|
|
24145
|
+
}
|
|
24146
|
+
return out;
|
|
24147
|
+
}
|
|
24148
|
+
|
|
24149
|
+
// src/payment/index.ts
|
|
24150
|
+
init_network_kind();
|
|
24151
|
+
|
|
24152
|
+
// src/checkout_compute_first.ts
|
|
24153
|
+
var import_crypto2 = require("crypto");
|
|
24154
|
+
|
|
24155
|
+
// src/discovery/index.ts
|
|
24156
|
+
init_probe();
|
|
24157
|
+
|
|
24158
|
+
// src/discovery/agentscore_content.ts
|
|
24159
|
+
var PURCHASE_MODE_NOTES = Object.freeze({
|
|
24160
|
+
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.",
|
|
24161
|
+
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).",
|
|
24162
|
+
paid_only: "Codes are NOT accepted. Settle at the listed price. Submitting a `redemption_code` field returns 400 codes_not_accepted."
|
|
24163
|
+
});
|
|
24164
|
+
function buildSuccessNextSteps(opts) {
|
|
24165
|
+
const out = {
|
|
24166
|
+
action: "done",
|
|
24167
|
+
user_message: opts.userMessage ?? "Payment complete. Your AgentScore Passport is now active across every AgentScore-gated merchant."
|
|
24168
|
+
};
|
|
24169
|
+
if (opts.orderStatusUrl) out.order_status_url = opts.orderStatusUrl;
|
|
24170
|
+
if (opts.fulfillmentEta !== void 0) out.fulfillment_eta = opts.fulfillmentEta;
|
|
24171
|
+
return out;
|
|
24172
|
+
}
|
|
24173
|
+
|
|
24174
|
+
// src/discovery/index.ts
|
|
24175
|
+
init_well_known();
|
|
24176
|
+
|
|
24177
|
+
// src/quote_cache.ts
|
|
24178
|
+
var import_crypto = require("crypto");
|
|
24179
|
+
|
|
24180
|
+
// src/_redis.ts
|
|
24181
|
+
async function tryCreateRedis(opts) {
|
|
24182
|
+
const url2 = opts.url ?? process.env.REDIS_URL;
|
|
24183
|
+
if (!url2) return null;
|
|
24184
|
+
try {
|
|
24185
|
+
const mod = await import("ioredis");
|
|
24186
|
+
const client = new mod.default(url2, {
|
|
24187
|
+
connectTimeout: opts.connectTimeout ?? 3e3,
|
|
24188
|
+
maxRetriesPerRequest: opts.maxRetriesPerRequest ?? 1,
|
|
24189
|
+
tls: url2.startsWith("rediss://") ? {} : void 0
|
|
24190
|
+
});
|
|
24191
|
+
client.on("error", (err) => console.error(`[${opts.label}] Redis error:`, err.message));
|
|
24192
|
+
return client;
|
|
24193
|
+
} catch {
|
|
24194
|
+
return null;
|
|
24195
|
+
}
|
|
24196
|
+
}
|
|
24197
|
+
function memoizedRedis(opts) {
|
|
24198
|
+
let promise2 = null;
|
|
24199
|
+
return () => {
|
|
24200
|
+
if (!promise2) promise2 = tryCreateRedis(opts);
|
|
24201
|
+
return promise2;
|
|
24202
|
+
};
|
|
24203
|
+
}
|
|
24204
|
+
|
|
24205
|
+
// src/quote_cache.ts
|
|
24206
|
+
function canonicalize2(value) {
|
|
24207
|
+
if (Array.isArray(value)) return value.map(canonicalize2);
|
|
24208
|
+
if (value && typeof value === "object") {
|
|
24209
|
+
const sorted = {};
|
|
24210
|
+
for (const key of Object.keys(value).sort()) {
|
|
24211
|
+
sorted[key] = canonicalize2(value[key]);
|
|
24212
|
+
}
|
|
24213
|
+
return sorted;
|
|
24214
|
+
}
|
|
24215
|
+
return value;
|
|
24216
|
+
}
|
|
24217
|
+
function createQuoteCache(opts = {}) {
|
|
24218
|
+
const ttlMs = opts.ttlMs ?? 5 * 6e4;
|
|
24219
|
+
const keyPrefix = opts.keyPrefix ?? "quote:";
|
|
24220
|
+
const memMap = /* @__PURE__ */ new Map();
|
|
24221
|
+
const getRedis = memoizedRedis({ url: opts.redisUrl, label: "quote-cache" });
|
|
24222
|
+
const evictExpired = () => {
|
|
24223
|
+
const now = Date.now();
|
|
24224
|
+
for (const [k, v] of memMap.entries()) {
|
|
24225
|
+
if (v.expiresAt <= now) memMap.delete(k);
|
|
24226
|
+
}
|
|
24227
|
+
};
|
|
24228
|
+
return {
|
|
24229
|
+
bodyHashKey(prefix, body) {
|
|
24230
|
+
const canonical = JSON.stringify(canonicalize2(body));
|
|
24231
|
+
const hash3 = (0, import_crypto.createHash)("sha256").update(`${prefix}::${canonical}`).digest("hex").slice(0, 24);
|
|
24232
|
+
return `${prefix}::${hash3}`;
|
|
24233
|
+
},
|
|
24234
|
+
async read(key) {
|
|
24235
|
+
const r = await getRedis();
|
|
24236
|
+
if (r) {
|
|
24237
|
+
try {
|
|
24238
|
+
const raw = await r.get(`${keyPrefix}${key}`);
|
|
24239
|
+
if (!raw) return null;
|
|
24240
|
+
return JSON.parse(raw);
|
|
24241
|
+
} catch {
|
|
24242
|
+
}
|
|
24243
|
+
}
|
|
24244
|
+
evictExpired();
|
|
24245
|
+
const entry = memMap.get(key);
|
|
24246
|
+
return entry ? entry.entry : null;
|
|
24247
|
+
},
|
|
24248
|
+
async write(key, body, priceCents, recipients = {}) {
|
|
24249
|
+
const cached2 = { body, priceCents, recipients };
|
|
24250
|
+
const r = await getRedis();
|
|
24251
|
+
if (r) {
|
|
24252
|
+
try {
|
|
24253
|
+
await r.set(`${keyPrefix}${key}`, JSON.stringify(cached2), "PX", ttlMs);
|
|
24254
|
+
return;
|
|
24255
|
+
} catch {
|
|
24256
|
+
}
|
|
24257
|
+
}
|
|
24258
|
+
memMap.set(key, { entry: cached2, expiresAt: Date.now() + ttlMs });
|
|
24259
|
+
},
|
|
24260
|
+
async clear() {
|
|
24261
|
+
memMap.clear();
|
|
24262
|
+
const r = await getRedis();
|
|
24263
|
+
if (r) {
|
|
24264
|
+
try {
|
|
24265
|
+
await r.flushdb();
|
|
24266
|
+
} catch {
|
|
24267
|
+
}
|
|
24268
|
+
}
|
|
24269
|
+
}
|
|
24270
|
+
};
|
|
24271
|
+
}
|
|
24272
|
+
|
|
24273
|
+
// src/checkout_compute_first.ts
|
|
24274
|
+
var DEFAULT_TTL_MS = 5 * 6e4;
|
|
24275
|
+
function decimalsForUnit(unitPriceCents) {
|
|
24276
|
+
if (Number.isInteger(unitPriceCents)) return 2;
|
|
24277
|
+
const str = unitPriceCents.toString();
|
|
24278
|
+
const dotIdx = str.indexOf(".");
|
|
24279
|
+
const frac = dotIdx === -1 ? 0 : str.length - dotIdx - 1;
|
|
24280
|
+
return 2 + frac;
|
|
24281
|
+
}
|
|
24282
|
+
function computeFirstCheckout(opts) {
|
|
24283
|
+
const cache = opts.cache ?? createQuoteCache({ ttlMs: opts.cacheTtlMs ?? DEFAULT_TTL_MS });
|
|
24284
|
+
const decimals = opts.decimals ?? decimalsForUnit(opts.unitPriceCents);
|
|
24285
|
+
const appUrl = opts.appUrl ?? new URL(opts.url).origin;
|
|
24286
|
+
async function mintAndResolveRecipients(req, body, priceCents) {
|
|
24287
|
+
const minted = opts.mintRecipients ? await opts.mintRecipients({ request: req, body, priceCents }) : {};
|
|
24288
|
+
const out = {};
|
|
24289
|
+
const tempo = minted.tempo ?? (opts.rails.tempo ? await resolveRecipient(opts.rails.tempo.recipient) : void 0);
|
|
24290
|
+
const x402Base = minted.x402_base ?? (opts.rails.x402_base ? await resolveRecipient(opts.rails.x402_base.recipient) : void 0);
|
|
24291
|
+
const solana = minted.solana_mpp ?? (opts.rails.solana_mpp ? await resolveRecipient(opts.rails.solana_mpp.recipient) : void 0);
|
|
24292
|
+
if (tempo) out.tempo = tempo;
|
|
24293
|
+
if (x402Base) out.x402_base = x402Base;
|
|
24294
|
+
if (solana) out.solana_mpp = solana;
|
|
24295
|
+
return out;
|
|
24296
|
+
}
|
|
24297
|
+
async function emit402(req, body, priceCents, recipients) {
|
|
24298
|
+
const totalUsd = formatUsdCents(priceCents, decimals);
|
|
24299
|
+
const tempoRecipient = recipients.tempo;
|
|
24300
|
+
const x402BaseRecipient = recipients.x402_base;
|
|
24301
|
+
const solanaRecipient = recipients.solana_mpp;
|
|
24302
|
+
const includeStripeInDiscovery = opts.rails.stripe !== void 0 && Number(totalUsd) >= STRIPE_MIN_CHARGE_USD;
|
|
24303
|
+
const accepted = await buildAcceptedMethods({
|
|
24304
|
+
...tempoRecipient && opts.rails.tempo && { tempo: { ...opts.rails.tempo, recipient: tempoRecipient } },
|
|
24305
|
+
...solanaRecipient && opts.rails.solana_mpp && { solana_mpp: { ...opts.rails.solana_mpp, recipient: solanaRecipient } },
|
|
24306
|
+
...includeStripeInDiscovery && { stripe: opts.rails.stripe }
|
|
24307
|
+
});
|
|
24308
|
+
if (x402BaseRecipient && opts.rails.x402_base) {
|
|
24309
|
+
try {
|
|
24310
|
+
const resolvedX402PayTo = await resolveRecipient(x402BaseRecipient);
|
|
24311
|
+
const x402Entries = await buildX402AcceptsFor402(opts.x402Server, {
|
|
24312
|
+
network: opts.rails.x402_base.network ?? "eip155:8453",
|
|
24313
|
+
price: `$${totalUsd}`,
|
|
24314
|
+
payTo: resolvedX402PayTo,
|
|
24315
|
+
maxTimeoutSeconds: 300
|
|
24316
|
+
});
|
|
24317
|
+
accepted.push(...x402Entries);
|
|
24318
|
+
} catch (err) {
|
|
24319
|
+
console.warn(
|
|
24320
|
+
`[${opts.name}.computeFirst] buildX402AcceptsFor402 failed; dropping x402 from accepts:`,
|
|
24321
|
+
err instanceof Error ? err.message : err
|
|
24322
|
+
);
|
|
24323
|
+
}
|
|
24324
|
+
}
|
|
24325
|
+
const howToPay = buildHowToPay({
|
|
24326
|
+
url: opts.url,
|
|
24327
|
+
retryBodyJson: JSON.stringify(body),
|
|
24328
|
+
totalUsd,
|
|
24329
|
+
decimals,
|
|
24330
|
+
rails: {
|
|
24331
|
+
...tempoRecipient && opts.rails.tempo && { tempo: { ...opts.rails.tempo, recipient: tempoRecipient } },
|
|
24332
|
+
...x402BaseRecipient && opts.rails.x402_base && { x402_base: { ...opts.rails.x402_base, recipient: x402BaseRecipient } },
|
|
24333
|
+
...solanaRecipient && opts.rails.solana_mpp && { solana_mpp: { ...opts.rails.solana_mpp, recipient: solanaRecipient } },
|
|
24334
|
+
...opts.rails.stripe && { stripe: opts.rails.stripe }
|
|
24335
|
+
}
|
|
24336
|
+
});
|
|
24337
|
+
const pricing = buildPricingBlock({ subtotalCents: priceCents, currency: "USD", decimals });
|
|
24338
|
+
const agentInstructions = buildAgentInstructions({
|
|
24339
|
+
howToPay,
|
|
24340
|
+
warnings: [
|
|
24341
|
+
"The quoted price is exact: it was derived from the actual number of results returned by the work on the probe leg.",
|
|
24342
|
+
"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."
|
|
24343
|
+
]
|
|
24344
|
+
});
|
|
24345
|
+
let mppChallengeHeaders = {};
|
|
24346
|
+
if (opts.composeMppx) {
|
|
24347
|
+
try {
|
|
24348
|
+
const mppResult = await opts.composeMppx({
|
|
24349
|
+
request: req,
|
|
24350
|
+
cachedBody: body,
|
|
24351
|
+
priceCents,
|
|
24352
|
+
priceUsd: totalUsd,
|
|
24353
|
+
recipients
|
|
24354
|
+
});
|
|
24355
|
+
if (mppResult.status === 402 && mppResult.headers) {
|
|
24356
|
+
mppChallengeHeaders = mppResult.headers;
|
|
24357
|
+
}
|
|
24358
|
+
} catch (err) {
|
|
24359
|
+
console.warn(
|
|
24360
|
+
`[${opts.name}.computeFirst] composeMppx probe-leg failed; dropping MPP rails from 402 challenge:`,
|
|
24361
|
+
err instanceof Error ? err.message : err
|
|
24362
|
+
);
|
|
24363
|
+
}
|
|
24364
|
+
}
|
|
24365
|
+
const body402 = build402Body({
|
|
24366
|
+
product: { id: opts.name, name: opts.name },
|
|
24367
|
+
acceptedMethods: accepted,
|
|
24368
|
+
pricing,
|
|
24369
|
+
agentInstructions,
|
|
24370
|
+
amountUsd: totalUsd,
|
|
24371
|
+
currency: "USD",
|
|
24372
|
+
orderId: null,
|
|
24373
|
+
retryBody: body
|
|
24374
|
+
});
|
|
24375
|
+
const headers = new Headers({ "Content-Type": "application/json" });
|
|
24376
|
+
for (const [k, v] of Object.entries(mppChallengeHeaders)) headers.set(k, v);
|
|
24377
|
+
headers.set(
|
|
24378
|
+
"PAYMENT-REQUIRED",
|
|
24379
|
+
paymentRequiredHeader({ x402Version: 2, accepts: accepted, resource: { url: opts.url } })
|
|
24380
|
+
);
|
|
24381
|
+
return new Response(JSON.stringify(body402), { status: 402, headers });
|
|
24382
|
+
}
|
|
24383
|
+
async function handleX402Settle(req, referenceId, cachedBody, priceCents, recipients) {
|
|
24384
|
+
const verified = await verifyX402Request({
|
|
24385
|
+
request: req,
|
|
24386
|
+
isCachedAddress: async () => true,
|
|
24387
|
+
acceptedNetwork: opts.rails.x402_base?.network ?? "eip155:8453"
|
|
24388
|
+
});
|
|
24389
|
+
if (!verified.ok) {
|
|
24390
|
+
return new Response(JSON.stringify(verified.body), {
|
|
24391
|
+
status: verified.status,
|
|
24392
|
+
headers: { "Content-Type": "application/json" }
|
|
24393
|
+
});
|
|
24394
|
+
}
|
|
24395
|
+
const actualUsd = formatUsdCents(priceCents, decimals);
|
|
24396
|
+
const settle = await processX402Settle({
|
|
24397
|
+
x402Server: opts.x402Server,
|
|
24398
|
+
payload: verified.payload,
|
|
24399
|
+
resourceConfig: {
|
|
24400
|
+
scheme: "exact",
|
|
24401
|
+
network: verified.signedNetwork,
|
|
24402
|
+
price: `$${actualUsd}`,
|
|
24403
|
+
payTo: verified.signedPayTo,
|
|
24404
|
+
maxTimeoutSeconds: 300
|
|
24405
|
+
},
|
|
24406
|
+
resourceMeta: {
|
|
24407
|
+
url: req.url,
|
|
24408
|
+
description: `Agent purchase via x402-exact (${opts.name})`,
|
|
24409
|
+
mimeType: "application/json"
|
|
24410
|
+
}
|
|
24411
|
+
});
|
|
24412
|
+
if (!settle.success) {
|
|
24413
|
+
const detail = settle.error?.message ?? "unknown";
|
|
24414
|
+
return new Response(
|
|
24415
|
+
JSON.stringify({
|
|
24416
|
+
id: referenceId,
|
|
24417
|
+
endpoint: opts.name,
|
|
24418
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24419
|
+
payment_status: "failed",
|
|
24420
|
+
charged_usd: "0.00",
|
|
24421
|
+
rail: `x402-base (${verified.signedNetwork})`,
|
|
24422
|
+
error: {
|
|
24423
|
+
code: "settle_failed",
|
|
24424
|
+
message: "Facilitator rejected the exact settle; no on-chain capture occurred.",
|
|
24425
|
+
detail
|
|
24426
|
+
}
|
|
24427
|
+
}),
|
|
24428
|
+
{ status: 502, headers: { "Content-Type": "application/json" } }
|
|
24429
|
+
);
|
|
24430
|
+
}
|
|
24431
|
+
const signer = await extractPaymentSigner(req, readX402PaymentHeader(req));
|
|
24432
|
+
const signerInfo = signer ? { address: signer.address, network: signer.network } : void 0;
|
|
24433
|
+
const railLabel = `Base (${verified.signedNetwork})`;
|
|
24434
|
+
if (opts.onSettled) {
|
|
24435
|
+
try {
|
|
24436
|
+
await opts.onSettled({
|
|
24437
|
+
request: req,
|
|
24438
|
+
rail: "x402",
|
|
24439
|
+
cachedBody,
|
|
24440
|
+
priceCents,
|
|
24441
|
+
priceUsd: actualUsd,
|
|
24442
|
+
recipients,
|
|
24443
|
+
...signerInfo ? { signer: signerInfo } : {}
|
|
24444
|
+
});
|
|
24445
|
+
} catch (err) {
|
|
24446
|
+
console.warn(`[${opts.name}.computeFirst.onSettled] x402 side-effect failed:`, err instanceof Error ? err.message : err);
|
|
24447
|
+
}
|
|
24448
|
+
}
|
|
24449
|
+
const buildBody = opts.buildSuccessBody ?? defaultSuccessBody(appUrl);
|
|
24450
|
+
const body = buildBody({
|
|
24451
|
+
referenceId,
|
|
24452
|
+
endpoint: opts.name,
|
|
24453
|
+
chargedUsd: actualUsd,
|
|
24454
|
+
rail: railLabel,
|
|
24455
|
+
...signerInfo ? { signer: signerInfo } : {},
|
|
24456
|
+
cachedBody
|
|
24457
|
+
});
|
|
24458
|
+
return new Response(JSON.stringify(body), { status: 200, headers: { "Content-Type": "application/json" } });
|
|
24459
|
+
}
|
|
24460
|
+
function mppRailLabel(method) {
|
|
24461
|
+
const scheme = method?.split("/")[0];
|
|
24462
|
+
if (scheme === "tempo") {
|
|
24463
|
+
const networkName = opts.rails.tempo?.testnet ? "tempo-testnet" : opts.rails.tempo?.network ?? "tempo-mainnet";
|
|
24464
|
+
return `Tempo (${networkName})`;
|
|
24465
|
+
}
|
|
24466
|
+
if (scheme === "solana") {
|
|
24467
|
+
const networkName = opts.rails.solana_mpp?.network ?? "solana";
|
|
24468
|
+
return `Solana (${networkName})`;
|
|
24469
|
+
}
|
|
24470
|
+
if (scheme === "stripe") return "Stripe (card+link)";
|
|
24471
|
+
return "MPP";
|
|
24472
|
+
}
|
|
24473
|
+
async function handleMppSettle(req, referenceId, cachedBody, priceCents, recipients) {
|
|
24474
|
+
if (!opts.composeMppx) {
|
|
24475
|
+
return new Response(
|
|
24476
|
+
JSON.stringify({
|
|
24477
|
+
id: referenceId,
|
|
24478
|
+
endpoint: opts.name,
|
|
24479
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24480
|
+
payment_status: "failed",
|
|
24481
|
+
charged_usd: "0.00",
|
|
24482
|
+
error: { code: "mpp_unavailable", message: "MPP settle hook not configured on this endpoint." }
|
|
24483
|
+
}),
|
|
24484
|
+
{ status: 503, headers: { "Content-Type": "application/json" } }
|
|
24485
|
+
);
|
|
24486
|
+
}
|
|
24487
|
+
const priceUsd = formatUsdCents(priceCents, decimals);
|
|
24488
|
+
const result = await opts.composeMppx({ request: req, cachedBody, priceCents, priceUsd, recipients });
|
|
24489
|
+
if (result.status !== 200) {
|
|
24490
|
+
const headers = result.headers ?? {};
|
|
24491
|
+
return new Response(
|
|
24492
|
+
JSON.stringify({
|
|
24493
|
+
id: referenceId,
|
|
24494
|
+
endpoint: opts.name,
|
|
24495
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24496
|
+
payment_status: "failed",
|
|
24497
|
+
charged_usd: "0.00",
|
|
24498
|
+
error: { code: "mpp_settle_failed", message: "MPP compose did not return 200; credential rejected." }
|
|
24499
|
+
}),
|
|
24500
|
+
{ status: 400, headers: { "Content-Type": "application/json", ...headers } }
|
|
24501
|
+
);
|
|
24502
|
+
}
|
|
24503
|
+
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);
|
|
24504
|
+
const method = await deriveMppxReceiptMethod(result.raw);
|
|
24505
|
+
const railLabel = mppRailLabel(method);
|
|
24506
|
+
if (opts.onSettled) {
|
|
24507
|
+
try {
|
|
24508
|
+
await opts.onSettled({
|
|
24509
|
+
request: req,
|
|
24510
|
+
rail: "mpp",
|
|
24511
|
+
mppMethod: method,
|
|
24512
|
+
cachedBody,
|
|
24513
|
+
priceCents,
|
|
24514
|
+
priceUsd,
|
|
24515
|
+
recipients,
|
|
24516
|
+
...signer ? { signer } : {},
|
|
24517
|
+
...result.txHash ? { paymentIntentId: result.txHash } : {}
|
|
24518
|
+
});
|
|
24519
|
+
} catch (err) {
|
|
24520
|
+
console.warn(`[${opts.name}.computeFirst.onSettled] MPP side-effect failed:`, err instanceof Error ? err.message : err);
|
|
24521
|
+
}
|
|
24522
|
+
}
|
|
24523
|
+
const buildBody = opts.buildSuccessBody ?? defaultSuccessBody(appUrl);
|
|
24524
|
+
const body = buildBody({
|
|
24525
|
+
referenceId,
|
|
24526
|
+
endpoint: opts.name,
|
|
24527
|
+
chargedUsd: priceUsd,
|
|
24528
|
+
rail: railLabel,
|
|
24529
|
+
...result.txHash ? { paymentIntentId: result.txHash } : {},
|
|
24530
|
+
...signer ? { signer } : {},
|
|
24531
|
+
cachedBody
|
|
24532
|
+
});
|
|
24533
|
+
return new Response(JSON.stringify(body), { status: 200, headers: { "Content-Type": "application/json" } });
|
|
24534
|
+
}
|
|
24535
|
+
async function handle(req) {
|
|
24536
|
+
const referenceId = `${opts.name}_${(0, import_crypto2.randomUUID)()}`;
|
|
24537
|
+
let body;
|
|
24538
|
+
try {
|
|
24539
|
+
body = await req.clone().json();
|
|
24540
|
+
} catch {
|
|
24541
|
+
body = {};
|
|
24542
|
+
}
|
|
24543
|
+
try {
|
|
24544
|
+
opts.validateInput?.(body);
|
|
24545
|
+
} catch (err) {
|
|
24546
|
+
if (err instanceof CheckoutValidationError) {
|
|
24547
|
+
return new Response(
|
|
24548
|
+
JSON.stringify({
|
|
24549
|
+
error: { code: err.code, message: err.message },
|
|
24550
|
+
...err.action ? { next_steps: { action: err.action, user_message: err.message } } : {},
|
|
24551
|
+
...err.extra
|
|
24552
|
+
}),
|
|
24553
|
+
{ status: err.status, headers: { "Content-Type": "application/json" } }
|
|
24554
|
+
);
|
|
24555
|
+
}
|
|
24556
|
+
throw err;
|
|
24557
|
+
}
|
|
24558
|
+
const cacheKey2 = cache.bodyHashKey(opts.name, body);
|
|
24559
|
+
if (hasX402Header(req.headers) || hasMppxHeader(req.headers)) {
|
|
24560
|
+
const quote2 = await cache.read(cacheKey2);
|
|
24561
|
+
if (!quote2) {
|
|
24562
|
+
return new Response(
|
|
24563
|
+
JSON.stringify({
|
|
24564
|
+
id: referenceId,
|
|
24565
|
+
endpoint: opts.name,
|
|
24566
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24567
|
+
payment_status: "failed",
|
|
24568
|
+
charged_usd: "0.00",
|
|
24569
|
+
error: {
|
|
24570
|
+
code: "stale_quote",
|
|
24571
|
+
message: "No active quote for this request body. The quote may have expired or the body changed since the probe."
|
|
24572
|
+
},
|
|
24573
|
+
next_steps: {
|
|
24574
|
+
action: "re_probe",
|
|
24575
|
+
suggestion: "Send the same body without a payment header to get a fresh 402 quote, then retry with the payment credential."
|
|
24576
|
+
}
|
|
24577
|
+
}),
|
|
24578
|
+
{ status: 400, headers: { "Content-Type": "application/json" } }
|
|
24579
|
+
);
|
|
24580
|
+
}
|
|
24581
|
+
if (hasX402Header(req.headers)) return handleX402Settle(req, referenceId, quote2.body, quote2.priceCents, quote2.recipients);
|
|
24582
|
+
return handleMppSettle(req, referenceId, quote2.body, quote2.priceCents, quote2.recipients);
|
|
24583
|
+
}
|
|
24584
|
+
let quote = await cache.read(cacheKey2);
|
|
24585
|
+
if (!quote) {
|
|
24586
|
+
let outcome;
|
|
24587
|
+
try {
|
|
24588
|
+
outcome = await opts.runWork(body, { request: req });
|
|
24589
|
+
} catch {
|
|
24590
|
+
return new Response(
|
|
24591
|
+
JSON.stringify({
|
|
24592
|
+
id: referenceId,
|
|
24593
|
+
endpoint: opts.name,
|
|
24594
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24595
|
+
payment_status: "no_charge",
|
|
24596
|
+
charged_usd: "0.00",
|
|
24597
|
+
result: { matches: [], total: 0 },
|
|
24598
|
+
error: {
|
|
24599
|
+
code: "upstream_failed",
|
|
24600
|
+
message: "The wrapped endpoint failed; no charge was applied."
|
|
24601
|
+
}
|
|
24602
|
+
}),
|
|
24603
|
+
{ status: 200, headers: { "Content-Type": "application/json" } }
|
|
24604
|
+
);
|
|
24605
|
+
}
|
|
24606
|
+
if (outcome.resultCount === 0) {
|
|
24607
|
+
return new Response(
|
|
24608
|
+
JSON.stringify({
|
|
24609
|
+
id: referenceId,
|
|
24610
|
+
endpoint: opts.name,
|
|
24611
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24612
|
+
payment_status: "no_charge",
|
|
24613
|
+
charged_usd: "0.00",
|
|
24614
|
+
result: outcome.body
|
|
24615
|
+
}),
|
|
24616
|
+
{ status: 200, headers: { "Content-Type": "application/json" } }
|
|
24617
|
+
);
|
|
24618
|
+
}
|
|
24619
|
+
const priceCents = opts.unitPriceCents * outcome.resultCount;
|
|
24620
|
+
const recipients = await mintAndResolveRecipients(req, body, priceCents);
|
|
24621
|
+
await cache.write(cacheKey2, outcome.body, priceCents, recipients);
|
|
24622
|
+
quote = { body: outcome.body, priceCents, recipients };
|
|
24623
|
+
}
|
|
24624
|
+
return emit402(req, body, quote.priceCents, quote.recipients);
|
|
24625
|
+
}
|
|
24626
|
+
return {
|
|
24627
|
+
handleWeb: handle,
|
|
24628
|
+
async handleHono(c) {
|
|
24629
|
+
return handle(c.req.raw);
|
|
24630
|
+
}
|
|
24631
|
+
};
|
|
24632
|
+
}
|
|
24633
|
+
function defaultSuccessBody(appUrl) {
|
|
24634
|
+
return ({ referenceId, endpoint, chargedUsd, rail, paymentIntentId, signer, cachedBody }) => ({
|
|
24635
|
+
id: referenceId,
|
|
24636
|
+
endpoint,
|
|
24637
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24638
|
+
payment_status: "completed",
|
|
24639
|
+
charged_usd: chargedUsd,
|
|
24640
|
+
rail,
|
|
24641
|
+
...paymentIntentId ? { payment_intent_id: paymentIntentId } : {},
|
|
24642
|
+
...signer ? { signer } : {},
|
|
24643
|
+
result: cachedBody,
|
|
24644
|
+
next_steps: buildSuccessNextSteps({ orderStatusUrl: `${appUrl}/health` }),
|
|
24645
|
+
agent_memory: firstEncounterAgentMemory({ firstEncounter: true })
|
|
24646
|
+
});
|
|
24647
|
+
}
|
|
24648
|
+
|
|
24649
|
+
// src/identity/default_denied.ts
|
|
24650
|
+
function createDefaultOnDenied(opts) {
|
|
24651
|
+
const supportContext = opts.supportContext ?? "Contact support if you believe this denial is in error.";
|
|
24652
|
+
const paymentRequiredMessage = opts.paymentRequiredMessage ?? "AgentScore tier does not support assess. Contact support.";
|
|
24653
|
+
const walletNotTrustedMessage = opts.walletNotTrustedMessage ?? `Identity check did not satisfy policy for ${opts.merchantName}.`;
|
|
24654
|
+
return function defaultOnDenied(reason) {
|
|
24655
|
+
if (reason.code === "wallet_signer_mismatch" || reason.code === "wallet_auth_requires_wallet_signing") {
|
|
24656
|
+
const body = buildSignerMismatchBody({
|
|
24657
|
+
result: {
|
|
24658
|
+
kind: reason.code,
|
|
24659
|
+
claimedOperator: reason.claimed_operator ?? null,
|
|
24660
|
+
actualSignerOperator: reason.actual_signer_operator ?? null,
|
|
24661
|
+
expectedSigner: reason.expected_signer ?? "",
|
|
24662
|
+
actualSigner: reason.actual_signer ?? "",
|
|
24663
|
+
linkedWallets: reason.linked_wallets ?? [],
|
|
24664
|
+
agentInstructions: reason.agent_instructions ?? "",
|
|
24665
|
+
claimedWallet: reason.expected_signer ?? ""
|
|
24666
|
+
}
|
|
24667
|
+
});
|
|
24668
|
+
return { status: 403, body: body ?? denialReasonToBody(reason) };
|
|
24669
|
+
}
|
|
24670
|
+
if (reason.code === "wallet_not_trusted") {
|
|
24671
|
+
return {
|
|
24672
|
+
status: 403,
|
|
24673
|
+
body: {
|
|
24674
|
+
error: { code: "compliance_denied", message: walletNotTrustedMessage },
|
|
24675
|
+
reasons: reason.reasons ?? [],
|
|
24676
|
+
policy_result: reason.data?.policy_result,
|
|
24677
|
+
verify_url: reason.verify_url,
|
|
24678
|
+
next_steps: buildContactSupportNextSteps(opts.supportEmail, supportContext)
|
|
24679
|
+
}
|
|
24680
|
+
};
|
|
24681
|
+
}
|
|
24682
|
+
if (reason.code === "payment_required") {
|
|
24683
|
+
return {
|
|
24684
|
+
status: 403,
|
|
24685
|
+
body: {
|
|
24686
|
+
...denialReasonToBody(reason),
|
|
24687
|
+
error: { code: "compliance_error", message: paymentRequiredMessage }
|
|
24688
|
+
}
|
|
24689
|
+
};
|
|
24690
|
+
}
|
|
24691
|
+
const status = reason.code === "token_expired" || reason.code === "invalid_credential" ? 401 : reason.code === "api_error" ? 503 : 403;
|
|
24692
|
+
return {
|
|
24693
|
+
status,
|
|
24694
|
+
body: denialReasonToBody(reason),
|
|
24695
|
+
...status >= 500 && { headers: { "Cache-Control": "no-store" } }
|
|
24696
|
+
};
|
|
24697
|
+
};
|
|
24698
|
+
}
|
|
24699
|
+
function defaultReadOnlyOnDenied(reason) {
|
|
24700
|
+
const message = reason.code === "missing_identity" ? "X-Wallet-Address or X-Operator-Token header required" : "Invalid identity";
|
|
24701
|
+
return {
|
|
24702
|
+
status: 401,
|
|
24703
|
+
body: {
|
|
24704
|
+
...denialReasonToBody(reason),
|
|
24705
|
+
error: { code: "unauthorized", message }
|
|
24706
|
+
},
|
|
24707
|
+
headers: { "Cache-Control": "no-store" }
|
|
24708
|
+
};
|
|
24709
|
+
}
|
|
23849
24710
|
// Annotate the CommonJS export names for ESM import in node:
|
|
23850
24711
|
0 && (module.exports = {
|
|
24712
|
+
A2A_DEFAULT_TRANSPORT,
|
|
24713
|
+
A2A_PROTOCOL_VERSION,
|
|
23851
24714
|
AGENTSCORE_UCP_CAPABILITY,
|
|
23852
24715
|
Checkout,
|
|
23853
24716
|
CheckoutValidationError,
|
|
@@ -23858,18 +24721,29 @@ async function loadSolanaFeePayer(opts) {
|
|
|
23858
24721
|
buildA2AAgentCard,
|
|
23859
24722
|
buildAgentMemoryHint,
|
|
23860
24723
|
buildContactSupportNextSteps,
|
|
24724
|
+
buildDefaultCheckoutRails,
|
|
23861
24725
|
buildGateFromPolicy,
|
|
23862
24726
|
buildJWKSResponse,
|
|
24727
|
+
buildMppxComposeRails,
|
|
23863
24728
|
buildSignerMismatchBody,
|
|
23864
24729
|
buildUCPProfile,
|
|
24730
|
+
buildVerificationRequiredBody,
|
|
24731
|
+
computeFirstCheckout,
|
|
24732
|
+
createDefaultOnDenied,
|
|
24733
|
+
createQuoteCache,
|
|
24734
|
+
defaultReadOnlyOnDenied,
|
|
23865
24735
|
denialReasonStatus,
|
|
23866
24736
|
denialReasonToBody,
|
|
24737
|
+
extractOwnerScope,
|
|
23867
24738
|
extractPaymentSigner,
|
|
23868
24739
|
extractPaymentSignerFromAuth,
|
|
23869
24740
|
extractSignerForPrecheck,
|
|
23870
24741
|
formatUsdCents,
|
|
23871
24742
|
generateUCPSigningKey,
|
|
23872
24743
|
getIdentityStatus,
|
|
24744
|
+
hasMppxHeader,
|
|
24745
|
+
hasPaymentHeader,
|
|
24746
|
+
hasX402Header,
|
|
23873
24747
|
hashOperatorToken,
|
|
23874
24748
|
isFixableDenial,
|
|
23875
24749
|
loadSolanaFeePayer,
|