mppx 0.6.31 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/README.md +20 -11
- package/dist/Challenge.d.ts.map +1 -1
- package/dist/Challenge.js +27 -13
- package/dist/Challenge.js.map +1 -1
- package/dist/Constants.d.ts +46 -0
- package/dist/Constants.d.ts.map +1 -0
- package/dist/Constants.js +46 -0
- package/dist/Constants.js.map +1 -0
- package/dist/Credential.d.ts.map +1 -1
- package/dist/Credential.js +5 -4
- package/dist/Credential.js.map +1 -1
- package/dist/Mcp.d.ts +3 -0
- package/dist/Mcp.d.ts.map +1 -1
- package/dist/Mcp.js +2 -0
- package/dist/Mcp.js.map +1 -1
- package/dist/Method.d.ts +32 -4
- package/dist/Method.d.ts.map +1 -1
- package/dist/Method.js +5 -2
- package/dist/Method.js.map +1 -1
- package/dist/PaymentRequest.d.ts +10 -10
- package/dist/PaymentRequest.js +8 -8
- package/dist/Receipt.d.ts.map +1 -1
- package/dist/Receipt.js +3 -2
- package/dist/Receipt.js.map +1 -1
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +19 -11
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/plugins/tempo.d.ts.map +1 -1
- package/dist/cli/plugins/tempo.js +17 -6
- package/dist/cli/plugins/tempo.js.map +1 -1
- package/dist/cli/utils.d.ts +5 -0
- package/dist/cli/utils.d.ts.map +1 -1
- package/dist/cli/utils.js +10 -0
- package/dist/cli/utils.js.map +1 -1
- package/dist/client/Methods.d.ts +5 -2
- package/dist/client/Methods.d.ts.map +1 -1
- package/dist/client/Methods.js +5 -2
- package/dist/client/Methods.js.map +1 -1
- package/dist/client/Mppx.js +2 -2
- package/dist/client/Mppx.js.map +1 -1
- package/dist/client/Transport.d.ts +11 -16
- package/dist/client/Transport.d.ts.map +1 -1
- package/dist/client/Transport.js +55 -76
- package/dist/client/Transport.js.map +1 -1
- package/dist/client/index.d.ts +5 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +3 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal/Fetch.d.ts.map +1 -1
- package/dist/client/internal/Fetch.js +60 -13
- package/dist/client/internal/Fetch.js.map +1 -1
- package/dist/client/internal/protocols/Mcp.d.ts +7 -0
- package/dist/client/internal/protocols/Mcp.d.ts.map +1 -0
- package/dist/client/internal/protocols/Mcp.js +159 -0
- package/dist/client/internal/protocols/Mcp.js.map +1 -0
- package/dist/client/internal/protocols/Mpp.d.ts +4 -0
- package/dist/client/internal/protocols/Mpp.d.ts.map +1 -0
- package/dist/client/internal/protocols/Mpp.js +18 -0
- package/dist/client/internal/protocols/Mpp.js.map +1 -0
- package/dist/client/internal/protocols/Protocol.d.ts +10 -0
- package/dist/client/internal/protocols/Protocol.d.ts.map +1 -0
- package/dist/client/internal/protocols/Protocol.js +2 -0
- package/dist/client/internal/protocols/Protocol.js.map +1 -0
- package/dist/client/internal/protocols/Shared.d.ts +5 -0
- package/dist/client/internal/protocols/Shared.d.ts.map +1 -0
- package/dist/client/internal/protocols/Shared.js +20 -0
- package/dist/client/internal/protocols/Shared.js.map +1 -0
- package/dist/client/internal/protocols/X402.d.ts +8 -0
- package/dist/client/internal/protocols/X402.d.ts.map +1 -0
- package/dist/client/internal/protocols/X402.js +39 -0
- package/dist/client/internal/protocols/X402.js.map +1 -0
- package/dist/evm/client/index.d.ts +1 -0
- package/dist/evm/client/index.d.ts.map +1 -1
- package/dist/evm/client/index.js +1 -0
- package/dist/evm/client/index.js.map +1 -1
- package/dist/evm/index.d.ts +2 -0
- package/dist/evm/index.d.ts.map +1 -1
- package/dist/evm/index.js +2 -0
- package/dist/evm/index.js.map +1 -1
- package/dist/evm/server/Methods.d.ts +1 -1
- package/dist/evm/server/Methods.d.ts.map +1 -1
- package/dist/evm/server/index.d.ts +1 -0
- package/dist/evm/server/index.d.ts.map +1 -1
- package/dist/evm/server/index.js +1 -0
- package/dist/evm/server/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/AcceptPayment.d.ts +3 -0
- package/dist/internal/AcceptPayment.d.ts.map +1 -1
- package/dist/internal/AcceptPayment.js +15 -11
- package/dist/internal/AcceptPayment.js.map +1 -1
- package/dist/mcp/client/McpClient.d.ts +101 -0
- package/dist/mcp/client/McpClient.d.ts.map +1 -0
- package/dist/mcp/client/McpClient.js +162 -0
- package/dist/mcp/client/McpClient.js.map +1 -0
- package/dist/mcp/client/index.d.ts.map +1 -0
- package/dist/mcp/client/index.js.map +1 -0
- package/dist/mcp/server/Transport.d.ts.map +1 -0
- package/dist/mcp/server/Transport.js.map +1 -0
- package/dist/mcp/server/index.d.ts.map +1 -0
- package/dist/mcp/server/index.js.map +1 -0
- package/dist/server/Mppx.d.ts +12 -4
- package/dist/server/Mppx.d.ts.map +1 -1
- package/dist/server/Mppx.js +85 -27
- package/dist/server/Mppx.js.map +1 -1
- package/dist/server/Response.d.ts.map +1 -1
- package/dist/server/Response.js +2 -1
- package/dist/server/Response.js.map +1 -1
- package/dist/server/Transport.d.ts +1 -1
- package/dist/server/Transport.d.ts.map +1 -1
- package/dist/server/Transport.js +5 -4
- package/dist/server/Transport.js.map +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -0
- package/dist/server/index.js.map +1 -1
- package/dist/stripe/client/Charge.d.ts +1 -1
- package/dist/stripe/client/Charge.d.ts.map +1 -1
- package/dist/stripe/client/Charge.js +3 -1
- package/dist/stripe/client/Charge.js.map +1 -1
- package/dist/stripe/server/Charge.d.ts +1 -1
- package/dist/stripe/server/Charge.d.ts.map +1 -1
- package/dist/stripe/server/Charge.js +9 -2
- package/dist/stripe/server/Charge.js.map +1 -1
- package/dist/stripe/server/Methods.d.ts +1 -1
- package/dist/stripe/server/Methods.d.ts.map +1 -1
- package/dist/stripe/server/internal/html.gen.d.ts +1 -1
- package/dist/stripe/server/internal/html.gen.d.ts.map +1 -1
- package/dist/stripe/server/internal/html.gen.js +1 -1
- package/dist/stripe/server/internal/html.gen.js.map +1 -1
- package/dist/tempo/Methods.d.ts +18 -0
- package/dist/tempo/Methods.d.ts.map +1 -1
- package/dist/tempo/Methods.js +16 -1
- package/dist/tempo/Methods.js.map +1 -1
- package/dist/tempo/Proof.d.ts +85 -1
- package/dist/tempo/Proof.d.ts.map +1 -1
- package/dist/tempo/Proof.js +35 -0
- package/dist/tempo/Proof.js.map +1 -1
- package/dist/tempo/client/Charge.d.ts +19 -1
- package/dist/tempo/client/Charge.d.ts.map +1 -1
- package/dist/tempo/client/Charge.js +47 -27
- package/dist/tempo/client/Charge.js.map +1 -1
- package/dist/tempo/client/Methods.d.ts +41 -10
- package/dist/tempo/client/Methods.d.ts.map +1 -1
- package/dist/tempo/client/Methods.js +16 -7
- package/dist/tempo/client/Methods.js.map +1 -1
- package/dist/tempo/client/ResolveAccount.d.ts +40 -0
- package/dist/tempo/client/ResolveAccount.d.ts.map +1 -0
- package/dist/tempo/client/ResolveAccount.js +2 -0
- package/dist/tempo/client/ResolveAccount.js.map +1 -0
- package/dist/tempo/client/index.d.ts +7 -4
- package/dist/tempo/client/index.d.ts.map +1 -1
- package/dist/tempo/client/index.js +5 -3
- package/dist/tempo/client/index.js.map +1 -1
- package/dist/tempo/index.d.ts +1 -0
- package/dist/tempo/index.d.ts.map +1 -1
- package/dist/tempo/index.js +1 -0
- package/dist/tempo/index.js.map +1 -1
- package/dist/tempo/internal/fee-payer.d.ts +29 -1
- package/dist/tempo/internal/fee-payer.d.ts.map +1 -1
- package/dist/tempo/internal/fee-payer.js +138 -4
- package/dist/tempo/internal/fee-payer.js.map +1 -1
- package/dist/tempo/internal/proof.d.ts +71 -5
- package/dist/tempo/internal/proof.d.ts.map +1 -1
- package/dist/tempo/internal/proof.js +42 -6
- package/dist/tempo/internal/proof.js.map +1 -1
- package/dist/tempo/{client → legacy/client}/ChannelOps.d.ts +19 -6
- package/dist/tempo/legacy/client/ChannelOps.d.ts.map +1 -0
- package/dist/tempo/{client → legacy/client}/ChannelOps.js +9 -3
- package/dist/tempo/legacy/client/ChannelOps.js.map +1 -0
- package/dist/tempo/{client → legacy/client}/Session.d.ts +23 -4
- package/dist/tempo/legacy/client/Session.d.ts.map +1 -0
- package/dist/tempo/{client → legacy/client}/Session.js +14 -7
- package/dist/tempo/legacy/client/Session.js.map +1 -0
- package/dist/tempo/{client → legacy/client}/SessionManager.d.ts +20 -5
- package/dist/tempo/legacy/client/SessionManager.d.ts.map +1 -0
- package/dist/tempo/{client → legacy/client}/SessionManager.js +30 -19
- package/dist/tempo/legacy/client/SessionManager.js.map +1 -0
- package/dist/tempo/legacy/client/index.d.ts +7 -0
- package/dist/tempo/legacy/client/index.d.ts.map +1 -0
- package/dist/tempo/legacy/client/index.js +5 -0
- package/dist/tempo/legacy/client/index.js.map +1 -0
- package/dist/tempo/legacy/index.d.ts +7 -0
- package/dist/tempo/legacy/index.d.ts.map +1 -0
- package/dist/tempo/legacy/index.js +7 -0
- package/dist/tempo/legacy/index.js.map +1 -0
- package/dist/tempo/{server → legacy/server}/Session.d.ts +28 -11
- package/dist/tempo/legacy/server/Session.d.ts.map +1 -0
- package/dist/tempo/{server → legacy/server}/Session.js +12 -10
- package/dist/tempo/legacy/server/Session.js.map +1 -0
- package/dist/tempo/legacy/server/index.d.ts +5 -0
- package/dist/tempo/legacy/server/index.d.ts.map +1 -0
- package/dist/tempo/legacy/server/index.js +5 -0
- package/dist/tempo/legacy/server/index.js.map +1 -0
- package/dist/tempo/{session → legacy/session}/Chain.d.ts +30 -23
- package/dist/tempo/legacy/session/Chain.d.ts.map +1 -0
- package/dist/tempo/{session → legacy/session}/Chain.js +12 -11
- package/dist/tempo/legacy/session/Chain.js.map +1 -0
- package/dist/tempo/{session → legacy/session}/Channel.d.ts +1 -0
- package/dist/tempo/legacy/session/Channel.d.ts.map +1 -0
- package/dist/tempo/legacy/session/Channel.js.map +1 -0
- package/dist/tempo/legacy/session/ChannelStore.d.ts +22 -0
- package/dist/tempo/legacy/session/ChannelStore.d.ts.map +1 -0
- package/dist/tempo/legacy/session/ChannelStore.js +6 -0
- package/dist/tempo/legacy/session/ChannelStore.js.map +1 -0
- package/dist/tempo/legacy/session/Types.d.ts +73 -0
- package/dist/tempo/legacy/session/Types.d.ts.map +1 -0
- package/dist/tempo/legacy/session/Types.js.map +1 -0
- package/dist/tempo/{session → legacy/session}/Voucher.d.ts +4 -4
- package/dist/tempo/legacy/session/Voucher.d.ts.map +1 -0
- package/dist/tempo/{session → legacy/session}/Voucher.js +1 -1
- package/dist/tempo/legacy/session/Voucher.js.map +1 -0
- package/dist/tempo/{session → legacy/session}/escrow.abi.d.ts +1 -0
- package/dist/tempo/{session → legacy/session}/escrow.abi.d.ts.map +1 -1
- package/dist/tempo/{session → legacy/session}/escrow.abi.js +1 -0
- package/dist/tempo/legacy/session/escrow.abi.js.map +1 -0
- package/dist/tempo/legacy/session/index.d.ts +9 -0
- package/dist/tempo/legacy/session/index.d.ts.map +1 -0
- package/dist/tempo/legacy/session/index.js +9 -0
- package/dist/tempo/legacy/session/index.js.map +1 -0
- package/dist/tempo/server/Charge.d.ts +1 -1
- package/dist/tempo/server/Charge.d.ts.map +1 -1
- package/dist/tempo/server/Charge.js +51 -30
- package/dist/tempo/server/Charge.js.map +1 -1
- package/dist/tempo/server/Methods.d.ts +67 -8
- package/dist/tempo/server/Methods.d.ts.map +1 -1
- package/dist/tempo/server/Methods.js +40 -10
- package/dist/tempo/server/Methods.js.map +1 -1
- package/dist/tempo/server/Subscription.d.ts +11 -1
- package/dist/tempo/server/Subscription.d.ts.map +1 -1
- package/dist/tempo/server/Subscription.js +135 -23
- package/dist/tempo/server/Subscription.js.map +1 -1
- package/dist/tempo/server/index.d.ts +6 -5
- package/dist/tempo/server/index.d.ts.map +1 -1
- package/dist/tempo/server/index.js +5 -5
- package/dist/tempo/server/index.js.map +1 -1
- package/dist/tempo/server/internal/html.gen.d.ts +1 -1
- package/dist/tempo/server/internal/html.gen.d.ts.map +1 -1
- package/dist/tempo/server/internal/html.gen.js +1 -1
- package/dist/tempo/server/internal/html.gen.js.map +1 -1
- package/dist/tempo/server/internal/request-body.d.ts +7 -2
- package/dist/tempo/server/internal/request-body.d.ts.map +1 -1
- package/dist/tempo/server/internal/request-body.js +20 -3
- package/dist/tempo/server/internal/request-body.js.map +1 -1
- package/dist/tempo/server/internal/transport.d.ts +8 -4
- package/dist/tempo/server/internal/transport.d.ts.map +1 -1
- package/dist/tempo/server/internal/transport.js +8 -7
- package/dist/tempo/server/internal/transport.js.map +1 -1
- package/dist/tempo/session/Snapshot.d.ts +32 -0
- package/dist/tempo/session/Snapshot.d.ts.map +1 -0
- package/dist/tempo/session/Snapshot.js +37 -0
- package/dist/tempo/session/Snapshot.js.map +1 -0
- package/dist/tempo/session/client/ChannelOps.d.ts +81 -0
- package/dist/tempo/session/client/ChannelOps.d.ts.map +1 -0
- package/dist/tempo/session/client/ChannelOps.js +201 -0
- package/dist/tempo/session/client/ChannelOps.js.map +1 -0
- package/dist/tempo/session/client/ChannelStore.d.ts +51 -0
- package/dist/tempo/session/client/ChannelStore.d.ts.map +1 -0
- package/dist/tempo/session/client/ChannelStore.js +63 -0
- package/dist/tempo/session/client/ChannelStore.js.map +1 -0
- package/dist/tempo/session/client/CredentialState.d.ts +245 -0
- package/dist/tempo/session/client/CredentialState.d.ts.map +1 -0
- package/dist/tempo/session/client/CredentialState.js +419 -0
- package/dist/tempo/session/client/CredentialState.js.map +1 -0
- package/dist/tempo/session/client/ReceiptCoordinator.d.ts +26 -0
- package/dist/tempo/session/client/ReceiptCoordinator.d.ts.map +1 -0
- package/dist/tempo/session/client/ReceiptCoordinator.js +61 -0
- package/dist/tempo/session/client/ReceiptCoordinator.js.map +1 -0
- package/dist/tempo/session/client/Runtime.d.ts +464 -0
- package/dist/tempo/session/client/Runtime.d.ts.map +1 -0
- package/dist/tempo/session/client/Runtime.js +499 -0
- package/dist/tempo/session/client/Runtime.js.map +1 -0
- package/dist/tempo/session/client/Session.d.ts +138 -0
- package/dist/tempo/session/client/Session.d.ts.map +1 -0
- package/dist/tempo/session/client/Session.js +69 -0
- package/dist/tempo/session/client/Session.js.map +1 -0
- package/dist/tempo/session/client/SessionManager.d.ts +84 -0
- package/dist/tempo/session/client/SessionManager.d.ts.map +1 -0
- package/dist/tempo/session/client/SessionManager.js +577 -0
- package/dist/tempo/session/client/SessionManager.js.map +1 -0
- package/dist/tempo/session/client/Transports.d.ts +449 -0
- package/dist/tempo/session/client/Transports.d.ts.map +1 -0
- package/dist/tempo/session/client/Transports.js +721 -0
- package/dist/tempo/session/client/Transports.js.map +1 -0
- package/dist/tempo/session/client/index.d.ts +11 -0
- package/dist/tempo/session/client/index.d.ts.map +1 -0
- package/dist/tempo/session/client/index.js +6 -0
- package/dist/tempo/session/client/index.js.map +1 -0
- package/dist/tempo/session/index.d.ts +7 -8
- package/dist/tempo/session/index.d.ts.map +1 -1
- package/dist/tempo/session/index.js +7 -8
- package/dist/tempo/session/index.js.map +1 -1
- package/dist/tempo/session/precompile/Chain.d.ts +319 -0
- package/dist/tempo/session/precompile/Chain.d.ts.map +1 -0
- package/dist/tempo/session/precompile/Chain.js +492 -0
- package/dist/tempo/session/precompile/Chain.js.map +1 -0
- package/dist/tempo/session/precompile/Channel.d.ts +46 -0
- package/dist/tempo/session/precompile/Channel.d.ts.map +1 -0
- package/dist/tempo/session/precompile/Channel.js +56 -0
- package/dist/tempo/session/precompile/Channel.js.map +1 -0
- package/dist/tempo/session/precompile/Protocol.d.ts +308 -0
- package/dist/tempo/session/precompile/Protocol.d.ts.map +1 -0
- package/dist/tempo/session/precompile/Protocol.js +264 -0
- package/dist/tempo/session/precompile/Protocol.js.map +1 -0
- package/dist/tempo/session/precompile/Voucher.d.ts +40 -0
- package/dist/tempo/session/precompile/Voucher.d.ts.map +1 -0
- package/dist/tempo/session/precompile/Voucher.js +125 -0
- package/dist/tempo/session/precompile/Voucher.js.map +1 -0
- package/dist/tempo/session/precompile/escrow.abi.d.ts +522 -0
- package/dist/tempo/session/precompile/escrow.abi.d.ts.map +1 -0
- package/dist/tempo/session/precompile/escrow.abi.js +224 -0
- package/dist/tempo/session/precompile/escrow.abi.js.map +1 -0
- package/dist/tempo/session/precompile/index.d.ts +24 -0
- package/dist/tempo/session/precompile/index.d.ts.map +1 -0
- package/dist/tempo/session/precompile/index.js +22 -0
- package/dist/tempo/session/precompile/index.js.map +1 -0
- package/dist/tempo/session/server/ChannelOps.d.ts +56 -0
- package/dist/tempo/session/server/ChannelOps.d.ts.map +1 -0
- package/dist/tempo/session/server/ChannelOps.js +91 -0
- package/dist/tempo/session/server/ChannelOps.js.map +1 -0
- package/dist/tempo/session/server/ChannelStore.d.ts +347 -0
- package/dist/tempo/session/server/ChannelStore.d.ts.map +1 -0
- package/dist/tempo/session/server/ChannelStore.js +404 -0
- package/dist/tempo/session/server/ChannelStore.js.map +1 -0
- package/dist/tempo/session/server/CredentialVerification.d.ts +85 -0
- package/dist/tempo/session/server/CredentialVerification.d.ts.map +1 -0
- package/dist/tempo/session/server/CredentialVerification.js +494 -0
- package/dist/tempo/session/server/CredentialVerification.js.map +1 -0
- package/dist/tempo/session/server/MeteredStream.d.ts +40 -0
- package/dist/tempo/session/server/MeteredStream.d.ts.map +1 -0
- package/dist/tempo/session/server/MeteredStream.js +42 -0
- package/dist/tempo/session/server/MeteredStream.js.map +1 -0
- package/dist/tempo/session/server/RequestState.d.ts +208 -0
- package/dist/tempo/session/server/RequestState.d.ts.map +1 -0
- package/dist/tempo/session/server/RequestState.js +252 -0
- package/dist/tempo/session/server/RequestState.js.map +1 -0
- package/dist/tempo/session/server/Session.d.ts +169 -0
- package/dist/tempo/session/server/Session.d.ts.map +1 -0
- package/dist/tempo/session/server/Session.js +351 -0
- package/dist/tempo/session/server/Session.js.map +1 -0
- package/dist/tempo/session/server/Settlement.d.ts +185 -0
- package/dist/tempo/session/server/Settlement.d.ts.map +1 -0
- package/dist/tempo/session/server/Settlement.js +252 -0
- package/dist/tempo/session/server/Settlement.js.map +1 -0
- package/dist/tempo/session/{Sse.d.ts → server/Sse.d.ts} +9 -56
- package/dist/tempo/session/server/Sse.d.ts.map +1 -0
- package/dist/tempo/session/server/Sse.js +184 -0
- package/dist/tempo/session/server/Sse.js.map +1 -0
- package/dist/tempo/session/server/Transports.d.ts +89 -0
- package/dist/tempo/session/server/Transports.d.ts.map +1 -0
- package/dist/tempo/session/server/Transports.js +149 -0
- package/dist/tempo/session/server/Transports.js.map +1 -0
- package/dist/tempo/session/server/Ws.d.ts +48 -0
- package/dist/tempo/session/server/Ws.d.ts.map +1 -0
- package/dist/tempo/session/server/Ws.js +244 -0
- package/dist/tempo/session/server/Ws.js.map +1 -0
- package/dist/tempo/session/server/index.d.ts +4 -0
- package/dist/tempo/session/server/index.d.ts.map +1 -0
- package/dist/tempo/session/server/index.js +2 -0
- package/dist/tempo/session/server/index.js.map +1 -0
- package/dist/tempo/subscription/KeyAuthorization.d.ts +712 -1
- package/dist/tempo/subscription/KeyAuthorization.d.ts.map +1 -1
- package/dist/tempo/subscription/Store.d.ts +2 -0
- package/dist/tempo/subscription/Store.d.ts.map +1 -1
- package/dist/tempo/subscription/Store.js +16 -1
- package/dist/tempo/subscription/Store.js.map +1 -1
- package/dist/x402/index.d.ts +1 -0
- package/dist/x402/index.d.ts.map +1 -1
- package/dist/x402/index.js +1 -0
- package/dist/x402/index.js.map +1 -1
- package/package.json +25 -9
- package/src/Challenge.test.ts +40 -0
- package/src/Challenge.ts +28 -13
- package/src/Constants.ts +58 -0
- package/src/Credential.ts +5 -4
- package/src/Mcp.ts +4 -0
- package/src/Method.ts +46 -5
- package/src/PaymentRequest.ts +10 -10
- package/src/Receipt.ts +3 -2
- package/src/cli/cli.test.ts +38 -43
- package/src/cli/cli.ts +23 -10
- package/src/cli/mcp.test.ts +21 -7
- package/src/cli/plugins/tempo.ts +21 -8
- package/src/cli/utils.test.ts +25 -1
- package/src/cli/utils.ts +10 -0
- package/src/client/Methods.ts +5 -2
- package/src/client/Mppx.test-d.ts +31 -1
- package/src/client/Mppx.test.ts +76 -1
- package/src/client/Mppx.ts +2 -2
- package/src/client/Transport.test.ts +225 -178
- package/src/client/Transport.ts +77 -84
- package/src/client/index.ts +25 -1
- package/src/client/internal/Fetch.test.ts +236 -6
- package/src/client/internal/Fetch.ts +69 -11
- package/src/client/internal/protocols/Mcp.test.ts +220 -0
- package/src/client/internal/protocols/Mcp.ts +162 -0
- package/src/client/internal/protocols/Mpp.ts +21 -0
- package/src/client/internal/protocols/Protocol.ts +10 -0
- package/src/client/internal/protocols/Shared.ts +25 -0
- package/src/client/internal/protocols/X402.ts +42 -0
- package/src/discovery/OpenApi.test.ts +1 -1
- package/src/env.d.ts +1 -1
- package/src/evm/PublicInterface.test-d.ts +1 -1
- package/src/evm/client/index.ts +1 -0
- package/src/evm/index.ts +2 -0
- package/src/evm/server/Charge.test.ts +1 -1
- package/src/evm/server/index.ts +1 -0
- package/src/index.ts +1 -0
- package/src/internal/AcceptPayment.test.ts +61 -0
- package/src/internal/AcceptPayment.ts +21 -14
- package/src/{mcp-sdk → mcp}/client/McpClient.integration.test.ts +18 -11
- package/src/{mcp-sdk → mcp}/client/McpClient.test-d.ts +45 -11
- package/src/{mcp-sdk → mcp}/client/McpClient.test.ts +211 -5
- package/src/mcp/client/McpClient.ts +307 -0
- package/src/mcp/client/McpClient.unit.test.ts +135 -0
- package/src/middlewares/elysia.test.ts +9 -5
- package/src/middlewares/express.test.ts +9 -5
- package/src/middlewares/hono.test.ts +5 -5
- package/src/middlewares/internal/mppx.test.ts +1 -1
- package/src/middlewares/nextjs.test.ts +9 -5
- package/src/proxy/Proxy.test.ts +9 -9
- package/src/proxy/services/anthropic.test.ts +1 -1
- package/src/proxy/services/openai.test.ts +1 -1
- package/src/proxy/services/stripe.test.ts +1 -1
- package/src/server/Mppx.authorize.test.ts +1 -1
- package/src/server/Mppx.test-d.ts +55 -1
- package/src/server/Mppx.test.ts +220 -9
- package/src/server/Mppx.ts +501 -407
- package/src/server/Response.ts +2 -1
- package/src/server/Transport.test.ts +6 -6
- package/src/server/Transport.ts +5 -4
- package/src/server/index.ts +1 -0
- package/src/stripe/Charge.integration.test.ts +1 -1
- package/src/stripe/client/Charge.test.ts +21 -6
- package/src/stripe/client/Charge.ts +6 -2
- package/src/stripe/server/Charge.test.ts +115 -2
- package/src/stripe/server/Charge.ts +13 -2
- package/src/stripe/server/internal/html/package.json +1 -1
- package/src/stripe/server/internal/html.gen.ts +1 -1
- package/src/tempo/AccessKeyAuthorization.test.ts +4 -94
- package/src/tempo/Methods.test.ts +45 -17
- package/src/tempo/Methods.ts +22 -0
- package/src/tempo/Proof.conformance.test.ts +146 -0
- package/src/tempo/Proof.test-d.ts +15 -0
- package/src/tempo/Proof.ts +52 -1
- package/src/tempo/PublicExports.test-d.ts +105 -0
- package/src/tempo/Subscription.integration.test.ts +1 -1
- package/src/tempo/client/Charge.test.ts +258 -0
- package/src/tempo/client/Charge.ts +84 -38
- package/src/tempo/client/Methods.ts +22 -8
- package/src/tempo/client/ResolveAccount.ts +46 -0
- package/src/tempo/client/index.ts +15 -4
- package/src/tempo/index.ts +1 -0
- package/src/tempo/internal/fee-payer.test.ts +296 -17
- package/src/tempo/internal/fee-payer.ts +186 -4
- package/src/tempo/internal/fee-token.test.ts +14 -9
- package/src/tempo/internal/proof.test.ts +12 -4
- package/src/tempo/internal/proof.ts +55 -6
- package/src/tempo/legacy/AccessKeyAuthorization.test.ts +162 -0
- package/src/tempo/legacy/README.md +9 -0
- package/src/tempo/{client → legacy/client}/ChannelOps.test.ts +6 -7
- package/src/tempo/{client → legacy/client}/ChannelOps.ts +22 -9
- package/src/tempo/{client → legacy/client}/Session.test.ts +51 -9
- package/src/tempo/{client → legacy/client}/Session.ts +25 -11
- package/src/tempo/{client → legacy/client}/SessionManager.test.ts +81 -9
- package/src/tempo/{client → legacy/client}/SessionManager.ts +52 -23
- package/src/tempo/legacy/client/index.ts +6 -0
- package/src/tempo/legacy/index.ts +6 -0
- package/src/tempo/{server → legacy/server}/Session.test.ts +136 -71
- package/src/tempo/{server → legacy/server}/Session.ts +32 -23
- package/src/tempo/legacy/server/index.ts +4 -0
- package/src/tempo/{session → legacy/session}/Chain.test.ts +3 -4
- package/src/tempo/{session → legacy/session}/Chain.ts +94 -63
- package/src/tempo/{session → legacy/session}/Channel.ts +1 -0
- package/src/tempo/legacy/session/ChannelStore.test.ts +58 -0
- package/src/tempo/legacy/session/ChannelStore.ts +39 -0
- package/src/tempo/legacy/session/Types.ts +91 -0
- package/src/tempo/{session → legacy/session}/Voucher.ts +12 -8
- package/src/tempo/{session → legacy/session}/escrow.abi.ts +1 -0
- package/src/tempo/legacy/session/index.ts +8 -0
- package/src/tempo/server/AtomicStore.test-d.ts +16 -11
- package/src/tempo/server/Charge.test.ts +480 -31
- package/src/tempo/server/Charge.ts +54 -30
- package/src/tempo/server/Methods.ts +58 -10
- package/src/tempo/server/Sse.test.ts +2 -2
- package/src/tempo/server/Subscription.test.ts +465 -3
- package/src/tempo/server/Subscription.ts +174 -19
- package/src/tempo/server/index.ts +6 -5
- package/src/tempo/server/internal/html/package.json +2 -2
- package/src/tempo/server/internal/html.gen.ts +1 -1
- package/src/tempo/server/internal/request-body.test.ts +37 -4
- package/src/tempo/server/internal/request-body.ts +25 -6
- package/src/tempo/server/internal/transport.test.ts +4 -4
- package/src/tempo/server/internal/transport.ts +19 -10
- package/src/tempo/session/Snapshot.test.ts +41 -0
- package/src/tempo/session/Snapshot.ts +74 -0
- package/src/tempo/session/client/ChannelOps.test.ts +163 -0
- package/src/tempo/session/client/ChannelOps.ts +330 -0
- package/src/tempo/session/client/ChannelStore.ts +111 -0
- package/src/tempo/session/client/CredentialState.test.ts +789 -0
- package/src/tempo/session/client/CredentialState.ts +799 -0
- package/src/tempo/session/client/ReceiptCoordinator.ts +95 -0
- package/src/tempo/session/client/Runtime.test.ts +1092 -0
- package/src/tempo/session/client/Runtime.ts +986 -0
- package/src/tempo/session/client/Session.test.ts +774 -0
- package/src/tempo/session/client/Session.ts +123 -0
- package/src/tempo/session/client/SessionManager.test.ts +1397 -0
- package/src/tempo/session/client/SessionManager.ts +751 -0
- package/src/tempo/session/client/Transports.test.ts +837 -0
- package/src/tempo/session/client/Transports.ts +1292 -0
- package/src/tempo/session/client/index.ts +40 -0
- package/src/tempo/session/index.ts +7 -8
- package/src/tempo/session/precompile/Chain.integration.test.ts +321 -0
- package/src/tempo/session/precompile/Chain.test.ts +1258 -0
- package/src/tempo/session/precompile/Chain.ts +979 -0
- package/src/tempo/session/precompile/Channel.test.ts +138 -0
- package/src/tempo/session/precompile/Channel.ts +103 -0
- package/src/tempo/session/precompile/Protocol.test.ts +358 -0
- package/src/tempo/session/precompile/Protocol.ts +520 -0
- package/src/tempo/session/precompile/Voucher.test.ts +354 -0
- package/src/tempo/session/precompile/Voucher.ts +162 -0
- package/src/tempo/session/precompile/escrow.abi.ts +226 -0
- package/src/tempo/session/precompile/index.ts +33 -0
- package/src/tempo/session/server/ChannelOps.test.ts +129 -0
- package/src/tempo/session/server/ChannelOps.ts +157 -0
- package/src/tempo/session/{ChannelStore.test.ts → server/ChannelStore.test.ts} +536 -29
- package/src/tempo/session/server/ChannelStore.ts +835 -0
- package/src/tempo/session/server/CredentialVerification.test.ts +146 -0
- package/src/tempo/session/server/CredentialVerification.ts +710 -0
- package/src/tempo/session/server/MeteredStream.ts +88 -0
- package/src/tempo/session/server/RequestState.test.ts +531 -0
- package/src/tempo/session/server/RequestState.ts +499 -0
- package/src/tempo/session/server/Session.integration.test.ts +444 -0
- package/src/tempo/session/server/Session.test.ts +3253 -0
- package/src/tempo/session/server/Session.ts +543 -0
- package/src/tempo/session/server/Settlement.test.ts +329 -0
- package/src/tempo/session/server/Settlement.ts +471 -0
- package/src/tempo/session/{Sse.test.ts → server/Sse.test.ts} +37 -3
- package/src/tempo/session/server/Sse.ts +254 -0
- package/src/tempo/session/server/Transports.test.ts +346 -0
- package/src/tempo/session/server/Transports.ts +255 -0
- package/src/tempo/session/{Ws.test.ts → server/Ws.test.ts} +4 -4
- package/src/tempo/session/server/Ws.ts +380 -0
- package/src/tempo/session/server/index.ts +8 -0
- package/src/tempo/subscription/Store.ts +27 -9
- package/src/x402/Exact.e2e.test.ts +1 -1
- package/src/x402/PublicInterface.test-d.ts +1 -1
- package/src/x402/index.ts +1 -0
- package/dist/mcp-sdk/client/McpClient.d.ts +0 -78
- package/dist/mcp-sdk/client/McpClient.d.ts.map +0 -1
- package/dist/mcp-sdk/client/McpClient.js +0 -105
- package/dist/mcp-sdk/client/McpClient.js.map +0 -1
- package/dist/mcp-sdk/client/index.d.ts.map +0 -1
- package/dist/mcp-sdk/client/index.js.map +0 -1
- package/dist/mcp-sdk/server/Transport.d.ts.map +0 -1
- package/dist/mcp-sdk/server/Transport.js.map +0 -1
- package/dist/mcp-sdk/server/index.d.ts.map +0 -1
- package/dist/mcp-sdk/server/index.js.map +0 -1
- package/dist/tempo/client/ChannelOps.d.ts.map +0 -1
- package/dist/tempo/client/ChannelOps.js.map +0 -1
- package/dist/tempo/client/Session.d.ts.map +0 -1
- package/dist/tempo/client/Session.js.map +0 -1
- package/dist/tempo/client/SessionManager.d.ts.map +0 -1
- package/dist/tempo/client/SessionManager.js.map +0 -1
- package/dist/tempo/server/Session.d.ts.map +0 -1
- package/dist/tempo/server/Session.js.map +0 -1
- package/dist/tempo/session/Chain.d.ts.map +0 -1
- package/dist/tempo/session/Chain.js.map +0 -1
- package/dist/tempo/session/Channel.d.ts.map +0 -1
- package/dist/tempo/session/Channel.js.map +0 -1
- package/dist/tempo/session/ChannelStore.d.ts +0 -117
- package/dist/tempo/session/ChannelStore.d.ts.map +0 -1
- package/dist/tempo/session/ChannelStore.js +0 -172
- package/dist/tempo/session/ChannelStore.js.map +0 -1
- package/dist/tempo/session/Receipt.d.ts +0 -22
- package/dist/tempo/session/Receipt.d.ts.map +0 -1
- package/dist/tempo/session/Receipt.js +0 -34
- package/dist/tempo/session/Receipt.js.map +0 -1
- package/dist/tempo/session/Sse.d.ts.map +0 -1
- package/dist/tempo/session/Sse.js +0 -363
- package/dist/tempo/session/Sse.js.map +0 -1
- package/dist/tempo/session/Types.d.ts +0 -78
- package/dist/tempo/session/Types.d.ts.map +0 -1
- package/dist/tempo/session/Types.js.map +0 -1
- package/dist/tempo/session/Voucher.d.ts.map +0 -1
- package/dist/tempo/session/Voucher.js.map +0 -1
- package/dist/tempo/session/Ws.d.ts +0 -87
- package/dist/tempo/session/Ws.d.ts.map +0 -1
- package/dist/tempo/session/Ws.js +0 -443
- package/dist/tempo/session/Ws.js.map +0 -1
- package/dist/tempo/session/escrow.abi.js.map +0 -1
- package/src/mcp-sdk/client/McpClient.ts +0 -196
- package/src/tempo/session/ChannelStore.ts +0 -308
- package/src/tempo/session/Receipt.test.ts +0 -89
- package/src/tempo/session/Receipt.ts +0 -46
- package/src/tempo/session/Sse.ts +0 -462
- package/src/tempo/session/Types.ts +0 -86
- package/src/tempo/session/Ws.ts +0 -576
- /package/dist/{mcp-sdk → mcp}/client/index.d.ts +0 -0
- /package/dist/{mcp-sdk → mcp}/client/index.js +0 -0
- /package/dist/{mcp-sdk → mcp}/server/Transport.d.ts +0 -0
- /package/dist/{mcp-sdk → mcp}/server/Transport.js +0 -0
- /package/dist/{mcp-sdk → mcp}/server/index.d.ts +0 -0
- /package/dist/{mcp-sdk → mcp}/server/index.js +0 -0
- /package/dist/tempo/{session → legacy/session}/Channel.js +0 -0
- /package/dist/tempo/{session → legacy/session}/Types.js +0 -0
- /package/src/{mcp-sdk → mcp}/client/index.ts +0 -0
- /package/src/{mcp-sdk → mcp}/server/Transport.test.ts +0 -0
- /package/src/{mcp-sdk → mcp}/server/Transport.ts +0 -0
- /package/src/{mcp-sdk → mcp}/server/index.ts +0 -0
- /package/src/tempo/{session → legacy/session}/Channel.test.ts +0 -0
- /package/src/tempo/{session → legacy/session}/Voucher.test.ts +0 -0
- /package/src/tempo/session/{Sse.fuzz.test.ts → server/Sse.fuzz.test.ts} +0 -0
package/src/server/Mppx.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { IncomingMessage, ServerResponse } from 'node:http'
|
|
|
2
2
|
import { isDeepStrictEqual } from 'node:util'
|
|
3
3
|
|
|
4
4
|
import * as Challenge from '../Challenge.js'
|
|
5
|
+
import * as Constants from '../Constants.js'
|
|
5
6
|
import * as Credential from '../Credential.js'
|
|
6
7
|
import * as Errors from '../Errors.js'
|
|
7
8
|
import * as Expires from '../Expires.js'
|
|
@@ -21,6 +22,9 @@ import * as NodeListener from './NodeListener.js'
|
|
|
21
22
|
import * as Request from './Request.js'
|
|
22
23
|
import * as Transport from './Transport.js'
|
|
23
24
|
|
|
25
|
+
const minimumSecretKeyBytes = 32
|
|
26
|
+
const secretKeyGenerationCommand = 'openssl rand -base64 32'
|
|
27
|
+
|
|
24
28
|
export type Methods = readonly (Method.AnyServer | readonly Method.AnyServer[])[]
|
|
25
29
|
|
|
26
30
|
export type ServerEventMap<
|
|
@@ -326,12 +330,30 @@ type UniqueIntentHandlers<
|
|
|
326
330
|
}
|
|
327
331
|
|
|
328
332
|
/** Nested handlers: `mppx.tempo.charge(...)`, grouped by method name then intent. */
|
|
333
|
+
type PublicAlias<method extends Method.AnyServer> = method extends {
|
|
334
|
+
alias?: infer alias
|
|
335
|
+
}
|
|
336
|
+
? Exclude<alias, undefined> extends infer definedAlias
|
|
337
|
+
? definedAlias extends string
|
|
338
|
+
? string extends definedAlias
|
|
339
|
+
? never
|
|
340
|
+
: definedAlias
|
|
341
|
+
: never
|
|
342
|
+
: never
|
|
343
|
+
: never
|
|
344
|
+
|
|
345
|
+
type PublicIntent<method extends Method.AnyServer> = [PublicAlias<method>] extends [never]
|
|
346
|
+
? method extends { intent: infer intent extends string }
|
|
347
|
+
? intent
|
|
348
|
+
: never
|
|
349
|
+
: PublicAlias<method>
|
|
350
|
+
|
|
329
351
|
type NestedHandlers<
|
|
330
352
|
methods extends readonly Method.AnyServer[],
|
|
331
353
|
transport extends Transport.AnyTransport,
|
|
332
354
|
> = {
|
|
333
355
|
[name in methods[number]['name'] as name extends ReservedKey ? never : name]: {
|
|
334
|
-
[mi in Extract<methods[number], { name: name }> as mi
|
|
356
|
+
[mi in Extract<methods[number], { name: name }> as PublicIntent<mi>]: MethodFn<
|
|
335
357
|
mi,
|
|
336
358
|
EffectiveTransportOf<mi, transport>,
|
|
337
359
|
NonNullable<mi['defaults']>
|
|
@@ -351,7 +373,12 @@ type Handlers<
|
|
|
351
373
|
> &
|
|
352
374
|
MethodExtensions<mi>
|
|
353
375
|
} & UniqueIntentHandlers<methods, transport> &
|
|
354
|
-
NestedHandlers<methods, transport>
|
|
376
|
+
NestedHandlers<methods, transport> & {
|
|
377
|
+
[mi in methods[number] as PublicAlias<mi> extends string
|
|
378
|
+
? `${mi['name']}/${PublicAlias<mi>}`
|
|
379
|
+
: never]: MethodFn<mi, EffectiveTransportOf<mi, transport>, NonNullable<mi['defaults']>> &
|
|
380
|
+
MethodExtensions<mi>
|
|
381
|
+
}
|
|
355
382
|
|
|
356
383
|
type MethodExtensions<method extends Method.AnyServer> = method extends {
|
|
357
384
|
extensions?: (infer extensions) | undefined
|
|
@@ -364,7 +391,7 @@ type MethodExtensions<method extends Method.AnyServer> = method extends {
|
|
|
364
391
|
/** Nested challenge generators: `mppx.challenge.tempo.charge(...)`. */
|
|
365
392
|
type ChallengeHandlers<methods extends readonly Method.AnyServer[]> = {
|
|
366
393
|
[name in methods[number]['name']]: {
|
|
367
|
-
[mi in Extract<methods[number], { name: name }> as mi
|
|
394
|
+
[mi in Extract<methods[number], { name: name }> as PublicIntent<mi>]: ChallengeFn<
|
|
368
395
|
mi,
|
|
369
396
|
NonNullable<mi['defaults']>
|
|
370
397
|
>
|
|
@@ -407,6 +434,7 @@ export function create<
|
|
|
407
434
|
'Missing secret key. Set the MPP_SECRET_KEY environment variable or pass `secretKey` to Mppx.create().',
|
|
408
435
|
)
|
|
409
436
|
}
|
|
437
|
+
assertSecretKey(secretKey)
|
|
410
438
|
|
|
411
439
|
const methods = config.methods.flat() as unknown as FlattenMethods<methods>
|
|
412
440
|
const serverEvents = createServerEventDispatcher<FlattenMethods<methods>, transport>()
|
|
@@ -426,6 +454,7 @@ export function create<
|
|
|
426
454
|
method: mi,
|
|
427
455
|
realm,
|
|
428
456
|
events: serverEvents as never,
|
|
457
|
+
preflight: mi.preflight as never,
|
|
429
458
|
request: mi.request as never,
|
|
430
459
|
respond: mi.respond as never,
|
|
431
460
|
secretKey,
|
|
@@ -433,8 +462,11 @@ export function create<
|
|
|
433
462
|
transport: (mi.transport ?? transport) as never,
|
|
434
463
|
verify: mi.verify as never,
|
|
435
464
|
})
|
|
465
|
+
const wireKey = `${mi.name}/${mi.intent}`
|
|
466
|
+
const aliasKey = mi.alias ? `${mi.name}/${mi.alias}` : undefined
|
|
436
467
|
if (mi.extensions) Object.assign(fn, mi.extensions)
|
|
437
|
-
handlers[
|
|
468
|
+
if (!aliasKey || !handlers[wireKey]) handlers[wireKey] = fn
|
|
469
|
+
if (aliasKey) handlers[aliasKey] = fn
|
|
438
470
|
}
|
|
439
471
|
|
|
440
472
|
// Also set shorthand intent key when there's no collision
|
|
@@ -445,16 +477,17 @@ export function create<
|
|
|
445
477
|
// Build nested handlers: mppx.tempo.charge(...)
|
|
446
478
|
for (const mi of methods) {
|
|
447
479
|
if (!handlers[mi.name]) handlers[mi.name] = {}
|
|
448
|
-
const
|
|
480
|
+
const key = mi.alias ? `${mi.name}/${mi.alias}` : `${mi.name}/${mi.intent}`
|
|
481
|
+
const fn = handlers[key] as AnyMethodFn & { _method?: Method.AnyServer }
|
|
449
482
|
fn._method = mi
|
|
450
|
-
;(handlers[mi.name] as Record<string, unknown>)[mi.intent] = fn
|
|
483
|
+
;(handlers[mi.name] as Record<string, unknown>)[mi.alias ?? mi.intent] = fn
|
|
451
484
|
}
|
|
452
485
|
|
|
453
486
|
// Build challenge generators: mppx.challenge.tempo.charge(...)
|
|
454
487
|
const challengeHandlers: Record<string, Record<string, unknown>> = {}
|
|
455
488
|
for (const mi of methods) {
|
|
456
489
|
if (!challengeHandlers[mi.name]) challengeHandlers[mi.name] = {}
|
|
457
|
-
challengeHandlers[mi.name]![mi.intent] = createChallengeFn({
|
|
490
|
+
challengeHandlers[mi.name]![mi.alias ?? mi.intent] = createChallengeFn({
|
|
458
491
|
defaults: mi.defaults,
|
|
459
492
|
method: mi,
|
|
460
493
|
realm,
|
|
@@ -472,11 +505,13 @@ export function create<
|
|
|
472
505
|
typeof input === 'string' ? Credential.deserialize(input) : input,
|
|
473
506
|
)
|
|
474
507
|
|
|
475
|
-
// Find matching method by name + intent
|
|
508
|
+
// Find matching method by name + intent, then use method-details markers
|
|
509
|
+
// when multiple handlers intentionally share the same wire identity.
|
|
476
510
|
const { method: credMethod, intent: credIntent } = credential.challenge
|
|
477
|
-
const
|
|
511
|
+
const methodCandidates = (methods as readonly Method.AnyServer[]).filter(
|
|
478
512
|
(m) => m.name === credMethod && m.intent === credIntent,
|
|
479
513
|
)
|
|
514
|
+
const mi = selectVerificationMethod(methodCandidates, credential.challenge)
|
|
480
515
|
const eventMethod =
|
|
481
516
|
mi ?? ({ intent: credIntent, name: credMethod } satisfies ServerMethodDescriptor)
|
|
482
517
|
|
|
@@ -688,8 +723,8 @@ export function create<
|
|
|
688
723
|
typeof methodOrKey === 'string'
|
|
689
724
|
? methodOrKey
|
|
690
725
|
: typeof methodOrKey === 'function' && '_method' in methodOrKey
|
|
691
|
-
? `${(methodOrKey._method as Method.AnyServer).name}/${(methodOrKey._method as Method.AnyServer).intent}`
|
|
692
|
-
: `${(methodOrKey as Method.AnyServer).name}/${(methodOrKey as Method.AnyServer).intent}`
|
|
726
|
+
? `${(methodOrKey._method as Method.AnyServer).name}/${(methodOrKey._method as Method.AnyServer).alias ?? (methodOrKey._method as Method.AnyServer).intent}`
|
|
727
|
+
: `${(methodOrKey as Method.AnyServer).name}/${(methodOrKey as Method.AnyServer).alias ?? (methodOrKey as Method.AnyServer).intent}`
|
|
693
728
|
const handlerFn = handlers[key] as AnyMethodFn | undefined
|
|
694
729
|
if (!handlerFn)
|
|
695
730
|
throw new Error(`No handler for "${key}". Is this method in your methods array?`)
|
|
@@ -731,6 +766,15 @@ export function create<
|
|
|
731
766
|
} as never
|
|
732
767
|
}
|
|
733
768
|
|
|
769
|
+
function assertSecretKey(secretKey: string) {
|
|
770
|
+
const byteLength = new TextEncoder().encode(secretKey).byteLength
|
|
771
|
+
if (byteLength >= minimumSecretKeyBytes) return
|
|
772
|
+
|
|
773
|
+
throw new Error(
|
|
774
|
+
`Secret key must be at least ${minimumSecretKeyBytes} bytes. Generate one with \`${secretKeyGenerationCommand}\` and set MPP_SECRET_KEY or pass it to Mppx.create().`,
|
|
775
|
+
)
|
|
776
|
+
}
|
|
777
|
+
|
|
734
778
|
export declare namespace create {
|
|
735
779
|
type Config<
|
|
736
780
|
methods extends Methods = Methods,
|
|
@@ -740,7 +784,7 @@ export declare namespace create {
|
|
|
740
784
|
methods: methods
|
|
741
785
|
/** Server realm (e.g., hostname). Resolution order: explicit value > env vars (`MPP_REALM`, `FLY_APP_NAME`, `VERCEL_URL`, etc.) > request URL hostname > `"MPP Payment"`. */
|
|
742
786
|
realm?: string | undefined
|
|
743
|
-
/** Secret key for HMAC-bound challenge IDs for stateless verification. Auto-detected from `MPP_SECRET_KEY` environment variable.
|
|
787
|
+
/** Secret key for HMAC-bound challenge IDs for stateless verification. Must be at least 32 bytes. Auto-detected from `MPP_SECRET_KEY` environment variable. */
|
|
744
788
|
secretKey?: string | undefined
|
|
745
789
|
/** Transport to use. @default Transport.http() */
|
|
746
790
|
transport?: transport | undefined
|
|
@@ -761,6 +805,7 @@ function createMethodFn(parameters: createMethodFn.Parameters): createMethodFn.R
|
|
|
761
805
|
defaults,
|
|
762
806
|
events,
|
|
763
807
|
method,
|
|
808
|
+
preflight,
|
|
764
809
|
realm,
|
|
765
810
|
respond,
|
|
766
811
|
secretKey,
|
|
@@ -772,75 +817,83 @@ function createMethodFn(parameters: createMethodFn.Parameters): createMethodFn.R
|
|
|
772
817
|
return (options) => {
|
|
773
818
|
const { description, meta, scope, ...rest } = options
|
|
774
819
|
const staticMeta = Scope.merge({ meta, scope })
|
|
820
|
+
const internal: ConfiguredHandler['_internal'] = {
|
|
821
|
+
...method,
|
|
822
|
+
...defaults,
|
|
823
|
+
...options,
|
|
824
|
+
...(staticMeta !== undefined ? { meta: staticMeta } : {}),
|
|
825
|
+
name: method.name,
|
|
826
|
+
intent: method.intent,
|
|
827
|
+
html: method.html,
|
|
828
|
+
_canonicalRequest: PaymentRequest.fromMethod(method, { ...defaults, ...rest }),
|
|
829
|
+
_stableBinding: stableBinding as never,
|
|
830
|
+
}
|
|
775
831
|
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
} as MethodFn.Response<Transport.Http>
|
|
783
|
-
|
|
784
|
-
const expires =
|
|
785
|
-
'expires' in options
|
|
786
|
-
? normalizeExpires(options.expires as z.DatetimeInput | undefined)
|
|
787
|
-
: Expires.minutes(5)
|
|
788
|
-
const capturedRequest = await captureRequest(transport, input)
|
|
789
|
-
const effectiveMeta =
|
|
790
|
-
scope === undefined && input instanceof globalThis.Request
|
|
791
|
-
? Scope.merge({ meta: staticMeta, scope: Scope.get(input) })
|
|
792
|
-
: staticMeta
|
|
793
|
-
|
|
794
|
-
// Extract credential once — getCredential may have side effects (e.g. SSE transports).
|
|
795
|
-
let [credential, credentialError] = (() => {
|
|
796
|
-
try {
|
|
797
|
-
const credential = transport.getCredential(input) as Credential.Credential | null
|
|
798
|
-
return [credential ? hydrateCredentialMeta(credential) : null, undefined] as const
|
|
799
|
-
} catch (e) {
|
|
800
|
-
return [null, e as Error] as const
|
|
801
|
-
}
|
|
802
|
-
})()
|
|
832
|
+
const handler = async (input: Transport.InputOf): Promise<MethodFn.Response> => {
|
|
833
|
+
if (method.html && isServiceWorkerRequest(input))
|
|
834
|
+
return {
|
|
835
|
+
status: 402,
|
|
836
|
+
challenge: createServiceWorkerResponse(),
|
|
837
|
+
} as MethodFn.Response<Transport.Http>
|
|
803
838
|
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
839
|
+
const expires =
|
|
840
|
+
'expires' in options
|
|
841
|
+
? normalizeExpires(options.expires as z.DatetimeInput | undefined)
|
|
842
|
+
: Expires.minutes(5)
|
|
843
|
+
const capturedRequest = await captureRequest(transport, input)
|
|
844
|
+
const effectiveMeta =
|
|
845
|
+
scope === undefined && input instanceof globalThis.Request
|
|
846
|
+
? Scope.merge({ meta: staticMeta, scope: Scope.get(input) })
|
|
847
|
+
: staticMeta
|
|
848
|
+
|
|
849
|
+
// Extract credential once — getCredential may have side effects (e.g. SSE transports).
|
|
850
|
+
let [credential, credentialError] = (() => {
|
|
851
|
+
try {
|
|
852
|
+
const credential = transport.getCredential(input) as Credential.Credential | null
|
|
853
|
+
return [credential ? hydrateCredentialMeta(credential) : null, undefined] as const
|
|
854
|
+
} catch (e) {
|
|
855
|
+
return [null, e as Error] as const
|
|
856
|
+
}
|
|
857
|
+
})()
|
|
858
|
+
|
|
859
|
+
if (preflight && input instanceof globalThis.Request) {
|
|
860
|
+
const response = await preflight({
|
|
861
|
+
capturedRequest,
|
|
862
|
+
credential,
|
|
863
|
+
expires,
|
|
864
|
+
input,
|
|
865
|
+
options: { ...defaults, ...rest },
|
|
866
|
+
realm: realm ?? new URL(input.url).hostname ?? 'MPP Payment',
|
|
867
|
+
secretKey,
|
|
868
|
+
} as never)
|
|
869
|
+
if (response) {
|
|
870
|
+
if (response.status === 402) return { challenge: response, status: 402 }
|
|
871
|
+
return {
|
|
872
|
+
status: 200,
|
|
873
|
+
withReceipt() {
|
|
874
|
+
return response
|
|
875
|
+
},
|
|
876
|
+
} as MethodFn.Response
|
|
831
877
|
}
|
|
878
|
+
}
|
|
832
879
|
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
880
|
+
const emitChallenge = async (parameters: {
|
|
881
|
+
challenge: Challenge.Challenge
|
|
882
|
+
credential?: Credential.Credential | null | undefined
|
|
883
|
+
error?: Errors.PaymentError | undefined
|
|
884
|
+
html?: Method.Method['html'] | undefined
|
|
885
|
+
request: Record<string, unknown>
|
|
886
|
+
}) => {
|
|
887
|
+
const response = await transport.respondChallenge({
|
|
888
|
+
challenge: parameters.challenge,
|
|
889
|
+
input,
|
|
890
|
+
...(parameters.error && { error: parameters.error }),
|
|
891
|
+
...(parameters.html && { html: parameters.html }),
|
|
892
|
+
})
|
|
893
|
+
if (isIssuedChallengeResponse(response))
|
|
841
894
|
await events.emit(
|
|
842
|
-
'
|
|
843
|
-
|
|
895
|
+
'challenge.created',
|
|
896
|
+
createChallengeContext({
|
|
844
897
|
capturedRequest,
|
|
845
898
|
challenge: parameters.challenge,
|
|
846
899
|
credential: parameters.credential,
|
|
@@ -848,272 +901,199 @@ function createMethodFn(parameters: createMethodFn.Parameters): createMethodFn.R
|
|
|
848
901
|
input,
|
|
849
902
|
method,
|
|
850
903
|
request: parameters.request,
|
|
851
|
-
retryChallenge: parameters.retryChallenge,
|
|
852
|
-
submittedChallenge: parameters.submittedChallenge,
|
|
853
904
|
}) as never,
|
|
854
905
|
)
|
|
855
|
-
|
|
906
|
+
return response
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
const emitPaymentFailed = async (parameters: {
|
|
910
|
+
challenge: Challenge.Challenge
|
|
911
|
+
credential: Credential.Credential | null
|
|
912
|
+
error: Errors.PaymentError
|
|
913
|
+
request: Record<string, unknown>
|
|
914
|
+
retryChallenge?: Challenge.Challenge | undefined
|
|
915
|
+
submittedChallenge?: Challenge.Challenge | undefined
|
|
916
|
+
}) => {
|
|
917
|
+
await events.emit(
|
|
918
|
+
'payment.failed',
|
|
919
|
+
createPaymentFailedContext({
|
|
920
|
+
capturedRequest,
|
|
921
|
+
challenge: parameters.challenge,
|
|
922
|
+
credential: parameters.credential,
|
|
923
|
+
error: parameters.error,
|
|
924
|
+
input,
|
|
925
|
+
method,
|
|
926
|
+
request: parameters.request,
|
|
927
|
+
retryChallenge: parameters.retryChallenge,
|
|
928
|
+
submittedChallenge: parameters.submittedChallenge,
|
|
929
|
+
}) as never,
|
|
930
|
+
)
|
|
931
|
+
}
|
|
856
932
|
|
|
857
|
-
|
|
933
|
+
const routeChallenge = await resolveRouteChallenge({
|
|
934
|
+
capturedRequest,
|
|
935
|
+
credential,
|
|
936
|
+
defaults,
|
|
937
|
+
description,
|
|
938
|
+
expires,
|
|
939
|
+
meta: effectiveMeta,
|
|
940
|
+
method,
|
|
941
|
+
realm,
|
|
942
|
+
request: parameters.request,
|
|
943
|
+
routeRequest: rest,
|
|
944
|
+
secretKey,
|
|
945
|
+
}).catch(async (e) => {
|
|
946
|
+
if (!(e instanceof Errors.PaymentError)) throw e
|
|
947
|
+
const challenge = createFallbackChallenge({
|
|
858
948
|
capturedRequest,
|
|
859
|
-
|
|
860
|
-
defaults,
|
|
949
|
+
defaults: defaults ?? {},
|
|
861
950
|
description,
|
|
862
951
|
expires,
|
|
863
952
|
meta: effectiveMeta,
|
|
864
953
|
method,
|
|
865
954
|
realm,
|
|
866
|
-
request: parameters.request,
|
|
867
955
|
routeRequest: rest,
|
|
868
956
|
secretKey,
|
|
869
|
-
})
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
capturedRequest,
|
|
873
|
-
defaults: defaults ?? {},
|
|
874
|
-
description,
|
|
875
|
-
expires,
|
|
876
|
-
meta: effectiveMeta,
|
|
877
|
-
method,
|
|
878
|
-
realm,
|
|
879
|
-
routeRequest: rest,
|
|
880
|
-
secretKey,
|
|
881
|
-
})
|
|
882
|
-
if (credential)
|
|
883
|
-
await emitPaymentFailed({
|
|
884
|
-
challenge,
|
|
885
|
-
credential,
|
|
886
|
-
error: e,
|
|
887
|
-
request: challenge.request,
|
|
888
|
-
retryChallenge: challenge,
|
|
889
|
-
submittedChallenge: credential.challenge,
|
|
890
|
-
})
|
|
891
|
-
const response = await emitChallenge({
|
|
957
|
+
})
|
|
958
|
+
if (credential)
|
|
959
|
+
await emitPaymentFailed({
|
|
892
960
|
challenge,
|
|
893
961
|
credential,
|
|
894
|
-
request: challenge.request,
|
|
895
962
|
error: e,
|
|
896
|
-
|
|
963
|
+
request: challenge.request,
|
|
964
|
+
retryChallenge: challenge,
|
|
965
|
+
submittedChallenge: credential.challenge,
|
|
897
966
|
})
|
|
898
|
-
|
|
967
|
+
const response = await emitChallenge({
|
|
968
|
+
challenge,
|
|
969
|
+
credential,
|
|
970
|
+
request: challenge.request,
|
|
971
|
+
error: e,
|
|
972
|
+
html: method.html,
|
|
899
973
|
})
|
|
900
|
-
|
|
901
|
-
|
|
974
|
+
return { response }
|
|
975
|
+
})
|
|
976
|
+
if ('response' in routeChallenge) return { challenge: routeChallenge.response, status: 402 }
|
|
977
|
+
const { challenge, parsedRequest, request } = routeChallenge
|
|
978
|
+
internal._canonicalRequest = parsedRequest
|
|
902
979
|
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
}
|
|
980
|
+
if (credential && transport.bindCredential) {
|
|
981
|
+
try {
|
|
982
|
+
credential = hydrateCredentialMeta(
|
|
983
|
+
(await transport.bindCredential({
|
|
984
|
+
challenge,
|
|
985
|
+
credential,
|
|
986
|
+
input,
|
|
987
|
+
})) as Credential.Credential,
|
|
988
|
+
)
|
|
989
|
+
} catch (e) {
|
|
990
|
+
credential = null
|
|
991
|
+
credentialError = e as Error
|
|
916
992
|
}
|
|
993
|
+
}
|
|
917
994
|
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
995
|
+
// Credential was provided but malformed
|
|
996
|
+
if (credentialError) {
|
|
997
|
+
const reason = getSafeCredentialReason(credentialError)
|
|
998
|
+
const error = new Errors.MalformedCredentialError(reason ? { reason } : {})
|
|
999
|
+
await emitPaymentFailed({
|
|
1000
|
+
challenge,
|
|
1001
|
+
credential: null,
|
|
1002
|
+
error,
|
|
1003
|
+
request: parsedRequest,
|
|
1004
|
+
retryChallenge: challenge,
|
|
1005
|
+
})
|
|
1006
|
+
const response = await emitChallenge({
|
|
1007
|
+
challenge,
|
|
1008
|
+
credential: null,
|
|
1009
|
+
request: parsedRequest,
|
|
1010
|
+
error,
|
|
1011
|
+
html: method.html,
|
|
1012
|
+
})
|
|
1013
|
+
return { challenge: response, status: 402 }
|
|
1014
|
+
}
|
|
938
1015
|
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
1016
|
+
const success = (
|
|
1017
|
+
receiptData: Receipt.Receipt,
|
|
1018
|
+
options: {
|
|
1019
|
+
challengeId?: string | undefined
|
|
1020
|
+
credentialForReceipt?: Credential.Credential | undefined
|
|
1021
|
+
envelopeForReceipt?: Method.VerifiedChallengeEnvelope | undefined
|
|
1022
|
+
managementResponse?: globalThis.Response | undefined
|
|
1023
|
+
} = {},
|
|
1024
|
+
): MethodFn.Response => {
|
|
1025
|
+
const {
|
|
1026
|
+
challengeId = challenge.id,
|
|
1027
|
+
credentialForReceipt = { challenge, payload: {} } as Credential.Credential,
|
|
1028
|
+
envelopeForReceipt,
|
|
1029
|
+
managementResponse,
|
|
1030
|
+
} = options
|
|
954
1031
|
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
return transport.respondReceipt({
|
|
960
|
-
challengeId,
|
|
961
|
-
credential: credentialForReceipt,
|
|
962
|
-
...(envelopeForReceipt ? { envelope: envelopeForReceipt } : {}),
|
|
963
|
-
input,
|
|
964
|
-
receipt: receiptData,
|
|
965
|
-
response: managementResponse as never,
|
|
966
|
-
}) as response
|
|
967
|
-
}
|
|
968
|
-
if (!response) throw new MissingReceiptResponseError()
|
|
1032
|
+
return {
|
|
1033
|
+
status: 200,
|
|
1034
|
+
withReceipt<response>(response?: response) {
|
|
1035
|
+
if (managementResponse) {
|
|
969
1036
|
return transport.respondReceipt({
|
|
970
1037
|
challengeId,
|
|
971
1038
|
credential: credentialForReceipt,
|
|
972
1039
|
...(envelopeForReceipt ? { envelope: envelopeForReceipt } : {}),
|
|
973
1040
|
input,
|
|
974
1041
|
receipt: receiptData,
|
|
975
|
-
response:
|
|
1042
|
+
response: managementResponse as never,
|
|
976
1043
|
}) as response
|
|
977
|
-
}
|
|
978
|
-
|
|
1044
|
+
}
|
|
1045
|
+
if (!response) throw new MissingReceiptResponseError()
|
|
1046
|
+
return transport.respondReceipt({
|
|
1047
|
+
challengeId,
|
|
1048
|
+
credential: credentialForReceipt,
|
|
1049
|
+
...(envelopeForReceipt ? { envelope: envelopeForReceipt } : {}),
|
|
1050
|
+
input,
|
|
1051
|
+
receipt: receiptData,
|
|
1052
|
+
response: response as never,
|
|
1053
|
+
}) as response
|
|
1054
|
+
},
|
|
979
1055
|
}
|
|
1056
|
+
}
|
|
980
1057
|
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
})
|
|
1005
|
-
}
|
|
1006
|
-
} catch (e) {
|
|
1007
|
-
if (!(e instanceof Errors.PaymentError))
|
|
1008
|
-
console.error('mppx: internal authorization error', e)
|
|
1009
|
-
const error =
|
|
1010
|
-
e instanceof Errors.PaymentError ? e : new Errors.VerificationFailedError()
|
|
1011
|
-
await emitPaymentFailed({
|
|
1012
|
-
challenge,
|
|
1013
|
-
credential: null,
|
|
1014
|
-
error,
|
|
1015
|
-
request: parsedRequest,
|
|
1016
|
-
retryChallenge: challenge,
|
|
1017
|
-
})
|
|
1018
|
-
const response = await emitChallenge({
|
|
1019
|
-
challenge,
|
|
1020
|
-
request: parsedRequest,
|
|
1021
|
-
error,
|
|
1022
|
-
html: method.html,
|
|
1058
|
+
// No credential provided—issue challenge
|
|
1059
|
+
if (!credential) {
|
|
1060
|
+
if (authorize && input instanceof globalThis.Request) {
|
|
1061
|
+
try {
|
|
1062
|
+
const authorized = await authorize({
|
|
1063
|
+
challenge,
|
|
1064
|
+
input,
|
|
1065
|
+
request: challenge.request,
|
|
1066
|
+
} as never)
|
|
1067
|
+
if (authorized) {
|
|
1068
|
+
await events.emit(
|
|
1069
|
+
'payment.success',
|
|
1070
|
+
createPaymentSuccessContext({
|
|
1071
|
+
capturedRequest,
|
|
1072
|
+
challenge,
|
|
1073
|
+
input,
|
|
1074
|
+
method,
|
|
1075
|
+
receipt: authorized.receipt,
|
|
1076
|
+
request: parsedRequest,
|
|
1077
|
+
}) as never,
|
|
1078
|
+
)
|
|
1079
|
+
return success(authorized.receipt, {
|
|
1080
|
+
managementResponse: authorized.response,
|
|
1023
1081
|
})
|
|
1024
|
-
return { challenge: response, status: 402 }
|
|
1025
1082
|
}
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
credential: null,
|
|
1032
|
-
request: parsedRequest,
|
|
1033
|
-
error,
|
|
1034
|
-
html: method.html,
|
|
1035
|
-
})
|
|
1036
|
-
return { challenge: response, status: 402 }
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
// ── Tier 1: HMAC provenance check (primary gate) ──────────────────
|
|
1040
|
-
//
|
|
1041
|
-
// Recompute the HMAC-SHA256 over the credential's echoed challenge
|
|
1042
|
-
// parameters (realm|method|intent|request|expires|digest|opaque) and
|
|
1043
|
-
// compare to the echoed `id`. This proves the challenge was issued by
|
|
1044
|
-
// this server with these exact parameters — including opaque/meta,
|
|
1045
|
-
// expires, and the full serialized request blob.
|
|
1046
|
-
//
|
|
1047
|
-
// This is the authoritative binding per §5.1.2.1.1 of the spec
|
|
1048
|
-
// (https://paymentauth.org/draft-httpauth-payment-00.html#section-5.1.2.1.1).
|
|
1049
|
-
// No database lookup is needed; the HMAC is stateless verification.
|
|
1050
|
-
if (!Challenge.verify(credential.challenge, { secretKey })) {
|
|
1051
|
-
const error = new Errors.InvalidChallengeError({
|
|
1052
|
-
id: credential.challenge.id,
|
|
1053
|
-
reason: 'challenge was not issued by this server',
|
|
1054
|
-
})
|
|
1055
|
-
await emitPaymentFailed({
|
|
1056
|
-
challenge,
|
|
1057
|
-
credential,
|
|
1058
|
-
error,
|
|
1059
|
-
request: parsedRequest,
|
|
1060
|
-
retryChallenge: challenge,
|
|
1061
|
-
submittedChallenge: credential.challenge,
|
|
1062
|
-
})
|
|
1063
|
-
const response = await emitChallenge({
|
|
1064
|
-
challenge,
|
|
1065
|
-
credential,
|
|
1066
|
-
request: parsedRequest,
|
|
1067
|
-
error,
|
|
1068
|
-
html: method.html,
|
|
1069
|
-
})
|
|
1070
|
-
return { challenge: response, status: 402 }
|
|
1071
|
-
}
|
|
1072
|
-
|
|
1073
|
-
// ── Tier 2: Pinned field safety net ──────────────────────────────
|
|
1074
|
-
//
|
|
1075
|
-
// The HMAC check above (Tier 1) is the primary gate — it already
|
|
1076
|
-
// covers ALL challenge fields including opaque, digest, and the full
|
|
1077
|
-
// serialized request. So why this second check?
|
|
1078
|
-
//
|
|
1079
|
-
// The `request()` hook can produce credential-dependent output: for
|
|
1080
|
-
// example, `feePayer` may differ between the 402 challenge call (no
|
|
1081
|
-
// credential) and the credential-bearing call. This means the
|
|
1082
|
-
// recomputed challenge here has a different `request` blob — and
|
|
1083
|
-
// thus a different HMAC — than the original challenge the client
|
|
1084
|
-
// echoes back. The HMAC check above verifies the *echoed* challenge
|
|
1085
|
-
// was signed by us, but it cannot verify that the echoed challenge
|
|
1086
|
-
// matches *this route's current configuration* when the request
|
|
1087
|
-
// hook transforms fields between calls.
|
|
1088
|
-
//
|
|
1089
|
-
// This check compares the fields that MUST be stable across both
|
|
1090
|
-
// calls. That includes the economically significant request fields
|
|
1091
|
-
// plus `opaque`, which can carry route-scoping metadata (for example,
|
|
1092
|
-
// sibling route identity) that must not be replayable across handlers.
|
|
1093
|
-
// `expires` still is not pinned here because its default is generated
|
|
1094
|
-
// per invocation, and `digest` is already bound by the echoed HMAC.
|
|
1095
|
-
{
|
|
1096
|
-
const mismatch = getChallengeBindingMismatch(
|
|
1097
|
-
challenge,
|
|
1098
|
-
credential.challenge,
|
|
1099
|
-
stableBinding as never,
|
|
1100
|
-
)
|
|
1101
|
-
if (mismatch) {
|
|
1102
|
-
const error = new Errors.InvalidChallengeError({
|
|
1103
|
-
id: credential.challenge.id,
|
|
1104
|
-
reason: `credential ${mismatch} does not match this route's requirements`,
|
|
1105
|
-
})
|
|
1083
|
+
} catch (e) {
|
|
1084
|
+
if (!(e instanceof Errors.PaymentError))
|
|
1085
|
+
console.error('mppx: internal authorization error', e)
|
|
1086
|
+
const error =
|
|
1087
|
+
e instanceof Errors.PaymentError ? e : new Errors.VerificationFailedError()
|
|
1106
1088
|
await emitPaymentFailed({
|
|
1107
1089
|
challenge,
|
|
1108
|
-
credential,
|
|
1090
|
+
credential: null,
|
|
1109
1091
|
error,
|
|
1110
1092
|
request: parsedRequest,
|
|
1111
1093
|
retryChallenge: challenge,
|
|
1112
|
-
submittedChallenge: credential.challenge,
|
|
1113
1094
|
})
|
|
1114
1095
|
const response = await emitChallenge({
|
|
1115
1096
|
challenge,
|
|
1116
|
-
credential,
|
|
1117
1097
|
request: parsedRequest,
|
|
1118
1098
|
error,
|
|
1119
1099
|
html: method.html,
|
|
@@ -1122,35 +1102,84 @@ function createMethodFn(parameters: createMethodFn.Parameters): createMethodFn.R
|
|
|
1122
1102
|
}
|
|
1123
1103
|
}
|
|
1124
1104
|
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1105
|
+
const error = new Errors.PaymentRequiredError({ description })
|
|
1106
|
+
const response = await emitChallenge({
|
|
1107
|
+
challenge,
|
|
1108
|
+
credential: null,
|
|
1109
|
+
request: parsedRequest,
|
|
1110
|
+
error,
|
|
1111
|
+
html: method.html,
|
|
1112
|
+
})
|
|
1113
|
+
return { challenge: response, status: 402 }
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
// ── Tier 1: HMAC provenance check (primary gate) ──────────────────
|
|
1117
|
+
//
|
|
1118
|
+
// Recompute the HMAC-SHA256 over the credential's echoed challenge
|
|
1119
|
+
// parameters (realm|method|intent|request|expires|digest|opaque) and
|
|
1120
|
+
// compare to the echoed `id`. This proves the challenge was issued by
|
|
1121
|
+
// this server with these exact parameters — including opaque/meta,
|
|
1122
|
+
// expires, and the full serialized request blob.
|
|
1123
|
+
//
|
|
1124
|
+
// This is the authoritative binding per §5.1.2.1.1 of the spec
|
|
1125
|
+
// (https://paymentauth.org/draft-httpauth-payment-00.html#section-5.1.2.1.1).
|
|
1126
|
+
// No database lookup is needed; the HMAC is stateless verification.
|
|
1127
|
+
if (!Challenge.verify(credential.challenge, { secretKey })) {
|
|
1128
|
+
const error = new Errors.InvalidChallengeError({
|
|
1129
|
+
id: credential.challenge.id,
|
|
1130
|
+
reason: 'challenge was not issued by this server',
|
|
1131
|
+
})
|
|
1132
|
+
await emitPaymentFailed({
|
|
1133
|
+
challenge,
|
|
1134
|
+
credential,
|
|
1135
|
+
error,
|
|
1136
|
+
request: parsedRequest,
|
|
1137
|
+
retryChallenge: challenge,
|
|
1138
|
+
submittedChallenge: credential.challenge,
|
|
1139
|
+
})
|
|
1140
|
+
const response = await emitChallenge({
|
|
1141
|
+
challenge,
|
|
1142
|
+
credential,
|
|
1143
|
+
request: parsedRequest,
|
|
1144
|
+
error,
|
|
1145
|
+
html: method.html,
|
|
1146
|
+
})
|
|
1147
|
+
return { challenge: response, status: 402 }
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
// ── Tier 2: Pinned field safety net ──────────────────────────────
|
|
1151
|
+
//
|
|
1152
|
+
// The HMAC check above (Tier 1) is the primary gate — it already
|
|
1153
|
+
// covers ALL challenge fields including opaque, digest, and the full
|
|
1154
|
+
// serialized request. So why this second check?
|
|
1155
|
+
//
|
|
1156
|
+
// The `request()` hook can produce credential-dependent output: for
|
|
1157
|
+
// example, `feePayer` may differ between the 402 challenge call (no
|
|
1158
|
+
// credential) and the credential-bearing call. This means the
|
|
1159
|
+
// recomputed challenge here has a different `request` blob — and
|
|
1160
|
+
// thus a different HMAC — than the original challenge the client
|
|
1161
|
+
// echoes back. The HMAC check above verifies the *echoed* challenge
|
|
1162
|
+
// was signed by us, but it cannot verify that the echoed challenge
|
|
1163
|
+
// matches *this route's current configuration* when the request
|
|
1164
|
+
// hook transforms fields between calls.
|
|
1165
|
+
//
|
|
1166
|
+
// This check compares the fields that MUST be stable across both
|
|
1167
|
+
// calls. That includes the economically significant request fields
|
|
1168
|
+
// plus `opaque`, which can carry route-scoping metadata (for example,
|
|
1169
|
+
// sibling route identity) that must not be replayable across handlers.
|
|
1170
|
+
// `expires` still is not pinned here because its default is generated
|
|
1171
|
+
// per invocation, and `digest` is already bound by the echoed HMAC.
|
|
1172
|
+
{
|
|
1173
|
+
const mismatch = getChallengeBindingMismatch(
|
|
1174
|
+
challenge,
|
|
1175
|
+
credential.challenge,
|
|
1176
|
+
stableBinding as never,
|
|
1177
|
+
)
|
|
1178
|
+
if (mismatch) {
|
|
1179
|
+
const error = new Errors.InvalidChallengeError({
|
|
1180
|
+
id: credential.challenge.id,
|
|
1181
|
+
reason: `credential ${mismatch} does not match this route's requirements`,
|
|
1142
1182
|
})
|
|
1143
|
-
return { challenge: response, status: 402 }
|
|
1144
|
-
}
|
|
1145
|
-
// Validate payload structure against method schema
|
|
1146
|
-
let parsedCredential: Credential.Credential
|
|
1147
|
-
try {
|
|
1148
|
-
parsedCredential = withParsedCredentialPayload(
|
|
1149
|
-
credential,
|
|
1150
|
-
method.schema.credential.payload.parse(credential.payload),
|
|
1151
|
-
)
|
|
1152
|
-
} catch {
|
|
1153
|
-
const error = new Errors.InvalidPayloadError()
|
|
1154
1183
|
await emitPaymentFailed({
|
|
1155
1184
|
challenge,
|
|
1156
1185
|
credential,
|
|
@@ -1164,92 +1193,129 @@ function createMethodFn(parameters: createMethodFn.Parameters): createMethodFn.R
|
|
|
1164
1193
|
credential,
|
|
1165
1194
|
request: parsedRequest,
|
|
1166
1195
|
error,
|
|
1196
|
+
html: method.html,
|
|
1167
1197
|
})
|
|
1168
1198
|
return { challenge: response, status: 402 }
|
|
1169
1199
|
}
|
|
1200
|
+
}
|
|
1170
1201
|
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1202
|
+
// Reject credentials without expires (fail-closed) or with expired timestamp
|
|
1203
|
+
try {
|
|
1204
|
+
Expires.assert(credential.challenge.expires, credential.challenge.id)
|
|
1205
|
+
} catch (error) {
|
|
1206
|
+
await emitPaymentFailed({
|
|
1207
|
+
challenge,
|
|
1208
|
+
credential,
|
|
1209
|
+
error: error as Errors.PaymentError,
|
|
1210
|
+
request: parsedRequest,
|
|
1211
|
+
retryChallenge: challenge,
|
|
1212
|
+
submittedChallenge: credential.challenge,
|
|
1213
|
+
})
|
|
1214
|
+
const response = await emitChallenge({
|
|
1215
|
+
challenge,
|
|
1216
|
+
credential,
|
|
1175
1217
|
request: parsedRequest,
|
|
1218
|
+
error: error as Errors.PaymentError,
|
|
1176
1219
|
})
|
|
1220
|
+
return { challenge: response, status: 402 }
|
|
1221
|
+
}
|
|
1222
|
+
// Validate payload structure against method schema
|
|
1223
|
+
let parsedCredential: Credential.Credential
|
|
1224
|
+
try {
|
|
1225
|
+
parsedCredential = withParsedCredentialPayload(
|
|
1226
|
+
credential,
|
|
1227
|
+
method.schema.credential.payload.parse(credential.payload),
|
|
1228
|
+
)
|
|
1229
|
+
} catch {
|
|
1230
|
+
const error = new Errors.InvalidPayloadError()
|
|
1231
|
+
await emitPaymentFailed({
|
|
1232
|
+
challenge,
|
|
1233
|
+
credential,
|
|
1234
|
+
error,
|
|
1235
|
+
request: parsedRequest,
|
|
1236
|
+
retryChallenge: challenge,
|
|
1237
|
+
submittedChallenge: credential.challenge,
|
|
1238
|
+
})
|
|
1239
|
+
const response = await emitChallenge({
|
|
1240
|
+
challenge,
|
|
1241
|
+
credential,
|
|
1242
|
+
request: parsedRequest,
|
|
1243
|
+
error,
|
|
1244
|
+
})
|
|
1245
|
+
return { challenge: response, status: 402 }
|
|
1246
|
+
}
|
|
1177
1247
|
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
if (!(e instanceof Errors.PaymentError))
|
|
1185
|
-
console.error('mppx: internal verification error', e)
|
|
1186
|
-
const error = e instanceof Errors.PaymentError ? e : new Errors.VerificationFailedError()
|
|
1187
|
-
await emitPaymentFailed({
|
|
1188
|
-
challenge,
|
|
1189
|
-
credential: parsedCredential,
|
|
1190
|
-
error,
|
|
1191
|
-
request: parsedRequest,
|
|
1192
|
-
retryChallenge: challenge,
|
|
1193
|
-
submittedChallenge: credential.challenge,
|
|
1194
|
-
})
|
|
1195
|
-
const response = await emitChallenge({
|
|
1196
|
-
challenge,
|
|
1197
|
-
credential: parsedCredential,
|
|
1198
|
-
request: parsedRequest,
|
|
1199
|
-
error,
|
|
1200
|
-
})
|
|
1201
|
-
return { challenge: response, status: 402 }
|
|
1202
|
-
}
|
|
1248
|
+
const envelope: Method.VerifiedChallengeEnvelope = Object.freeze({
|
|
1249
|
+
capturedRequest,
|
|
1250
|
+
challenge: credential.challenge,
|
|
1251
|
+
credential: parsedCredential,
|
|
1252
|
+
request: parsedRequest,
|
|
1253
|
+
})
|
|
1203
1254
|
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
:
|
|
1255
|
+
// User-provided verification (e.g., check signature, submit tx, verify payment).
|
|
1256
|
+
// If verification fails, re-issue the challenge so the client can retry.
|
|
1257
|
+
let receiptData: Receipt.Receipt
|
|
1258
|
+
try {
|
|
1259
|
+
receiptData = await verify({ credential: parsedCredential, envelope, request } as never)
|
|
1260
|
+
} catch (e) {
|
|
1261
|
+
if (!(e instanceof Errors.PaymentError))
|
|
1262
|
+
console.error('mppx: internal verification error', e)
|
|
1263
|
+
const error = e instanceof Errors.PaymentError ? e : new Errors.VerificationFailedError()
|
|
1264
|
+
await emitPaymentFailed({
|
|
1265
|
+
challenge,
|
|
1266
|
+
credential: parsedCredential,
|
|
1267
|
+
error,
|
|
1268
|
+
request: parsedRequest,
|
|
1269
|
+
retryChallenge: challenge,
|
|
1270
|
+
submittedChallenge: credential.challenge,
|
|
1271
|
+
})
|
|
1272
|
+
const response = await emitChallenge({
|
|
1273
|
+
challenge,
|
|
1274
|
+
credential: parsedCredential,
|
|
1275
|
+
request: parsedRequest,
|
|
1276
|
+
error,
|
|
1277
|
+
})
|
|
1278
|
+
return { challenge: response, status: 402 }
|
|
1279
|
+
}
|
|
1218
1280
|
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1281
|
+
// If the method's `respond` hook returns a Response, it means this
|
|
1282
|
+
// request is a management action (e.g. channel open, voucher POST)
|
|
1283
|
+
// and the user's route handler should NOT run. `withReceipt()` will
|
|
1284
|
+
// return the management response directly. If undefined, `withReceipt()`
|
|
1285
|
+
// expects the caller to pass the user handler's response instead.
|
|
1286
|
+
const managementResponse = respond
|
|
1287
|
+
? await respond({
|
|
1224
1288
|
credential: parsedCredential,
|
|
1225
1289
|
envelope,
|
|
1226
1290
|
input,
|
|
1227
|
-
method,
|
|
1228
1291
|
receipt: receiptData,
|
|
1229
|
-
request
|
|
1230
|
-
}
|
|
1231
|
-
|
|
1292
|
+
request,
|
|
1293
|
+
} as never)
|
|
1294
|
+
: undefined
|
|
1232
1295
|
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1296
|
+
await events.emit(
|
|
1297
|
+
'payment.success',
|
|
1298
|
+
createPaymentSuccessContext({
|
|
1299
|
+
capturedRequest,
|
|
1300
|
+
challenge: credential.challenge,
|
|
1301
|
+
credential: parsedCredential,
|
|
1302
|
+
envelope,
|
|
1303
|
+
input,
|
|
1304
|
+
method,
|
|
1305
|
+
receipt: receiptData,
|
|
1306
|
+
request: parsedRequest,
|
|
1307
|
+
}) as never,
|
|
1308
|
+
)
|
|
1309
|
+
|
|
1310
|
+
return success(receiptData, {
|
|
1311
|
+
challengeId: credential.challenge.id,
|
|
1312
|
+
credentialForReceipt: parsedCredential,
|
|
1313
|
+
envelopeForReceipt: envelope,
|
|
1314
|
+
managementResponse,
|
|
1315
|
+
})
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
return Object.assign(handler, { _internal: internal })
|
|
1253
1319
|
}
|
|
1254
1320
|
}
|
|
1255
1321
|
|
|
@@ -1305,6 +1371,7 @@ declare namespace createMethodFn {
|
|
|
1305
1371
|
defaults?: defaults
|
|
1306
1372
|
method: method
|
|
1307
1373
|
events: ServerEventDispatcher<readonly [method], transport>
|
|
1374
|
+
preflight?: Method.PreflightFn<method>
|
|
1308
1375
|
realm: string | undefined
|
|
1309
1376
|
request?: Method.RequestFn<method>
|
|
1310
1377
|
respond?: Method.RespondFn<method>
|
|
@@ -1767,7 +1834,7 @@ function captureRequestFromInput(input: unknown): Method.CapturedRequest {
|
|
|
1767
1834
|
}
|
|
1768
1835
|
|
|
1769
1836
|
const coreBindingFields = ['amount', 'currency', 'recipient'] as const
|
|
1770
|
-
const methodBindingFields = ['chainId', 'memo', 'splits', 'unitType'] as const
|
|
1837
|
+
const methodBindingFields = ['chainId', 'memo', 'sessionProtocol', 'splits', 'unitType'] as const
|
|
1771
1838
|
const pinnedRequestBindingFields = [...coreBindingFields, ...methodBindingFields] as const
|
|
1772
1839
|
|
|
1773
1840
|
type CoreBindingField = (typeof coreBindingFields)[number]
|
|
@@ -1776,6 +1843,31 @@ type PinnedRequestBindingField = (typeof pinnedRequestBindingFields)[number]
|
|
|
1776
1843
|
type PinnedChallengeField = 'method' | 'intent' | 'realm' | 'opaque' | PinnedRequestBindingField
|
|
1777
1844
|
type StableBinding = Record<string, unknown>
|
|
1778
1845
|
|
|
1846
|
+
function selectVerificationMethod(
|
|
1847
|
+
methods: readonly Method.AnyServer[],
|
|
1848
|
+
challenge: Challenge.Challenge,
|
|
1849
|
+
): Method.AnyServer | undefined {
|
|
1850
|
+
if (methods.length <= 1) return methods[0]
|
|
1851
|
+
if (
|
|
1852
|
+
challenge.method !== Constants.Methods.tempo ||
|
|
1853
|
+
challenge.intent !== Constants.Intents.session
|
|
1854
|
+
)
|
|
1855
|
+
return methods[0]
|
|
1856
|
+
|
|
1857
|
+
const sessionProtocolMarker = Constants.getMethodDetail(
|
|
1858
|
+
challenge.request.methodDetails,
|
|
1859
|
+
Constants.MethodDetailKeys.sessionProtocol,
|
|
1860
|
+
)
|
|
1861
|
+
if (
|
|
1862
|
+
sessionProtocolMarker === undefined ||
|
|
1863
|
+
sessionProtocolMarker === Constants.SessionProtocols.v1
|
|
1864
|
+
)
|
|
1865
|
+
return methods.find((method) => method.alias === 'sessionLegacy') ?? methods[0]
|
|
1866
|
+
if (sessionProtocolMarker === Constants.SessionProtocols.v2)
|
|
1867
|
+
return methods.find((method) => method.alias === undefined) ?? methods[0]
|
|
1868
|
+
return undefined
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1779
1871
|
function getChallengeBindingMismatch(
|
|
1780
1872
|
expectedChallenge: Challenge.Challenge,
|
|
1781
1873
|
actualChallenge: Challenge.Challenge,
|
|
@@ -1856,6 +1948,7 @@ function getPinnedRequestBinding(request: Record<string, unknown>): PinnedReques
|
|
|
1856
1948
|
const currency = normalizeScalar(request.currency ?? methodDetails.currency)
|
|
1857
1949
|
const memo = normalizeHex(methodDetails.memo)
|
|
1858
1950
|
const recipient = normalizeScalar(request.recipient ?? methodDetails.recipient)
|
|
1951
|
+
const sessionProtocol = normalizeScalar(methodDetails.sessionProtocol)
|
|
1859
1952
|
const splits = normalizeComparable(methodDetails.splits)
|
|
1860
1953
|
const unitType = normalizeScalar(request.unitType ?? methodDetails.unitType)
|
|
1861
1954
|
|
|
@@ -1868,6 +1961,7 @@ function getPinnedRequestBinding(request: Record<string, unknown>): PinnedReques
|
|
|
1868
1961
|
methodBinding: {
|
|
1869
1962
|
...(chainId !== undefined ? { chainId } : {}),
|
|
1870
1963
|
...(memo !== undefined ? { memo } : {}),
|
|
1964
|
+
...(sessionProtocol !== undefined ? { sessionProtocol } : {}),
|
|
1871
1965
|
...(splits !== undefined ? { splits } : {}),
|
|
1872
1966
|
...(unitType !== undefined ? { unitType } : {}),
|
|
1873
1967
|
},
|
|
@@ -2021,7 +2115,7 @@ type ConfiguredHandler = ((input: Request) => Promise<MethodFn.Response<Transpor
|
|
|
2021
2115
|
}
|
|
2022
2116
|
}
|
|
2023
2117
|
|
|
2024
|
-
const paymentAuthChallengeHeader =
|
|
2118
|
+
const paymentAuthChallengeHeader = Constants.Headers.wwwAuthenticate
|
|
2025
2119
|
|
|
2026
2120
|
const challengeHeaderMerges = [
|
|
2027
2121
|
{
|
|
@@ -2141,7 +2235,7 @@ export function compose(
|
|
|
2141
2235
|
// Try to extract a Payment credential to decide whether to dispatch or challenge.
|
|
2142
2236
|
// Only gate on the Payment scheme — other auth schemes (Bearer, Basic, etc.)
|
|
2143
2237
|
// should fall through to the merged-402 path so all offers are presented.
|
|
2144
|
-
const header = input.headers.get(
|
|
2238
|
+
const header = input.headers.get(Constants.Headers.authorization)
|
|
2145
2239
|
const paymentHeader = header ? Credential.extractPaymentScheme(header) : null
|
|
2146
2240
|
|
|
2147
2241
|
if (paymentHeader) {
|
|
@@ -2222,7 +2316,7 @@ export function compose(
|
|
|
2222
2316
|
})
|
|
2223
2317
|
}
|
|
2224
2318
|
|
|
2225
|
-
const acceptPayment = input.headers.get(
|
|
2319
|
+
const acceptPayment = input.headers.get(Constants.Headers.acceptPayment)
|
|
2226
2320
|
if (!acceptPayment) return entries
|
|
2227
2321
|
|
|
2228
2322
|
try {
|
|
@@ -2243,7 +2337,7 @@ export function compose(
|
|
|
2243
2337
|
result.status === 402 ? [result.challenge as Response] : [],
|
|
2244
2338
|
)
|
|
2245
2339
|
const unnegotiatedX402Responses =
|
|
2246
|
-
input.headers.has(
|
|
2340
|
+
input.headers.has(Constants.Headers.acceptPayment) || challengeEntries.length === 0
|
|
2247
2341
|
? []
|
|
2248
2342
|
: challengeResponses.filter(
|
|
2249
2343
|
(response) =>
|