mppx 0.8.14 → 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 +57 -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/cli/validate/payment.d.ts.map +1 -1
- package/dist/cli/validate/payment.js +18 -4
- package/dist/cli/validate/payment.js.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 +92 -13
- package/dist/client/internal/Fetch.js.map +1 -1
- package/dist/client/internal/MethodChallenge.d.ts +2 -0
- package/dist/client/internal/MethodChallenge.d.ts.map +1 -1
- package/dist/client/internal/MethodChallenge.js +4 -0
- package/dist/client/internal/MethodChallenge.js.map +1 -1
- package/dist/client/internal/MethodResponse.d.ts +15 -0
- package/dist/client/internal/MethodResponse.d.ts.map +1 -1
- package/dist/client/internal/MethodResponse.js +10 -0
- package/dist/client/internal/MethodResponse.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 +34 -12
- 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 +14 -5
- package/dist/tempo/server/Relay.d.ts.map +1 -1
- package/dist/tempo/server/Relay.js +6 -4
- package/dist/tempo/server/Relay.js.map +1 -1
- package/dist/tempo/server/SponsorBudget.d.ts.map +1 -1
- package/dist/tempo/server/SponsorBudget.js +7 -1
- package/dist/tempo/server/SponsorBudget.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.d.ts.map +1 -1
- package/dist/tempo/session/client/Session.js +128 -14
- package/dist/tempo/session/client/Session.js.map +1 -1
- package/dist/tempo/session/client/SessionManager.d.ts.map +1 -1
- package/dist/tempo/session/client/SessionManager.js +62 -20
- package/dist/tempo/session/client/SessionManager.js.map +1 -1
- package/dist/tempo/session/client/Transports.d.ts +9 -1
- package/dist/tempo/session/client/Transports.d.ts.map +1 -1
- package/dist/tempo/session/client/Transports.js +36 -13
- package/dist/tempo/session/client/Transports.js.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 +4 -0
- package/dist/tempo/session/server/Ws.js.map +1 -1
- package/dist/tempo/subscription/KeyAuthorization.d.ts +38 -866
- package/dist/tempo/subscription/KeyAuthorization.d.ts.map +1 -1
- package/dist/tempo/subscription/KeyAuthorization.js +14 -3
- package/dist/tempo/subscription/KeyAuthorization.js.map +1 -1
- package/dist/viem/Account.d.ts.map +1 -1
- package/dist/viem/Account.js.map +1 -1
- package/dist/viem/Client.d.ts.map +1 -1
- package/dist/viem/Client.js +6 -1
- package/dist/viem/Client.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 +20 -4
- 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/cli/validate/payment.ts +18 -4
- package/src/cli/validate.test.ts +16 -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.test.ts +77 -0
- package/src/client/internal/Fetch.ts +112 -14
- package/src/client/internal/MethodChallenge.ts +5 -0
- package/src/client/internal/MethodResponse.ts +28 -0
- 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 +92 -56
- package/src/tempo/server/Methods.ts +0 -20
- package/src/tempo/server/Relay.test.ts +161 -7
- package/src/tempo/server/Relay.ts +15 -6
- package/src/tempo/server/SponsorBudget.test.ts +29 -0
- package/src/tempo/server/SponsorBudget.ts +7 -1
- 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 +119 -0
- package/src/tempo/session/client/Session.test.ts +299 -33
- package/src/tempo/session/client/Session.ts +152 -16
- package/src/tempo/session/client/SessionManager.test.ts +216 -9
- package/src/tempo/session/client/SessionManager.ts +63 -17
- package/src/tempo/session/client/Transports.test.ts +22 -0
- package/src/tempo/session/client/Transports.ts +58 -22
- 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 +483 -36
- 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 +10 -1
- package/src/tempo/subscription/KeyAuthorization.test.ts +70 -1
- package/src/tempo/subscription/KeyAuthorization.ts +14 -3
- package/src/viem/Client.test.ts +18 -1
- package/src/viem/Client.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 {
|
|
@@ -10,6 +10,7 @@ import { rpcUrl } from '~test/tempo/rpc.js'
|
|
|
10
10
|
import { accounts, asset, chain, client, http } from '~test/tempo/viem.js'
|
|
11
11
|
|
|
12
12
|
import * as Fetch from './Fetch.js'
|
|
13
|
+
import * as MethodChallenge from './MethodChallenge.js'
|
|
13
14
|
import * as MethodResponse from './MethodResponse.js'
|
|
14
15
|
|
|
15
16
|
const realm = 'api.example.com'
|
|
@@ -337,6 +338,23 @@ const noopMethod = {
|
|
|
337
338
|
createCredential: async () => 'credential',
|
|
338
339
|
} as any
|
|
339
340
|
|
|
341
|
+
function trackedMethod(settlements: MethodResponse.AttemptOutcome['status'][]) {
|
|
342
|
+
const method = {
|
|
343
|
+
...noopMethod,
|
|
344
|
+
async createCredential(parameters: object) {
|
|
345
|
+
const attempt = MethodResponse.getAttempt(parameters)
|
|
346
|
+
if (attempt)
|
|
347
|
+
attempt.settle = (outcome) => {
|
|
348
|
+
settlements.push(outcome.status)
|
|
349
|
+
return outcome.status !== 'pending'
|
|
350
|
+
}
|
|
351
|
+
return 'credential'
|
|
352
|
+
},
|
|
353
|
+
}
|
|
354
|
+
MethodChallenge.register(method, () => undefined)
|
|
355
|
+
return MethodResponse.register(method, ({ response }) => response)
|
|
356
|
+
}
|
|
357
|
+
|
|
340
358
|
const x402PaymentRequired = {
|
|
341
359
|
accepts: [
|
|
342
360
|
{
|
|
@@ -418,6 +436,30 @@ describe('Fetch.from: method responses', () => {
|
|
|
418
436
|
expect(handle).toHaveBeenCalledWith(expect.objectContaining({ credential: 'credential' }))
|
|
419
437
|
expect(paidResponse?.clone).not.toHaveBeenCalled()
|
|
420
438
|
})
|
|
439
|
+
|
|
440
|
+
test.each([
|
|
441
|
+
['a rejected paid response', () => new Response('rejected', { status: 500 }), 500, undefined],
|
|
442
|
+
['the final payment retry', () => make402(), 402, 1],
|
|
443
|
+
[
|
|
444
|
+
'the paid request throwing',
|
|
445
|
+
() => Promise.reject(new Error('paid request failed')),
|
|
446
|
+
undefined,
|
|
447
|
+
undefined,
|
|
448
|
+
],
|
|
449
|
+
])('settles credential state after %s', async (_name, paidRequest, status, maxPaymentRetries) => {
|
|
450
|
+
const settlements: MethodResponse.AttemptOutcome['status'][] = []
|
|
451
|
+
let calls = 0
|
|
452
|
+
const fetch = Fetch.from({
|
|
453
|
+
fetch: async () => (++calls === 1 ? make402() : paidRequest()),
|
|
454
|
+
maxPaymentRetries,
|
|
455
|
+
methods: [trackedMethod(settlements)],
|
|
456
|
+
})
|
|
457
|
+
|
|
458
|
+
const result = fetch('https://example.com/paid')
|
|
459
|
+
if (status) expect((await result).status).toBe(status)
|
|
460
|
+
else await expect(result).rejects.toThrow('paid request failed')
|
|
461
|
+
expect(settlements).toEqual(['rejected'])
|
|
462
|
+
})
|
|
421
463
|
})
|
|
422
464
|
|
|
423
465
|
describe('Fetch.from: init passthrough (non-402)', () => {
|
|
@@ -1873,6 +1915,41 @@ describe('Fetch.from: 402 retry path', () => {
|
|
|
1873
1915
|
).toEqual(['credential-first', 'credential-second', 'credential-third'])
|
|
1874
1916
|
})
|
|
1875
1917
|
|
|
1918
|
+
test('invalidates a prepared credential across a generic challenge', async () => {
|
|
1919
|
+
const firstCredential = vi.fn(async () => 'first')
|
|
1920
|
+
const first = { ...noopMethod, name: 'first', createCredential: firstCredential }
|
|
1921
|
+
const second = { ...noopMethod, name: 'second', createCredential: async () => 'second' }
|
|
1922
|
+
MethodChallenge.register(first, () => undefined)
|
|
1923
|
+
const responses = [
|
|
1924
|
+
make402({ id: 'first', method: 'first' }),
|
|
1925
|
+
make402({ id: 'second', method: 'second' }),
|
|
1926
|
+
make402({ id: 'first', method: 'first' }),
|
|
1927
|
+
new Response('OK'),
|
|
1928
|
+
]
|
|
1929
|
+
const mockFetch = vi.fn(async () => responses.shift()!)
|
|
1930
|
+
const fetch = Fetch.from({ fetch: mockFetch, methods: [first, second] })
|
|
1931
|
+
|
|
1932
|
+
expect((await fetch('https://example.com/api')).status).toBe(200)
|
|
1933
|
+
expect(firstCredential).toHaveBeenCalledTimes(2)
|
|
1934
|
+
})
|
|
1935
|
+
|
|
1936
|
+
test('invalidates a prepared credential after an explicit context', async () => {
|
|
1937
|
+
const createCredential = vi.fn(async () => 'credential')
|
|
1938
|
+
const method = { ...noopMethod, createCredential }
|
|
1939
|
+
MethodChallenge.register(method, () => undefined)
|
|
1940
|
+
let challenges = 0
|
|
1941
|
+
const mockFetch = vi.fn(async () => (++challenges <= 3 ? make402() : new Response('OK')))
|
|
1942
|
+
const fetch = Fetch.from({
|
|
1943
|
+
fetch: mockFetch as typeof globalThis.fetch,
|
|
1944
|
+
methods: [method],
|
|
1945
|
+
onChallenge: async (_challenge, { createCredential: create }) =>
|
|
1946
|
+
challenges === 2 ? create({ override: true } as never) : undefined,
|
|
1947
|
+
})
|
|
1948
|
+
|
|
1949
|
+
expect((await fetch('https://example.com/api')).status).toBe(200)
|
|
1950
|
+
expect(createCredential).toHaveBeenCalledTimes(3)
|
|
1951
|
+
})
|
|
1952
|
+
|
|
1876
1953
|
test('caps repeated 402 retries at three', async () => {
|
|
1877
1954
|
let callCount = 0
|
|
1878
1955
|
const createCredential = vi.fn(async () => 'credential')
|
|
@@ -19,9 +19,33 @@ type WrappedFetch = typeof globalThis.fetch & {
|
|
|
19
19
|
[MPPX_FETCH_WRAPPER]?: typeof globalThis.fetch
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
/** Credential state retained between payment retries until its method settles it. */
|
|
23
|
+
type PreparedCredential = {
|
|
24
|
+
/** Method-owned preparation and settlement hooks. */
|
|
25
|
+
attempt: MethodResponse.Attempt
|
|
26
|
+
/** Serialized challenge used to recognize the same retry. */
|
|
27
|
+
key?: string | undefined
|
|
28
|
+
/** Method that prepared the credential. */
|
|
29
|
+
method: Method.AnyClient
|
|
30
|
+
/** Memoized credential reused for the same retry. */
|
|
31
|
+
promise: Promise<string>
|
|
32
|
+
}
|
|
33
|
+
|
|
22
34
|
let originalFetch: typeof globalThis.fetch | undefined
|
|
23
35
|
const eventObserverChecks = new WeakMap<object, (name: keyof ClientEventMap) => boolean>()
|
|
24
36
|
|
|
37
|
+
async function settleAttempt(
|
|
38
|
+
prepared: PreparedCredential | undefined,
|
|
39
|
+
outcome: MethodResponse.AttemptOutcome,
|
|
40
|
+
): Promise<boolean> {
|
|
41
|
+
const settle = prepared?.attempt.settle
|
|
42
|
+
if (!settle) return outcome.status !== 'pending'
|
|
43
|
+
prepared.attempt.settle = undefined
|
|
44
|
+
const settled = await settle(outcome)
|
|
45
|
+
if (!settled) prepared.attempt.settle = settle
|
|
46
|
+
return settled
|
|
47
|
+
}
|
|
48
|
+
|
|
25
49
|
export type ClientEventMap<
|
|
26
50
|
methods extends readonly Method.AnyClient[] = readonly Method.AnyClient[],
|
|
27
51
|
response = Response,
|
|
@@ -210,12 +234,11 @@ export function from<const methods extends readonly Method.AnyClient[]>(
|
|
|
210
234
|
let challenge: Challenge.Challenge | undefined
|
|
211
235
|
let challenges: readonly Challenge.Challenge[] | undefined
|
|
212
236
|
let mi: methods[number] | undefined
|
|
237
|
+
let preparedCredential: PreparedCredential | undefined
|
|
213
238
|
|
|
214
239
|
try {
|
|
215
240
|
for (let retry = 0; retry < maxPaymentRetries; retry++) {
|
|
216
|
-
challenges = transport.getChallenges
|
|
217
|
-
? await transport.getChallenges(response, transportRequest as never)
|
|
218
|
-
: [await transport.getChallenge(response, transportRequest as never)]
|
|
241
|
+
challenges = await transport.getChallenges(response, transportRequest as never)
|
|
219
242
|
|
|
220
243
|
const candidates = AcceptPayment.selectChallengeCandidates(
|
|
221
244
|
challenges,
|
|
@@ -229,6 +252,11 @@ export function from<const methods extends readonly Method.AnyClient[]>(
|
|
|
229
252
|
)
|
|
230
253
|
const selected = orderedCandidates[0]
|
|
231
254
|
if (!selected) {
|
|
255
|
+
await settleAttempt(preparedCredential, {
|
|
256
|
+
challenges,
|
|
257
|
+
response,
|
|
258
|
+
status: 'rejected',
|
|
259
|
+
})
|
|
232
260
|
// A post-payment 402 with no actionable challenge (e.g. rejected credential)
|
|
233
261
|
// is the server's final answer, not a new challenge round.
|
|
234
262
|
if (retry > 0) return response
|
|
@@ -247,16 +275,54 @@ export function from<const methods extends readonly Method.AnyClient[]>(
|
|
|
247
275
|
initialRequest.input,
|
|
248
276
|
initialRequest.input,
|
|
249
277
|
)
|
|
278
|
+
const previousCredential = preparedCredential
|
|
279
|
+
const key = Challenge.serialize(selectedChallenge)
|
|
280
|
+
const sameAttempt =
|
|
281
|
+
previousCredential?.method === selected.method && previousCredential?.key === key
|
|
282
|
+
let canReusePrevious = false
|
|
283
|
+
if (previousCredential) {
|
|
284
|
+
const settled = await settleAttempt(previousCredential, {
|
|
285
|
+
challenges,
|
|
286
|
+
response,
|
|
287
|
+
status: sameAttempt ? 'pending' : 'rejected',
|
|
288
|
+
})
|
|
289
|
+
canReusePrevious = sameAttempt && !settled
|
|
290
|
+
}
|
|
291
|
+
preparedCredential = canReusePrevious ? previousCredential : undefined
|
|
250
292
|
const createCredential = memoizeCreateCredential(
|
|
251
293
|
async (overrideContext?: AnyContextFor<methods>) => {
|
|
294
|
+
if (overrideContext === undefined && canReusePrevious && previousCredential) {
|
|
295
|
+
return previousCredential.promise
|
|
296
|
+
}
|
|
297
|
+
if (canReusePrevious && previousCredential) {
|
|
298
|
+
await settleAttempt(previousCredential, { status: 'rejected' })
|
|
299
|
+
preparedCredential = undefined
|
|
300
|
+
}
|
|
301
|
+
|
|
252
302
|
const credentialContext = overrideContext ?? context
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
303
|
+
if (!MethodChallenge.has(selected.method))
|
|
304
|
+
return resolveCredential(selectedChallenge, selected.method, credentialContext)
|
|
305
|
+
const attempt: MethodResponse.Attempt = {
|
|
306
|
+
prepare: () =>
|
|
307
|
+
MethodChallenge.handle(selected.method, {
|
|
308
|
+
challenge: selectedChallenge,
|
|
309
|
+
context: credentialContext,
|
|
310
|
+
fetch: baseFetch,
|
|
311
|
+
input: paymentInput,
|
|
312
|
+
}),
|
|
313
|
+
}
|
|
314
|
+
const promise = attempt
|
|
315
|
+
.prepare()
|
|
316
|
+
.then(() =>
|
|
317
|
+
resolveCredential(selectedChallenge, selected.method, credentialContext, attempt),
|
|
318
|
+
)
|
|
319
|
+
preparedCredential = {
|
|
320
|
+
attempt,
|
|
321
|
+
key: overrideContext === undefined ? key : undefined,
|
|
322
|
+
method: selected.method,
|
|
323
|
+
promise,
|
|
324
|
+
}
|
|
325
|
+
return promise
|
|
260
326
|
},
|
|
261
327
|
)
|
|
262
328
|
const eventCredential = await events.emit(
|
|
@@ -279,6 +345,11 @@ export function from<const methods extends readonly Method.AnyClient[]>(
|
|
|
279
345
|
})
|
|
280
346
|
: undefined)
|
|
281
347
|
const credential = onChallengeCredential ?? (await createCredential())
|
|
348
|
+
const prepared = preparedCredential
|
|
349
|
+
if (prepared && (await prepared.promise.catch(() => undefined)) !== credential) {
|
|
350
|
+
await settleAttempt(prepared, { status: 'rejected' })
|
|
351
|
+
preparedCredential = undefined
|
|
352
|
+
}
|
|
282
353
|
validateCredentialHeaderValue(credential)
|
|
283
354
|
await events.emit(
|
|
284
355
|
'credential.created',
|
|
@@ -303,6 +374,17 @@ export function from<const methods extends readonly Method.AnyClient[]>(
|
|
|
303
374
|
{ challenge: selectedChallenge },
|
|
304
375
|
),
|
|
305
376
|
)
|
|
377
|
+
const paymentRequired = await transport.isPaymentRequired(
|
|
378
|
+
response,
|
|
379
|
+
transportRequest as never,
|
|
380
|
+
)
|
|
381
|
+
if (!paymentRequired) {
|
|
382
|
+
await settleAttempt(prepared, {
|
|
383
|
+
response,
|
|
384
|
+
status: response.ok ? 'accepted' : 'rejected',
|
|
385
|
+
})
|
|
386
|
+
preparedCredential = undefined
|
|
387
|
+
}
|
|
306
388
|
// Cloning an unobserved stream would tee and buffer it indefinitely.
|
|
307
389
|
if (response.ok && hasEventObservers(events, 'payment.response'))
|
|
308
390
|
await events.emit(
|
|
@@ -316,7 +398,7 @@ export function from<const methods extends readonly Method.AnyClient[]>(
|
|
|
316
398
|
response,
|
|
317
399
|
}),
|
|
318
400
|
)
|
|
319
|
-
if (!
|
|
401
|
+
if (!paymentRequired) {
|
|
320
402
|
if (!response.ok) return response
|
|
321
403
|
return MethodResponse.handle(selected.method, {
|
|
322
404
|
challenge: selectedChallenge,
|
|
@@ -334,8 +416,22 @@ export function from<const methods extends readonly Method.AnyClient[]>(
|
|
|
334
416
|
})
|
|
335
417
|
}
|
|
336
418
|
}
|
|
419
|
+
challenges = undefined
|
|
420
|
+
try {
|
|
421
|
+
challenges = await transport.getChallenges(response, transportRequest as never)
|
|
422
|
+
} catch {}
|
|
423
|
+
await settleAttempt(preparedCredential, {
|
|
424
|
+
challenges,
|
|
425
|
+
response,
|
|
426
|
+
status: 'rejected',
|
|
427
|
+
})
|
|
337
428
|
return response
|
|
338
429
|
} catch (error) {
|
|
430
|
+
await settleAttempt(preparedCredential, {
|
|
431
|
+
challenges,
|
|
432
|
+
response,
|
|
433
|
+
status: 'rejected',
|
|
434
|
+
})
|
|
339
435
|
await events.emit(
|
|
340
436
|
'payment.failed',
|
|
341
437
|
createPaymentFailedPayload({
|
|
@@ -884,11 +980,13 @@ async function resolveCredential(
|
|
|
884
980
|
challenge: Challenge.Challenge,
|
|
885
981
|
mi: Method.AnyClient,
|
|
886
982
|
context: unknown,
|
|
983
|
+
attempt?: MethodResponse.Attempt | undefined,
|
|
887
984
|
): Promise<string> {
|
|
888
985
|
const parsedContext = mi.context && context !== undefined ? mi.context.parse(context) : undefined
|
|
889
|
-
|
|
890
|
-
parsedContext !== undefined ? { challenge, context: parsedContext } :
|
|
891
|
-
)
|
|
986
|
+
const parameters =
|
|
987
|
+
parsedContext !== undefined ? { challenge, context: parsedContext } : { challenge }
|
|
988
|
+
if (attempt) MethodResponse.attachAttempt(mi, parameters, attempt)
|
|
989
|
+
return mi.createCredential(parameters as never)
|
|
892
990
|
}
|
|
893
991
|
|
|
894
992
|
function resolvePaymentPreferences<methods extends readonly Method.AnyClient[]>(
|
|
@@ -24,6 +24,11 @@ export function register<const method extends Method.AnyClient>(
|
|
|
24
24
|
return method
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/** Returns whether a method registered pre-credential work. */
|
|
28
|
+
export function has(method: Method.AnyClient): boolean {
|
|
29
|
+
return handlers.has(method)
|
|
30
|
+
}
|
|
31
|
+
|
|
27
32
|
/** Runs method-specific work before creating a challenge credential. */
|
|
28
33
|
export function handle(method: Method.AnyClient, parameters: HandlerParameters): Promise<void> {
|
|
29
34
|
return Promise.resolve(handlers.get(method)?.(parameters))
|
|
@@ -3,6 +3,20 @@ import type { MaybePromise } from '../../internal/types.js'
|
|
|
3
3
|
import type * as Method from '../../Method.js'
|
|
4
4
|
|
|
5
5
|
const handlers = new WeakMap<Method.AnyClient, Handler>()
|
|
6
|
+
const attempts = new WeakMap<object, Attempt>()
|
|
7
|
+
|
|
8
|
+
export type AttemptOutcome = {
|
|
9
|
+
challenges?: readonly Challenge.Challenge[] | undefined
|
|
10
|
+
response?: Response | undefined
|
|
11
|
+
status: 'accepted' | 'pending' | 'rejected'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type Attempt = {
|
|
15
|
+
/** Re-runs method preparation when serialized state changed before signing. */
|
|
16
|
+
prepare: () => Promise<void>
|
|
17
|
+
/** Settles state created for one credential attempt. */
|
|
18
|
+
settle?: ((outcome: AttemptOutcome) => MaybePromise<boolean>) | undefined
|
|
19
|
+
}
|
|
6
20
|
|
|
7
21
|
/** Inputs available when a client method handles a successful paid response. */
|
|
8
22
|
export type HandlerParameters = {
|
|
@@ -33,6 +47,20 @@ export function unregister(method: Method.AnyClient): void {
|
|
|
33
47
|
handlers.delete(method)
|
|
34
48
|
}
|
|
35
49
|
|
|
50
|
+
/** Adds response lifecycle state to internal credential parameters. */
|
|
51
|
+
export function attachAttempt(
|
|
52
|
+
method: Method.AnyClient,
|
|
53
|
+
parameters: object,
|
|
54
|
+
attempt: Attempt,
|
|
55
|
+
): void {
|
|
56
|
+
if (handlers.has(method)) attempts.set(parameters, attempt)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Reads response lifecycle state when Fetch owns this credential. */
|
|
60
|
+
export function getAttempt(parameters: object): Attempt | undefined {
|
|
61
|
+
return attempts.get(parameters)
|
|
62
|
+
}
|
|
63
|
+
|
|
36
64
|
/** Lets the selected client method handle a successful paid response. */
|
|
37
65
|
export function handle(method: Method.AnyClient, parameters: HandlerParameters): Promise<Response> {
|
|
38
66
|
return Promise.resolve(handlers.get(method)?.(parameters) ?? parameters.response)
|