@devlab.group/agent-commerce 2.2.0 → 2.3.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 (56) hide show
  1. package/README.md +3 -3
  2. package/dist/ap2.js +3 -3
  3. package/dist/{chunk-IEW7NSP2.js → chunk-4ZSE5DCH.js} +3 -3
  4. package/dist/{chunk-IEW7NSP2.js.map → chunk-4ZSE5DCH.js.map} +1 -1
  5. package/dist/{chunk-7ZMMXZ4G.js → chunk-Q5TII32R.js} +3 -3
  6. package/dist/{chunk-7ZMMXZ4G.js.map → chunk-Q5TII32R.js.map} +1 -1
  7. package/dist/{chunk-HNRDZLSN.js → chunk-TNS7U5Q4.js} +19 -6
  8. package/dist/chunk-TNS7U5Q4.js.map +1 -0
  9. package/dist/{chunk-Y4RE3XYF.js → chunk-XVU46YAH.js} +24 -20
  10. package/dist/chunk-XVU46YAH.js.map +1 -0
  11. package/dist/cli/{ap2-MBMQHFX4.js → ap2-GINAXBFV.js} +3 -3
  12. package/dist/cli/{ap2-MBMQHFX4.js.map → ap2-GINAXBFV.js.map} +1 -1
  13. package/dist/cli/{chunk-2ZZOGI5I.js → chunk-2LN5PO5I.js} +3 -3
  14. package/dist/cli/{chunk-2ZZOGI5I.js.map → chunk-2LN5PO5I.js.map} +1 -1
  15. package/dist/cli/{chunk-RWVPYAKC.js → chunk-55N55KL4.js} +12 -9
  16. package/dist/cli/chunk-55N55KL4.js.map +1 -0
  17. package/dist/cli/{chunk-KLX2YZDG.js → chunk-BR7CMJOE.js} +20 -7
  18. package/dist/cli/chunk-BR7CMJOE.js.map +1 -0
  19. package/dist/cli/chunk-DYHVNKRB.js +8 -0
  20. package/dist/cli/{chunk-FRMLWGSS.js.map → chunk-DYHVNKRB.js.map} +1 -1
  21. package/dist/cli/{chunk-SS3QFF5N.js → chunk-KABFUZ6L.js} +32 -7
  22. package/dist/cli/chunk-KABFUZ6L.js.map +1 -0
  23. package/dist/cli/{chunk-NSPPEF5M.js → chunk-KTV52MCU.js} +24 -20
  24. package/dist/cli/chunk-KTV52MCU.js.map +1 -0
  25. package/dist/cli/{chunk-7JNYFUT3.js → chunk-OZ4LAWBK.js} +2 -2
  26. package/dist/cli/chunk-OZ4LAWBK.js.map +1 -0
  27. package/dist/cli/{config-4IBGVFSP.js → config-ZOFHJ5FB.js} +6 -6
  28. package/dist/cli/{config-4IBGVFSP.js.map → config-ZOFHJ5FB.js.map} +1 -1
  29. package/dist/cli/index.js +17 -10
  30. package/dist/cli/index.js.map +1 -1
  31. package/dist/cli/{mcp-CNWQ2MOE.js → mcp-V3BNRUWL.js} +3 -3
  32. package/dist/cli/{mcp-CNWQ2MOE.js.map → mcp-V3BNRUWL.js.map} +1 -1
  33. package/dist/cli/{provider-4BQDH56Y.js → provider-BTIFALIT.js} +6 -6
  34. package/dist/cli/{provider-4BQDH56Y.js.map → provider-BTIFALIT.js.map} +1 -1
  35. package/dist/cli/{run-5MB2D45X.js → run-DS2KXUTW.js} +40 -15
  36. package/dist/cli/run-DS2KXUTW.js.map +1 -0
  37. package/dist/cli/{x402-NKR3WQDQ.js → x402-YTKFNWVQ.js} +7 -7
  38. package/dist/cli/{x402-NKR3WQDQ.js.map → x402-YTKFNWVQ.js.map} +1 -1
  39. package/dist/index.d.ts +26 -4
  40. package/dist/index.js +67 -14
  41. package/dist/index.js.map +1 -1
  42. package/dist/mcp.js +1 -1
  43. package/dist/mpp.js +3 -3
  44. package/dist/{networks-olfflCI_.d.ts → networks-DTWRlj-K.d.ts} +2 -2
  45. package/dist/x402.d.ts +2 -2
  46. package/dist/x402.js +4 -4
  47. package/package.json +1 -1
  48. package/dist/chunk-HNRDZLSN.js.map +0 -1
  49. package/dist/chunk-Y4RE3XYF.js.map +0 -1
  50. package/dist/cli/chunk-7JNYFUT3.js.map +0 -1
  51. package/dist/cli/chunk-FRMLWGSS.js +0 -8
  52. package/dist/cli/chunk-KLX2YZDG.js.map +0 -1
  53. package/dist/cli/chunk-NSPPEF5M.js.map +0 -1
  54. package/dist/cli/chunk-RWVPYAKC.js.map +0 -1
  55. package/dist/cli/chunk-SS3QFF5N.js.map +0 -1
  56. package/dist/cli/run-5MB2D45X.js.map +0 -1
@@ -1,9 +1,9 @@
1
- import { chainIdFromCaip2 } from './chunk-KLX2YZDG.js';
2
- export { createX402PaymentProvider } from './chunk-KLX2YZDG.js';
3
- import './chunk-NSPPEF5M.js';
4
- export { SUPPORTED_NETWORK_IDS } from './chunk-7JNYFUT3.js';
1
+ import { chainIdFromCaip2 } from './chunk-BR7CMJOE.js';
2
+ export { createX402PaymentProvider } from './chunk-BR7CMJOE.js';
3
+ import './chunk-KTV52MCU.js';
4
+ export { SUPPORTED_NETWORK_IDS } from './chunk-OZ4LAWBK.js';
5
5
  import './chunk-OSTCU6ZK.js';
6
- import './chunk-FRMLWGSS.js';
6
+ import './chunk-DYHVNKRB.js';
7
7
  import { CommerceError } from './chunk-QQ3WY5L3.js';
8
8
  import './chunk-3M6U7ILB.js';
9
9
  import { PaymentRequirementsV2Schema } from '@x402/core/schemas';
@@ -92,5 +92,5 @@ function randomNonce() {
92
92
  }
93
93
 
94
94
  export { createPaymentProof };
95
- //# sourceMappingURL=x402-NKR3WQDQ.js.map
96
- //# sourceMappingURL=x402-NKR3WQDQ.js.map
95
+ //# sourceMappingURL=x402-YTKFNWVQ.js.map
96
+ //# sourceMappingURL=x402-YTKFNWVQ.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/payments/x402/client.ts"],"names":[],"mappings":";;;;;;;;;;;;AAkCA,IAAM,YAAA,GAAe,CAAA;AAErB,IAAM,iCAAA,GAAoC;AAAA,EACxC,yBAAA,EAA2B;AAAA,IACzB,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,SAAA,EAAU;AAAA,IAChC,EAAE,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,SAAA,EAAU;AAAA,IAC9B,EAAE,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,SAAA,EAAU;AAAA,IACjC,EAAE,IAAA,EAAM,YAAA,EAAc,IAAA,EAAM,SAAA,EAAU;AAAA,IACtC,EAAE,IAAA,EAAM,aAAA,EAAe,IAAA,EAAM,SAAA,EAAU;AAAA,IACvC,EAAE,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,SAAA;AAAU;AAErC,CAAA;AAGA,eAAsB,mBAAmB,OAAA,EAAqD;AAC5F,EAAA,MAAM,YAAA,GAAe,2BAAA,CAA4B,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA;AACtE,EAAA,MAAM,MAAA,GAAS,YAAA,CAAa,KAAA,GAAQ,qBAAqB,CAAA;AACzD,EAAA,IAAI,MAAA,KAAW,MAAA,IAAa,MAAA,KAAW,SAAA,EAAW;AAChD,IAAA,MAAM,IAAI,aAAA;AAAA,MACR,eAAA;AAAA,MACA,CAAA,8DAAA,EAAiE,MAAA,CAAO,MAAM,CAAC,CAAA,oCAAA;AAAA,KACjF;AAAA,EACF;AACA,EAAA,IACE,CAAC,YAAA,CAAa,KAAA,IACd,OAAO,aAAa,KAAA,CAAM,MAAM,CAAA,KAAM,QAAA,IACtC,OAAO,YAAA,CAAa,KAAA,CAAM,SAAS,MAAM,QAAA,EACzC;AACA,IAAA,MAAM,IAAI,aAAA;AAAA,MACR,eAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAEA,EAAA,MAAM,OAAA,GAAU,gBAAA,CAAiB,YAAA,CAAa,OAAO,CAAA;AACrD,EAAA,IAAI,YAAY,MAAA,EAAW;AACzB,IAAA,MAAM,IAAI,aAAA;AAAA,MACR,eAAA;AAAA,MACA,CAAA,6BAAA,EAAgC,aAAa,OAAO,CAAA,4EAAA;AAAA,KACtD;AAAA,EACF;AAEA,EAAA,MAAM,OAAA,GAAU,mBAAA,CAAoB,OAAA,CAAQ,eAAe,CAAA;AAE3D,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,SAAA,EAAW,KAAA,IAAS,WAAA,EAAY;AACtD,EAAA,MAAM,aAAa,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,KAAQ,GAAI,CAAA;AAG/C,EAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,SAAA,EAAW,UAAA,IAAc,CAAA;AACpD,EAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,SAAA,EAAW,WAAA,IAAe,aAAa,YAAA,CAAa,iBAAA;AAChF,EAAA,MAAM,KAAK,UAAA,CAAY,OAAA,CAAQ,SAAA,EAAW,KAAA,IAAS,aAAa,KAAuB,CAAA;AACvF,EAAA,MAAM,QAAQ,MAAA,CAAO,OAAA,CAAQ,SAAA,EAAW,KAAA,IAAS,aAAa,MAAM,CAAA;AAEpE,EAAA,MAAM,SAAA,GAAY,MAAM,OAAA,CAAQ,aAAA,CAAc;AAAA,IAC5C,MAAA,EAAQ;AAAA,MACN,IAAA,EAAM,YAAA,CAAa,KAAA,CAAM,MAAM,CAAA;AAAA,MAC/B,OAAA,EAAS,YAAA,CAAa,KAAA,CAAM,SAAS,CAAA;AAAA,MACrC,OAAA;AAAA,MACA,iBAAA,EAAmB,UAAA,CAAW,YAAA,CAAa,KAAsB;AAAA,KACnE;AAAA,IACA,KAAA,EAAO,iCAAA;AAAA,IACP,WAAA,EAAa,2BAAA;AAAA,IACb,OAAA,EAAS;AAAA,MACP,MAAM,OAAA,CAAQ,OAAA;AAAA,MACd,EAAA;AAAA,MACA,KAAA;AAAA,MACA,UAAA,EAAY,OAAO,UAAU,CAAA;AAAA,MAC7B,WAAA,EAAa,OAAO,WAAW,CAAA;AAAA,MAC/B;AAAA;AACF,GACD,CAAA;AAKD,EAAA,MAAM,OAAA,GAA0B;AAAA,IAC9B,WAAA,EAAa,YAAA;AAAA,IACb,QAAA,EAAU,YAAA;AAAA,IACV,OAAA,EAAS;AAAA,MACP,SAAA;AAAA,MACA,aAAA,EAAe;AAAA,QACb,MAAM,OAAA,CAAQ,OAAA;AAAA,QACd,EAAA;AAAA,QACA,KAAA,EAAO,MAAM,QAAA,EAAS;AAAA,QACtB,UAAA,EAAY,WAAW,QAAA,EAAS;AAAA,QAChC,WAAA,EAAa,YAAY,QAAA,EAAS;AAAA,QAClC;AAAA;AACF;AACF,GACF;AAEA,EAAA,OAAO,MAAA,CAAO,KAAK,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA,EAAG,MAAM,CAAA,CAAE,QAAA,CAAS,QAAQ,CAAA;AACvE;AAEA,SAAS,WAAA,GAA6B;AACpC,EAAA,MAAM,KAAA,GAAQ,IAAI,UAAA,CAAW,EAAE,CAAA;AAC/B,EAAA,MAAA,CAAO,gBAAgB,KAAK,CAAA;AAC5B,EAAA,OAAO,MAAM,KAAK,CAAA;AACpB","file":"x402-NKR3WQDQ.js","sourcesContent":["/**\n * Client-side payment helper: builds and EIP-712-signs an x402 v2 `exact`/EVM\n * authorization on the buyer's side. The demo buyer agent and the test suites\n * use it, and the `/x402` entry exports it. The gateway never calls it and\n * never holds a buyer key.\n *\n * It signs directly rather than through the SDK's `x402Client` because of\n * `overrides`: negative tests need deliberately wrong authorizations that a\n * conforming client will not produce. The x402 settlement E2E suite also\n * settles a payment built by `x402Client` itself to cover interoperability.\n */\n\nimport { PaymentRequirementsV2Schema } from '@x402/core/schemas';\nimport type { PaymentPayload, PaymentRequirements } from '@x402/core/types';\nimport { getAddress, toHex } from 'viem';\nimport { privateKeyToAccount } from 'viem/accounts';\nimport { CommerceError } from '../../core';\nimport { chainIdFromCaip2 } from './chain';\n\nexport interface CreatePaymentProofOptions {\n /** The buyer's private key. It signs locally and is never sent anywhere */\n readonly buyerPrivateKey: `0x${string}`;\n /** One entry from PaymentRequiredEnvelope.payment.accepts, verbatim */\n readonly accepts: Readonly<Record<string, unknown>>;\n /** For negative tests only: a wrong amount, recipient, nonce or validity window */\n readonly overrides?: {\n readonly value?: string;\n readonly payTo?: string;\n readonly nonce?: `0x${string}`;\n readonly validBefore?: number;\n readonly validAfter?: number;\n };\n}\n\nconst X402_VERSION = 2;\n\nconst TRANSFER_WITH_AUTHORIZATION_TYPES = {\n TransferWithAuthorization: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'validAfter', type: 'uint256' },\n { name: 'validBefore', type: 'uint256' },\n { name: 'nonce', type: 'bytes32' },\n ],\n} as const;\n\n/** Returns the base64 `PAYMENT-SIGNATURE` value to send back to the gateway */\nexport async function createPaymentProof(options: CreatePaymentProofOptions): Promise<string> {\n const requirements = PaymentRequirementsV2Schema.parse(options.accepts);\n const method = requirements.extra?.['assetTransferMethod'];\n if (method !== undefined && method !== 'eip3009') {\n throw new CommerceError(\n 'INPUT_INVALID',\n `createPaymentProof: signs EIP-3009 only, and this offer uses \"${String(method)}\"; sign it with the SDK's x402Client`,\n );\n }\n if (\n !requirements.extra ||\n typeof requirements.extra['name'] !== 'string' ||\n typeof requirements.extra['version'] !== 'string'\n ) {\n throw new CommerceError(\n 'INPUT_INVALID',\n 'createPaymentProof: payment requirement is missing extra.name/extra.version, so the EIP-712 domain cannot be built',\n );\n }\n\n const chainId = chainIdFromCaip2(requirements.network);\n if (chainId === undefined) {\n throw new CommerceError(\n 'INPUT_INVALID',\n `createPaymentProof: network \"${requirements.network}\" is not a CAIP-2 eip155 identifier, so there is no chain id to sign against`,\n );\n }\n\n const account = privateKeyToAccount(options.buyerPrivateKey);\n\n const nonce = options.overrides?.nonce ?? randomNonce();\n const nowSeconds = Math.floor(Date.now() / 1000);\n // 0, as in the SDK's own v2 client: nothing here wants the authorization\n // delayed\n const validAfter = options.overrides?.validAfter ?? 0;\n const validBefore = options.overrides?.validBefore ?? nowSeconds + requirements.maxTimeoutSeconds;\n const to = getAddress((options.overrides?.payTo ?? requirements.payTo) as `0x${string}`);\n const value = BigInt(options.overrides?.value ?? requirements.amount);\n\n const signature = await account.signTypedData({\n domain: {\n name: requirements.extra['name'],\n version: requirements.extra['version'],\n chainId,\n verifyingContract: getAddress(requirements.asset as `0x${string}`),\n },\n types: TRANSFER_WITH_AUTHORIZATION_TYPES,\n primaryType: 'TransferWithAuthorization',\n message: {\n from: account.address,\n to,\n value,\n validAfter: BigInt(validAfter),\n validBefore: BigInt(validBefore),\n nonce,\n },\n });\n\n // v2 echoes the chosen requirement back as `accepted` so a stateless\n // facilitator knows which offer was taken. The gateway verifies against its\n // own copy.\n const payload: PaymentPayload = {\n x402Version: X402_VERSION,\n accepted: requirements as PaymentRequirements,\n payload: {\n signature,\n authorization: {\n from: account.address,\n to,\n value: value.toString(),\n validAfter: validAfter.toString(),\n validBefore: validBefore.toString(),\n nonce,\n },\n },\n };\n\n return Buffer.from(JSON.stringify(payload), 'utf8').toString('base64');\n}\n\nfunction randomNonce(): `0x${string}` {\n const bytes = new Uint8Array(32);\n crypto.getRandomValues(bytes);\n return toHex(bytes);\n}\n"]}
1
+ {"version":3,"sources":["../../src/payments/x402/client.ts"],"names":[],"mappings":"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","file":"x402-YTKFNWVQ.js","sourcesContent":["/**\n * Client-side payment helper: builds and EIP-712-signs an x402 v2 `exact`/EVM\n * authorization on the buyer's side. The demo buyer agent and the test suites\n * use it, and the `/x402` entry exports it. The gateway never calls it and\n * never holds a buyer key.\n *\n * It signs directly rather than through the SDK's `x402Client` because of\n * `overrides`: negative tests need deliberately wrong authorizations that a\n * conforming client will not produce. The x402 settlement E2E suite also\n * settles a payment built by `x402Client` itself to cover interoperability.\n */\n\nimport { PaymentRequirementsV2Schema } from '@x402/core/schemas';\nimport type { PaymentPayload, PaymentRequirements } from '@x402/core/types';\nimport { getAddress, toHex } from 'viem';\nimport { privateKeyToAccount } from 'viem/accounts';\nimport { CommerceError } from '../../core';\nimport { chainIdFromCaip2 } from './chain';\n\nexport interface CreatePaymentProofOptions {\n /** The buyer's private key. It signs locally and is never sent anywhere */\n readonly buyerPrivateKey: `0x${string}`;\n /** One entry from PaymentRequiredEnvelope.payment.accepts, verbatim */\n readonly accepts: Readonly<Record<string, unknown>>;\n /** For negative tests only: a wrong amount, recipient, nonce or validity window */\n readonly overrides?: {\n readonly value?: string;\n readonly payTo?: string;\n readonly nonce?: `0x${string}`;\n readonly validBefore?: number;\n readonly validAfter?: number;\n };\n}\n\nconst X402_VERSION = 2;\n\nconst TRANSFER_WITH_AUTHORIZATION_TYPES = {\n TransferWithAuthorization: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'validAfter', type: 'uint256' },\n { name: 'validBefore', type: 'uint256' },\n { name: 'nonce', type: 'bytes32' },\n ],\n} as const;\n\n/** Returns the base64 `PAYMENT-SIGNATURE` value to send back to the gateway */\nexport async function createPaymentProof(options: CreatePaymentProofOptions): Promise<string> {\n const requirements = PaymentRequirementsV2Schema.parse(options.accepts);\n const method = requirements.extra?.['assetTransferMethod'];\n if (method !== undefined && method !== 'eip3009') {\n throw new CommerceError(\n 'INPUT_INVALID',\n `createPaymentProof: signs EIP-3009 only, and this offer uses \"${String(method)}\"; sign it with the SDK's x402Client`,\n );\n }\n if (\n !requirements.extra ||\n typeof requirements.extra['name'] !== 'string' ||\n typeof requirements.extra['version'] !== 'string'\n ) {\n throw new CommerceError(\n 'INPUT_INVALID',\n 'createPaymentProof: payment requirement is missing extra.name/extra.version, so the EIP-712 domain cannot be built',\n );\n }\n\n const chainId = chainIdFromCaip2(requirements.network);\n if (chainId === undefined) {\n throw new CommerceError(\n 'INPUT_INVALID',\n `createPaymentProof: network \"${requirements.network}\" is not a CAIP-2 eip155 identifier, so there is no chain id to sign against`,\n );\n }\n\n const account = privateKeyToAccount(options.buyerPrivateKey);\n\n const nonce = options.overrides?.nonce ?? randomNonce();\n const nowSeconds = Math.floor(Date.now() / 1000);\n // 0, as in the SDK's own v2 client: nothing here wants the authorization\n // delayed\n const validAfter = options.overrides?.validAfter ?? 0;\n const validBefore = options.overrides?.validBefore ?? nowSeconds + requirements.maxTimeoutSeconds;\n const to = getAddress((options.overrides?.payTo ?? requirements.payTo) as `0x${string}`);\n const value = BigInt(options.overrides?.value ?? requirements.amount);\n\n const signature = await account.signTypedData({\n domain: {\n name: requirements.extra['name'],\n version: requirements.extra['version'],\n chainId,\n verifyingContract: getAddress(requirements.asset as `0x${string}`),\n },\n types: TRANSFER_WITH_AUTHORIZATION_TYPES,\n primaryType: 'TransferWithAuthorization',\n message: {\n from: account.address,\n to,\n value,\n validAfter: BigInt(validAfter),\n validBefore: BigInt(validBefore),\n nonce,\n },\n });\n\n // v2 echoes the chosen requirement back as `accepted` so a stateless\n // facilitator knows which offer was taken. The gateway verifies against its\n // own copy.\n const payload: PaymentPayload = {\n x402Version: X402_VERSION,\n accepted: requirements as PaymentRequirements,\n payload: {\n signature,\n authorization: {\n from: account.address,\n to,\n value: value.toString(),\n validAfter: validAfter.toString(),\n validBefore: validBefore.toString(),\n nonce,\n },\n },\n };\n\n return Buffer.from(JSON.stringify(payload), 'utf8').toString('base64');\n}\n\nfunction randomNonce(): `0x${string}` {\n const bytes = new Uint8Array(32);\n crypto.getRandomValues(bytes);\n return toHex(bytes);\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import { I as IsoTimestamp, D as DecimalAmount, P as PaymentMethodName, a as Com
3
3
  export { f as AdapterHealthComponent, g as AuthorizationMethodName, h as BackendMethod, i as DEFAULT_BACKEND_TIMEOUT_MS, J as JsonSchema, N as NOOP_LOGGER, j as PAYMENT_METHOD_NAMES, k as PROTOCOL_NAMES, l as PaymentChallenge, m as PaymentContext, n as PaymentRequirement, o as PaymentResult, p as PaymentSettlementContext, q as PaymentVerificationContext, r as Pricing, s as ProtocolName, t as systemClock } from './runtime-7vLNYvmU.js';
4
4
  import { M as MppNetwork } from './constants-nackLItD.js';
5
5
  import { X as X402PaymentFlow, a as X402FacilitatorConfig } from './guardrails-CX_jYXvZ.js';
6
- import { C as CustomNetworks } from './networks-olfflCI_.js';
6
+ import { C as CustomNetworks } from './networks-DTWRlj-K.js';
7
7
  import { a as AuthorizationRequirement, b as AuthorizationSubmission, A as AuthorizationProvider } from './authorization-CMkIuAkO.js';
8
8
  export { c as AuthorizationFinalizeContext, d as AuthorizationRecord, e as AuthorizationVerification, f as AuthorizationVerificationContext } from './authorization-CMkIuAkO.js';
9
9
  import { D as DeliveredOutcome, P as PaymentRequiredOutcome, C as CommerceEvent, a as PaymentAttempt, b as CommerceReceipt, E as ExecutionPipeline, c as ProtocolAdapter, H as HttpProtocolAdapter, A as AdapterHttpRoute, d as ProtocolAdapterContext } from './protocol-adapter-CfxU8Z2T.js';
@@ -329,6 +329,20 @@ interface ListOptions {
329
329
  readonly limit?: number;
330
330
  readonly requestId?: string;
331
331
  }
332
+ interface ReceiptListOptions extends ListOptions {
333
+ /**
334
+ * When true, return only receipts counted by {@link ReceiptStore.countUndeliveredReceipts}.
335
+ * Stores ignoring this flag also return delivered receipts.
336
+ */
337
+ readonly undelivered?: boolean;
338
+ }
339
+ interface PaymentAttemptListOptions extends ListOptions {
340
+ /**
341
+ * When true, return only attempts counted by {@link ReceiptStore.countUncertainPaymentAttempts}.
342
+ * Stores that ignore this flag do not filter by settlement status.
343
+ */
344
+ readonly uncertain?: boolean;
345
+ }
332
346
  interface ReceiptStore {
333
347
  init(): Promise<void>;
334
348
  /** Append a canonical event. Must not throw into the caller's flow */
@@ -347,7 +361,7 @@ interface ReceiptStore {
347
361
  updatePaymentAttempt(update: PaymentAttemptUpdate): Promise<void>;
348
362
  saveReceipt(receipt: CommerceReceipt): Promise<void>;
349
363
  getReceipt(id: string): Promise<CommerceReceipt | undefined>;
350
- listReceipts(options?: ListOptions): Promise<readonly CommerceReceipt[]>;
364
+ listReceipts(options?: ReceiptListOptions): Promise<readonly CommerceReceipt[]>;
351
365
  /**
352
366
  * Total receipts held. `listReceipts` clamps every page, so counting a list's
353
367
  * length would stop at the clamp.
@@ -364,8 +378,16 @@ interface ReceiptStore {
364
378
  * notice, because settlement is final and the gateway issues no refunds.
365
379
  */
366
380
  countUndeliveredReceipts(): Promise<number>;
381
+ /**
382
+ * Counts `settlement-uncertain` and legacy `failed` payment attempts.
383
+ * Funds may have moved, but the pipeline withholds delivery and writes no
384
+ * receipt for an uncertain settlement. {@link countUndeliveredReceipts}
385
+ * therefore misses these attempts. Reconcile them on chain using
386
+ * `externalReference` when it holds a transaction hash.
387
+ */
388
+ countUncertainPaymentAttempts(): Promise<number>;
367
389
  listEvents(options?: ListOptions): Promise<readonly CommerceEvent[]>;
368
- listPaymentAttempts(options?: ListOptions): Promise<readonly PaymentAttempt[]>;
390
+ listPaymentAttempts(options?: PaymentAttemptListOptions): Promise<readonly PaymentAttempt[]>;
369
391
  readonly descriptor: AdapterDescriptor;
370
392
  health(): Promise<AdapterHealth>;
371
393
  close(): Promise<void>;
@@ -718,4 +740,4 @@ interface SqliteReceiptStoreOptions {
718
740
  }
719
741
  declare function createSqliteReceiptStore(options: SqliteReceiptStoreOptions): ReceiptStore;
720
742
 
721
- export { A2A_AGENT_CARD_PATH, A2A_PROTOCOL_VERSION, A2A_SPEC_VERSION, type A2aAdapterOptions, ACP_API_VERSION, ACP_SPEC_VERSION, ACP_WELL_KNOWN_PATH, AUTHORIZATION_HEADER, AUTHORIZATION_INPUT_FIELD, type AcpAdapterOptions, AdapterDescriptor, AdapterHealth, AdapterHttpRoute, AuthorizationProvider, AuthorizationRequirement, AuthorizationSubmission, type BackendExecutor, BackendHandler, type BackendRequest, type BackendResponse, COMMERCE_ERROR_CODES, COMMERCE_ERROR_HTTP_STATUS, Clock, CommerceError, type CommerceErrorCode, type CommerceErrorInfo, type CommerceErrorOptions, CommerceEvent, CommerceReceipt, CommerceResource, DELIVERY_SUMMARY_META_KEY, DecimalAmount, DeliveredOutcome, type DeliverySummary, type ErrorEnvelope, ExecutionPipeline, type GatewayConfig, type GatewayInstance, type GatewayOptions, HttpProtocolAdapter, IdGenerator, IsoTimestamp, type ListOptions, Logger, MAX_AUTHORIZATION_HEADER_BYTES, PAYMENT_HEADER, PAYMENT_INPUT_FIELD, PAYMENT_REQUIRED_HEADER, PAYMENT_RESPONSE_HEADER, PaymentAttempt, type PaymentAttemptReservation, type PaymentAttemptUpdate, PaymentMethodName, PaymentProvider, type PaymentRequiredEnvelope, PaymentRequiredOutcome, PaymentSubmission, ProtocolAdapter, ProtocolAdapterContext, RESERVED_INPUT_FIELDS, RETRYABLE_ERROR_CODES, type ReceiptStore, ResourceRegistry, createA2aAdapter, createAcpAdapter, createGateway, createSqliteReceiptStore, extractReservedInputFields, isCommerceError, isPaymentRequiredEnvelope, loadConfig, parseAuthorizationHeader, parseAuthorizationSubmission, parseConfig, createSqliteReceiptStore as receipts, toCommerceError, toDeliverySummary, toErrorEnvelope, toPaymentRequiredEnvelope };
743
+ export { A2A_AGENT_CARD_PATH, A2A_PROTOCOL_VERSION, A2A_SPEC_VERSION, type A2aAdapterOptions, ACP_API_VERSION, ACP_SPEC_VERSION, ACP_WELL_KNOWN_PATH, AUTHORIZATION_HEADER, AUTHORIZATION_INPUT_FIELD, type AcpAdapterOptions, AdapterDescriptor, AdapterHealth, AdapterHttpRoute, AuthorizationProvider, AuthorizationRequirement, AuthorizationSubmission, type BackendExecutor, BackendHandler, type BackendRequest, type BackendResponse, COMMERCE_ERROR_CODES, COMMERCE_ERROR_HTTP_STATUS, Clock, CommerceError, type CommerceErrorCode, type CommerceErrorInfo, type CommerceErrorOptions, CommerceEvent, CommerceReceipt, CommerceResource, DELIVERY_SUMMARY_META_KEY, DecimalAmount, DeliveredOutcome, type DeliverySummary, type ErrorEnvelope, ExecutionPipeline, type GatewayConfig, type GatewayInstance, type GatewayOptions, HttpProtocolAdapter, IdGenerator, IsoTimestamp, type ListOptions, Logger, MAX_AUTHORIZATION_HEADER_BYTES, PAYMENT_HEADER, PAYMENT_INPUT_FIELD, PAYMENT_REQUIRED_HEADER, PAYMENT_RESPONSE_HEADER, PaymentAttempt, type PaymentAttemptListOptions, type PaymentAttemptReservation, type PaymentAttemptUpdate, PaymentMethodName, PaymentProvider, type PaymentRequiredEnvelope, PaymentRequiredOutcome, PaymentSubmission, ProtocolAdapter, ProtocolAdapterContext, RESERVED_INPUT_FIELDS, RETRYABLE_ERROR_CODES, type ReceiptListOptions, type ReceiptStore, ResourceRegistry, createA2aAdapter, createAcpAdapter, createGateway, createSqliteReceiptStore, extractReservedInputFields, isCommerceError, isPaymentRequiredEnvelope, loadConfig, parseAuthorizationHeader, parseAuthorizationSubmission, parseConfig, createSqliteReceiptStore as receipts, toCommerceError, toDeliverySummary, toErrorEnvelope, toPaymentRequiredEnvelope };
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
- import { openSqliteDatabase, AP2_SPEC_VERSION, AP2_MODES, AP2_DEFAULT_CLOCK_SKEW_SECONDS, AP2_JWK_MEMBERS, AP2_KEY_TYPE, AP2_SIGNING_ALGORITHM, AP2_JWK_CURVE, AP2_JWK_COORDINATE_BYTES, AP2_MAX_CLOCK_SKEW_SECONDS } from './chunk-IEW7NSP2.js';
1
+ import { openSqliteDatabase, AP2_SPEC_VERSION, AP2_MODES, AP2_DEFAULT_CLOCK_SKEW_SECONDS, AP2_JWK_MEMBERS, AP2_KEY_TYPE, AP2_SIGNING_ALGORITHM, AP2_JWK_CURVE, AP2_JWK_COORDINATE_BYTES, AP2_MAX_CLOCK_SKEW_SECONDS } from './chunk-4ZSE5DCH.js';
2
2
  import { readCappedBody, createBearerCheck, MCP_TOOL_NAME_PATTERN, settlementResponse, joinUrl, settlementResponseFromDetails, settlementFailure, x402ErrorCode, x402RefusalStatus } from './chunk-ES3V6ECS.js';
3
3
  import { MPP_DEFAULT_NETWORK, isMppNetwork, MPP_NETWORKS, MPP_DEFAULT_PAYMENT_FLOW, MPP_MIN_CHALLENGE_SECRET_LENGTH, MPP_PROFILE } from './chunk-6Z2H53CG.js';
4
4
  import { contentDigest, CONTENT_DIGEST_METADATA_KEY, mppProblem, mppProblemDetail } from './chunk-5ZYXBCDX.js';
5
- import { X402_PAYMENT_FLOWS, validateCustomNetworks, findX402Network, X402_DEFAULT_PAYMENT_FLOW, resolveX402Deployment, SETTLE_AFTER_BACKEND_METADATA_KEY, resolveDeploymentMode, requireX402Network, resolveX402Option, isEvmAddress, isEvmZeroAddress, x402OfferName, REUSE_REJECTED_AUTHORIZATION_METADATA_KEY } from './chunk-Y4RE3XYF.js';
6
- import { RESERVED_INPUT_FIELDS, PROTOCOL_NAMES, PAYMENT_METHOD_NAMES, PAYMENT_HEADER, AUTHORIZATION_HEADER, CommerceError, systemClock, NOOP_LOGGER, PACKAGE_VERSION, toCommerceError, DEFAULT_BACKEND_TIMEOUT_MS, isCommerceError, describeError, isHttpProtocolAdapter, toLogInfo, extractReservedInputFields, parseAuthorizationHeader, toPaymentRequiredEnvelope, PAYMENT_REQUIRED_HEADER, PAYMENT_RESPONSE_HEADER, toErrorEnvelope, DELIVERY_SUMMARY_META_KEY, toDeliverySummary, PAYMENT_INPUT_FIELD, AUTHORIZATION_INPUT_FIELD, parseAuthorizationSubmission } from './chunk-7ZMMXZ4G.js';
7
- export { AUTHORIZATION_HEADER, AUTHORIZATION_INPUT_FIELD, COMMERCE_ERROR_CODES, COMMERCE_ERROR_HTTP_STATUS, COMMERCE_EVENT_TYPES, CommerceError, DEFAULT_BACKEND_TIMEOUT_MS, DELIVERY_SUMMARY_META_KEY, MAX_AUTHORIZATION_HEADER_BYTES, NOOP_LOGGER, PAYMENT_HEADER, PAYMENT_INPUT_FIELD, PAYMENT_METHOD_NAMES, PAYMENT_REQUIRED_HEADER, PAYMENT_RESPONSE_HEADER, PROTOCOL_NAMES, RESERVED_INPUT_FIELDS, RETRYABLE_ERROR_CODES, extractReservedInputFields, isCommerceError, isHttpProtocolAdapter, isPaymentRequiredEnvelope, parseAuthorizationHeader, parseAuthorizationSubmission, systemClock, toCommerceError, toDeliverySummary, toErrorEnvelope, toPaymentRequiredEnvelope } from './chunk-7ZMMXZ4G.js';
5
+ import { X402_PAYMENT_FLOWS, validateCustomNetworks, findX402Network, X402_DEFAULT_PAYMENT_FLOW, resolveX402Deployment, SETTLE_AFTER_BACKEND_METADATA_KEY, resolveDeploymentMode, requireX402Network, resolveX402Option, isEvmAddress, isEvmZeroAddress, x402OfferName, REUSE_REJECTED_AUTHORIZATION_METADATA_KEY } from './chunk-XVU46YAH.js';
6
+ import { RESERVED_INPUT_FIELDS, PROTOCOL_NAMES, PAYMENT_METHOD_NAMES, PAYMENT_HEADER, AUTHORIZATION_HEADER, CommerceError, systemClock, NOOP_LOGGER, PACKAGE_VERSION, toCommerceError, DEFAULT_BACKEND_TIMEOUT_MS, isCommerceError, describeError, isHttpProtocolAdapter, toLogInfo, extractReservedInputFields, parseAuthorizationHeader, toPaymentRequiredEnvelope, PAYMENT_REQUIRED_HEADER, PAYMENT_RESPONSE_HEADER, toErrorEnvelope, DELIVERY_SUMMARY_META_KEY, toDeliverySummary, PAYMENT_INPUT_FIELD, AUTHORIZATION_INPUT_FIELD, parseAuthorizationSubmission } from './chunk-Q5TII32R.js';
7
+ export { AUTHORIZATION_HEADER, AUTHORIZATION_INPUT_FIELD, COMMERCE_ERROR_CODES, COMMERCE_ERROR_HTTP_STATUS, COMMERCE_EVENT_TYPES, CommerceError, DEFAULT_BACKEND_TIMEOUT_MS, DELIVERY_SUMMARY_META_KEY, MAX_AUTHORIZATION_HEADER_BYTES, NOOP_LOGGER, PAYMENT_HEADER, PAYMENT_INPUT_FIELD, PAYMENT_METHOD_NAMES, PAYMENT_REQUIRED_HEADER, PAYMENT_RESPONSE_HEADER, PROTOCOL_NAMES, RESERVED_INPUT_FIELDS, RETRYABLE_ERROR_CODES, extractReservedInputFields, isCommerceError, isHttpProtocolAdapter, isPaymentRequiredEnvelope, parseAuthorizationHeader, parseAuthorizationSubmission, systemClock, toCommerceError, toDeliverySummary, toErrorEnvelope, toPaymentRequiredEnvelope } from './chunk-Q5TII32R.js';
8
8
  import { isRecord } from './chunk-2CJNA7MS.js';
9
9
  import { promises, accessSync, constants } from 'fs';
10
10
  import * as path from 'path';
@@ -678,7 +678,9 @@ function normalizeX402(raw, resources) {
678
678
  facilitator,
679
679
  ...allowMainnet !== void 0 ? { allowMainnet } : {},
680
680
  ...allowUnauthenticatedFacilitator !== void 0 ? { allowUnauthenticatedFacilitator } : {},
681
- ...networks !== void 0 ? { customNetworks: networks } : {}
681
+ ...networks !== void 0 ? { customNetworks: networks } : {},
682
+ // resolveX402Option required the token's own metadata
683
+ allowOtherEvmToken: true
682
684
  });
683
685
  if (firstMode !== void 0 && mode !== firstMode) {
684
686
  throw x402Invalid(
@@ -830,8 +832,8 @@ var MerchantSchema = z.object({
830
832
  var ServerSchema = z.object({
831
833
  port: NumberOrString,
832
834
  host: z.string().min(1),
833
- // Shared secret gating /api/receipts and /api/events. Without it both
834
- // routes 404.
835
+ // Required for /api/receipts, /api/events and /api/payment-attempts;
836
+ // these routes return 404 when the token is unset
835
837
  adminToken: z.string().min(1).optional(),
836
838
  // Browser origins allowed to call the gateway; none by default. A request
837
839
  // with any other `Origin` gets 403 on every route. Entries match the
@@ -863,7 +865,8 @@ var RESERVED_GATEWAY_PATHS = [
863
865
  "/api/resources",
864
866
  "/api/resources/:id/invoke",
865
867
  "/api/receipts",
866
- "/api/events"
868
+ "/api/events",
869
+ "/api/payment-attempts"
867
870
  ];
868
871
  var MountPathSchema = z.string().min(1).refine((value) => value.startsWith("/"), {
869
872
  message: 'must start with "/" - it is an absolute gateway path, e.g. "/mcp".'
@@ -3738,13 +3741,28 @@ function registerRoutes(options) {
3738
3741
  server.get(
3739
3742
  "/api/receipts",
3740
3743
  { onRequest: tokenHook },
3741
- ledgerHandler("receipts", (list) => options.store.listReceipts(list))
3744
+ ledgerHandler(
3745
+ "receipts",
3746
+ (list, query) => options.store.listReceipts(
3747
+ parseFlag(query["undelivered"], "undelivered") ? { ...list, undelivered: true } : list
3748
+ )
3749
+ )
3742
3750
  );
3743
3751
  server.get(
3744
3752
  "/api/events",
3745
3753
  { onRequest: tokenHook },
3746
3754
  ledgerHandler("events", (list) => options.store.listEvents(list))
3747
3755
  );
3756
+ server.get(
3757
+ "/api/payment-attempts",
3758
+ { onRequest: tokenHook },
3759
+ ledgerHandler(
3760
+ "paymentAttempts",
3761
+ (list, query) => options.store.listPaymentAttempts(
3762
+ parseFlag(query["uncertain"], "uncertain") ? { ...list, uncertain: true } : list
3763
+ )
3764
+ )
3765
+ );
3748
3766
  }
3749
3767
  var bodyDigests = /* @__PURE__ */ new WeakMap();
3750
3768
  function digestingStream(request) {
@@ -3763,8 +3781,10 @@ function digestingStream(request) {
3763
3781
  function ledgerHandler(key, list) {
3764
3782
  return async (request, reply) => {
3765
3783
  try {
3766
- const limit = parseLimit(request.query["limit"]);
3767
- return { [key]: await list(limit !== void 0 ? { limit } : {}) };
3784
+ const query = request.query;
3785
+ const limit = parseLimit(query["limit"]);
3786
+ const page = await list(limit !== void 0 ? { limit } : {}, query);
3787
+ return { [key]: page };
3768
3788
  } catch (error) {
3769
3789
  const commerceError = toCommerceError(error);
3770
3790
  reply.status(commerceError.httpStatus).send(toErrorEnvelope(commerceError));
@@ -3952,6 +3972,14 @@ function parseLimit(value) {
3952
3972
  }
3953
3973
  return n;
3954
3974
  }
3975
+ function parseFlag(value, field) {
3976
+ if (Array.isArray(value)) return parseFlag(value[0], field);
3977
+ if (value === void 0 || value === "false") return false;
3978
+ if (value === "true") return true;
3979
+ throw new CommerceError("INPUT_INVALID", `Query parameter "${field}" must be true or false`, {
3980
+ details: { field }
3981
+ });
3982
+ }
3955
3983
 
3956
3984
  // src/gateway/server.ts
3957
3985
  var REQUEST_ID_HEADER = "x-request-id";
@@ -10442,6 +10470,8 @@ function clampListLimit(limit) {
10442
10470
  const base = limit !== void 0 && Number.isFinite(limit) ? limit : DEFAULT_LIST_LIMIT;
10443
10471
  return Math.min(Math.max(Math.trunc(base), 1), MAX_LIST_LIMIT);
10444
10472
  }
10473
+ var UNDELIVERED = "backend_status NOT BETWEEN 200 AND 299";
10474
+ var UNCERTAIN = "status IN ('settlement-uncertain', 'failed')";
10445
10475
  var defaultIds = {
10446
10476
  next: (prefix) => prefix !== void 0 ? `${prefix}_${randomUUID()}` : randomUUID()
10447
10477
  };
@@ -10467,11 +10497,17 @@ function createSqliteReceiptStore(options) {
10467
10497
  const listReceiptsByRequestStmt = db.prepare(
10468
10498
  "SELECT * FROM receipts WHERE request_id = ? ORDER BY delivered_at DESC, seq DESC LIMIT ?"
10469
10499
  );
10500
+ const listUndeliveredReceiptsStmt = db.prepare(
10501
+ `SELECT * FROM receipts WHERE ${UNDELIVERED} ORDER BY delivered_at DESC, seq DESC LIMIT ?`
10502
+ );
10503
+ const listUndeliveredReceiptsByRequestStmt = db.prepare(
10504
+ `SELECT * FROM receipts WHERE request_id = ? AND ${UNDELIVERED} ORDER BY delivered_at DESC, seq DESC LIMIT ?`
10505
+ );
10470
10506
  const countReceiptsStmt = db.prepare(
10471
10507
  "SELECT COUNT(*) AS count FROM receipts"
10472
10508
  );
10473
10509
  const countUndeliveredReceiptsStmt = db.prepare(
10474
- "SELECT COUNT(*) AS count FROM receipts WHERE backend_status NOT BETWEEN 200 AND 299"
10510
+ `SELECT COUNT(*) AS count FROM receipts WHERE ${UNDELIVERED}`
10475
10511
  );
10476
10512
  const insertEventStmt = db.prepare(
10477
10513
  `INSERT INTO events (id, type, request_id, resource_id, at, adapter, payment_provider, duration_ms, status, data_json)
@@ -10515,6 +10551,15 @@ function createSqliteReceiptStore(options) {
10515
10551
  const listPaymentAttemptsByRequestStmt = db.prepare(
10516
10552
  "SELECT * FROM payment_attempts WHERE request_id = ? ORDER BY created_at DESC, seq DESC LIMIT ?"
10517
10553
  );
10554
+ const listUncertainPaymentAttemptsStmt = db.prepare(
10555
+ `SELECT * FROM payment_attempts WHERE ${UNCERTAIN} ORDER BY created_at DESC, seq DESC LIMIT ?`
10556
+ );
10557
+ const listUncertainPaymentAttemptsByRequestStmt = db.prepare(
10558
+ `SELECT * FROM payment_attempts WHERE request_id = ? AND ${UNCERTAIN} ORDER BY created_at DESC, seq DESC LIMIT ?`
10559
+ );
10560
+ const countUncertainPaymentAttemptsStmt = db.prepare(
10561
+ `SELECT COUNT(*) AS count FROM payment_attempts WHERE ${UNCERTAIN}`
10562
+ );
10518
10563
  const paymentAttemptStatusStmt = db.prepare(
10519
10564
  "SELECT status FROM payment_attempts WHERE replay_key = ?"
10520
10565
  );
@@ -10630,7 +10675,11 @@ function createSqliteReceiptStore(options) {
10630
10675
  },
10631
10676
  async listReceipts(listOptions = {}) {
10632
10677
  const limit = clampListLimit(listOptions.limit);
10633
- const rows = listOptions.requestId !== void 0 ? listReceiptsByRequestStmt.all(listOptions.requestId, limit) : listReceiptsStmt.all(limit);
10678
+ const undelivered = listOptions.undelivered === true;
10679
+ const rows = listOptions.requestId !== void 0 ? (undelivered ? listUndeliveredReceiptsByRequestStmt : listReceiptsByRequestStmt).all(
10680
+ listOptions.requestId,
10681
+ limit
10682
+ ) : (undelivered ? listUndeliveredReceiptsStmt : listReceiptsStmt).all(limit);
10634
10683
  return rows.map(rowToReceipt);
10635
10684
  },
10636
10685
  // Exact total, not bounded by the listReceipts clamp (see ReceiptStore.countReceipts)
@@ -10641,6 +10690,9 @@ function createSqliteReceiptStore(options) {
10641
10690
  async countUndeliveredReceipts() {
10642
10691
  return countUndeliveredReceiptsStmt.get()?.count ?? 0;
10643
10692
  },
10693
+ async countUncertainPaymentAttempts() {
10694
+ return countUncertainPaymentAttemptsStmt.get()?.count ?? 0;
10695
+ },
10644
10696
  async listEvents(listOptions = {}) {
10645
10697
  const limit = clampListLimit(listOptions.limit);
10646
10698
  const rows = listOptions.requestId !== void 0 ? listEventsByRequestStmt.all(listOptions.requestId, limit) : listEventsStmt.all(limit);
@@ -10648,7 +10700,8 @@ function createSqliteReceiptStore(options) {
10648
10700
  },
10649
10701
  async listPaymentAttempts(listOptions = {}) {
10650
10702
  const limit = clampListLimit(listOptions.limit);
10651
- const rows = listOptions.requestId !== void 0 ? listPaymentAttemptsByRequestStmt.all(listOptions.requestId, limit) : listPaymentAttemptsStmt.all(limit);
10703
+ const uncertain = listOptions.uncertain === true;
10704
+ const rows = listOptions.requestId !== void 0 ? (uncertain ? listUncertainPaymentAttemptsByRequestStmt : listPaymentAttemptsByRequestStmt).all(listOptions.requestId, limit) : (uncertain ? listUncertainPaymentAttemptsStmt : listPaymentAttemptsStmt).all(limit);
10652
10705
  return rows.map(rowToPaymentAttempt);
10653
10706
  },
10654
10707
  descriptor,