@devlab.group/agent-commerce 2.4.1 → 2.5.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 (108) hide show
  1. package/README.md +115 -15
  2. package/dist/ap2.d.ts +24 -12
  3. package/dist/ap2.js +31 -13
  4. package/dist/ap2.js.map +1 -1
  5. package/dist/{chunk-DTKU3Z2M.js → chunk-3OTCFFFT.js} +37 -4
  6. package/dist/chunk-3OTCFFFT.js.map +1 -0
  7. package/dist/{chunk-QPV3EGJO.js → chunk-4K7FIBJM.js} +25 -4
  8. package/dist/chunk-4K7FIBJM.js.map +1 -0
  9. package/dist/{chunk-CXWC5LWM.js → chunk-FKQK5XZA.js} +652 -68
  10. package/dist/chunk-FKQK5XZA.js.map +1 -0
  11. package/dist/chunk-GA3O2A7R.js +92 -0
  12. package/dist/chunk-GA3O2A7R.js.map +1 -0
  13. package/dist/{chunk-WZW5ORZH.js → chunk-VUCMBGUR.js} +3 -3
  14. package/dist/{chunk-WZW5ORZH.js.map → chunk-VUCMBGUR.js.map} +1 -1
  15. package/dist/cli/{ap2-GWSP4LYY.js → ap2-YAPLERSC.js} +34 -15
  16. package/dist/cli/ap2-YAPLERSC.js.map +1 -0
  17. package/dist/cli/{chunk-G2JEY7MB.js → chunk-2J2IQQ4X.js} +8 -7
  18. package/dist/cli/chunk-2J2IQQ4X.js.map +1 -0
  19. package/dist/cli/chunk-2UPPX3FJ.js +311 -0
  20. package/dist/cli/chunk-2UPPX3FJ.js.map +1 -0
  21. package/dist/cli/{chunk-WYOGIANL.js → chunk-4H2QLHQI.js} +4 -4
  22. package/dist/cli/{chunk-WYOGIANL.js.map → chunk-4H2QLHQI.js.map} +1 -1
  23. package/dist/cli/{chunk-OZ4LAWBK.js → chunk-5R7DM5LM.js} +25 -4
  24. package/dist/cli/chunk-5R7DM5LM.js.map +1 -0
  25. package/dist/cli/chunk-663ALDZA.js +92 -0
  26. package/dist/cli/chunk-663ALDZA.js.map +1 -0
  27. package/dist/cli/{chunk-QQ3WY5L3.js → chunk-IDY2735M.js} +36 -104
  28. package/dist/cli/chunk-IDY2735M.js.map +1 -0
  29. package/dist/cli/chunk-JFVRG2HH.js +107 -0
  30. package/dist/cli/chunk-JFVRG2HH.js.map +1 -0
  31. package/dist/cli/chunk-M7NXVRU5.js +8 -0
  32. package/dist/cli/{chunk-ITWNSS2B.js.map → chunk-M7NXVRU5.js.map} +1 -1
  33. package/dist/cli/chunk-NIU5EMSB.js +119 -0
  34. package/dist/cli/chunk-NIU5EMSB.js.map +1 -0
  35. package/dist/cli/{chunk-TNMLDPUO.js → chunk-QA2OPHBF.js} +655 -70
  36. package/dist/cli/chunk-QA2OPHBF.js.map +1 -0
  37. package/dist/cli/{chunk-GJIMDMYT.js → chunk-QLUCNPRT.js} +404 -161
  38. package/dist/cli/chunk-QLUCNPRT.js.map +1 -0
  39. package/dist/cli/chunk-SYQLJXIU.js +105 -0
  40. package/dist/cli/chunk-SYQLJXIU.js.map +1 -0
  41. package/dist/cli/{chunk-3MGAJ5FX.js → chunk-VJ4EO4LE.js} +3 -3
  42. package/dist/cli/{chunk-3MGAJ5FX.js.map → chunk-VJ4EO4LE.js.map} +1 -1
  43. package/dist/cli/{chunk-PIMFPCNZ.js → chunk-Z34UMZBB.js} +234 -85
  44. package/dist/cli/chunk-Z34UMZBB.js.map +1 -0
  45. package/dist/cli/config-BWFMN2ZB.js +12 -0
  46. package/dist/cli/{config-UI4EDG4L.js.map → config-BWFMN2ZB.js.map} +1 -1
  47. package/dist/cli/index.js +258 -11
  48. package/dist/cli/index.js.map +1 -1
  49. package/dist/cli/{mcp-PGBRWZVA.js → mcp-KZEMXLHR.js} +5 -4
  50. package/dist/cli/mcp-KZEMXLHR.js.map +1 -0
  51. package/dist/cli/{near-5AY3HWYF.js → near-U6365VFX.js} +15 -4
  52. package/dist/cli/near-U6365VFX.js.map +1 -0
  53. package/dist/cli/payment-providers-SZL36H3Y.js +6 -0
  54. package/dist/cli/payment-providers-SZL36H3Y.js.map +1 -0
  55. package/dist/cli/{provider-I2ESL6RS.js → provider-6TKB5ADJ.js} +26 -15
  56. package/dist/cli/provider-6TKB5ADJ.js.map +1 -0
  57. package/dist/cli/receipts-ZGLJWMQG.js +8 -0
  58. package/dist/cli/receipts-ZGLJWMQG.js.map +1 -0
  59. package/dist/cli/reconcile-IC22MJD5.js +4 -0
  60. package/dist/cli/reconcile-IC22MJD5.js.map +1 -0
  61. package/dist/cli/{run-JK4ERPJV.js → run-ZTYPQI4D.js} +151 -115
  62. package/dist/cli/run-ZTYPQI4D.js.map +1 -0
  63. package/dist/cli/svm-KDSPDFJG.js +48 -0
  64. package/dist/cli/svm-KDSPDFJG.js.map +1 -0
  65. package/dist/cli/{x402-7WBFZQXV.js → x402-WLYBLODI.js} +10 -9
  66. package/dist/cli/x402-WLYBLODI.js.map +1 -0
  67. package/dist/index.d.ts +112 -12
  68. package/dist/index.js +948 -157
  69. package/dist/index.js.map +1 -1
  70. package/dist/mcp.d.ts +1 -2
  71. package/dist/mcp.js +1 -1
  72. package/dist/mpp.js +20 -10
  73. package/dist/mpp.js.map +1 -1
  74. package/dist/{near-D6C42VPE.js → near-FH7HPZV3.js} +15 -4
  75. package/dist/near-FH7HPZV3.js.map +1 -0
  76. package/dist/{protocol-adapter-C9odYl6l.d.ts → protocol-adapter-DEXpdp8m.d.ts} +102 -48
  77. package/dist/{runtime-Cl_BLVZV.d.ts → runtime-Dz2fSO-P.d.ts} +220 -2
  78. package/dist/svm-KNC3PHMS.js +48 -0
  79. package/dist/svm-KNC3PHMS.js.map +1 -0
  80. package/dist/x402.js +5 -5
  81. package/package.json +1 -1
  82. package/dist/authorization-DjAecwuW.d.ts +0 -115
  83. package/dist/chunk-CXWC5LWM.js.map +0 -1
  84. package/dist/chunk-DTKU3Z2M.js.map +0 -1
  85. package/dist/chunk-KA2AX5FH.js +0 -44
  86. package/dist/chunk-KA2AX5FH.js.map +0 -1
  87. package/dist/chunk-QPV3EGJO.js.map +0 -1
  88. package/dist/cli/ap2-GWSP4LYY.js.map +0 -1
  89. package/dist/cli/chunk-G2JEY7MB.js.map +0 -1
  90. package/dist/cli/chunk-GJIMDMYT.js.map +0 -1
  91. package/dist/cli/chunk-ITWNSS2B.js +0 -8
  92. package/dist/cli/chunk-OSTCU6ZK.js +0 -44
  93. package/dist/cli/chunk-OSTCU6ZK.js.map +0 -1
  94. package/dist/cli/chunk-OZ4LAWBK.js.map +0 -1
  95. package/dist/cli/chunk-PIMFPCNZ.js.map +0 -1
  96. package/dist/cli/chunk-QQ3WY5L3.js.map +0 -1
  97. package/dist/cli/chunk-TNMLDPUO.js.map +0 -1
  98. package/dist/cli/config-UI4EDG4L.js +0 -11
  99. package/dist/cli/mcp-PGBRWZVA.js.map +0 -1
  100. package/dist/cli/near-5AY3HWYF.js.map +0 -1
  101. package/dist/cli/provider-I2ESL6RS.js.map +0 -1
  102. package/dist/cli/run-JK4ERPJV.js.map +0 -1
  103. package/dist/cli/svm-3MMYFPC7.js +0 -33
  104. package/dist/cli/svm-3MMYFPC7.js.map +0 -1
  105. package/dist/cli/x402-7WBFZQXV.js.map +0 -1
  106. package/dist/near-D6C42VPE.js.map +0 -1
  107. package/dist/svm-QEUAUNPQ.js +0 -33
  108. package/dist/svm-QEUAUNPQ.js.map +0 -1
package/dist/mcp.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { HttpProtocolAdapter } from './index.js';
2
2
  import 'node:http';
3
- import './runtime-Cl_BLVZV.js';
4
- import './authorization-DjAecwuW.js';
3
+ import './runtime-Dz2fSO-P.js';
5
4
 
6
5
  interface McpAdapterOptions {
7
6
  /** Path prefix the gateway mounts this adapter at. Default '/mcp' */
package/dist/mcp.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { MCP_TOOL_NAME_PATTERN, readCappedBody, MCP_MODERN_PROTOCOL_REVISION, x402ErrorCode, settlementFailure, settlementResponseFromDetails, x402McpPaymentSubmission, X402_MCP_PAYMENT_META_KEY, X402_MCP_PAYMENT_RESPONSE_META_KEY, settlementResponse, X402_MCP_ERROR_META_KEY } from './chunk-ES3V6ECS.js';
2
2
  import { mcpPaymentRequired, MPP_MCP_CREDENTIAL_META_KEY, receiptObject, MPP_MCP_RECEIPT_META_KEY, MPP_MCP_PAYMENT_REQUIRED_META_KEY } from './chunk-5ZYXBCDX.js';
3
- import { PACKAGE_VERSION, toLogInfo, toCommerceError, CommerceError, extractReservedInputFields, PAYMENT_INPUT_FIELD, AUTHORIZATION_INPUT_FIELD, toErrorEnvelope, DELIVERY_SUMMARY_META_KEY, toDeliverySummary, toPaymentRequiredEnvelope } from './chunk-DTKU3Z2M.js';
3
+ import { PACKAGE_VERSION, toLogInfo, toCommerceError, CommerceError, extractReservedInputFields, PAYMENT_INPUT_FIELD, AUTHORIZATION_INPUT_FIELD, toErrorEnvelope, DELIVERY_SUMMARY_META_KEY, toDeliverySummary, toPaymentRequiredEnvelope } from './chunk-3OTCFFFT.js';
4
4
  import { isRecord } from './chunk-2CJNA7MS.js';
5
5
  import { createMcpHandler, Server, ProtocolError, ProtocolErrorCode, LATEST_PROTOCOL_VERSION } from '@modelcontextprotocol/server';
6
6
 
package/dist/mpp.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { MPP_PROFILE, MPP_NETWORKS, MPP_SUPPORTED_SPEC, MPP_DEFAULT_NETWORK, MPP_MIN_CHALLENGE_SECRET_LENGTH, isMppNetwork, MPP_DEFAULT_PAYMENT_FLOW, MPP_SPEC_DRAFTS } from './chunk-6Z2H53CG.js';
2
2
  export { MPPX_VERSION, MPP_PROFILE, MPP_SPEC_COMMIT, MPP_SPEC_DRAFTS, MPP_SPEC_REPOSITORY, MPP_SUPPORTED_SPEC } from './chunk-6Z2H53CG.js';
3
3
  import { CONTENT_DIGEST_METADATA_KEY } from './chunk-5ZYXBCDX.js';
4
- import { createX402PaymentProvider, DEFAULT_IDS, parseCanonicalAmount } from './chunk-CXWC5LWM.js';
5
- import { SETTLE_AFTER_BACKEND_METADATA_KEY } from './chunk-QPV3EGJO.js';
6
- import { PACKAGE_VERSION, systemClock, CommerceError } from './chunk-DTKU3Z2M.js';
7
- import { computeReplayKey } from './chunk-KA2AX5FH.js';
4
+ import { createX402PaymentProvider, DEFAULT_IDS, parseCanonicalAmount } from './chunk-FKQK5XZA.js';
5
+ import { SETTLE_AFTER_BACKEND_METADATA_KEY } from './chunk-4K7FIBJM.js';
6
+ import { PACKAGE_VERSION, systemClock, CommerceError, RECONCILIATION_METADATA_KEY } from './chunk-3OTCFFFT.js';
7
+ import { computeReplayKey, eip3009Locator } from './chunk-GA3O2A7R.js';
8
8
  import './chunk-2CJNA7MS.js';
9
9
  import { PERMIT2_ADDRESS } from '@x402/evm';
10
10
  import { Challenge, Method, Receipt, Credential, PaymentRequest, Errors } from 'mppx';
@@ -299,11 +299,10 @@ function createMppProviderWithSettlement(options, settlement, nonceUsed) {
299
299
  } catch (error) {
300
300
  return rejected(requirement, verificationReason(error));
301
301
  }
302
- const nonce = credential.payload.nonce;
302
+ const authorization = credential.payload;
303
+ const nonce = authorization.nonce;
303
304
  const replayKey = computeReplayKey({ chainId, asset, from: payer, nonce });
304
- const x402Verification = await settlement.verify(
305
- await toX402Context(context, credential.payload)
306
- );
305
+ const x402Verification = await settlement.verify(await toX402Context(context, authorization));
307
306
  if (x402Verification.status !== "verified") {
308
307
  const reason = x402Verification.rejectionReason;
309
308
  const spent = reason === NONCE_ALREADY_USED || (await nonceUsed?.(payer, nonce).catch(() => false) ?? false);
@@ -324,7 +323,9 @@ function createMppProviderWithSettlement(options, settlement, nonceUsed) {
324
323
  currency: requirement.currency,
325
324
  network,
326
325
  asset,
327
- replayKey
326
+ replayKey,
327
+ // Share x402's locator builder so both rails identify the same authorization
328
+ metadata: { [RECONCILIATION_METADATA_KEY]: eip3009Locator(network, asset, authorization) }
328
329
  };
329
330
  }
330
331
  async function toX402Context(context, authorization) {
@@ -389,7 +390,16 @@ function createMppProviderWithSettlement(options, settlement, nonceUsed) {
389
390
  function health() {
390
391
  return settlement.health();
391
392
  }
392
- return { name: "mpp", descriptor: MPP_DESCRIPTOR, createRequirement, verify, settle, health };
393
+ const reconcile = settlement.reconcile?.bind(settlement);
394
+ return {
395
+ name: "mpp",
396
+ descriptor: MPP_DESCRIPTOR,
397
+ createRequirement,
398
+ verify,
399
+ settle,
400
+ ...reconcile !== void 0 ? { reconcile } : {},
401
+ health
402
+ };
393
403
  }
394
404
 
395
405
  export { MPP_DESCRIPTOR, createMppPaymentProvider, createMppPaymentProvider as mpp };
package/dist/mpp.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/payments/mpp/descriptor.ts","../src/payments/mpp/credential.ts","../src/payments/mpp/options.ts","../src/payments/mpp/provider.ts"],"names":["isAddress","getAddress"],"mappings":"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","file":"mpp.js","sourcesContent":["/**\n * Describes the MPP profile and its unsupported variants.\n *\n * The protocol name alone cannot identify a compatible intent, method and\n * extension set, so the descriptor lists both the target and its gaps.\n *\n * Importing the descriptor does not load `mppx`.\n */\nimport type { AdapterDescriptor } from '../../core/public-types';\nimport { PACKAGE_VERSION } from '../../version';\nimport { MPP_NETWORKS, MPP_PROFILE, MPP_SUPPORTED_SPEC } from './constants';\n\nexport const MPP_DESCRIPTOR: AdapterDescriptor = {\n name: 'mpp',\n kind: 'payment',\n implementationVersion: PACKAGE_VERSION,\n supportedSpec: MPP_SUPPORTED_SPEC,\n capabilities: [\n `intent=${MPP_PROFILE.intent}`,\n `method=${MPP_PROFILE.method}`,\n `credential=${MPP_PROFILE.credentialType}`,\n 'eip-3009',\n ...MPP_NETWORKS.map((network) => `network=${network}`),\n `asset=${MPP_PROFILE.assetSymbol}`,\n 'verify-before-settle',\n 'authorization-flow',\n 'upfront-flow',\n 'payment-receipt',\n // HTTP request bodies only; MCP and A2A carry the proof in the body\n 'challenge-digest-binding',\n ],\n // The pinned specs are drafts and mppx is pre-1.0; the wire format may change\n status: 'experimental',\n unsupported: [\n // Name other methods as a class instead of maintaining a second list\n 'methods other than evm',\n // This profile supports only the EIP-3009 `authorization` credential\n 'credential=permit2',\n 'credential=transaction',\n 'credential=hash',\n // The draft allows splits only with permit2 credentials\n 'splits',\n 'intent=subscription',\n // A separate EVM draft, not an option of charge\n 'evm sessions',\n 'discovery extension',\n ],\n};\n","// Reading an MPP credential: its decoding, its binding to the challenge, and the x402 proof it carries\nimport { type Challenge, Credential, Errors, PaymentRequest } from 'mppx';\nimport type { Types } from 'mppx/evm';\nimport { getAddress, isAddress } from 'viem';\nimport type { PaymentRequirement, PaymentSubmission } from '../../core';\n\n// mppx reports a verification failure only as message text. The pinned\n// release's wording maps to stable reasons, and the tests cover every entry;\n// unmapped text becomes `authorization_invalid`.\nconst VERIFICATION_REASONS: readonly (readonly [string, string])[] = [\n ['EVM authorization challenge hash mismatch', 'wrong_nonce'],\n ['EVM authorization signature mismatch', 'invalid_signature'],\n ['EVM authorization is not valid yet', 'authorization_not_yet_valid'],\n ['EVM authorization has expired', 'authorization_expired'],\n ['EVM authorization source mismatch', 'source_mismatch'],\n ['EVM authorization amount mismatch', 'wrong_amount'],\n ['EVM authorization recipient mismatch', 'wrong_recipient'],\n];\n\nexport function verificationReason(error: unknown): string {\n if (error instanceof Errors.PaymentExpiredError) return 'challenge_expired';\n if (error instanceof Errors.InvalidPayloadError) return 'invalid_payload';\n if (error instanceof Errors.InvalidChallengeError) return 'invalid_challenge';\n if (error instanceof Errors.VerificationFailedError) {\n const match = VERIFICATION_REASONS.find(([text]) => error.message.includes(text));\n if (match) return match[1];\n }\n return 'authorization_invalid';\n}\n\n// Accept the HTTP `Authorization: Payment ...` value or a JSON credential\n// from MCP `_meta`. Serialize the object for mppx deserialization\nexport function decodeCredential(payload: string): Credential.Credential {\n const serialized = payload.trimStart().startsWith('{')\n ? Credential.serialize(JSON.parse(payload) as Credential.Credential)\n : payload;\n return Credential.deserialize(serialized);\n}\n\n// Compares the echoed challenge with the one issued for this request. Both\n// carry a valid HMAC by now, so any difference means the credential answers a\n// challenge issued for other terms. The final comparison catches a difference\n// in any request field the named checks do not cover.\nexport function bindingMismatch(\n echoed: Challenge.Challenge,\n issued: Challenge.Challenge,\n resourceId: string,\n): string | undefined {\n if (echoed.realm !== issued.realm) return 'wrong_realm';\n if (echoed.method !== issued.method || echoed.intent !== issued.intent) {\n return 'unsupported_method';\n }\n // Only the encoded `opaque` survives the credential round trip, not `meta`,\n // so compare it with the encoding of this resource's binding\n if (echoed.opaque !== PaymentRequest.serialize({ resource: resourceId })) {\n return 'wrong_resource';\n }\n // `issued` was built for the request carrying this credential, so a\n // different body, or none, fails here. A challenge without a digest binds\n // no body, as the core draft reads it.\n if (echoed.digest !== undefined && echoed.digest !== issued.digest) {\n return 'body_digest_mismatch';\n }\n const got = echoed.request as ChargeRequest;\n const want = issued.request as ChargeRequest;\n if (got.amount !== want.amount) return 'wrong_amount';\n if (!sameAddress(got.recipient, want.recipient)) return 'wrong_recipient';\n if (got.methodDetails?.chainId !== want.methodDetails?.chainId) return 'wrong_network';\n if (!sameAddress(got.currency, want.currency)) return 'wrong_asset';\n if (canonical(got.methodDetails) !== canonical(want.methodDetails)) {\n return 'unsupported_credential';\n }\n if (canonical(got) !== canonical(want)) return 'wrong_terms';\n return undefined;\n}\n\n// Rewrap the MPP authorization as the x402 `exact` payload expected by settlement\nexport function toX402Submission(\n x402Requirement: PaymentRequirement,\n authorization: Types.AuthorizationPayload,\n): PaymentSubmission {\n const { signature, from, to, value, validAfter, validBefore, nonce } = authorization;\n const payment = {\n x402Version: 2,\n accepted: x402Requirement.challenge.accepts[0],\n payload: { signature, authorization: { from, to, value, validAfter, validBefore, nonce } },\n };\n return { method: 'x402', payload: Buffer.from(JSON.stringify(payment)).toString('base64') };\n}\n\ninterface ChargeRequest {\n readonly amount?: string;\n readonly currency?: string;\n readonly recipient?: string;\n readonly methodDetails?: { readonly chainId?: number };\n}\n\n// The encoding mppx binds into the challenge HMAC, so key order cannot\n// produce a false mismatch\nfunction canonical(value: object | undefined): string {\n return value === undefined ? '' : PaymentRequest.serialize(value as PaymentRequest.Request);\n}\n\nexport function sameAddress(a: string | undefined, b: string | undefined): boolean {\n return a !== undefined && b !== undefined && isAddress(a) && isAddress(b)\n ? getAddress(a) === getAddress(b)\n : false;\n}\n","// The MPP provider's options, checked once at construction\nimport { isAddress } from 'viem';\nimport { type Clock, CommerceError, type IdGenerator, type Logger } from '../../core';\nimport type { X402FacilitatorConfig } from '../x402/guardrails';\nimport type { X402PaymentFlow } from '../x402/payment-flow';\nimport { isMppNetwork, MPP_MIN_CHALLENGE_SECRET_LENGTH, MPP_NETWORKS } from './constants';\n\n/** Whether the token contract has recorded `nonce` as used by `payer` */\nexport type NonceUsedReader = (payer: `0x${string}`, nonce: `0x${string}`) => Promise<boolean>;\n\nexport interface MppProviderOptions {\n /** Merchant-controlled settlement destination. Never gateway-owned */\n readonly recipient: `0x${string}`;\n /** EIP-3009 token the charge is paid in */\n readonly asset: `0x${string}`;\n /** EIP-712 domain name of the asset, e.g. 'USDC' or 'MockUSDC' */\n readonly assetName: string;\n /** EIP-712 domain version of the asset, e.g. '2' */\n readonly assetVersion: string;\n /** Value of each challenge's `realm`, such as the gateway's host */\n readonly realm: string;\n /** Key that binds each challenge to this gateway. Never logged or published */\n readonly challengeSecret: string;\n /** RPC endpoint of the settlement chain */\n readonly rpcUrl: string;\n /** The x402 facilitator that verifies and broadcasts the authorization */\n readonly facilitator: X402FacilitatorConfig;\n /** Must be `true` before anything settles on a mainnet. Never a default */\n readonly allowMainnet?: boolean;\n /** Required on mainnet when facilitator auth is `none` */\n readonly allowUnauthenticatedFacilitator?: boolean;\n readonly logger?: Logger;\n /**\n * Seconds a challenge stays valid, 300 by default. The mppx client signs its\n * authorization to expire at the same moment.\n */\n readonly challengeTtlSeconds?: number;\n /**\n * CAIP-2 network: `eip155:31337` (local Anvil), `eip155:84532` (Base\n * Sepolia, the default) or `eip155:8453` (Base)\n */\n readonly network?: string;\n /**\n * Same flow values as x402. The default, `upfront`, settles before the\n * backend; `authorization` settles after it\n */\n readonly paymentFlow?: X402PaymentFlow;\n /** Per-resource overrides of `paymentFlow`, keyed by resource id */\n readonly resourcePaymentFlows?: Readonly<Record<string, X402PaymentFlow>>;\n readonly clock?: Clock;\n readonly ids?: IdGenerator;\n}\n\nexport function configInvalid(message: string): CommerceError {\n return new CommerceError('CONFIG_INVALID', message);\n}\n\nexport type MppChallengeOptions = Omit<\n MppProviderOptions,\n 'rpcUrl' | 'facilitator' | 'allowMainnet' | 'allowUnauthenticatedFacilitator' | 'logger'\n>;\n\nexport function validateOptions(options: MppChallengeOptions): void {\n if (!isAddress(options.recipient)) throw configInvalid('MPP recipient is not an EVM address');\n if (!isAddress(options.asset)) throw configInvalid('MPP asset is not an EVM address');\n if (options.assetName.length === 0 || options.assetVersion.length === 0) {\n throw configInvalid('MPP asset needs its EIP-712 domain name and version');\n }\n // mppx refuses CR or LF in the quoted realm parameter, so checking here fails\n // at construction instead of on every challenge\n if (options.realm.length === 0 || /[\\r\\n]/.test(options.realm)) {\n throw configInvalid('MPP realm must be a non-empty single-line string');\n }\n if (options.challengeSecret.length < MPP_MIN_CHALLENGE_SECRET_LENGTH) {\n throw configInvalid(\n `MPP challenge secret must have length at least ${MPP_MIN_CHALLENGE_SECRET_LENGTH}`,\n );\n }\n const ttl = options.challengeTtlSeconds;\n if (ttl !== undefined && (!Number.isInteger(ttl) || ttl <= 0)) {\n throw configInvalid('MPP challenge TTL must be a positive whole number of seconds');\n }\n if (options.network !== undefined && !isMppNetwork(options.network)) {\n throw configInvalid(`MPP network must be one of ${MPP_NETWORKS.join(', ')}`);\n }\n}\n","/**\n * MPP payment provider for the `charge` intent, the `evm` method and the\n * EIP-3009 `authorization` credential.\n *\n * It issues challenges and verifies credentials without moving funds: local\n * checks first, then a read-only check by an x402 facilitator. Settlement hands\n * the same signed authorization to that facilitator through an internal x402\n * provider built from these options. The MPP layer adds no signing key.\n *\n * Under the default `upfront` flow settlement precedes the backend call; under\n * `authorization` it follows a successful one. The drafts require a confirmed\n * transaction before a `Payment-Receipt`.\n */\nimport { PERMIT2_ADDRESS } from '@x402/evm';\nimport { Challenge, type Credential, Method, Receipt } from 'mppx';\nimport { Methods, type Types } from 'mppx/evm';\nimport { charge } from 'mppx/evm/server';\nimport { createPublicClient, getAddress, http, parseAbi } from 'viem';\nimport {\n type AdapterHealth,\n CommerceError,\n type PaymentContext,\n type PaymentProvider,\n type PaymentRequirement,\n type PaymentResult,\n type PaymentSettlementContext,\n type PaymentVerificationContext,\n systemClock,\n} from '../../core';\nimport { SETTLE_AFTER_BACKEND_METADATA_KEY } from '../../core/execution/settlement-order';\nimport { parseCanonicalAmount } from '../x402/amount';\nimport { createX402PaymentProvider, DEFAULT_IDS } from '../x402/provider';\nimport { computeReplayKey } from '../x402/replay-key';\nimport {\n MPP_DEFAULT_NETWORK,\n MPP_DEFAULT_PAYMENT_FLOW,\n MPP_PROFILE,\n MPP_SPEC_DRAFTS,\n} from './constants';\nimport {\n bindingMismatch,\n decodeCredential,\n sameAddress,\n toX402Submission,\n verificationReason,\n} from './credential';\nimport { MPP_DESCRIPTOR } from './descriptor';\nimport {\n configInvalid,\n type MppChallengeOptions,\n type MppProviderOptions,\n type NonceUsedReader,\n validateOptions,\n} from './options';\nimport { CONTENT_DIGEST_METADATA_KEY } from './transport';\n\nconst DEFAULT_CHALLENGE_TTL_SECONDS = 300;\n\n// The x402 SDK's verify reason for an EIP-3009 nonce already spent on chain\nconst NONCE_ALREADY_USED = 'invalid_exact_evm_nonce_already_used';\n\nconst AUTHORIZATION_STATE_ABI = parseAbi([\n 'function authorizationState(address authorizer, bytes32 nonce) view returns (bool)',\n]);\n\nconst NONCE_READ_TIMEOUT_MS = 5_000;\n\nexport function createMppPaymentProvider(options: MppProviderOptions): PaymentProvider {\n const { rpcUrl, facilitator, allowMainnet, allowUnauthenticatedFacilitator, logger, ...rest } =\n options;\n // Checked first so a bad MPP option is reported as one, not as an x402 error\n validateOptions(rest);\n // Built from the same terms, and never registered as a rail, so an MPP-only\n // deployment needs no x402 configuration\n const settlement = createX402PaymentProvider({\n network: options.network ?? MPP_DEFAULT_NETWORK,\n rpcUrl,\n asset: options.asset,\n assetName: options.assetName,\n assetVersion: options.assetVersion,\n assetDecimals: MPP_PROFILE.assetDecimals,\n payTo: options.recipient,\n facilitator,\n ...(allowMainnet !== undefined ? { allowMainnet } : {}),\n ...(allowUnauthenticatedFacilitator !== undefined ? { allowUnauthenticatedFacilitator } : {}),\n ...(logger !== undefined ? { logger } : {}),\n ...(options.clock !== undefined ? { clock: options.clock } : {}),\n });\n // One attempt: the read only names the reason for a refusal already decided\n const chain = createPublicClient({\n transport: http(rpcUrl, { timeout: NONCE_READ_TIMEOUT_MS, retryCount: 0 }),\n });\n const nonceUsed: NonceUsedReader = (payer, nonce) =>\n chain.readContract({\n address: options.asset,\n abi: AUTHORIZATION_STATE_ABI,\n functionName: 'authorizationState',\n args: [payer, nonce],\n });\n return createMppProviderWithSettlement(rest, settlement, nonceUsed);\n}\n\n/**\n * Internal seam: tests inject a settlement provider and the nonce reader. Not\n * exported from the `./mpp` entry.\n */\nexport function createMppProviderWithSettlement(\n options: MppChallengeOptions,\n settlement: PaymentProvider,\n nonceUsed?: NonceUsedReader,\n): PaymentProvider {\n validateOptions(options);\n if (settlement.name !== 'x402') {\n throw configInvalid('MPP settlement must be an x402 payment provider');\n }\n const network = options.network ?? MPP_DEFAULT_NETWORK;\n const chainId = Number(network.split(':')[1]);\n const clock = options.clock ?? systemClock;\n const ttlSeconds = options.challengeTtlSeconds ?? DEFAULT_CHALLENGE_TTL_SECONDS;\n const recipient = getAddress(options.recipient);\n const asset = getAddress(options.asset);\n const ids = options.ids ?? DEFAULT_IDS;\n // The settlement provider's terms are fixed at construction, so one passing\n // check covers every later challenge\n let settlementTermsChecked = false;\n\n // charge() requires a callback even though this provider never invokes the\n // mppx broadcast path. Settlement is delegated to the x402 provider.\n const method = charge({\n currency: asset,\n recipient,\n chainId,\n decimals: MPP_PROFILE.assetDecimals,\n authorization: { name: options.assetName, version: options.assetVersion },\n settle: async () => {\n throw new CommerceError('INTERNAL_ERROR', 'MPP direct broadcast is disabled');\n },\n });\n\n function rejected(requirement: PaymentRequirement, reason: string): PaymentResult {\n return {\n status: 'rejected',\n provider: 'mpp',\n amount: requirement.amount,\n currency: requirement.currency,\n network,\n asset,\n rejectionReason: reason,\n };\n }\n\n async function createRequirement(context: PaymentContext): Promise<PaymentRequirement> {\n if (context.currency !== MPP_PROFILE.assetSymbol) {\n throw configInvalid(\n `Resource \"${context.resource.id}\" is priced in ${context.currency}, but MPP charges ${MPP_PROFILE.assetSymbol}`,\n );\n }\n // Strict parse first: mppx converts with viem's parseUnits, which rounds\n // excess precision instead of refusing it\n if (parseCanonicalAmount(context.amount, MPP_PROFILE.assetDecimals) <= 0n) {\n throw new CommerceError('PAYMENT_INVALID', `Amount \"${context.amount}\" must be above zero`, {\n details: { amount: context.amount },\n });\n }\n // Reject a mismatched settlement requirement before the buyer signs\n if (!settlementTermsChecked) {\n await settlementRequirement(context);\n settlementTermsChecked = true;\n }\n const paymentFlow =\n options.resourcePaymentFlows?.[context.resource.id] ??\n options.paymentFlow ??\n MPP_DEFAULT_PAYMENT_FLOW;\n // mppx signs `validBefore` at this expiry. Under `authorization`, the\n // backend must finish before then for settlement to proceed.\n const expires = new Date(clock.now().getTime() + ttlSeconds * 1000);\n const digest = context.metadata?.[CONTENT_DIGEST_METADATA_KEY];\n const challenge = Challenge.fromMethod(Methods.charge, {\n secretKey: options.challengeSecret,\n realm: options.realm,\n expires,\n // Present for an HTTP request with a body. MCP and A2A carry the proof\n // in the body itself, so their challenges bind none.\n ...(typeof digest === 'string' ? { digest } : {}),\n // Bound by the challenge HMAC, so a challenge for one resource cannot pay\n // for another at the same price\n meta: { resource: context.resource.id },\n request: {\n amount: context.amount,\n currency: asset,\n recipient,\n chainId,\n decimals: MPP_PROFILE.assetDecimals,\n credentialTypes: [MPP_PROFILE.credentialType],\n // Required by draft-evm-charge-00 for every credential type\n permit2Address: PERMIT2_ADDRESS,\n },\n });\n return {\n id: ids.next('payreq'),\n requestId: context.requestId,\n resourceId: context.resource.id,\n provider: 'mpp',\n amount: context.amount,\n currency: context.currency,\n destination: recipient,\n network,\n asset,\n expiresAt: expires.toISOString(),\n challenge: {\n provider: 'mpp',\n version: MPP_SPEC_DRAFTS.core,\n accepts: [challenge],\n // Build both carrier forms here because the HTTP route and MCP\n // adapter cannot import mppx: a header value for HTTP and challenge\n // objects for MCP\n envelope: { wwwAuthenticate: Challenge.serialize(challenge), challenges: [challenge] },\n },\n metadata: { [SETTLE_AFTER_BACKEND_METADATA_KEY]: paymentFlow === 'authorization' },\n };\n }\n\n async function verify(context: PaymentVerificationContext): Promise<PaymentResult> {\n const { requirement, resource, submission } = context;\n if (requirement.provider !== 'mpp' || requirement.challenge.provider !== 'mpp') {\n return rejected(requirement, 'wrong_provider');\n }\n const issued = requirement.challenge.accepts[0] as Challenge.Challenge | undefined;\n if (!issued) return rejected(requirement, 'missing_challenge');\n\n let credential: Credential.Credential;\n try {\n credential = decodeCredential(submission.payload);\n } catch {\n return rejected(requirement, 'malformed_credential');\n }\n const echoed = credential.challenge;\n\n // A valid HMAC means this gateway issued the challenge, not that it was\n // issued for this resource and price. The binding checks below close that gap.\n if (!Challenge.verify(echoed, { secretKey: options.challengeSecret })) {\n return rejected(requirement, 'challenge_not_issued');\n }\n const binding = bindingMismatch(echoed, issued, resource.id);\n if (binding) return rejected(requirement, binding);\n if (!echoed.expires || new Date(echoed.expires).getTime() <= clock.now().getTime()) {\n return rejected(requirement, 'challenge_expired');\n }\n if ((credential.payload as { type?: unknown } | null)?.type !== MPP_PROFILE.credentialType) {\n return rejected(requirement, 'unsupported_credential');\n }\n\n // Local checks only: signature recovery, nonce == challenge hash, the\n // validity window and payload terms. With no network call involved, any\n // failure here is a verdict on the credential, not an outage.\n let payer: `0x${string}`;\n try {\n const validation = await Method.validateCredential([method], credential);\n payer = getAddress((validation.details as { payer: string }).payer);\n } catch (error) {\n return rejected(requirement, verificationReason(error));\n }\n\n // validateCredential proved it equals the 32-byte challenge hash\n const nonce = (credential.payload as Types.AuthorizationPayload).nonce as `0x${string}`;\n // Match x402's key so the same authorization collides across both rails\n const replayKey = computeReplayKey({ chainId, asset, from: payer, nonce });\n\n // The facilitator check runs before the pipeline reserves the replay key,\n // so an outage throws the x402 provider's retryable error and uses up\n // nothing, and a refusal is an ordinary rejection\n const x402Verification = await settlement.verify(\n await toX402Context(context, credential.payload as Types.AuthorizationPayload),\n );\n if (x402Verification.status !== 'verified') {\n // A spent challenge-hash nonce means the challenge was used. Check\n // the token when the facilitator reports only a simulation failure;\n // keep its reason if the token read fails.\n const reason = x402Verification.rejectionReason;\n const spent =\n reason === NONCE_ALREADY_USED ||\n ((await nonceUsed?.(payer, nonce).catch(() => false)) ?? false);\n return rejected(\n requirement,\n spent ? 'challenge_already_used' : (reason ?? 'settlement_rejected'),\n );\n }\n // A different key would settle an authorization the pipeline did not reserve\n if (x402Verification.replayKey !== replayKey) {\n return rejected(requirement, 'settlement_mismatch');\n }\n\n return {\n status: 'verified',\n provider: 'mpp',\n payer,\n payee: recipient,\n amount: requirement.amount,\n currency: requirement.currency,\n network,\n asset,\n replayKey,\n };\n }\n\n // The same payment as an x402 requirement and `exact` submission\n async function toX402Context(\n context: PaymentVerificationContext,\n authorization: Types.AuthorizationPayload,\n ): Promise<PaymentVerificationContext> {\n const { requestId, requirement, resource } = context;\n const x402Requirement = await settlementRequirement({\n requestId,\n resource,\n amount: requirement.amount,\n currency: requirement.currency,\n requestedAt: clock.nowIso(),\n });\n return {\n requestId,\n resource,\n requirement: x402Requirement,\n submission: toX402Submission(x402Requirement, authorization),\n };\n }\n\n async function settlementRequirement(context: PaymentContext): Promise<PaymentRequirement> {\n const x402 = await settlement.createRequirement(context);\n const extra = (x402.challenge.accepts[0]?.['extra'] ?? {}) as Record<string, unknown>;\n if (\n x402.network !== network ||\n !sameAddress(x402.asset, asset) ||\n !sameAddress(x402.destination, recipient) ||\n extra['name'] !== options.assetName ||\n extra['version'] !== options.assetVersion\n ) {\n throw configInvalid(\n 'MPP settlement provider must use the same network, asset, EIP-712 domain and recipient',\n );\n }\n return x402;\n }\n\n async function settle(context: PaymentSettlementContext): Promise<PaymentResult> {\n const { requestId, requirement, resource, submission, verification } = context;\n if (verification.status !== 'verified' || verification.replayKey === undefined) {\n throw new CommerceError(\n 'PAYMENT_INVALID',\n 'MPP settle() called without a successful verify()',\n );\n }\n\n // verify() already ran the facilitator check, and the facilitator checks\n // again before broadcasting. A throw may follow a broadcast, so it\n // propagates and the pipeline marks the payment uncertain.\n const credential = decodeCredential(submission.payload);\n const authorization = credential.payload as Types.AuthorizationPayload;\n const settled = await settlement.settle({\n ...(await toX402Context({ requestId, requirement, resource, submission }, authorization)),\n verification: { ...verification, provider: 'x402' },\n });\n const result: PaymentResult = {\n ...settled,\n provider: 'mpp',\n amount: requirement.amount,\n currency: requirement.currency,\n replayKey: verification.replayKey,\n };\n if (settled.status !== 'settled' || settled.externalReference === undefined) return result;\n // Include the EVM method's `challengeId` and `chainId` in the receipt\n // sent through the HTTP `Payment-Receipt` header\n const fields: Receipt.Receipt & { challengeId: string; chainId: number } = {\n method: MPP_PROFILE.method,\n reference: settled.externalReference,\n status: 'success',\n timestamp: settled.settledAt ?? clock.nowIso(),\n challengeId: credential.challenge.id,\n chainId,\n };\n const receipt = Receipt.from(fields);\n return { ...result, metadata: { ...settled.metadata, receipt: Receipt.serialize(receipt) } };\n }\n\n function health(): Promise<AdapterHealth> {\n return settlement.health();\n }\n\n return { name: 'mpp', descriptor: MPP_DESCRIPTOR, createRequirement, verify, settle, health };\n}\n\nexport type { MppProviderOptions, NonceUsedReader } from './options';\n"]}
1
+ {"version":3,"sources":["../src/payments/mpp/descriptor.ts","../src/payments/mpp/credential.ts","../src/payments/mpp/options.ts","../src/payments/mpp/provider.ts"],"names":["isAddress","getAddress"],"mappings":"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","file":"mpp.js","sourcesContent":["/**\n * Describes the MPP profile and its unsupported variants.\n *\n * The protocol name alone cannot identify a compatible intent, method and\n * extension set, so the descriptor lists both the target and its gaps.\n *\n * Importing the descriptor does not load `mppx`.\n */\nimport type { AdapterDescriptor } from '../../core/public-types';\nimport { PACKAGE_VERSION } from '../../version';\nimport { MPP_NETWORKS, MPP_PROFILE, MPP_SUPPORTED_SPEC } from './constants';\n\nexport const MPP_DESCRIPTOR: AdapterDescriptor = {\n name: 'mpp',\n kind: 'payment',\n implementationVersion: PACKAGE_VERSION,\n supportedSpec: MPP_SUPPORTED_SPEC,\n capabilities: [\n `intent=${MPP_PROFILE.intent}`,\n `method=${MPP_PROFILE.method}`,\n `credential=${MPP_PROFILE.credentialType}`,\n 'eip-3009',\n ...MPP_NETWORKS.map((network) => `network=${network}`),\n `asset=${MPP_PROFILE.assetSymbol}`,\n 'verify-before-settle',\n 'authorization-flow',\n 'upfront-flow',\n 'payment-receipt',\n // HTTP request bodies only; MCP and A2A carry the proof in the body\n 'challenge-digest-binding',\n ],\n // The pinned specs are drafts and mppx is pre-1.0; the wire format may change\n status: 'experimental',\n unsupported: [\n // Name other methods as a class instead of maintaining a second list\n 'methods other than evm',\n // This profile supports only the EIP-3009 `authorization` credential\n 'credential=permit2',\n 'credential=transaction',\n 'credential=hash',\n // The draft allows splits only with permit2 credentials\n 'splits',\n 'intent=subscription',\n // A separate EVM draft, not an option of charge\n 'evm sessions',\n 'discovery extension',\n ],\n};\n","// Reading an MPP credential: its decoding, its binding to the challenge, and the x402 proof it carries\nimport { type Challenge, Credential, Errors, PaymentRequest } from 'mppx';\nimport type { Types } from 'mppx/evm';\nimport { getAddress, isAddress } from 'viem';\nimport type { PaymentRequirement, PaymentSubmission } from '../../core';\n\n// mppx reports a verification failure only as message text. The pinned\n// release's wording maps to stable reasons, and the tests cover every entry;\n// unmapped text becomes `authorization_invalid`.\nconst VERIFICATION_REASONS: readonly (readonly [string, string])[] = [\n ['EVM authorization challenge hash mismatch', 'wrong_nonce'],\n ['EVM authorization signature mismatch', 'invalid_signature'],\n ['EVM authorization is not valid yet', 'authorization_not_yet_valid'],\n ['EVM authorization has expired', 'authorization_expired'],\n ['EVM authorization source mismatch', 'source_mismatch'],\n ['EVM authorization amount mismatch', 'wrong_amount'],\n ['EVM authorization recipient mismatch', 'wrong_recipient'],\n];\n\nexport function verificationReason(error: unknown): string {\n if (error instanceof Errors.PaymentExpiredError) return 'challenge_expired';\n if (error instanceof Errors.InvalidPayloadError) return 'invalid_payload';\n if (error instanceof Errors.InvalidChallengeError) return 'invalid_challenge';\n if (error instanceof Errors.VerificationFailedError) {\n const match = VERIFICATION_REASONS.find(([text]) => error.message.includes(text));\n if (match) return match[1];\n }\n return 'authorization_invalid';\n}\n\n// Accept the HTTP `Authorization: Payment ...` value or a JSON credential\n// from MCP `_meta`. Serialize the object for mppx deserialization\nexport function decodeCredential(payload: string): Credential.Credential {\n const serialized = payload.trimStart().startsWith('{')\n ? Credential.serialize(JSON.parse(payload) as Credential.Credential)\n : payload;\n return Credential.deserialize(serialized);\n}\n\n// Compares the echoed challenge with the one issued for this request. Both\n// carry a valid HMAC by now, so any difference means the credential answers a\n// challenge issued for other terms. The final comparison catches a difference\n// in any request field the named checks do not cover.\nexport function bindingMismatch(\n echoed: Challenge.Challenge,\n issued: Challenge.Challenge,\n resourceId: string,\n): string | undefined {\n if (echoed.realm !== issued.realm) return 'wrong_realm';\n if (echoed.method !== issued.method || echoed.intent !== issued.intent) {\n return 'unsupported_method';\n }\n // Only the encoded `opaque` survives the credential round trip, not `meta`,\n // so compare it with the encoding of this resource's binding\n if (echoed.opaque !== PaymentRequest.serialize({ resource: resourceId })) {\n return 'wrong_resource';\n }\n // `issued` was built for the request carrying this credential, so a\n // different body, or none, fails here. A challenge without a digest binds\n // no body, as the core draft reads it.\n if (echoed.digest !== undefined && echoed.digest !== issued.digest) {\n return 'body_digest_mismatch';\n }\n const got = echoed.request as ChargeRequest;\n const want = issued.request as ChargeRequest;\n if (got.amount !== want.amount) return 'wrong_amount';\n if (!sameAddress(got.recipient, want.recipient)) return 'wrong_recipient';\n if (got.methodDetails?.chainId !== want.methodDetails?.chainId) return 'wrong_network';\n if (!sameAddress(got.currency, want.currency)) return 'wrong_asset';\n if (canonical(got.methodDetails) !== canonical(want.methodDetails)) {\n return 'unsupported_credential';\n }\n if (canonical(got) !== canonical(want)) return 'wrong_terms';\n return undefined;\n}\n\n// Rewrap the MPP authorization as the x402 `exact` payload expected by settlement\nexport function toX402Submission(\n x402Requirement: PaymentRequirement,\n authorization: Types.AuthorizationPayload,\n): PaymentSubmission {\n const { signature, from, to, value, validAfter, validBefore, nonce } = authorization;\n const payment = {\n x402Version: 2,\n accepted: x402Requirement.challenge.accepts[0],\n payload: { signature, authorization: { from, to, value, validAfter, validBefore, nonce } },\n };\n return { method: 'x402', payload: Buffer.from(JSON.stringify(payment)).toString('base64') };\n}\n\ninterface ChargeRequest {\n readonly amount?: string;\n readonly currency?: string;\n readonly recipient?: string;\n readonly methodDetails?: { readonly chainId?: number };\n}\n\n// The encoding mppx binds into the challenge HMAC, so key order cannot\n// produce a false mismatch\nfunction canonical(value: object | undefined): string {\n return value === undefined ? '' : PaymentRequest.serialize(value as PaymentRequest.Request);\n}\n\nexport function sameAddress(a: string | undefined, b: string | undefined): boolean {\n return a !== undefined && b !== undefined && isAddress(a) && isAddress(b)\n ? getAddress(a) === getAddress(b)\n : false;\n}\n","// The MPP provider's options, checked once at construction\nimport { isAddress } from 'viem';\nimport { type Clock, CommerceError, type IdGenerator, type Logger } from '../../core';\nimport type { X402FacilitatorConfig } from '../x402/guardrails';\nimport type { X402PaymentFlow } from '../x402/payment-flow';\nimport { isMppNetwork, MPP_MIN_CHALLENGE_SECRET_LENGTH, MPP_NETWORKS } from './constants';\n\n/** Whether the token contract has recorded `nonce` as used by `payer` */\nexport type NonceUsedReader = (payer: `0x${string}`, nonce: `0x${string}`) => Promise<boolean>;\n\nexport interface MppProviderOptions {\n /** Merchant-controlled settlement destination. Never gateway-owned */\n readonly recipient: `0x${string}`;\n /** EIP-3009 token the charge is paid in */\n readonly asset: `0x${string}`;\n /** EIP-712 domain name of the asset, e.g. 'USDC' or 'MockUSDC' */\n readonly assetName: string;\n /** EIP-712 domain version of the asset, e.g. '2' */\n readonly assetVersion: string;\n /** Value of each challenge's `realm`, such as the gateway's host */\n readonly realm: string;\n /** Key that binds each challenge to this gateway. Never logged or published */\n readonly challengeSecret: string;\n /** RPC endpoint of the settlement chain */\n readonly rpcUrl: string;\n /** The x402 facilitator that verifies and broadcasts the authorization */\n readonly facilitator: X402FacilitatorConfig;\n /** Must be `true` before anything settles on a mainnet. Never a default */\n readonly allowMainnet?: boolean;\n /** Required on mainnet when facilitator auth is `none` */\n readonly allowUnauthenticatedFacilitator?: boolean;\n readonly logger?: Logger;\n /**\n * Seconds a challenge stays valid, 300 by default. The mppx client signs its\n * authorization to expire at the same moment.\n */\n readonly challengeTtlSeconds?: number;\n /**\n * CAIP-2 network: `eip155:31337` (local Anvil), `eip155:84532` (Base\n * Sepolia, the default) or `eip155:8453` (Base)\n */\n readonly network?: string;\n /**\n * Same flow values as x402. The default, `upfront`, settles before the\n * backend; `authorization` settles after it\n */\n readonly paymentFlow?: X402PaymentFlow;\n /** Per-resource overrides of `paymentFlow`, keyed by resource id */\n readonly resourcePaymentFlows?: Readonly<Record<string, X402PaymentFlow>>;\n readonly clock?: Clock;\n readonly ids?: IdGenerator;\n}\n\nexport function configInvalid(message: string): CommerceError {\n return new CommerceError('CONFIG_INVALID', message);\n}\n\nexport type MppChallengeOptions = Omit<\n MppProviderOptions,\n 'rpcUrl' | 'facilitator' | 'allowMainnet' | 'allowUnauthenticatedFacilitator' | 'logger'\n>;\n\nexport function validateOptions(options: MppChallengeOptions): void {\n if (!isAddress(options.recipient)) throw configInvalid('MPP recipient is not an EVM address');\n if (!isAddress(options.asset)) throw configInvalid('MPP asset is not an EVM address');\n if (options.assetName.length === 0 || options.assetVersion.length === 0) {\n throw configInvalid('MPP asset needs its EIP-712 domain name and version');\n }\n // mppx refuses CR or LF in the quoted realm parameter, so checking here fails\n // at construction instead of on every challenge\n if (options.realm.length === 0 || /[\\r\\n]/.test(options.realm)) {\n throw configInvalid('MPP realm must be a non-empty single-line string');\n }\n if (options.challengeSecret.length < MPP_MIN_CHALLENGE_SECRET_LENGTH) {\n throw configInvalid(\n `MPP challenge secret must have length at least ${MPP_MIN_CHALLENGE_SECRET_LENGTH}`,\n );\n }\n const ttl = options.challengeTtlSeconds;\n if (ttl !== undefined && (!Number.isInteger(ttl) || ttl <= 0)) {\n throw configInvalid('MPP challenge TTL must be a positive whole number of seconds');\n }\n if (options.network !== undefined && !isMppNetwork(options.network)) {\n throw configInvalid(`MPP network must be one of ${MPP_NETWORKS.join(', ')}`);\n }\n}\n","/**\n * MPP payment provider for the `charge` intent, the `evm` method and the\n * EIP-3009 `authorization` credential.\n *\n * It issues challenges and verifies credentials without moving funds: local\n * checks first, then a read-only check by an x402 facilitator. Settlement hands\n * the same signed authorization to that facilitator through an internal x402\n * provider built from these options. The MPP layer adds no signing key.\n *\n * Under the default `upfront` flow settlement precedes the backend call; under\n * `authorization` it follows a successful one. The drafts require a confirmed\n * transaction before a `Payment-Receipt`.\n */\nimport { PERMIT2_ADDRESS } from '@x402/evm';\nimport { Challenge, type Credential, Method, Receipt } from 'mppx';\nimport { Methods, type Types } from 'mppx/evm';\nimport { charge } from 'mppx/evm/server';\nimport { createPublicClient, getAddress, http, parseAbi } from 'viem';\nimport {\n type AdapterHealth,\n CommerceError,\n type PaymentContext,\n type PaymentProvider,\n type PaymentRequirement,\n type PaymentResult,\n type PaymentSettlementContext,\n type PaymentVerificationContext,\n RECONCILIATION_METADATA_KEY,\n systemClock,\n} from '../../core';\nimport { SETTLE_AFTER_BACKEND_METADATA_KEY } from '../../core/execution/settlement-order';\nimport { parseCanonicalAmount } from '../x402/amount';\nimport { eip3009Locator } from '../x402/locator';\nimport { createX402PaymentProvider, DEFAULT_IDS } from '../x402/provider';\nimport { computeReplayKey } from '../x402/replay-key';\nimport {\n MPP_DEFAULT_NETWORK,\n MPP_DEFAULT_PAYMENT_FLOW,\n MPP_PROFILE,\n MPP_SPEC_DRAFTS,\n} from './constants';\nimport {\n bindingMismatch,\n decodeCredential,\n sameAddress,\n toX402Submission,\n verificationReason,\n} from './credential';\nimport { MPP_DESCRIPTOR } from './descriptor';\nimport {\n configInvalid,\n type MppChallengeOptions,\n type MppProviderOptions,\n type NonceUsedReader,\n validateOptions,\n} from './options';\nimport { CONTENT_DIGEST_METADATA_KEY } from './transport';\n\nconst DEFAULT_CHALLENGE_TTL_SECONDS = 300;\n\n// The x402 SDK's verify reason for an EIP-3009 nonce already spent on chain\nconst NONCE_ALREADY_USED = 'invalid_exact_evm_nonce_already_used';\n\nconst AUTHORIZATION_STATE_ABI = parseAbi([\n 'function authorizationState(address authorizer, bytes32 nonce) view returns (bool)',\n]);\n\nconst NONCE_READ_TIMEOUT_MS = 5_000;\n\nexport function createMppPaymentProvider(options: MppProviderOptions): PaymentProvider {\n const { rpcUrl, facilitator, allowMainnet, allowUnauthenticatedFacilitator, logger, ...rest } =\n options;\n // Checked first so a bad MPP option is reported as one, not as an x402 error\n validateOptions(rest);\n // Built from the same terms, and never registered as a rail, so an MPP-only\n // deployment needs no x402 configuration\n const settlement = createX402PaymentProvider({\n network: options.network ?? MPP_DEFAULT_NETWORK,\n rpcUrl,\n asset: options.asset,\n assetName: options.assetName,\n assetVersion: options.assetVersion,\n assetDecimals: MPP_PROFILE.assetDecimals,\n payTo: options.recipient,\n facilitator,\n ...(allowMainnet !== undefined ? { allowMainnet } : {}),\n ...(allowUnauthenticatedFacilitator !== undefined ? { allowUnauthenticatedFacilitator } : {}),\n ...(logger !== undefined ? { logger } : {}),\n ...(options.clock !== undefined ? { clock: options.clock } : {}),\n });\n // One attempt: the read only names the reason for a refusal already decided\n const chain = createPublicClient({\n transport: http(rpcUrl, { timeout: NONCE_READ_TIMEOUT_MS, retryCount: 0 }),\n });\n const nonceUsed: NonceUsedReader = (payer, nonce) =>\n chain.readContract({\n address: options.asset,\n abi: AUTHORIZATION_STATE_ABI,\n functionName: 'authorizationState',\n args: [payer, nonce],\n });\n return createMppProviderWithSettlement(rest, settlement, nonceUsed);\n}\n\n/**\n * Internal seam: tests inject a settlement provider and the nonce reader. Not\n * exported from the `./mpp` entry.\n */\nexport function createMppProviderWithSettlement(\n options: MppChallengeOptions,\n settlement: PaymentProvider,\n nonceUsed?: NonceUsedReader,\n): PaymentProvider {\n validateOptions(options);\n if (settlement.name !== 'x402') {\n throw configInvalid('MPP settlement must be an x402 payment provider');\n }\n const network = options.network ?? MPP_DEFAULT_NETWORK;\n const chainId = Number(network.split(':')[1]);\n const clock = options.clock ?? systemClock;\n const ttlSeconds = options.challengeTtlSeconds ?? DEFAULT_CHALLENGE_TTL_SECONDS;\n const recipient = getAddress(options.recipient);\n const asset = getAddress(options.asset);\n const ids = options.ids ?? DEFAULT_IDS;\n // The settlement provider's terms are fixed at construction, so one passing\n // check covers every later challenge\n let settlementTermsChecked = false;\n\n // charge() requires a callback even though this provider never invokes the\n // mppx broadcast path. Settlement is delegated to the x402 provider.\n const method = charge({\n currency: asset,\n recipient,\n chainId,\n decimals: MPP_PROFILE.assetDecimals,\n authorization: { name: options.assetName, version: options.assetVersion },\n settle: async () => {\n throw new CommerceError('INTERNAL_ERROR', 'MPP direct broadcast is disabled');\n },\n });\n\n function rejected(requirement: PaymentRequirement, reason: string): PaymentResult {\n return {\n status: 'rejected',\n provider: 'mpp',\n amount: requirement.amount,\n currency: requirement.currency,\n network,\n asset,\n rejectionReason: reason,\n };\n }\n\n async function createRequirement(context: PaymentContext): Promise<PaymentRequirement> {\n if (context.currency !== MPP_PROFILE.assetSymbol) {\n throw configInvalid(\n `Resource \"${context.resource.id}\" is priced in ${context.currency}, but MPP charges ${MPP_PROFILE.assetSymbol}`,\n );\n }\n // Strict parse first: mppx converts with viem's parseUnits, which rounds\n // excess precision instead of refusing it\n if (parseCanonicalAmount(context.amount, MPP_PROFILE.assetDecimals) <= 0n) {\n throw new CommerceError('PAYMENT_INVALID', `Amount \"${context.amount}\" must be above zero`, {\n details: { amount: context.amount },\n });\n }\n // Reject a mismatched settlement requirement before the buyer signs\n if (!settlementTermsChecked) {\n await settlementRequirement(context);\n settlementTermsChecked = true;\n }\n const paymentFlow =\n options.resourcePaymentFlows?.[context.resource.id] ??\n options.paymentFlow ??\n MPP_DEFAULT_PAYMENT_FLOW;\n // mppx signs `validBefore` at this expiry. Under `authorization`, the\n // backend must finish before then for settlement to proceed.\n const expires = new Date(clock.now().getTime() + ttlSeconds * 1000);\n const digest = context.metadata?.[CONTENT_DIGEST_METADATA_KEY];\n const challenge = Challenge.fromMethod(Methods.charge, {\n secretKey: options.challengeSecret,\n realm: options.realm,\n expires,\n // Present for an HTTP request with a body. MCP and A2A carry the proof\n // in the body itself, so their challenges bind none.\n ...(typeof digest === 'string' ? { digest } : {}),\n // Bound by the challenge HMAC, so a challenge for one resource cannot pay\n // for another at the same price\n meta: { resource: context.resource.id },\n request: {\n amount: context.amount,\n currency: asset,\n recipient,\n chainId,\n decimals: MPP_PROFILE.assetDecimals,\n credentialTypes: [MPP_PROFILE.credentialType],\n // Required by draft-evm-charge-00 for every credential type\n permit2Address: PERMIT2_ADDRESS,\n },\n });\n return {\n id: ids.next('payreq'),\n requestId: context.requestId,\n resourceId: context.resource.id,\n provider: 'mpp',\n amount: context.amount,\n currency: context.currency,\n destination: recipient,\n network,\n asset,\n expiresAt: expires.toISOString(),\n challenge: {\n provider: 'mpp',\n version: MPP_SPEC_DRAFTS.core,\n accepts: [challenge],\n // Build both carrier forms here because the HTTP route and MCP\n // adapter cannot import mppx: a header value for HTTP and challenge\n // objects for MCP\n envelope: { wwwAuthenticate: Challenge.serialize(challenge), challenges: [challenge] },\n },\n metadata: { [SETTLE_AFTER_BACKEND_METADATA_KEY]: paymentFlow === 'authorization' },\n };\n }\n\n async function verify(context: PaymentVerificationContext): Promise<PaymentResult> {\n const { requirement, resource, submission } = context;\n if (requirement.provider !== 'mpp' || requirement.challenge.provider !== 'mpp') {\n return rejected(requirement, 'wrong_provider');\n }\n const issued = requirement.challenge.accepts[0] as Challenge.Challenge | undefined;\n if (!issued) return rejected(requirement, 'missing_challenge');\n\n let credential: Credential.Credential;\n try {\n credential = decodeCredential(submission.payload);\n } catch {\n return rejected(requirement, 'malformed_credential');\n }\n const echoed = credential.challenge;\n\n // A valid HMAC means this gateway issued the challenge, not that it was\n // issued for this resource and price. The binding checks below close that gap.\n if (!Challenge.verify(echoed, { secretKey: options.challengeSecret })) {\n return rejected(requirement, 'challenge_not_issued');\n }\n const binding = bindingMismatch(echoed, issued, resource.id);\n if (binding) return rejected(requirement, binding);\n if (!echoed.expires || new Date(echoed.expires).getTime() <= clock.now().getTime()) {\n return rejected(requirement, 'challenge_expired');\n }\n if ((credential.payload as { type?: unknown } | null)?.type !== MPP_PROFILE.credentialType) {\n return rejected(requirement, 'unsupported_credential');\n }\n\n // Local checks only: signature recovery, nonce == challenge hash, the\n // validity window and payload terms. With no network call involved, any\n // failure here is a verdict on the credential, not an outage.\n let payer: `0x${string}`;\n try {\n const validation = await Method.validateCredential([method], credential);\n payer = getAddress((validation.details as { payer: string }).payer);\n } catch (error) {\n return rejected(requirement, verificationReason(error));\n }\n\n const authorization = credential.payload as Types.AuthorizationPayload;\n // validateCredential proved it equals the 32-byte challenge hash\n const nonce = authorization.nonce as `0x${string}`;\n // Match x402's key so the same authorization collides across both rails\n const replayKey = computeReplayKey({ chainId, asset, from: payer, nonce });\n\n // The facilitator check runs before the pipeline reserves the replay key,\n // so an outage throws the x402 provider's retryable error and uses up\n // nothing, and a refusal is an ordinary rejection\n const x402Verification = await settlement.verify(await toX402Context(context, authorization));\n if (x402Verification.status !== 'verified') {\n // A spent challenge-hash nonce means the challenge was used. Check\n // the token when the facilitator reports only a simulation failure;\n // keep its reason if the token read fails.\n const reason = x402Verification.rejectionReason;\n const spent =\n reason === NONCE_ALREADY_USED ||\n ((await nonceUsed?.(payer, nonce).catch(() => false)) ?? false);\n return rejected(\n requirement,\n spent ? 'challenge_already_used' : (reason ?? 'settlement_rejected'),\n );\n }\n // A different key would settle an authorization the pipeline did not reserve\n if (x402Verification.replayKey !== replayKey) {\n return rejected(requirement, 'settlement_mismatch');\n }\n\n return {\n status: 'verified',\n provider: 'mpp',\n payer,\n payee: recipient,\n amount: requirement.amount,\n currency: requirement.currency,\n network,\n asset,\n replayKey,\n // Share x402's locator builder so both rails identify the same authorization\n metadata: { [RECONCILIATION_METADATA_KEY]: eip3009Locator(network, asset, authorization) },\n };\n }\n\n // The same payment as an x402 requirement and `exact` submission\n async function toX402Context(\n context: PaymentVerificationContext,\n authorization: Types.AuthorizationPayload,\n ): Promise<PaymentVerificationContext> {\n const { requestId, requirement, resource } = context;\n const x402Requirement = await settlementRequirement({\n requestId,\n resource,\n amount: requirement.amount,\n currency: requirement.currency,\n requestedAt: clock.nowIso(),\n });\n return {\n requestId,\n resource,\n requirement: x402Requirement,\n submission: toX402Submission(x402Requirement, authorization),\n };\n }\n\n async function settlementRequirement(context: PaymentContext): Promise<PaymentRequirement> {\n const x402 = await settlement.createRequirement(context);\n const extra = (x402.challenge.accepts[0]?.['extra'] ?? {}) as Record<string, unknown>;\n if (\n x402.network !== network ||\n !sameAddress(x402.asset, asset) ||\n !sameAddress(x402.destination, recipient) ||\n extra['name'] !== options.assetName ||\n extra['version'] !== options.assetVersion\n ) {\n throw configInvalid(\n 'MPP settlement provider must use the same network, asset, EIP-712 domain and recipient',\n );\n }\n return x402;\n }\n\n async function settle(context: PaymentSettlementContext): Promise<PaymentResult> {\n const { requestId, requirement, resource, submission, verification } = context;\n if (verification.status !== 'verified' || verification.replayKey === undefined) {\n throw new CommerceError(\n 'PAYMENT_INVALID',\n 'MPP settle() called without a successful verify()',\n );\n }\n\n // verify() already ran the facilitator check, and the facilitator checks\n // again before broadcasting. A throw may follow a broadcast, so it\n // propagates and the pipeline marks the payment uncertain.\n const credential = decodeCredential(submission.payload);\n const authorization = credential.payload as Types.AuthorizationPayload;\n const settled = await settlement.settle({\n ...(await toX402Context({ requestId, requirement, resource, submission }, authorization)),\n verification: { ...verification, provider: 'x402' },\n });\n const result: PaymentResult = {\n ...settled,\n provider: 'mpp',\n amount: requirement.amount,\n currency: requirement.currency,\n replayKey: verification.replayKey,\n };\n if (settled.status !== 'settled' || settled.externalReference === undefined) return result;\n // Include the EVM method's `challengeId` and `chainId` in the receipt\n // sent through the HTTP `Payment-Receipt` header\n const fields: Receipt.Receipt & { challengeId: string; chainId: number } = {\n method: MPP_PROFILE.method,\n reference: settled.externalReference,\n status: 'success',\n timestamp: settled.settledAt ?? clock.nowIso(),\n challengeId: credential.challenge.id,\n chainId,\n };\n const receipt = Receipt.from(fields);\n return { ...result, metadata: { ...settled.metadata, receipt: Receipt.serialize(receipt) } };\n }\n\n function health(): Promise<AdapterHealth> {\n return settlement.health();\n }\n\n // Reuse the settlement provider's reconciliation for the credential's\n // EIP-3009 authorization\n const reconcile = settlement.reconcile?.bind(settlement);\n return {\n name: 'mpp',\n descriptor: MPP_DESCRIPTOR,\n createRequirement,\n verify,\n settle,\n ...(reconcile !== undefined ? { reconcile } : {}),\n health,\n };\n}\n\nexport type { MppProviderOptions, NonceUsedReader } from './options';\n"]}
@@ -1,4 +1,4 @@
1
- import { computeNearReplayKey } from './chunk-KA2AX5FH.js';
1
+ import { LOCATOR_VERSION, computeNearReplayKey } from './chunk-GA3O2A7R.js';
2
2
  import { isRecord } from './chunk-2CJNA7MS.js';
3
3
  import { decodeSignedDelegateB64, parseFtTransferArgs } from '@x402/near';
4
4
 
@@ -39,7 +39,18 @@ function inspectNearPayload(payload, terms) {
39
39
  senderId: delegate.senderId,
40
40
  publicKey: delegate.publicKey,
41
41
  nonce: delegate.nonce
42
- })
42
+ }),
43
+ locator: {
44
+ v: LOCATOR_VERSION,
45
+ network: terms.network,
46
+ senderId: delegate.senderId,
47
+ publicKey: delegate.publicKey,
48
+ nonce: delegate.nonce.toString(),
49
+ maxBlockHeight: delegate.maxBlockHeight.toString(),
50
+ asset: delegate.receiverId,
51
+ receiver: args.receiver_id,
52
+ amount: args.amount
53
+ }
43
54
  };
44
55
  }
45
56
  function isCanonical(encoded) {
@@ -54,5 +65,5 @@ function isCanonical(encoded) {
54
65
  }
55
66
 
56
67
  export { inspectNearPayload };
57
- //# sourceMappingURL=near-D6C42VPE.js.map
58
- //# sourceMappingURL=near-D6C42VPE.js.map
68
+ //# sourceMappingURL=near-FH7HPZV3.js.map
69
+ //# sourceMappingURL=near-FH7HPZV3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/payments/x402/near.ts"],"names":[],"mappings":";;;;AAgBA,IAAM,0BAAA,GAA6B,IAAA;AAEnC,IAAM,SAAA,GAAY,EAAA;AAgBX,SAAS,kBAAA,CACd,SACA,KAAA,EAOS;AACT,EAAA,MAAM,UAAU,QAAA,CAAS,OAAO,CAAA,GAAI,OAAA,CAAQ,sBAAsB,CAAA,GAAI,MAAA;AACtE,EAAA,IAAI,OAAO,OAAA,KAAY,QAAA,IAAY,OAAA,CAAQ,SAAS,0BAAA,EAA4B;AAC9E,IAAA,OAAO,kCAAA;AAAA,EACT;AACA,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI;AACF,IAAA,QAAA,GAAW,uBAAA,CAAwB,OAAO,CAAA,CAAE,QAAA;AAAA,EAC9C,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,mDAAA;AAAA,EACT;AACA,EAAA,IAAI,CAAC,WAAA,CAAY,OAAO,CAAA,EAAG,OAAO,mDAAA;AAClC,EAAA,IAAI,QAAA,CAAS,WAAA,KAAgB,CAAA,EAAG,OAAO,yCAAA;AACvC,EAAA,MAAM,OAAO,QAAA,CAAS,YAAA;AACtB,EAAA,IAAI,CAAC,MAAM,OAAO,wCAAA;AAClB,EAAA,IAAI,IAAA,CAAK,UAAA,KAAe,aAAA,EAAe,OAAO,wCAAA;AAC9C,EAAA,IAAI,QAAA,CAAS,UAAA,KAAe,KAAA,CAAM,KAAA,EAAO;AACvC,IAAA,OAAO,oDAAA;AAAA,EACT;AACA,EAAA,IAAI,IAAA;AACJ,EAAA,IAAI;AACF,IAAA,IAAA,GAAO,mBAAA,CAAoB,KAAK,IAAI,CAAA;AAAA,EACtC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,6CAAA;AAAA,EACT;AACA,EAAA,IAAI,IAAA,CAAK,WAAA,KAAgB,KAAA,CAAM,KAAA,EAAO,OAAO,+CAAA;AAC7C,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,KAAA,CAAM,MAAA,EAAQ,OAAO,4CAAA;AACzC,EAAA,IAAI,IAAA,CAAK,OAAA,KAAY,SAAA,EAAW,OAAO,6CAAA;AACvC,EAAA,OAAO;AAAA,IACL,OAAO,QAAA,CAAS,QAAA;AAAA,IAChB,WAAW,oBAAA,CAAqB;AAAA,MAC9B,SAAS,KAAA,CAAM,OAAA;AAAA,MACf,UAAU,QAAA,CAAS,QAAA;AAAA,MACnB,WAAW,QAAA,CAAS,SAAA;AAAA,MACpB,OAAO,QAAA,CAAS;AAAA,KACjB,CAAA;AAAA,IACD,OAAA,EAAS;AAAA,MACP,CAAA,EAAG,eAAA;AAAA,MACH,SAAS,KAAA,CAAM,OAAA;AAAA,MACf,UAAU,QAAA,CAAS,QAAA;AAAA,MACnB,WAAW,QAAA,CAAS,SAAA;AAAA,MACpB,KAAA,EAAO,QAAA,CAAS,KAAA,CAAM,QAAA,EAAS;AAAA,MAC/B,cAAA,EAAgB,QAAA,CAAS,cAAA,CAAe,QAAA,EAAS;AAAA,MACjD,OAAO,QAAA,CAAS,UAAA;AAAA,MAChB,UAAU,IAAA,CAAK,WAAA;AAAA,MACf,QAAQ,IAAA,CAAK;AAAA;AACf,GACF;AACF;AAOA,SAAS,YAAY,OAAA,EAA0B;AAC7C,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,OAAA,EAAS,QAAQ,CAAA;AAC3C,EAAA,IAAI,KAAA,CAAM,QAAA,CAAS,QAAQ,CAAA,KAAM,SAAS,OAAO,KAAA;AACjD,EAAA,IAAI;AACF,IAAA,uBAAA,CAAwB,KAAA,CAAM,SAAS,CAAA,EAAG,KAAA,CAAM,SAAS,CAAC,CAAA,CAAE,QAAA,CAAS,QAAQ,CAAC,CAAA;AAC9E,IAAA,OAAO,KAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF","file":"near-FH7HPZV3.js","sourcesContent":["/**\n * NEAR `exact` payload inspection with bounded decoding of the NEP-366 signed\n * delegate action, transfer checks, replay identity and reconciliation\n * coordinates. The provider loads this module, including its `@x402/near`\n * import, when a NEAR offer is configured.\n *\n * The facilitator checks the signature, the access key and its nonce, the\n * delegate window and chain state. The gateway checks the transfer the buyer\n * signed against the offer, so a proof for other terms never reaches it.\n */\nimport { decodeSignedDelegateB64, parseFtTransferArgs } from '@x402/near';\nimport { isRecord } from '../../core/is-record';\nimport { LOCATOR_VERSION } from './locator';\nimport { computeNearReplayKey } from './replay-key';\n\n// One `ft_transfer` delegate is a few hundred bytes; this bounds the decoder\nconst MAX_SIGNED_DELEGATE_BASE64 = 4096;\n// NEP-141 requires exactly one yoctoNEAR on `ft_transfer`\nconst ONE_YOCTO = 1n;\n\nexport interface NearTransferTerms {\n readonly network: string;\n /** The NEP-141 token contract the delegate must call */\n readonly asset: string;\n readonly payTo: string;\n /** Atomic units, as the offer states them */\n readonly amount: string;\n}\n\n/**\n * Returns the payer, replay key and locator for a NEAR `exact` payload that\n * matches the offer, or an SDK refusal reason. The provider adds relayers from\n * the facilitator's `/supported` response.\n */\nexport function inspectNearPayload(\n payload: unknown,\n terms: NearTransferTerms,\n):\n | {\n readonly payer: string;\n readonly replayKey: string;\n readonly locator: Readonly<Record<string, unknown>>;\n }\n | string {\n const encoded = isRecord(payload) ? payload['signedDelegateAction'] : undefined;\n if (typeof encoded !== 'string' || encoded.length > MAX_SIGNED_DELEGATE_BASE64) {\n return 'invalid_exact_near_payload_shape';\n }\n let delegate: ReturnType<typeof decodeSignedDelegateB64>['delegate'];\n try {\n delegate = decodeSignedDelegateB64(encoded).delegate;\n } catch {\n return 'invalid_exact_near_payload_signed_delegate_action';\n }\n if (!isCanonical(encoded)) return 'invalid_exact_near_payload_signed_delegate_action';\n if (delegate.actionCount !== 1) return 'invalid_exact_near_payload_action_count';\n const call = delegate.functionCall;\n if (!call) return 'invalid_exact_near_payload_action_kind';\n if (call.methodName !== 'ft_transfer') return 'invalid_exact_near_payload_method_name';\n if (delegate.receiverId !== terms.asset) {\n return 'invalid_exact_near_payload_token_contract_mismatch';\n }\n let args: ReturnType<typeof parseFtTransferArgs>;\n try {\n args = parseFtTransferArgs(call.args);\n } catch {\n return 'invalid_exact_near_payload_ft_transfer_args';\n }\n if (args.receiver_id !== terms.payTo) return 'invalid_exact_near_payload_recipient_mismatch';\n if (args.amount !== terms.amount) return 'invalid_exact_near_payload_amount_mismatch';\n if (call.deposit !== ONE_YOCTO) return 'invalid_exact_near_payload_attached_deposit';\n return {\n payer: delegate.senderId,\n replayKey: computeNearReplayKey({\n network: terms.network,\n senderId: delegate.senderId,\n publicKey: delegate.publicKey,\n nonce: delegate.nonce,\n }),\n locator: {\n v: LOCATOR_VERSION,\n network: terms.network,\n senderId: delegate.senderId,\n publicKey: delegate.publicKey,\n nonce: delegate.nonce.toString(),\n maxBlockHeight: delegate.maxBlockHeight.toString(),\n asset: delegate.receiverId,\n receiver: args.receiver_id,\n amount: args.amount,\n },\n };\n}\n\n/**\n * One delegate, one encoding: canonical base64, and no bytes after the signed\n * delegate. The SDK decoder ignores such bytes, so the check decodes the\n * payload without its last byte: a canonical encoding then runs short.\n */\nfunction isCanonical(encoded: string): boolean {\n const bytes = Buffer.from(encoded, 'base64');\n if (bytes.toString('base64') !== encoded) return false;\n try {\n decodeSignedDelegateB64(bytes.subarray(0, bytes.length - 1).toString('base64'));\n return false;\n } catch {\n return true;\n }\n}\n"]}
@@ -1,6 +1,5 @@
1
1
  import { IncomingMessage, ServerResponse } from 'node:http';
2
- import { I as IsoTimestamp, o as PaymentResult, s as ProtocolName, b as PaymentSubmission, n as PaymentRequirement, A as AdapterDescriptor, R as ResourceRegistry, L as Logger, C as Clock, e as IdGenerator, c as AdapterHealth } from './runtime-Cl_BLVZV.js';
3
- import { d as AuthorizationRecord, b as AuthorizationSubmission, a as AuthorizationRequirement } from './authorization-DjAecwuW.js';
2
+ import { I as IsoTimestamp, e as ProtocolName, P as PaymentMethodName, g as PaymentAttempt, D as DecimalAmount, f as AuthorizationRecord, c as PaymentSubmission, d as AuthorizationSubmission, F as PaymentResult, h as CommerceReceipt, E as PaymentRequirement, a as AuthorizationRequirement, j as AdapterDescriptor, R as ResourceRegistry, L as Logger, C as Clock, m as IdGenerator, k as AdapterHealth } from './runtime-Dz2fSO-P.js';
4
3
 
5
4
  /**
6
5
  * Canonical commerce events. FROZEN CONTRACT. Every event in one flow shares
@@ -14,6 +13,8 @@ interface CommerceEvent {
14
13
  readonly id: string;
15
14
  readonly type: CommerceEventType;
16
15
  readonly requestId: string;
16
+ /** Links events from one execution; optional for compatibility with pre-2.5.0 rows */
17
+ readonly transactionId?: string;
17
18
  readonly resourceId?: string;
18
19
  readonly at: IsoTimestamp;
19
20
  /** Protocol adapter that originated the request, e.g. 'mcp' or 'http' */
@@ -32,56 +33,102 @@ interface EventSink {
32
33
  emit(event: CommerceEvent): Promise<void>;
33
34
  }
34
35
 
35
- interface CommerceReceipt {
36
- readonly id: string;
37
- readonly requestId: string;
38
- readonly resourceId: string;
39
- /** Absent for free resources */
40
- readonly payment?: PaymentResult;
41
- /**
42
- * Present only when the resource required authorization. A method and a digest,
43
- * so the receipt records that consent existed without storing the proof.
44
- */
45
- readonly authorization?: AuthorizationRecord;
46
- readonly deliveredAt: IsoTimestamp;
47
- readonly backendStatus: number;
48
- readonly durationMs?: number;
49
- readonly protocol?: string;
50
- /** Non-secret summary only, never a sensitive backend body */
51
- readonly metadata?: Readonly<Record<string, unknown>>;
52
- }
53
- /** Record of a single payment authorization seen by the gateway */
54
- interface PaymentAttempt {
36
+ /**
37
+ * Canonical transaction model. FROZEN CONTRACT.
38
+ *
39
+ * A transaction links a paid purchase's request, payment attempt, optional
40
+ * authorization hold, backend call and receipt by ID. PaymentAttempt owns the
41
+ * payment status; journal readers must read it from the attempt rather than
42
+ * maintain a separate copy.
43
+ */
44
+
45
+ /**
46
+ * States derived by {@link transactionState}. Experimental: may change in a
47
+ * minor release.
48
+ */
49
+ declare const TRANSACTION_STATES: readonly ["payment-pending", "payment-failed", "payment-uncertain", "settled-undelivered", "delivery-started", "delivery-unknown", "delivered"];
50
+ /**
51
+ * Open to state names added by later releases; consumers must handle values
52
+ * outside {@link TRANSACTION_STATES}. Experimental: may change in a minor release.
53
+ */
54
+ type TransactionState = (typeof TRANSACTION_STATES)[number] | (string & {});
55
+ /** Last hold state communicated to the authorization provider */
56
+ type AuthorizationHoldState = 'reserved' | 'consumed' | 'released' | 'uncertain';
57
+ /**
58
+ * Store writes reported as failed during an execution. Consumers must handle
59
+ * unlisted labels that later releases may add.
60
+ */
61
+ type PersistenceFailure = 'payment-attempt' | 'receipt' | 'journal' | (string & {});
62
+ /**
63
+ * Journal record for a paid purchase, starting with replay reservation.
64
+ * Store only references and digests, never payment proofs, signatures, mandates
65
+ * or input bodies. Experimental: may change in a minor release.
66
+ */
67
+ interface Transaction {
55
68
  readonly id: string;
69
+ /** The request that created it */
56
70
  readonly requestId: string;
57
71
  readonly resourceId: string;
58
- readonly provider: string;
59
- /** Unique across the store; see `PaymentResult.replayKey` */
60
- readonly replayKey: string;
61
- /**
62
- * State of the authorization, as far as the gateway can prove it.
63
- *
64
- * `settlement-uncertain` means settlement was attempted and no verdict came
65
- * back (RPC timeout, dropped connection, a facilitator that accepted the
66
- * transfer and lost the response). The transfer may or may not have
67
- * happened, so the attempt is unresolved rather than terminal and needs
68
- * evidence from the chain, not a retry. `externalReference` holds the
69
- * broadcast transaction hash when one is known.
70
- *
71
- * The execution pipeline never writes `failed`: a throw out of `settle()`
72
- * never proves that nothing moved. It stays in the union because existing
73
- * databases hold rows with that status.
74
- */
75
- readonly status: 'reserved' | 'verified' | 'settled' | 'rejected' | 'failed' | 'settlement-uncertain';
76
- readonly amount: string;
77
- readonly currency: string;
78
- readonly payer?: string;
79
- readonly payee?: string;
80
- readonly externalReference?: string;
81
- readonly rejectionReason?: string;
72
+ readonly protocol: ProtocolName;
73
+ /** Cached derived state; readers must recompute it with {@link transactionState} */
74
+ readonly state: TransactionState;
75
+ readonly payment: {
76
+ readonly provider: PaymentMethodName;
77
+ readonly attemptId: string;
78
+ readonly replayKey: string;
79
+ /** Read from PaymentAttempt, not maintained independently */
80
+ readonly status: PaymentAttempt['status'];
81
+ readonly amount: DecimalAmount;
82
+ readonly currency: string;
83
+ readonly network?: string;
84
+ readonly asset?: string;
85
+ readonly payee?: string;
86
+ readonly externalReference?: string;
87
+ /**
88
+ * Public coordinates for the provider's `reconcile` hook, governed by
89
+ * `RECONCILIATION_METADATA_KEY`
90
+ */
91
+ readonly locator?: Readonly<Record<string, unknown>>;
92
+ /** When the provider's `settle` was called */
93
+ readonly settlingAt?: IsoTimestamp;
94
+ /** The authorization cannot land after this */
95
+ readonly expiresAt?: IsoTimestamp;
96
+ };
97
+ readonly authorization?: AuthorizationRecord & {
98
+ /** The handle the authorization provider consumes or releases */
99
+ readonly reservationId: string;
100
+ readonly hold: AuthorizationHoldState;
101
+ };
102
+ readonly backend?: {
103
+ readonly dispatchedAt: IsoTimestamp;
104
+ /** Dispatch time plus the backend timeout and a margin */
105
+ readonly deadlineAt: IsoTimestamp;
106
+ /** 0 if the call ended without a status, such as a timeout or transport failure */
107
+ readonly status?: number;
108
+ readonly errorCode?: string;
109
+ };
110
+ readonly receiptId?: string;
111
+ /** `sha256:` followed by the canonical JSON input digest in hex; omit for non-I-JSON input */
112
+ readonly inputDigest?: string;
113
+ /** Digest of pricing and settlement terms, excluding credentials */
114
+ readonly configDigest: string;
115
+ readonly persistenceFailures?: readonly PersistenceFailure[];
82
116
  readonly createdAt: IsoTimestamp;
83
117
  readonly updatedAt: IsoTimestamp;
118
+ /** Time of the pipeline's last journal write before returning the outcome */
119
+ readonly completedAt?: IsoTimestamp;
84
120
  }
121
+ /** What {@link transactionState} reads */
122
+ type TransactionFacts = Pick<Transaction, 'backend' | 'completedAt'> & {
123
+ readonly payment: Pick<Transaction['payment'], 'status'>;
124
+ };
125
+ /**
126
+ * Derive state from payment status, backend facts and pipeline completion.
127
+ * For a settled payment, a dispatched call with no result after `deadlineAt`
128
+ * means `delivery-unknown`; a timeout does not prove that the backend never ran.
129
+ * Experimental: may change in a minor release.
130
+ */
131
+ declare function transactionState(facts: TransactionFacts, now: IsoTimestamp): (typeof TRANSACTION_STATES)[number];
85
132
 
86
133
  /**
87
134
  * Canonical request/response model for the execution pipeline.
@@ -121,6 +168,7 @@ interface CanonicalRequest {
121
168
  interface DeliveredOutcome {
122
169
  readonly kind: 'delivered';
123
170
  readonly requestId: string;
171
+ readonly transactionId?: string;
124
172
  readonly resourceId: string;
125
173
  readonly backendStatus: number;
126
174
  readonly body: unknown;
@@ -128,11 +176,17 @@ interface DeliveredOutcome {
128
176
  readonly payment?: PaymentResult;
129
177
  readonly receipt: CommerceReceipt;
130
178
  readonly durationMs: number;
179
+ /**
180
+ * Failed store writes that did not prevent delivery. A `receipt` entry
181
+ * marks `receipt.id` as uncommitted.
182
+ */
183
+ readonly persistenceFailures?: readonly PersistenceFailure[];
131
184
  }
132
185
  /** The resource costs money and the request carried no payment proof */
133
186
  interface PaymentRequiredOutcome {
134
187
  readonly kind: 'payment-required';
135
188
  readonly requestId: string;
189
+ readonly transactionId?: string;
136
190
  readonly resourceId: string;
137
191
  readonly requirement: PaymentRequirement;
138
192
  /** Authorization the buyer must also present on the retry, when the resource requires one */
@@ -237,5 +291,5 @@ interface AdapterHttpRoute {
237
291
  }
238
292
  declare function isHttpProtocolAdapter(adapter: ProtocolAdapter): adapter is HttpProtocolAdapter;
239
293
 
240
- export { COMMERCE_EVENT_TYPES as e, isHttpProtocolAdapter as j };
241
- export type { AdapterHttpRoute as A, CommerceEvent as C, DeliveredOutcome as D, ExecutionPipeline as E, HttpProtocolAdapter as H, PaymentRequiredOutcome as P, PaymentAttempt as a, CommerceReceipt as b, ProtocolAdapter as c, ProtocolAdapterContext as d, CanonicalRequest as f, CommerceEventType as g, EventSink as h, ExecutionOutcome as i };
294
+ export { COMMERCE_EVENT_TYPES as f, TRANSACTION_STATES as k, isHttpProtocolAdapter as m, transactionState as t };
295
+ export type { AuthorizationHoldState as A, CommerceEvent as C, DeliveredOutcome as D, ExecutionPipeline as E, HttpProtocolAdapter as H, PaymentRequiredOutcome as P, Transaction as T, PersistenceFailure as a, TransactionState as b, ProtocolAdapter as c, AdapterHttpRoute as d, ProtocolAdapterContext as e, CanonicalRequest as g, CommerceEventType as h, EventSink as i, ExecutionOutcome as j, TransactionFacts as l };