mppx 0.8.15 → 0.8.17
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 +36 -0
- package/dist/Challenge.d.ts.map +1 -1
- package/dist/Challenge.js +40 -35
- package/dist/Challenge.js.map +1 -1
- package/dist/Constants.d.ts +17 -17
- package/dist/Constants.d.ts.map +1 -1
- package/dist/Credential.d.ts.map +1 -1
- package/dist/Errors.d.ts +3 -3
- package/dist/Errors.d.ts.map +1 -1
- package/dist/Errors.js.map +1 -1
- package/dist/Method.d.ts +35 -5
- package/dist/Method.d.ts.map +1 -1
- package/dist/Method.js +7 -22
- package/dist/Method.js.map +1 -1
- package/dist/Store.d.ts +19 -0
- package/dist/Store.d.ts.map +1 -1
- package/dist/Store.js +43 -0
- package/dist/Store.js.map +1 -1
- package/dist/attestation/Client.d.ts +17 -0
- package/dist/attestation/Client.d.ts.map +1 -0
- package/dist/attestation/Client.js +28 -0
- package/dist/attestation/Client.js.map +1 -0
- package/dist/attestation/Constants.d.ts +15 -0
- package/dist/attestation/Constants.d.ts.map +1 -0
- package/dist/attestation/Constants.js +15 -0
- package/dist/attestation/Constants.js.map +1 -0
- package/dist/attestation/Server.d.ts +4 -0
- package/dist/attestation/Server.d.ts.map +1 -0
- package/dist/attestation/Server.js +8 -0
- package/dist/attestation/Server.js.map +1 -0
- package/dist/attestation/Types.d.ts +76 -0
- package/dist/attestation/Types.d.ts.map +1 -0
- package/dist/attestation/Types.js +2 -0
- package/dist/attestation/Types.js.map +1 -0
- package/dist/attestation/index.d.ts +6 -0
- package/dist/attestation/index.d.ts.map +1 -0
- package/dist/attestation/index.js +6 -0
- package/dist/attestation/index.js.map +1 -0
- package/dist/attestation/internal/HttpMessageSignature.d.ts +73 -0
- package/dist/attestation/internal/HttpMessageSignature.d.ts.map +1 -0
- package/dist/attestation/internal/HttpMessageSignature.js +320 -0
- package/dist/attestation/internal/HttpMessageSignature.js.map +1 -0
- package/dist/attestation/internal/SigningContext.d.ts +4 -0
- package/dist/attestation/internal/SigningContext.d.ts.map +1 -0
- package/dist/attestation/internal/SigningContext.js +11 -0
- package/dist/attestation/internal/SigningContext.js.map +1 -0
- package/dist/cli/account.d.ts +14 -14
- package/dist/cli/account.d.ts.map +1 -1
- package/dist/cli/cli.d.ts +6 -6
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +1 -0
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/plugins/tempo.js.map +1 -1
- package/dist/cli/sessions/commands.d.ts +4 -4
- package/dist/cli/sessions/commands.d.ts.map +1 -1
- package/dist/cli/sessions/commands.js.map +1 -1
- package/dist/cli/sessions/store.d.ts.map +1 -1
- package/dist/cli/sessions/store.js.map +1 -1
- package/dist/cli/utils.d.ts +1 -1
- package/dist/cli/utils.d.ts.map +1 -1
- package/dist/cli/utils.js.map +1 -1
- package/dist/cli/validate/discovery.js.map +1 -1
- package/dist/cli/validate/index.d.ts +3 -3
- package/dist/cli/validate/index.d.ts.map +1 -1
- package/dist/client/Mppx.d.ts +3 -0
- package/dist/client/Mppx.d.ts.map +1 -1
- package/dist/client/Mppx.js +13 -5
- package/dist/client/Mppx.js.map +1 -1
- package/dist/client/Transport.d.ts +3 -5
- package/dist/client/Transport.d.ts.map +1 -1
- package/dist/client/Transport.js +1 -17
- package/dist/client/Transport.js.map +1 -1
- package/dist/client/internal/Fetch.d.ts.map +1 -1
- package/dist/client/internal/Fetch.js +2 -6
- package/dist/client/internal/Fetch.js.map +1 -1
- package/dist/client/node.js.map +1 -1
- package/dist/discovery/OpenApi.d.ts +3 -5
- package/dist/discovery/OpenApi.d.ts.map +1 -1
- package/dist/discovery/OpenApi.js +13 -34
- package/dist/discovery/OpenApi.js.map +1 -1
- package/dist/discovery/internal/Metadata.d.ts +20 -0
- package/dist/discovery/internal/Metadata.d.ts.map +1 -0
- package/dist/discovery/internal/Metadata.js +36 -0
- package/dist/discovery/internal/Metadata.js.map +1 -0
- package/dist/evm/Methods.d.ts +11 -11
- package/dist/evm/Methods.d.ts.map +1 -1
- package/dist/evm/Types.d.ts +17 -17
- package/dist/evm/Types.d.ts.map +1 -1
- package/dist/evm/client/Charge.d.ts +11 -11
- package/dist/evm/client/Methods.d.ts +11 -11
- package/dist/evm/server/Charge.d.ts +1 -1
- package/dist/evm/server/Charge.d.ts.map +1 -1
- package/dist/evm/server/Charge.js +2 -0
- package/dist/evm/server/Charge.js.map +1 -1
- package/dist/evm/server/Methods.d.ts +11 -11
- package/dist/internal/HeaderCodec.d.ts +2 -2
- package/dist/internal/HeaderCodec.d.ts.map +1 -1
- package/dist/internal/types.d.ts +6 -0
- package/dist/internal/types.d.ts.map +1 -1
- package/dist/middlewares/elysia.js.map +1 -1
- package/dist/middlewares/express.js.map +1 -1
- package/dist/middlewares/hono.js.map +1 -1
- package/dist/middlewares/nextjs.js.map +1 -1
- package/dist/proxy/Proxy.d.ts +2 -0
- package/dist/proxy/Proxy.d.ts.map +1 -1
- package/dist/proxy/Proxy.js +117 -9
- package/dist/proxy/Proxy.js.map +1 -1
- package/dist/proxy/Service.d.ts +36 -1
- package/dist/proxy/Service.d.ts.map +1 -1
- package/dist/proxy/Service.js +9 -8
- package/dist/proxy/Service.js.map +1 -1
- package/dist/proxy/services/anthropic.d.ts.map +1 -1
- package/dist/proxy/services/anthropic.js +1 -0
- package/dist/proxy/services/anthropic.js.map +1 -1
- package/dist/proxy/services/openai.d.ts.map +1 -1
- package/dist/proxy/services/openai.js +1 -0
- package/dist/proxy/services/openai.js.map +1 -1
- package/dist/proxy/services/stripe.d.ts.map +1 -1
- package/dist/proxy/services/stripe.js +1 -0
- package/dist/proxy/services/stripe.js.map +1 -1
- package/dist/server/Mppx.d.ts +75 -13
- package/dist/server/Mppx.d.ts.map +1 -1
- package/dist/server/Mppx.js +201 -23
- package/dist/server/Mppx.js.map +1 -1
- package/dist/server/internal/html/config.d.ts +9 -9
- package/dist/server/internal/html/config.d.ts.map +1 -1
- package/dist/server/internal/html/constants.d.ts +17 -17
- package/dist/server/internal/html/constants.d.ts.map +1 -1
- package/dist/stripe/Methods.d.ts +10 -10
- package/dist/stripe/Methods.d.ts.map +1 -1
- package/dist/stripe/client/Charge.d.ts +10 -10
- package/dist/stripe/client/Methods.d.ts +10 -10
- package/dist/stripe/internal/constants.d.ts +1 -1
- package/dist/stripe/internal/constants.js +1 -1
- package/dist/stripe/internal/types.d.ts +1 -0
- package/dist/stripe/internal/types.d.ts.map +1 -1
- package/dist/stripe/server/Charge.d.ts +11 -11
- package/dist/stripe/server/Charge.d.ts.map +1 -1
- package/dist/stripe/server/Charge.js +49 -1
- package/dist/stripe/server/Charge.js.map +1 -1
- package/dist/stripe/server/Methods.d.ts +137 -48
- package/dist/stripe/server/Methods.d.ts.map +1 -1
- package/dist/stripe/server/Methods.js +259 -4
- package/dist/stripe/server/Methods.js.map +1 -1
- package/dist/stripe/server/internal/deposit-address.d.ts +13 -0
- package/dist/stripe/server/internal/deposit-address.d.ts.map +1 -0
- package/dist/stripe/server/internal/deposit-address.js +28 -0
- package/dist/stripe/server/internal/deposit-address.js.map +1 -0
- 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/stripe/server/internal/record-payment.d.ts +15 -0
- package/dist/stripe/server/internal/record-payment.d.ts.map +1 -0
- package/dist/stripe/server/internal/record-payment.js +42 -0
- package/dist/stripe/server/internal/record-payment.js.map +1 -0
- package/dist/stripe/server/internal/request.d.ts +25 -0
- package/dist/stripe/server/internal/request.d.ts.map +1 -0
- package/dist/stripe/server/internal/request.js +29 -0
- package/dist/stripe/server/internal/request.js.map +1 -0
- package/dist/tap/Constants.d.ts +28 -0
- package/dist/tap/Constants.d.ts.map +1 -0
- package/dist/tap/Constants.js +32 -0
- package/dist/tap/Constants.js.map +1 -0
- package/dist/tap/Types.d.ts +11 -0
- package/dist/tap/Types.d.ts.map +1 -0
- package/dist/tap/Types.js +2 -0
- package/dist/tap/Types.js.map +1 -0
- package/dist/tap/client/index.d.ts +26 -0
- package/dist/tap/client/index.d.ts.map +1 -0
- package/dist/tap/client/index.js +33 -0
- package/dist/tap/client/index.js.map +1 -0
- package/dist/tap/index.d.ts +5 -0
- package/dist/tap/index.d.ts.map +1 -0
- package/dist/tap/index.js +5 -0
- package/dist/tap/index.js.map +1 -0
- package/dist/tap/server/index.d.ts +20 -0
- package/dist/tap/server/index.d.ts.map +1 -0
- package/dist/tap/server/index.js +36 -0
- package/dist/tap/server/index.js.map +1 -0
- package/dist/tempo/Attribution.d.ts +1 -1
- package/dist/tempo/Methods.d.ts +60 -60
- package/dist/tempo/Methods.d.ts.map +1 -1
- package/dist/tempo/Proof.d.ts +16 -16
- package/dist/tempo/client/Charge.d.ts +19 -19
- package/dist/tempo/client/Charge.d.ts.map +1 -1
- package/dist/tempo/client/Charge.js +1 -7
- package/dist/tempo/client/Charge.js.map +1 -1
- package/dist/tempo/client/Methods.d.ts +38 -38
- package/dist/tempo/client/Methods.js.map +1 -1
- package/dist/tempo/client/Subscription.d.ts +23 -23
- package/dist/tempo/client/Subscription.js.map +1 -1
- package/dist/tempo/internal/address.d.ts +2 -1
- package/dist/tempo/internal/address.d.ts.map +1 -1
- package/dist/tempo/internal/address.js +3 -1
- package/dist/tempo/internal/address.js.map +1 -1
- package/dist/tempo/internal/auto-swap.d.ts.map +1 -1
- package/dist/tempo/internal/auto-swap.js +4 -19
- package/dist/tempo/internal/auto-swap.js.map +1 -1
- package/dist/tempo/internal/defaults.d.ts +6 -6
- package/dist/tempo/internal/defaults.d.ts.map +1 -1
- package/dist/tempo/internal/fee-payer.d.ts +12 -12
- package/dist/tempo/internal/fee-payer.d.ts.map +1 -1
- package/dist/tempo/internal/fee-payer.js.map +1 -1
- package/dist/tempo/internal/proof.d.ts +17 -17
- package/dist/tempo/internal/proof.d.ts.map +1 -1
- package/dist/tempo/legacy/client/Session.d.ts +20 -20
- package/dist/tempo/legacy/client/Session.js.map +1 -1
- package/dist/tempo/legacy/client/SessionManager.js.map +1 -1
- package/dist/tempo/legacy/index.d.ts +1 -3
- package/dist/tempo/legacy/index.d.ts.map +1 -1
- package/dist/tempo/legacy/index.js +1 -3
- package/dist/tempo/legacy/index.js.map +1 -1
- package/dist/tempo/legacy/session/escrow.abi.d.ts +374 -374
- package/dist/tempo/legacy/session/escrow.abi.d.ts.map +1 -1
- package/dist/tempo/server/Charge.d.ts +25 -11
- package/dist/tempo/server/Charge.d.ts.map +1 -1
- package/dist/tempo/server/Charge.js +44 -39
- package/dist/tempo/server/Charge.js.map +1 -1
- package/dist/tempo/server/Methods.d.ts +37 -52
- package/dist/tempo/server/Methods.d.ts.map +1 -1
- package/dist/tempo/server/Methods.js +0 -14
- package/dist/tempo/server/Methods.js.map +1 -1
- package/dist/tempo/server/Relay.d.ts +1 -1
- package/dist/tempo/server/Relay.d.ts.map +1 -1
- package/dist/tempo/server/Relay.js +2 -2
- package/dist/tempo/server/Relay.js.map +1 -1
- package/dist/tempo/server/Subscription.d.ts +25 -25
- package/dist/tempo/server/Subscription.d.ts.map +1 -1
- package/dist/tempo/server/Subscription.js +2 -0
- package/dist/tempo/server/Subscription.js.map +1 -1
- package/dist/tempo/server/index.d.ts +1 -1
- package/dist/tempo/server/index.d.ts.map +1 -1
- package/dist/tempo/server/index.js +1 -1
- 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/transport.d.ts +2 -0
- package/dist/tempo/server/internal/transport.d.ts.map +1 -1
- package/dist/tempo/server/internal/transport.js +9 -2
- package/dist/tempo/server/internal/transport.js.map +1 -1
- package/dist/tempo/session/client/ChannelOps.js.map +1 -1
- package/dist/tempo/session/client/CredentialState.d.ts +1 -1
- package/dist/tempo/session/client/CredentialState.js.map +1 -1
- package/dist/tempo/session/client/ReceiptCoordinator.js.map +1 -1
- package/dist/tempo/session/client/Runtime.js.map +1 -1
- package/dist/tempo/session/client/Session.d.ts +19 -19
- package/dist/tempo/session/client/Session.js.map +1 -1
- package/dist/tempo/session/client/SessionManager.js.map +1 -1
- package/dist/tempo/session/client/Transports.d.ts.map +1 -1
- package/dist/tempo/session/precompile/Chain.d.ts +27 -0
- package/dist/tempo/session/precompile/Chain.d.ts.map +1 -1
- package/dist/tempo/session/precompile/Chain.js +68 -7
- package/dist/tempo/session/precompile/Chain.js.map +1 -1
- package/dist/tempo/session/precompile/Protocol.js.map +1 -1
- package/dist/tempo/session/precompile/Voucher.d.ts +4 -4
- package/dist/tempo/session/precompile/Voucher.d.ts.map +1 -1
- package/dist/tempo/session/precompile/escrow.abi.d.ts +306 -306
- package/dist/tempo/session/precompile/escrow.abi.d.ts.map +1 -1
- package/dist/tempo/session/server/ChannelStore.d.ts +9 -0
- package/dist/tempo/session/server/ChannelStore.d.ts.map +1 -1
- package/dist/tempo/session/server/ChannelStore.js +16 -8
- package/dist/tempo/session/server/ChannelStore.js.map +1 -1
- package/dist/tempo/session/server/CredentialVerification.d.ts +30 -13
- package/dist/tempo/session/server/CredentialVerification.d.ts.map +1 -1
- package/dist/tempo/session/server/CredentialVerification.js +207 -13
- package/dist/tempo/session/server/CredentialVerification.js.map +1 -1
- package/dist/tempo/session/server/MeteredStream.d.ts +3 -0
- package/dist/tempo/session/server/MeteredStream.d.ts.map +1 -1
- package/dist/tempo/session/server/MeteredStream.js +3 -1
- package/dist/tempo/session/server/MeteredStream.js.map +1 -1
- package/dist/tempo/session/server/Session.d.ts +32 -21
- package/dist/tempo/session/server/Session.d.ts.map +1 -1
- package/dist/tempo/session/server/Session.js +116 -53
- package/dist/tempo/session/server/Session.js.map +1 -1
- package/dist/tempo/session/server/Sse.d.ts +3 -1
- package/dist/tempo/session/server/Sse.d.ts.map +1 -1
- package/dist/tempo/session/server/Sse.js +2 -1
- package/dist/tempo/session/server/Sse.js.map +1 -1
- package/dist/tempo/session/server/Transports.d.ts +1 -1
- package/dist/tempo/session/server/Transports.d.ts.map +1 -1
- package/dist/tempo/session/server/Transports.js +1 -0
- package/dist/tempo/session/server/Transports.js.map +1 -1
- package/dist/tempo/session/server/Ws.d.ts +6 -1
- package/dist/tempo/session/server/Ws.d.ts.map +1 -1
- package/dist/tempo/session/server/Ws.js +1 -0
- package/dist/tempo/session/server/Ws.js.map +1 -1
- package/dist/tempo/subscription/KeyAuthorization.d.ts +39 -39
- package/dist/tempo/subscription/KeyAuthorization.d.ts.map +1 -1
- package/dist/viem/Account.d.ts.map +1 -1
- package/dist/viem/Account.js.map +1 -1
- package/dist/web-bot-auth/Constants.d.ts +20 -0
- package/dist/web-bot-auth/Constants.d.ts.map +1 -0
- package/dist/web-bot-auth/Constants.js +24 -0
- package/dist/web-bot-auth/Constants.js.map +1 -0
- package/dist/web-bot-auth/Types.d.ts +10 -0
- package/dist/web-bot-auth/Types.d.ts.map +1 -0
- package/dist/web-bot-auth/Types.js +2 -0
- package/dist/web-bot-auth/Types.js.map +1 -0
- package/dist/web-bot-auth/client/index.d.ts +29 -0
- package/dist/web-bot-auth/client/index.d.ts.map +1 -0
- package/dist/web-bot-auth/client/index.js +64 -0
- package/dist/web-bot-auth/client/index.js.map +1 -0
- package/dist/web-bot-auth/index.d.ts +7 -0
- package/dist/web-bot-auth/index.d.ts.map +1 -0
- package/dist/web-bot-auth/index.js +7 -0
- package/dist/web-bot-auth/index.js.map +1 -0
- package/dist/web-bot-auth/internal/JwkThumbprint.d.ts +5 -0
- package/dist/web-bot-auth/internal/JwkThumbprint.d.ts.map +1 -0
- package/dist/web-bot-auth/internal/JwkThumbprint.js +20 -0
- package/dist/web-bot-auth/internal/JwkThumbprint.js.map +1 -0
- package/dist/web-bot-auth/internal/SignatureAgent.d.ts +3 -0
- package/dist/web-bot-auth/internal/SignatureAgent.d.ts.map +1 -0
- package/dist/web-bot-auth/internal/SignatureAgent.js +18 -0
- package/dist/web-bot-auth/internal/SignatureAgent.js.map +1 -0
- package/dist/web-bot-auth/server/index.d.ts +35 -0
- package/dist/web-bot-auth/server/index.d.ts.map +1 -0
- package/dist/web-bot-auth/server/index.js +88 -0
- package/dist/web-bot-auth/server/index.js.map +1 -0
- package/dist/x402/Assets.d.ts.map +1 -1
- package/dist/x402/Types.d.ts +6 -6
- package/dist/x402/Types.d.ts.map +1 -1
- package/dist/x402/server/EvmCharge.d.ts.map +1 -1
- package/dist/x402/server/EvmCharge.js +32 -20
- package/dist/x402/server/EvmCharge.js.map +1 -1
- package/package.json +19 -3
- package/src/Challenge.fuzz.test.ts +80 -47
- package/src/Challenge.test.ts +65 -0
- package/src/Challenge.ts +39 -35
- package/src/Method.ts +82 -68
- package/src/Store.test-d.ts +16 -0
- package/src/Store.test.ts +50 -0
- package/src/Store.ts +68 -0
- package/src/attestation/Attestation.integration.test.ts +208 -0
- package/src/attestation/Client.test.ts +83 -0
- package/src/attestation/Client.ts +34 -0
- package/src/attestation/Constants.ts +15 -0
- package/src/attestation/Server.test.ts +60 -0
- package/src/attestation/Server.ts +12 -0
- package/src/attestation/Types.test-d.ts +54 -0
- package/src/attestation/Types.ts +77 -0
- package/src/attestation/index.ts +5 -0
- package/src/attestation/internal/HttpMessageSignature.test.ts +101 -0
- package/src/attestation/internal/HttpMessageSignature.ts +429 -0
- package/src/attestation/internal/SigningContext.ts +13 -0
- package/src/bin.js +2 -0
- package/src/cli/cli.ts +1 -0
- package/src/client/Mppx.test-d.ts +17 -0
- package/src/client/Mppx.test.ts +14 -14
- package/src/client/Mppx.ts +25 -4
- package/src/client/Transport.test.ts +12 -45
- package/src/client/Transport.ts +3 -24
- package/src/client/internal/Fetch.ts +2 -6
- package/src/discovery/OpenApi.test.ts +170 -0
- package/src/discovery/OpenApi.ts +16 -48
- package/src/discovery/internal/Metadata.ts +51 -0
- package/src/evm/server/Charge.ts +6 -1
- package/src/internal/AcceptPayment.test.ts +12 -8
- package/src/internal/types.ts +9 -0
- package/src/mcp/client/McpClient.integration.test.ts +19 -32
- package/src/middlewares/elysia.test.ts +2 -12
- package/src/middlewares/express.test.ts +2 -12
- package/src/middlewares/hono.test.ts +6 -9
- package/src/middlewares/nextjs.test.ts +2 -12
- package/src/proxy/Proxy.test.ts +26 -19
- package/src/proxy/Proxy.ts +147 -9
- package/src/proxy/Proxy.upstreamError.test.ts +364 -0
- package/src/proxy/Service.test.ts +73 -3
- package/src/proxy/Service.ts +50 -23
- package/src/proxy/services/anthropic.ts +1 -0
- package/src/proxy/services/hooks.test-d.ts +14 -0
- package/src/proxy/services/hooks.test.ts +44 -0
- package/src/proxy/services/openai.ts +1 -0
- package/src/proxy/services/stripe.ts +1 -0
- package/src/server/Methods.test-d.ts +88 -0
- package/src/server/Methods.test.ts +69 -0
- package/src/server/Mppx.test-d.ts +141 -7
- package/src/server/Mppx.test.ts +1017 -119
- package/src/server/Mppx.ts +350 -54
- package/src/stripe/internal/constants.ts +1 -1
- package/src/stripe/internal/types.ts +1 -0
- package/src/stripe/server/Charge.test-d.ts +16 -1
- package/src/stripe/server/Charge.test.ts +79 -0
- package/src/stripe/server/Charge.ts +54 -1
- package/src/stripe/server/Methods.test-d.ts +157 -0
- package/src/stripe/server/Methods.test.ts +403 -0
- package/src/stripe/server/Methods.ts +423 -6
- package/src/stripe/server/internal/deposit-address.ts +57 -0
- package/src/stripe/server/internal/html/node_modules/.bin/mppx +3 -3
- package/src/stripe/server/internal/html/package.json +1 -1
- package/src/stripe/server/internal/html.gen.ts +1 -1
- package/src/stripe/server/internal/record-payment.ts +66 -0
- package/src/stripe/server/internal/request.ts +49 -0
- package/src/tap/Constants.ts +32 -0
- package/src/tap/Tap.test.ts +125 -0
- package/src/tap/Types.ts +11 -0
- package/src/tap/client/index.ts +54 -0
- package/src/tap/index.ts +4 -0
- package/src/tap/server/index.ts +48 -0
- package/src/tempo/PublicExports.test-d.ts +3 -3
- package/src/tempo/client/Charge.ts +1 -19
- package/src/tempo/internal/address.test.ts +42 -0
- package/src/tempo/internal/address.ts +3 -3
- package/src/tempo/internal/auto-swap.test.ts +4 -4
- package/src/tempo/internal/auto-swap.ts +7 -50
- package/src/tempo/legacy/README.md +5 -5
- package/src/tempo/legacy/index.ts +1 -3
- package/src/tempo/server/AtomicStore.test-d.ts +13 -0
- package/src/tempo/server/Charge.test.ts +19 -84
- package/src/tempo/server/Charge.ts +83 -55
- package/src/tempo/server/Methods.ts +0 -20
- package/src/tempo/server/Relay.test.ts +5 -5
- package/src/tempo/server/Relay.ts +2 -2
- package/src/tempo/server/Subscription.ts +4 -1
- package/src/tempo/server/index.ts +1 -1
- package/src/tempo/server/internal/html/node_modules/.bin/mppx +3 -3
- package/src/tempo/server/internal/html/package.json +1 -1
- package/src/tempo/server/internal/html.gen.ts +1 -1
- package/src/tempo/server/internal/transport.test.ts +22 -3
- package/src/tempo/server/internal/transport.ts +15 -3
- package/src/tempo/session/README.md +112 -0
- package/src/tempo/session/precompile/Chain.ts +131 -11
- package/src/tempo/session/server/ChannelStore.ts +33 -12
- package/src/tempo/session/server/CredentialVerification.test.ts +4 -4
- package/src/tempo/session/server/CredentialVerification.ts +340 -28
- package/src/tempo/session/server/MeteredStream.ts +5 -1
- package/src/tempo/session/server/Session.test.ts +428 -43
- package/src/tempo/session/server/Session.ts +159 -60
- package/src/tempo/session/server/Sse.test.ts +77 -0
- package/src/tempo/session/server/Sse.ts +8 -1
- package/src/tempo/session/server/Transports.ts +2 -1
- package/src/tempo/session/server/Ws.test.ts +171 -0
- package/src/tempo/session/server/Ws.ts +7 -1
- package/src/web-bot-auth/Constants.ts +24 -0
- package/src/web-bot-auth/Types.ts +9 -0
- package/src/web-bot-auth/WebBotAuth.test.ts +182 -0
- package/src/web-bot-auth/client/index.ts +84 -0
- package/src/web-bot-auth/index.ts +6 -0
- package/src/web-bot-auth/internal/JwkThumbprint.ts +21 -0
- package/src/web-bot-auth/internal/SignatureAgent.ts +18 -0
- package/src/web-bot-auth/server/index.ts +113 -0
- package/src/x402/Exact.e2e.test.ts +121 -81
- package/src/x402/Exact.localnet.test.ts +1 -1
- package/src/x402/server/EvmCharge.ts +35 -19
- package/dist/tempo/legacy/server/Session.d.ts +0 -208
- package/dist/tempo/legacy/server/Session.d.ts.map +0 -1
- package/dist/tempo/legacy/server/Session.js +0 -698
- package/dist/tempo/legacy/server/Session.js.map +0 -1
- package/dist/tempo/legacy/server/index.d.ts +0 -5
- package/dist/tempo/legacy/server/index.d.ts.map +0 -1
- package/dist/tempo/legacy/server/index.js +0 -5
- package/dist/tempo/legacy/server/index.js.map +0 -1
- package/dist/tempo/legacy/session/ChannelStore.d.ts +0 -22
- package/dist/tempo/legacy/session/ChannelStore.d.ts.map +0 -1
- package/dist/tempo/legacy/session/ChannelStore.js +0 -6
- package/dist/tempo/legacy/session/ChannelStore.js.map +0 -1
- package/src/tempo/legacy/server/Defaults.test-d.ts +0 -9
- package/src/tempo/legacy/server/Session.test.ts +0 -6370
- package/src/tempo/legacy/server/Session.ts +0 -1024
- package/src/tempo/legacy/server/index.ts +0 -4
- package/src/tempo/legacy/session/ChannelStore.test.ts +0 -58
- package/src/tempo/legacy/session/ChannelStore.ts +0 -39
|
@@ -77,38 +77,6 @@ describe('http', () => {
|
|
|
77
77
|
})
|
|
78
78
|
})
|
|
79
79
|
|
|
80
|
-
describe('getChallenge', () => {
|
|
81
|
-
test('default', () => {
|
|
82
|
-
const transport = Transport.http()
|
|
83
|
-
const response = new Response(null, {
|
|
84
|
-
status: 402,
|
|
85
|
-
headers: {
|
|
86
|
-
'WWW-Authenticate': Challenge.serialize(challenge),
|
|
87
|
-
},
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
expect(transport.getChallenge(response)).toMatchObject({
|
|
91
|
-
expires: '2025-01-01T00:00:00.000Z',
|
|
92
|
-
id: expect.any(String),
|
|
93
|
-
intent: 'charge',
|
|
94
|
-
method: 'tempo',
|
|
95
|
-
realm: 'api.example.com',
|
|
96
|
-
request: {
|
|
97
|
-
amount: '1000',
|
|
98
|
-
currency: '0x20c0000000000000000000000000000000000001',
|
|
99
|
-
recipient: '0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00',
|
|
100
|
-
},
|
|
101
|
-
})
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
test('throws for non-402 response', () => {
|
|
105
|
-
const transport = Transport.http()
|
|
106
|
-
const response = new Response(null, { status: 200 })
|
|
107
|
-
|
|
108
|
-
expect(() => transport.getChallenge(response)).toThrow()
|
|
109
|
-
})
|
|
110
|
-
})
|
|
111
|
-
|
|
112
80
|
describe('getChallenges', () => {
|
|
113
81
|
test.each([
|
|
114
82
|
{
|
|
@@ -188,7 +156,7 @@ describe('http', () => {
|
|
|
188
156
|
status: 402,
|
|
189
157
|
headers: headers(),
|
|
190
158
|
})
|
|
191
|
-
const challenges =
|
|
159
|
+
const challenges = await transport.getChallenges(response)
|
|
192
160
|
|
|
193
161
|
expect(challenges.map((entry) => entry.id)).toEqual(expectedIds)
|
|
194
162
|
expect(challenges.map((entry) => entry.method)).toEqual(expectedMethods)
|
|
@@ -207,7 +175,7 @@ describe('http', () => {
|
|
|
207
175
|
},
|
|
208
176
|
})
|
|
209
177
|
|
|
210
|
-
const challenges =
|
|
178
|
+
const challenges = await transport.getChallenges(response)
|
|
211
179
|
|
|
212
180
|
expect(challenges.map((entry) => entry.id)).toEqual([challenge.id])
|
|
213
181
|
expect(challenges.map((entry) => entry.method)).toEqual(['tempo'])
|
|
@@ -225,9 +193,8 @@ describe('http', () => {
|
|
|
225
193
|
},
|
|
226
194
|
})
|
|
227
195
|
|
|
228
|
-
const challenges =
|
|
196
|
+
const challenges = await transport.getChallenges(response)
|
|
229
197
|
expect(challenges).toEqual([])
|
|
230
|
-
expect(() => transport.getChallenge(response)).toThrow('No challenge in response.')
|
|
231
198
|
})
|
|
232
199
|
})
|
|
233
200
|
|
|
@@ -265,7 +232,7 @@ describe('http', () => {
|
|
|
265
232
|
|
|
266
233
|
test('writes x402 credentials for x402 challenges from the same transport', () => {
|
|
267
234
|
const transport = Transport.http()
|
|
268
|
-
const [x402Challenge] = transport.getChallenges
|
|
235
|
+
const [x402Challenge] = transport.getChallenges(
|
|
269
236
|
new Response(null, {
|
|
270
237
|
status: 402,
|
|
271
238
|
headers: {
|
|
@@ -306,7 +273,7 @@ describe('http', () => {
|
|
|
306
273
|
method: 'POST',
|
|
307
274
|
body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'tools/call', params: {} }),
|
|
308
275
|
} satisfies RequestInit
|
|
309
|
-
const [nativeChallenge] = transport.getChallenges
|
|
276
|
+
const [nativeChallenge] = transport.getChallenges(
|
|
310
277
|
new Response(null, {
|
|
311
278
|
status: 402,
|
|
312
279
|
headers: { 'WWW-Authenticate': Challenge.serialize(challenge) },
|
|
@@ -326,7 +293,7 @@ describe('http', () => {
|
|
|
326
293
|
test('marks x402 challenges with the brand the evm charge client reads', async () => {
|
|
327
294
|
// Provenance guard: `evm/client/Charge.ts` recognizes x402 challenges via the same
|
|
328
295
|
// brand the x402 adapter stamps. If the marking site drifts, EVM x402 charges misroute.
|
|
329
|
-
const [x402Challenge] = await Transport.http().getChallenges
|
|
296
|
+
const [x402Challenge] = await Transport.http().getChallenges(
|
|
330
297
|
new Response(null, {
|
|
331
298
|
status: 402,
|
|
332
299
|
headers: {
|
|
@@ -339,7 +306,7 @@ describe('http', () => {
|
|
|
339
306
|
|
|
340
307
|
test('removes stale credential headers before setting the retry credential', async () => {
|
|
341
308
|
const transport = Transport.http()
|
|
342
|
-
const [x402Challenge] = await transport.getChallenges
|
|
309
|
+
const [x402Challenge] = await transport.getChallenges(
|
|
343
310
|
new Response(null, {
|
|
344
311
|
status: 402,
|
|
345
312
|
headers: {
|
|
@@ -497,16 +464,16 @@ describe('http (MCP-over-HTTP)', () => {
|
|
|
497
464
|
expect(await Transport.http().isPaymentRequired(ok, jsonRpcRequest)).toBe(false)
|
|
498
465
|
})
|
|
499
466
|
test('getChallenges extracts the MCP challenge (via the mcp protocol)', async () => {
|
|
500
|
-
const challenges = await Transport.http().getChallenges
|
|
467
|
+
const challenges = await Transport.http().getChallenges(sseBody(), jsonRpcRequest)
|
|
501
468
|
expect(challenges.map((entry) => entry.id)).toEqual([challenge.id])
|
|
502
469
|
})
|
|
503
470
|
test('getChallenges extracts an MCP result metadata challenge', async () => {
|
|
504
|
-
const challenges = await Transport.http().getChallenges
|
|
471
|
+
const challenges = await Transport.http().getChallenges(jsonResultBody(), jsonRpcRequest)
|
|
505
472
|
expect(challenges.map((entry) => entry.id)).toEqual([challenge.id])
|
|
506
473
|
})
|
|
507
474
|
test('setCredential routes the MCP challenge into the JSON-RPC _meta', async () => {
|
|
508
475
|
const transport = Transport.http()
|
|
509
|
-
const [mcpChallenge] = await transport.getChallenges
|
|
476
|
+
const [mcpChallenge] = await transport.getChallenges(sseBody(), jsonRpcRequest)
|
|
510
477
|
const result = transport.setCredential(jsonRpcRequest, Credential.serialize(credential), {
|
|
511
478
|
challenge: mcpChallenge,
|
|
512
479
|
}) as RequestInit
|
|
@@ -593,7 +560,7 @@ describe('mcp', () => {
|
|
|
593
560
|
const transport = Transport.mcp()
|
|
594
561
|
|
|
595
562
|
expect(await transport.isPaymentRequired(mcpResponse)).toBe(true)
|
|
596
|
-
expect((await transport.getChallenges
|
|
563
|
+
expect((await transport.getChallenges(mcpResponse)).map((entry) => entry.id)).toEqual([
|
|
597
564
|
challenge.id,
|
|
598
565
|
])
|
|
599
566
|
})
|
|
@@ -602,7 +569,7 @@ describe('mcp', () => {
|
|
|
602
569
|
const transport = Transport.mcp()
|
|
603
570
|
|
|
604
571
|
expect(await transport.isPaymentRequired(mcpResult)).toBe(true)
|
|
605
|
-
expect((await transport.getChallenges
|
|
572
|
+
expect((await transport.getChallenges(mcpResult)).map((entry) => entry.id)).toEqual([
|
|
606
573
|
challenge.id,
|
|
607
574
|
])
|
|
608
575
|
})
|
package/src/client/Transport.ts
CHANGED
|
@@ -21,16 +21,11 @@ export type Transport<in out request = unknown, in out response = unknown> = {
|
|
|
21
21
|
* body reads) and be async (to read a response body).
|
|
22
22
|
*/
|
|
23
23
|
isPaymentRequired: (response: response, request?: request) => boolean | Promise<boolean>
|
|
24
|
-
/** Extracts all challenges from a payment-required response
|
|
25
|
-
getChallenges
|
|
24
|
+
/** Extracts all challenges from a payment-required response. */
|
|
25
|
+
getChallenges: (
|
|
26
26
|
response: response,
|
|
27
27
|
request?: request,
|
|
28
28
|
) => Challenge.Challenge[] | Promise<Challenge.Challenge[]>
|
|
29
|
-
/** Extracts the challenge from a payment-required response. */
|
|
30
|
-
getChallenge: (
|
|
31
|
-
response: response,
|
|
32
|
-
request?: request,
|
|
33
|
-
) => Challenge.Challenge | Promise<Challenge.Challenge>
|
|
34
29
|
/** Attaches a credential to a request. */
|
|
35
30
|
setCredential: (
|
|
36
31
|
request: request,
|
|
@@ -65,7 +60,7 @@ export type RequestOf<transport extends Transport> =
|
|
|
65
60
|
* const custom = Transport.from({
|
|
66
61
|
* name: 'custom',
|
|
67
62
|
* isPaymentRequired(response) { ... },
|
|
68
|
-
*
|
|
63
|
+
* getChallenges(response) { ... },
|
|
69
64
|
* setCredential(request, credential) { ... },
|
|
70
65
|
* })
|
|
71
66
|
* ```
|
|
@@ -125,16 +120,6 @@ export function http(): Transport<RequestInit, Response> {
|
|
|
125
120
|
return collect(response, request)
|
|
126
121
|
},
|
|
127
122
|
|
|
128
|
-
getChallenge(response, request) {
|
|
129
|
-
const pick = (challenges: Challenge.Challenge[]): Challenge.Challenge => {
|
|
130
|
-
const challenge = challenges[0]
|
|
131
|
-
if (!challenge) throw new Error('No challenge in response.')
|
|
132
|
-
return challenge
|
|
133
|
-
}
|
|
134
|
-
const challenges = collect(response, request)
|
|
135
|
-
return challenges instanceof Promise ? challenges.then(pick) : pick(challenges)
|
|
136
|
-
},
|
|
137
|
-
|
|
138
123
|
setCredential(request, credential, options) {
|
|
139
124
|
const protocol = options?.challenge ? protocolForChallenge.get(options.challenge) : undefined
|
|
140
125
|
const fallback = protocols[0]
|
|
@@ -168,12 +153,6 @@ export function mcp() {
|
|
|
168
153
|
return mcpPaymentRequiredChallenges(response)
|
|
169
154
|
},
|
|
170
155
|
|
|
171
|
-
getChallenge(response) {
|
|
172
|
-
const challenge = mcpPaymentRequiredChallenges(response)[0]
|
|
173
|
-
if (!challenge) throw new Error('No challenge in response.')
|
|
174
|
-
return challenge
|
|
175
|
-
},
|
|
176
|
-
|
|
177
156
|
setCredential(request, credential) {
|
|
178
157
|
const parsed = Credential.deserialize(credential)
|
|
179
158
|
return {
|
|
@@ -238,9 +238,7 @@ export function from<const methods extends readonly Method.AnyClient[]>(
|
|
|
238
238
|
|
|
239
239
|
try {
|
|
240
240
|
for (let retry = 0; retry < maxPaymentRetries; retry++) {
|
|
241
|
-
challenges = transport.getChallenges
|
|
242
|
-
? await transport.getChallenges(response, transportRequest as never)
|
|
243
|
-
: [await transport.getChallenge(response, transportRequest as never)]
|
|
241
|
+
challenges = await transport.getChallenges(response, transportRequest as never)
|
|
244
242
|
|
|
245
243
|
const candidates = AcceptPayment.selectChallengeCandidates(
|
|
246
244
|
challenges,
|
|
@@ -420,9 +418,7 @@ export function from<const methods extends readonly Method.AnyClient[]>(
|
|
|
420
418
|
}
|
|
421
419
|
challenges = undefined
|
|
422
420
|
try {
|
|
423
|
-
challenges = transport.getChallenges
|
|
424
|
-
? await transport.getChallenges(response, transportRequest as never)
|
|
425
|
-
: [await transport.getChallenge(response, transportRequest as never)]
|
|
421
|
+
challenges = await transport.getChallenges(response, transportRequest as never)
|
|
426
422
|
} catch {}
|
|
427
423
|
await settleAttempt(preparedCredential, {
|
|
428
424
|
challenges,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as Challenge from '../Challenge.js'
|
|
1
2
|
import * as Method from '../Method.js'
|
|
2
3
|
import * as Mppx from '../server/Mppx.js'
|
|
3
4
|
import * as z from '../zod.js'
|
|
@@ -56,6 +57,8 @@ const subscribe = Method.toServer(
|
|
|
56
57
|
credential: { payload: z.object({ signature: z.string() }) },
|
|
57
58
|
request: z.object({
|
|
58
59
|
amount: z.string(),
|
|
60
|
+
interval: z.string(),
|
|
61
|
+
recipient: z.string(),
|
|
59
62
|
}),
|
|
60
63
|
},
|
|
61
64
|
}),
|
|
@@ -69,6 +72,38 @@ const subscribe = Method.toServer(
|
|
|
69
72
|
},
|
|
70
73
|
)
|
|
71
74
|
|
|
75
|
+
const transformedCharge = Method.toServer(
|
|
76
|
+
Method.from({
|
|
77
|
+
intent: 'charge',
|
|
78
|
+
name: 'transformed',
|
|
79
|
+
schema: {
|
|
80
|
+
credential: { payload: z.object({ signature: z.string() }) },
|
|
81
|
+
request: z.pipe(
|
|
82
|
+
z.object({
|
|
83
|
+
amount: z.string(),
|
|
84
|
+
asset: z.string(),
|
|
85
|
+
decimals: z.number(),
|
|
86
|
+
recipient: z.string(),
|
|
87
|
+
}),
|
|
88
|
+
z.transform(({ amount, asset, decimals, recipient }) => ({
|
|
89
|
+
amount: String(Number(amount) * 10 ** decimals),
|
|
90
|
+
currency: asset,
|
|
91
|
+
methodDetails: { decimals },
|
|
92
|
+
recipient,
|
|
93
|
+
})),
|
|
94
|
+
),
|
|
95
|
+
},
|
|
96
|
+
}),
|
|
97
|
+
{
|
|
98
|
+
verify: async () => ({
|
|
99
|
+
method: 'transformed',
|
|
100
|
+
reference: '',
|
|
101
|
+
status: 'success' as const,
|
|
102
|
+
timestamp: '',
|
|
103
|
+
}),
|
|
104
|
+
},
|
|
105
|
+
)
|
|
106
|
+
|
|
72
107
|
function createMppx<const methods extends Mppx.Methods>(methods: methods) {
|
|
73
108
|
return Mppx.create({
|
|
74
109
|
methods,
|
|
@@ -169,6 +204,7 @@ describe('generate', () => {
|
|
|
169
204
|
{
|
|
170
205
|
"amount": "50",
|
|
171
206
|
"currency": "usd",
|
|
207
|
+
"description": "Search credits",
|
|
172
208
|
"intent": "charge",
|
|
173
209
|
"method": "tempo",
|
|
174
210
|
"recipient": "0x1",
|
|
@@ -182,6 +218,140 @@ describe('generate', () => {
|
|
|
182
218
|
`)
|
|
183
219
|
})
|
|
184
220
|
|
|
221
|
+
test('matches handler discovery to its canonical runtime challenge', async () => {
|
|
222
|
+
const mppx = createMppx([transformedCharge])
|
|
223
|
+
const handler = mppx.charge({
|
|
224
|
+
amount: '2',
|
|
225
|
+
asset: '0xUSDC',
|
|
226
|
+
decimals: 6,
|
|
227
|
+
description: 'Canonical price',
|
|
228
|
+
recipient: '0x1',
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
const doc = generate(mppx, {
|
|
232
|
+
routes: [{ handler, method: 'post', path: '/api/resource' }],
|
|
233
|
+
}) as any
|
|
234
|
+
const result = await handler(new Request('https://example.com/api/resource'))
|
|
235
|
+
if (result.status !== 402) throw new Error('Expected payment challenge')
|
|
236
|
+
const challenge = Challenge.fromResponse(result.challenge)
|
|
237
|
+
|
|
238
|
+
expect(doc.paths['/api/resource'].post['x-payment-info'].offers[0]).toEqual({
|
|
239
|
+
amount: challenge.request.amount,
|
|
240
|
+
currency: challenge.request.currency,
|
|
241
|
+
description: challenge.description,
|
|
242
|
+
intent: challenge.intent,
|
|
243
|
+
method: challenge.method,
|
|
244
|
+
recipient: challenge.request.recipient,
|
|
245
|
+
})
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
test('applies method schema transforms to legacy route discovery', () => {
|
|
249
|
+
const mppx = createMppx([transformedCharge])
|
|
250
|
+
const doc = generate(mppx, {
|
|
251
|
+
routes: [
|
|
252
|
+
{
|
|
253
|
+
intent: 'charge',
|
|
254
|
+
method: 'post',
|
|
255
|
+
options: {
|
|
256
|
+
amount: '2',
|
|
257
|
+
asset: '0xUSDC',
|
|
258
|
+
decimals: 6,
|
|
259
|
+
description: 'Canonical price',
|
|
260
|
+
recipient: '0x1',
|
|
261
|
+
},
|
|
262
|
+
path: '/api/resource',
|
|
263
|
+
},
|
|
264
|
+
],
|
|
265
|
+
}) as any
|
|
266
|
+
|
|
267
|
+
expect(doc.paths['/api/resource'].post['x-payment-info'].offers[0]).toEqual({
|
|
268
|
+
amount: '2000000',
|
|
269
|
+
currency: '0xUSDC',
|
|
270
|
+
description: 'Canonical price',
|
|
271
|
+
intent: 'charge',
|
|
272
|
+
method: 'transformed',
|
|
273
|
+
recipient: '0x1',
|
|
274
|
+
})
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
test('derives only explicitly composed payment offers from a handler', () => {
|
|
278
|
+
const mppx = createMppx([charge, session])
|
|
279
|
+
const handler = mppx.compose(
|
|
280
|
+
['tempo/charge', { amount: '50', currency: '0xUSDC', description: 'USDC', recipient: '0x1' }],
|
|
281
|
+
[
|
|
282
|
+
'tempo/charge',
|
|
283
|
+
{ amount: '50', currency: '0xNANOUSD', description: 'NANOUSD', recipient: '0x1' },
|
|
284
|
+
],
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
const doc = generate(mppx, {
|
|
288
|
+
routes: [{ handler, method: 'post', path: '/api/search' }],
|
|
289
|
+
}) as any
|
|
290
|
+
|
|
291
|
+
expect(doc.paths['/api/search'].post['x-payment-info'].offers).toEqual([
|
|
292
|
+
{
|
|
293
|
+
amount: '50',
|
|
294
|
+
currency: '0xUSDC',
|
|
295
|
+
description: 'USDC',
|
|
296
|
+
intent: 'charge',
|
|
297
|
+
method: 'tempo',
|
|
298
|
+
recipient: '0x1',
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
amount: '50',
|
|
302
|
+
currency: '0xNANOUSD',
|
|
303
|
+
description: 'NANOUSD',
|
|
304
|
+
intent: 'charge',
|
|
305
|
+
method: 'tempo',
|
|
306
|
+
recipient: '0x1',
|
|
307
|
+
},
|
|
308
|
+
])
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
test('keeps nested composed discovery in runtime challenge order', async () => {
|
|
312
|
+
const mppx = createMppx([charge])
|
|
313
|
+
const handler = Mppx.compose(
|
|
314
|
+
mppx.charge({
|
|
315
|
+
amount: '1',
|
|
316
|
+
currency: '0xUSDC',
|
|
317
|
+
description: 'USDC',
|
|
318
|
+
recipient: '0x1',
|
|
319
|
+
}),
|
|
320
|
+
Mppx.compose(
|
|
321
|
+
mppx.charge({
|
|
322
|
+
amount: '2',
|
|
323
|
+
currency: '0xNANOUSD',
|
|
324
|
+
description: 'NANOUSD',
|
|
325
|
+
recipient: '0x1',
|
|
326
|
+
}),
|
|
327
|
+
mppx.charge({
|
|
328
|
+
amount: '3',
|
|
329
|
+
currency: 'usd',
|
|
330
|
+
description: 'Card',
|
|
331
|
+
recipient: '0x1',
|
|
332
|
+
}),
|
|
333
|
+
),
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
const doc = generate(mppx, {
|
|
337
|
+
routes: [{ handler, method: 'post', path: '/api/search' }],
|
|
338
|
+
}) as any
|
|
339
|
+
const result = await handler(new Request('https://example.com/api/search'))
|
|
340
|
+
if (result.status !== 402) throw new Error('Expected payment challenge')
|
|
341
|
+
|
|
342
|
+
const discovered = doc.paths['/api/search'].post['x-payment-info'].offers
|
|
343
|
+
const challenged = Challenge.fromResponseList(result.challenge).map((challenge) => ({
|
|
344
|
+
amount: challenge.request.amount,
|
|
345
|
+
currency: challenge.request.currency,
|
|
346
|
+
description: challenge.description,
|
|
347
|
+
intent: challenge.intent,
|
|
348
|
+
method: challenge.method,
|
|
349
|
+
recipient: challenge.request.recipient,
|
|
350
|
+
}))
|
|
351
|
+
|
|
352
|
+
expect(discovered).toEqual(challenged)
|
|
353
|
+
})
|
|
354
|
+
|
|
185
355
|
test('handles null amount for session intent', () => {
|
|
186
356
|
const mppx = createMppx([session])
|
|
187
357
|
const doc = generate(mppx, {
|
package/src/discovery/OpenApi.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import type * as Method from '../Method.js'
|
|
2
|
+
import * as PaymentRequest from '../PaymentRequest.js'
|
|
2
3
|
import { PaymentInfo, type ServiceInfo } from './Discovery.js'
|
|
4
|
+
import * as Metadata from './internal/Metadata.js'
|
|
3
5
|
|
|
6
|
+
/** Payment handler carrying metadata used to generate discovery documents. */
|
|
4
7
|
export type DiscoveryHandler = ((...args: any[]) => unknown) & {
|
|
5
|
-
_internal?:
|
|
6
|
-
_canonicalRequest: Record<string, unknown>
|
|
7
|
-
intent: string
|
|
8
|
-
name: string
|
|
9
|
-
}
|
|
8
|
+
_internal?: Metadata.Metadata
|
|
10
9
|
}
|
|
11
10
|
|
|
12
11
|
export type LegacyRouteConfig = {
|
|
@@ -151,11 +150,9 @@ function resolveRoute(
|
|
|
151
150
|
return {
|
|
152
151
|
method: route.method,
|
|
153
152
|
path: route.path,
|
|
154
|
-
payment:
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
method: internal.name,
|
|
158
|
-
}),
|
|
153
|
+
payment: {
|
|
154
|
+
offers: Metadata.offers(internal).map(Metadata.paymentOffer),
|
|
155
|
+
},
|
|
159
156
|
...(route.requestBody ? { requestBody: route.requestBody } : {}),
|
|
160
157
|
...(route.summary ? { summary: route.summary } : {}),
|
|
161
158
|
}
|
|
@@ -168,52 +165,23 @@ function resolveRoute(
|
|
|
168
165
|
)
|
|
169
166
|
}
|
|
170
167
|
|
|
168
|
+
const { description, ...options } = route.options
|
|
169
|
+
const metadata: Metadata.Offer = {
|
|
170
|
+
_canonicalRequest: PaymentRequest.fromMethod(mi, options as never),
|
|
171
|
+
...(typeof description === 'string' ? { description } : {}),
|
|
172
|
+
intent: mi.intent,
|
|
173
|
+
name: mi.name,
|
|
174
|
+
}
|
|
175
|
+
|
|
171
176
|
return {
|
|
172
177
|
method: route.method,
|
|
173
178
|
path: route.path,
|
|
174
|
-
payment:
|
|
175
|
-
canonicalRequest: route.options,
|
|
176
|
-
intent: mi.intent,
|
|
177
|
-
method: mi.name,
|
|
178
|
-
}),
|
|
179
|
+
payment: Metadata.paymentOffer(metadata),
|
|
179
180
|
...(route.requestBody ? { requestBody: route.requestBody } : {}),
|
|
180
181
|
...(route.summary ? { summary: route.summary } : {}),
|
|
181
182
|
}
|
|
182
183
|
}
|
|
183
184
|
|
|
184
|
-
function paymentInfoFromCanonical(route: {
|
|
185
|
-
canonicalRequest: Record<string, unknown>
|
|
186
|
-
intent: string
|
|
187
|
-
method: string
|
|
188
|
-
}) {
|
|
189
|
-
const { canonicalRequest, intent, method } = route
|
|
190
|
-
const methodDetails = (canonicalRequest.methodDetails ?? {}) as Record<string, unknown>
|
|
191
|
-
|
|
192
|
-
const amount = pickString(canonicalRequest.amount) ?? pickString(methodDetails.amount) ?? null
|
|
193
|
-
const currency = pickString(canonicalRequest.currency) ?? pickString(methodDetails.currency)
|
|
194
|
-
const description = pickString(canonicalRequest.description)
|
|
195
|
-
|
|
196
|
-
const base: Record<string, unknown> = {
|
|
197
|
-
amount,
|
|
198
|
-
...(currency ? { currency } : {}),
|
|
199
|
-
...(description ? { description } : {}),
|
|
200
|
-
intent,
|
|
201
|
-
method,
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Forward any extra canonical params that aren't already covered.
|
|
205
|
-
const reserved = new Set(['amount', 'currency', 'description', 'methodDetails'])
|
|
206
|
-
for (const [key, value] of Object.entries(canonicalRequest)) {
|
|
207
|
-
if (!reserved.has(key) && value !== undefined) base[key] = value
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
return base
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
function pickString(value: unknown) {
|
|
214
|
-
return typeof value === 'string' ? value : undefined
|
|
215
|
-
}
|
|
216
|
-
|
|
217
185
|
function withBasePath(basePath: string | undefined, path: string) {
|
|
218
186
|
if (!basePath) return path
|
|
219
187
|
const normalizedBasePath = basePath.startsWith('/') ? basePath : `/${basePath}`
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/** Metadata retained by one explicitly configured payment handler. */
|
|
2
|
+
export type Offer = {
|
|
3
|
+
_canonicalRequest: Record<string, unknown>
|
|
4
|
+
description?: string | undefined
|
|
5
|
+
intent: string
|
|
6
|
+
name: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Metadata retained by a single or composed payment handler. */
|
|
10
|
+
export type Metadata = Offer | { offers: readonly Offer[] }
|
|
11
|
+
|
|
12
|
+
/** Returns every explicitly configured offer from discovery metadata. */
|
|
13
|
+
export function offers(metadata: Metadata): readonly Offer[] {
|
|
14
|
+
if (isComposed(metadata)) return metadata.offers
|
|
15
|
+
return [metadata]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Converts configured handler metadata into a discovery payment offer. */
|
|
19
|
+
export function paymentOffer(metadata: Offer): Record<string, unknown> {
|
|
20
|
+
const { _canonicalRequest: request, intent, name: method } = metadata
|
|
21
|
+
const methodDetails = (request.methodDetails ?? {}) as Record<string, unknown>
|
|
22
|
+
|
|
23
|
+
const amount = pickString(request.amount) ?? pickString(methodDetails.amount) ?? null
|
|
24
|
+
const currency = pickString(request.currency) ?? pickString(methodDetails.currency)
|
|
25
|
+
const description = pickString(metadata.description) ?? pickString(request.description)
|
|
26
|
+
|
|
27
|
+
const offer: Record<string, unknown> = {
|
|
28
|
+
amount,
|
|
29
|
+
...(currency ? { currency } : {}),
|
|
30
|
+
...(description ? { description } : {}),
|
|
31
|
+
intent,
|
|
32
|
+
method,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Preserve extension fields emitted by method request schemas.
|
|
36
|
+
const reserved = new Set(['amount', 'currency', 'description', 'methodDetails'])
|
|
37
|
+
for (const [key, value] of Object.entries(request)) {
|
|
38
|
+
if (!reserved.has(key) && value !== undefined) offer[key] = value
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return offer
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Returns whether metadata represents a composed handler. */
|
|
45
|
+
export function isComposed(metadata: Metadata): metadata is Extract<Metadata, { offers: unknown }> {
|
|
46
|
+
return 'offers' in metadata && !('_canonicalRequest' in metadata)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function pickString(value: unknown) {
|
|
50
|
+
return typeof value === 'string' ? value : undefined
|
|
51
|
+
}
|
package/src/evm/server/Charge.ts
CHANGED
|
@@ -24,6 +24,8 @@ export function charge(parameters: charge.NativeConfig): Method.AnyServer {
|
|
|
24
24
|
const transport = httpTransport(paths)
|
|
25
25
|
|
|
26
26
|
return Method.toServer<typeof Methods.charge, charge.Defaults, typeof transport>(Methods.charge, {
|
|
27
|
+
canOffer: parameters.canOffer,
|
|
28
|
+
onPaymentSuccess: parameters.onPaymentSuccess,
|
|
27
29
|
defaults: {
|
|
28
30
|
chainId: config.chainId,
|
|
29
31
|
currency: config.currency,
|
|
@@ -107,7 +109,10 @@ export declare namespace charge {
|
|
|
107
109
|
type Parameters = NativeConfig
|
|
108
110
|
type Native = Method.Server<typeof Methods.charge, Defaults>
|
|
109
111
|
|
|
110
|
-
type NativeConfig = BaseConfig &
|
|
112
|
+
type NativeConfig = BaseConfig &
|
|
113
|
+
CurrencyConfig &
|
|
114
|
+
RecipientConfig &
|
|
115
|
+
Method.ComposableHooks<typeof Methods.charge>
|
|
111
116
|
|
|
112
117
|
type BaseConfig = {
|
|
113
118
|
/** EIP-3009 token domain metadata. Required for raw addresses and viem tokens; inferred for known assets. */
|
|
@@ -226,21 +226,21 @@ describe('AcceptPayment', () => {
|
|
|
226
226
|
test('selectChallengeCandidates supports duplicate method keys with challenge predicates', () => {
|
|
227
227
|
const challenges = [
|
|
228
228
|
{
|
|
229
|
-
id: '
|
|
229
|
+
id: 'primary',
|
|
230
230
|
intent: 'session',
|
|
231
231
|
method: 'tempo',
|
|
232
232
|
realm: 'test',
|
|
233
|
-
request: { methodDetails: { sessionProtocol: '
|
|
233
|
+
request: { methodDetails: { sessionProtocol: 'primary' } },
|
|
234
234
|
},
|
|
235
235
|
{
|
|
236
|
-
id: '
|
|
236
|
+
id: 'fallback',
|
|
237
237
|
intent: 'session',
|
|
238
238
|
method: 'tempo',
|
|
239
239
|
realm: 'test',
|
|
240
|
-
request: { methodDetails: { sessionProtocol: '
|
|
240
|
+
request: { methodDetails: { sessionProtocol: 'fallback' } },
|
|
241
241
|
},
|
|
242
242
|
{
|
|
243
|
-
id: '
|
|
243
|
+
id: 'unmarked',
|
|
244
244
|
intent: 'session',
|
|
245
245
|
method: 'tempo',
|
|
246
246
|
realm: 'test',
|
|
@@ -257,7 +257,7 @@ describe('AcceptPayment', () => {
|
|
|
257
257
|
challenge: AcceptPayment.ChallengeCandidate['challenge']
|
|
258
258
|
}) =>
|
|
259
259
|
(challenge.request.methodDetails as { sessionProtocol?: string } | undefined)
|
|
260
|
-
?.sessionProtocol === '
|
|
260
|
+
?.sessionProtocol === 'primary',
|
|
261
261
|
},
|
|
262
262
|
{
|
|
263
263
|
name: 'tempo',
|
|
@@ -270,7 +270,7 @@ describe('AcceptPayment', () => {
|
|
|
270
270
|
const sessionProtocol = (
|
|
271
271
|
challenge.request.methodDetails as { sessionProtocol?: string } | undefined
|
|
272
272
|
)?.sessionProtocol
|
|
273
|
-
return sessionProtocol === undefined || sessionProtocol === '
|
|
273
|
+
return sessionProtocol === undefined || sessionProtocol === 'fallback'
|
|
274
274
|
},
|
|
275
275
|
},
|
|
276
276
|
] as const
|
|
@@ -281,7 +281,11 @@ describe('AcceptPayment', () => {
|
|
|
281
281
|
AcceptPayment.parse('tempo/session'),
|
|
282
282
|
)
|
|
283
283
|
|
|
284
|
-
expect(candidates.map(({ challenge }) => challenge.id)).toEqual([
|
|
284
|
+
expect(candidates.map(({ challenge }) => challenge.id)).toEqual([
|
|
285
|
+
'primary',
|
|
286
|
+
'fallback',
|
|
287
|
+
'unmarked',
|
|
288
|
+
])
|
|
285
289
|
})
|
|
286
290
|
|
|
287
291
|
test('selectChallenge honors a specific opt-out over a broader wildcard', () => {
|
package/src/internal/types.ts
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
// https://twitter.com/mattpocockuk/status/1622730173446557697?s=20&t=NdpAcmEFXY01xkqU3KO0Mg
|
|
3
3
|
export type Compute<type> = { [key in keyof type]: type[key] } & unknown
|
|
4
4
|
|
|
5
|
+
/** Recursively makes every property of a value readonly. */
|
|
6
|
+
export type DeepReadonly<type> = type extends (...args: infer _arguments) => infer _return
|
|
7
|
+
? type
|
|
8
|
+
: type extends readonly unknown[]
|
|
9
|
+
? { readonly [key in keyof type]: DeepReadonly<type[key]> }
|
|
10
|
+
: type extends object
|
|
11
|
+
? { readonly [key in keyof type]: DeepReadonly<type[key]> }
|
|
12
|
+
: type
|
|
13
|
+
|
|
5
14
|
declare const symbol: unique symbol
|
|
6
15
|
|
|
7
16
|
/**
|