@agent-score/commerce 2.0.1 → 2.1.0

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