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
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isInnerList,
|
|
3
|
+
parseDictionary,
|
|
4
|
+
serializeItem,
|
|
5
|
+
serializeDictionary,
|
|
6
|
+
serializeInnerList,
|
|
7
|
+
serializeParameters,
|
|
8
|
+
} from 'structured-headers'
|
|
9
|
+
import type { BareItem, Dictionary, InnerList, Item } from 'structured-headers'
|
|
10
|
+
|
|
11
|
+
import type { MaybePromise } from '../../internal/types.js'
|
|
12
|
+
import * as Store from '../../Store.js'
|
|
13
|
+
import { Algorithms, Headers as AttestationHeaders } from '../Constants.js'
|
|
14
|
+
import type { KeyResolver, SignatureAlgorithm, SigningContext } from '../Types.js'
|
|
15
|
+
import * as SigningContextInternal from './SigningContext.js'
|
|
16
|
+
|
|
17
|
+
/** RFC 9421 constants used by request-attestation signature profiles. */
|
|
18
|
+
export const Constants = {
|
|
19
|
+
/** Derived request components supported by this narrow request profile. */
|
|
20
|
+
components: {
|
|
21
|
+
/** The target host and non-default port. */
|
|
22
|
+
authority: '@authority',
|
|
23
|
+
/** The request URL path without its query string. */
|
|
24
|
+
path: '@path',
|
|
25
|
+
/** The lowercased `Signature-Agent` request header. */
|
|
26
|
+
signatureAgent: 'signature-agent',
|
|
27
|
+
/** The signature's canonicalized covered-components and parameters. */
|
|
28
|
+
signatureParams: '@signature-params',
|
|
29
|
+
},
|
|
30
|
+
} as const
|
|
31
|
+
|
|
32
|
+
const algorithmDescriptors = {
|
|
33
|
+
[Algorithms.ed25519]: {
|
|
34
|
+
hash: undefined,
|
|
35
|
+
keyAlgorithm: 'Ed25519',
|
|
36
|
+
webCryptoAlgorithm: 'Ed25519',
|
|
37
|
+
},
|
|
38
|
+
[Algorithms.rsaPssSha512]: {
|
|
39
|
+
hash: 'SHA-512',
|
|
40
|
+
keyAlgorithm: 'RSA-PSS',
|
|
41
|
+
webCryptoAlgorithm: { name: 'RSA-PSS', saltLength: 64 },
|
|
42
|
+
},
|
|
43
|
+
} as const satisfies Record<
|
|
44
|
+
SignatureAlgorithm,
|
|
45
|
+
{
|
|
46
|
+
hash: string | undefined
|
|
47
|
+
keyAlgorithm: string
|
|
48
|
+
webCryptoAlgorithm: AlgorithmIdentifier | RsaPssParams
|
|
49
|
+
}
|
|
50
|
+
>
|
|
51
|
+
|
|
52
|
+
/** A covered HTTP message component and its RFC 9421 component parameters. */
|
|
53
|
+
export type Component = {
|
|
54
|
+
/** Derived component identifier or lowercased HTTP field name. */
|
|
55
|
+
id: string
|
|
56
|
+
/** Parameters that qualify the component, such as `;key="agent"`. */
|
|
57
|
+
parameters?: ReadonlyMap<string, BareItem> | undefined
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Input accepted by signers; bare strings denote unparameterized components. */
|
|
61
|
+
export type ComponentInput = string | Component
|
|
62
|
+
|
|
63
|
+
export type SignatureInput = {
|
|
64
|
+
algorithm: SignatureAlgorithm
|
|
65
|
+
components: readonly Component[]
|
|
66
|
+
created: number
|
|
67
|
+
expires: number
|
|
68
|
+
keyId: string
|
|
69
|
+
label: string
|
|
70
|
+
nonce: string
|
|
71
|
+
parameters: ReadonlyMap<string, BareItem>
|
|
72
|
+
tag: string
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Result of validating one supported RFC 9421 signature. */
|
|
76
|
+
export type VerificationResult =
|
|
77
|
+
| { status: 'absent' }
|
|
78
|
+
| { status: 'invalid'; reason: string }
|
|
79
|
+
| { status: 'unverified'; reason: string }
|
|
80
|
+
| { status: 'verified'; input: SignatureInput }
|
|
81
|
+
|
|
82
|
+
/** Signs a request using the configured RFC 9421-derived component list. */
|
|
83
|
+
export async function sign(
|
|
84
|
+
request: Request,
|
|
85
|
+
options: {
|
|
86
|
+
components: readonly ComponentInput[]
|
|
87
|
+
expiresIn?: number | undefined
|
|
88
|
+
keyId: string
|
|
89
|
+
key: CryptoKey
|
|
90
|
+
label: string
|
|
91
|
+
context?: SigningContext | undefined
|
|
92
|
+
tag: string
|
|
93
|
+
},
|
|
94
|
+
): Promise<Request> {
|
|
95
|
+
const context = options.context ?? SigningContextInternal.create()
|
|
96
|
+
const created = context.created
|
|
97
|
+
const expires = created + (options.expiresIn ?? 60)
|
|
98
|
+
const algorithm = algorithmFromKey(options.key)
|
|
99
|
+
const parameters = new Map<string, BareItem>([
|
|
100
|
+
['created', created],
|
|
101
|
+
['expires', expires],
|
|
102
|
+
['keyid', options.keyId],
|
|
103
|
+
['alg', algorithm],
|
|
104
|
+
['nonce', context.nonce],
|
|
105
|
+
['tag', options.tag],
|
|
106
|
+
])
|
|
107
|
+
const input: SignatureInput = {
|
|
108
|
+
algorithm,
|
|
109
|
+
components: options.components.map(toComponent),
|
|
110
|
+
created,
|
|
111
|
+
expires,
|
|
112
|
+
keyId: options.keyId,
|
|
113
|
+
label: options.label,
|
|
114
|
+
nonce: context.nonce,
|
|
115
|
+
parameters,
|
|
116
|
+
tag: options.tag,
|
|
117
|
+
}
|
|
118
|
+
const signature = await crypto.subtle.sign(
|
|
119
|
+
webCryptoAlgorithm(algorithm),
|
|
120
|
+
options.key,
|
|
121
|
+
toArrayBuffer(encode(signatureBase(request, input))),
|
|
122
|
+
)
|
|
123
|
+
const headers = new Headers(request.headers)
|
|
124
|
+
const inputs = parseHeaderDictionary(headers, AttestationHeaders.signatureInput)
|
|
125
|
+
const signatures = parseHeaderDictionary(headers, AttestationHeaders.signature)
|
|
126
|
+
if (!haveSameKeys(inputs, signatures))
|
|
127
|
+
throw new Error('Signature-Input and Signature must contain the same labels.')
|
|
128
|
+
if (inputs.has(input.label) || signatures.has(input.label))
|
|
129
|
+
throw new Error(`HTTP message signature label "${input.label}" already exists.`)
|
|
130
|
+
inputs.set(input.label, toInnerList(input))
|
|
131
|
+
signatures.set(input.label, [signature, new Map()])
|
|
132
|
+
headers.set(AttestationHeaders.signatureInput, serializeDictionary(inputs))
|
|
133
|
+
headers.set(AttestationHeaders.signature, serializeDictionary(signatures))
|
|
134
|
+
return new Request(request, { headers })
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Verifies a request signature, its lifetime, and optionally its nonce. */
|
|
138
|
+
export async function verify(
|
|
139
|
+
request: Request,
|
|
140
|
+
options: {
|
|
141
|
+
keyResolver: KeyResolver
|
|
142
|
+
maxAge: number
|
|
143
|
+
nonceNamespace: string
|
|
144
|
+
nonceStore: Store.AtomicStore
|
|
145
|
+
requiredComponents: readonly string[]
|
|
146
|
+
tag: string | readonly string[]
|
|
147
|
+
validate?: ((input: SignatureInput, request: Request) => string | undefined) | undefined
|
|
148
|
+
validateKey?:
|
|
149
|
+
| ((
|
|
150
|
+
key: CryptoKey,
|
|
151
|
+
input: SignatureInput,
|
|
152
|
+
request: Request,
|
|
153
|
+
) => MaybePromise<string | undefined>)
|
|
154
|
+
| undefined
|
|
155
|
+
},
|
|
156
|
+
): Promise<VerificationResult> {
|
|
157
|
+
const parsed = parse(request, options.tag)
|
|
158
|
+
if (!parsed) return { status: 'absent' }
|
|
159
|
+
if (parsed.reason) return { status: 'invalid', reason: parsed.reason }
|
|
160
|
+
if (!parsed.input || !parsed.signature)
|
|
161
|
+
return { status: 'invalid', reason: 'The HTTP message signature is malformed.' }
|
|
162
|
+
const { input, signature } = parsed
|
|
163
|
+
|
|
164
|
+
if (!options.requiredComponents.every((component) => hasComponent(input.components, component)))
|
|
165
|
+
return {
|
|
166
|
+
status: 'invalid',
|
|
167
|
+
reason: 'The signature does not cover the required request components.',
|
|
168
|
+
}
|
|
169
|
+
const now = Math.floor(Date.now() / 1000)
|
|
170
|
+
if (input.created > now || input.expires <= now || input.expires - input.created > options.maxAge)
|
|
171
|
+
return { status: 'invalid', reason: 'The signature is expired or has an invalid lifetime.' }
|
|
172
|
+
if (options.validate) {
|
|
173
|
+
const reason = options.validate(input, request)
|
|
174
|
+
if (reason) return { status: 'invalid', reason }
|
|
175
|
+
}
|
|
176
|
+
let key: CryptoKey | undefined
|
|
177
|
+
try {
|
|
178
|
+
key = await options.keyResolver({
|
|
179
|
+
algorithm: input.algorithm,
|
|
180
|
+
keyId: input.keyId,
|
|
181
|
+
request,
|
|
182
|
+
})
|
|
183
|
+
} catch {
|
|
184
|
+
return { status: 'unverified', reason: 'The public key could not be resolved.' }
|
|
185
|
+
}
|
|
186
|
+
if (!key)
|
|
187
|
+
return {
|
|
188
|
+
status: 'unverified',
|
|
189
|
+
reason: 'No public key is available for the signature key ID.',
|
|
190
|
+
}
|
|
191
|
+
if (!keySupportsAlgorithm(key, input.algorithm))
|
|
192
|
+
return {
|
|
193
|
+
status: 'invalid',
|
|
194
|
+
reason: 'The public key does not support the signature algorithm.',
|
|
195
|
+
}
|
|
196
|
+
if (options.validateKey) {
|
|
197
|
+
const reason = await options.validateKey(key, input, request)
|
|
198
|
+
if (reason) return { status: 'invalid', reason }
|
|
199
|
+
}
|
|
200
|
+
let valid: boolean
|
|
201
|
+
try {
|
|
202
|
+
valid = await crypto.subtle.verify(
|
|
203
|
+
webCryptoAlgorithm(input.algorithm),
|
|
204
|
+
key,
|
|
205
|
+
toArrayBuffer(signature),
|
|
206
|
+
toArrayBuffer(encode(signatureBase(request, input))),
|
|
207
|
+
)
|
|
208
|
+
} catch {
|
|
209
|
+
valid = false
|
|
210
|
+
}
|
|
211
|
+
if (!valid) return { status: 'invalid', reason: 'The HTTP message signature is invalid.' }
|
|
212
|
+
try {
|
|
213
|
+
if (
|
|
214
|
+
!(await Store.tryClaim(
|
|
215
|
+
options.nonceStore,
|
|
216
|
+
`${options.nonceNamespace}:${input.keyId}:${input.nonce}`,
|
|
217
|
+
input.expires * 1000,
|
|
218
|
+
))
|
|
219
|
+
)
|
|
220
|
+
return { status: 'invalid', reason: 'The signature nonce has already been used.' }
|
|
221
|
+
} catch {
|
|
222
|
+
return { status: 'unverified', reason: 'Replay protection is unavailable.' }
|
|
223
|
+
}
|
|
224
|
+
return { status: 'verified', input }
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function parse(
|
|
228
|
+
request: Request,
|
|
229
|
+
expectedTag: string | readonly string[],
|
|
230
|
+
): { input?: SignatureInput; reason?: string; signature?: Uint8Array } | undefined {
|
|
231
|
+
const inputHeader = request.headers.get(AttestationHeaders.signatureInput)
|
|
232
|
+
const signatureHeader = request.headers.get(AttestationHeaders.signature)
|
|
233
|
+
if (!inputHeader && !signatureHeader) return undefined
|
|
234
|
+
if (!inputHeader || !signatureHeader)
|
|
235
|
+
return { reason: 'Signature-Input and Signature must both be provided.' }
|
|
236
|
+
let inputs: Dictionary
|
|
237
|
+
let signatures: Dictionary
|
|
238
|
+
try {
|
|
239
|
+
inputs = parseDictionary(inputHeader)
|
|
240
|
+
signatures = parseDictionary(signatureHeader)
|
|
241
|
+
} catch {
|
|
242
|
+
return { reason: 'The HTTP message signature is malformed.' }
|
|
243
|
+
}
|
|
244
|
+
if (!haveSameKeys(inputs, signatures))
|
|
245
|
+
return { reason: 'Signature-Input and Signature do not contain the same labels.' }
|
|
246
|
+
const tags = new Set(typeof expectedTag === 'string' ? [expectedTag] : expectedTag)
|
|
247
|
+
for (const [label, entry] of inputs) {
|
|
248
|
+
if (!hasExpectedTag(entry, tags)) continue
|
|
249
|
+
const input = toSignatureInput(label, entry)
|
|
250
|
+
if (!input) return { reason: 'The HTTP message signature is malformed.' }
|
|
251
|
+
const signature = signatures.get(label)
|
|
252
|
+
if (!signature || isInnerList(signature) || !(signature[0] instanceof ArrayBuffer))
|
|
253
|
+
return { reason: 'No matching HTTP message signature was provided.' }
|
|
254
|
+
return { input, signature: new Uint8Array(signature[0]) }
|
|
255
|
+
}
|
|
256
|
+
return undefined
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function serializeInput(input: SignatureInput): string {
|
|
260
|
+
return serializeInnerList(toInnerList(input))
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function toInnerList(input: SignatureInput): InnerList {
|
|
264
|
+
const components: InnerList[0] = input.components.map((component) => [
|
|
265
|
+
component.id,
|
|
266
|
+
new Map(component.parameters),
|
|
267
|
+
])
|
|
268
|
+
return [components, new Map(input.parameters)]
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function toSignatureInput(label: string, entry: unknown): SignatureInput | undefined {
|
|
272
|
+
const innerList = entry as InnerList
|
|
273
|
+
if (!isInnerList(innerList)) return undefined
|
|
274
|
+
const [componentEntries, parameters] = innerList
|
|
275
|
+
if (
|
|
276
|
+
!componentEntries.length ||
|
|
277
|
+
!componentEntries.every(([component]) => typeof component === 'string')
|
|
278
|
+
)
|
|
279
|
+
return undefined
|
|
280
|
+
const components = componentEntries.map(([id, parameters]) => ({
|
|
281
|
+
id: id as string,
|
|
282
|
+
parameters,
|
|
283
|
+
}))
|
|
284
|
+
const created = parameters.get('created')
|
|
285
|
+
const expires = parameters.get('expires')
|
|
286
|
+
const algorithm = parameters.get('alg')
|
|
287
|
+
const keyId = parameters.get('keyid')
|
|
288
|
+
const nonce = parameters.get('nonce')
|
|
289
|
+
const tag = parameters.get('tag')
|
|
290
|
+
if (
|
|
291
|
+
!isInteger(created) ||
|
|
292
|
+
!isInteger(expires) ||
|
|
293
|
+
!isSignatureAlgorithm(algorithm) ||
|
|
294
|
+
typeof keyId !== 'string' ||
|
|
295
|
+
typeof nonce !== 'string' ||
|
|
296
|
+
typeof tag !== 'string'
|
|
297
|
+
)
|
|
298
|
+
return undefined
|
|
299
|
+
return {
|
|
300
|
+
algorithm,
|
|
301
|
+
components,
|
|
302
|
+
created,
|
|
303
|
+
expires,
|
|
304
|
+
keyId,
|
|
305
|
+
label,
|
|
306
|
+
nonce,
|
|
307
|
+
parameters,
|
|
308
|
+
tag,
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function algorithmFromKey(key: CryptoKey): SignatureAlgorithm {
|
|
313
|
+
for (const algorithm of Object.values(Algorithms))
|
|
314
|
+
if (keySupportsAlgorithm(key, algorithm)) return algorithm
|
|
315
|
+
throw new TypeError('Request attestation requires an Ed25519 or RSA-PSS SHA-512 signing key.')
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function isInteger(value: unknown): value is number {
|
|
319
|
+
return typeof value === 'number' && Number.isInteger(value)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function isSignatureAlgorithm(value: unknown): value is SignatureAlgorithm {
|
|
323
|
+
return typeof value === 'string' && Object.hasOwn(algorithmDescriptors, value)
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function keySupportsAlgorithm(key: CryptoKey, algorithm: SignatureAlgorithm): boolean {
|
|
327
|
+
const { hash, keyAlgorithm } = algorithmDescriptors[algorithm]
|
|
328
|
+
return (
|
|
329
|
+
key.algorithm.name === keyAlgorithm &&
|
|
330
|
+
(!hash || (key.algorithm as RsaHashedKeyAlgorithm).hash.name === hash)
|
|
331
|
+
)
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function webCryptoAlgorithm(algorithm: SignatureAlgorithm): AlgorithmIdentifier | RsaPssParams {
|
|
335
|
+
return algorithmDescriptors[algorithm].webCryptoAlgorithm
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function signatureBase(request: Request, input: SignatureInput): string {
|
|
339
|
+
const lines = input.components.map(
|
|
340
|
+
(component) => `${serializeComponent(component)}: ${componentValue(request, component)}`,
|
|
341
|
+
)
|
|
342
|
+
lines.push(`"${Constants.components.signatureParams}": ${serializeInput(input)}`)
|
|
343
|
+
return lines.join('\n')
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function componentValue(request: Request, component: Component): string {
|
|
347
|
+
const url = new URL(request.url)
|
|
348
|
+
if (component.id === Constants.components.authority) {
|
|
349
|
+
if (component.parameters?.size) throw new Error('Unsupported parameters for "@authority".')
|
|
350
|
+
return url.host
|
|
351
|
+
}
|
|
352
|
+
if (component.id === Constants.components.path) {
|
|
353
|
+
if (component.parameters?.size) throw new Error('Unsupported parameters for "@path".')
|
|
354
|
+
return url.pathname
|
|
355
|
+
}
|
|
356
|
+
if (component.parameters?.size)
|
|
357
|
+
return componentDictionaryValue(request, component.id, component.parameters)
|
|
358
|
+
const value = request.headers.get(component.id)
|
|
359
|
+
if (value === null) throw new Error(`Missing signed HTTP header "${component.id}".`)
|
|
360
|
+
// RFC 9421 signs the serialized field value, not a Unicode-normalized string.
|
|
361
|
+
if (!/^[\x20-\x7e]*$/.test(value))
|
|
362
|
+
throw new Error(`Signed HTTP header "${component.id}" is not ASCII.`)
|
|
363
|
+
return value
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function componentDictionaryValue(
|
|
367
|
+
request: Request,
|
|
368
|
+
component: string,
|
|
369
|
+
parameters: ReadonlyMap<string, BareItem>,
|
|
370
|
+
): string {
|
|
371
|
+
const key = parameters.get('key')
|
|
372
|
+
if (typeof key !== 'string' || parameters.size !== 1)
|
|
373
|
+
throw new Error(`Unsupported parameters for signed HTTP header "${component}".`)
|
|
374
|
+
const value = request.headers.get(component)
|
|
375
|
+
if (value === null) throw new Error(`Missing signed HTTP header "${component}".`)
|
|
376
|
+
let dictionary: Dictionary
|
|
377
|
+
try {
|
|
378
|
+
dictionary = parseDictionary(value)
|
|
379
|
+
} catch {
|
|
380
|
+
throw new Error(`Signed HTTP header "${component}" is not a structured dictionary.`)
|
|
381
|
+
}
|
|
382
|
+
const member = dictionary.get(key)
|
|
383
|
+
if (!member || isInnerList(member))
|
|
384
|
+
throw new Error(`Signed HTTP header "${component}" has no member "${key}".`)
|
|
385
|
+
return serializeItem(member)
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function hasComponent(components: readonly Component[], expected: string): boolean {
|
|
389
|
+
return components.some((component) => component.id === expected)
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function haveSameKeys(left: Dictionary, right: Dictionary): boolean {
|
|
393
|
+
return left.size === right.size && [...left.keys()].every((key) => right.has(key))
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function hasExpectedTag(entry: unknown, tags: ReadonlySet<string>): boolean {
|
|
397
|
+
const value = entry as Item | InnerList
|
|
398
|
+
if (!isInnerList(value)) return false
|
|
399
|
+
const tag = value[1].get('tag')
|
|
400
|
+
return typeof tag === 'string' && tags.has(tag)
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function serializeComponent(component: Component): string {
|
|
404
|
+
return `"${component.id}"${component.parameters?.size ? serializeParameters(new Map(component.parameters)) : ''}`
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function toComponent(component: ComponentInput): Component {
|
|
408
|
+
return typeof component === 'string'
|
|
409
|
+
? { id: component }
|
|
410
|
+
: { id: component.id, parameters: component.parameters && new Map(component.parameters) }
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
function parseHeaderDictionary(headers: Headers, name: string): Dictionary {
|
|
414
|
+
const value = headers.get(name)
|
|
415
|
+
if (!value) return new Map()
|
|
416
|
+
try {
|
|
417
|
+
return parseDictionary(value)
|
|
418
|
+
} catch {
|
|
419
|
+
throw new Error(`HTTP header "${name}" is not a structured dictionary.`)
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function encode(value: string): Uint8Array {
|
|
424
|
+
return new TextEncoder().encode(value)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function toArrayBuffer(value: Uint8Array): ArrayBuffer {
|
|
428
|
+
return value.buffer.slice(value.byteOffset, value.byteOffset + value.byteLength) as ArrayBuffer
|
|
429
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Base64 } from 'ox'
|
|
2
|
+
|
|
3
|
+
import type * as Types from '../Types.js'
|
|
4
|
+
|
|
5
|
+
/** Creates the signing context for one outbound HTTP request attempt. */
|
|
6
|
+
export function create(): Types.SigningContext {
|
|
7
|
+
const bytes = new Uint8Array(64)
|
|
8
|
+
crypto.getRandomValues(bytes)
|
|
9
|
+
return Object.freeze({
|
|
10
|
+
created: Math.floor(Date.now() / 1_000),
|
|
11
|
+
nonce: Base64.fromBytes(bytes, { pad: false, url: true }),
|
|
12
|
+
})
|
|
13
|
+
}
|
package/src/bin.js
ADDED
package/src/cli/cli.ts
CHANGED
|
@@ -212,6 +212,7 @@ function findService(
|
|
|
212
212
|
}
|
|
213
213
|
|
|
214
214
|
const cli = Cli.create('mppx', {
|
|
215
|
+
mcp: { tools: { discovery: 'direct' } },
|
|
215
216
|
version: packageJson.version,
|
|
216
217
|
description: 'Make HTTP requests with automatic payment handling',
|
|
217
218
|
usage: [{ suffix: '<url> [options]' }],
|
|
@@ -46,6 +46,20 @@ async function provisionAndPayTestnet(
|
|
|
46
46
|
await Promise.all(hashes.map((hash) => waitForTransactionReceipt(client, { hash })))
|
|
47
47
|
if (!silent) console.log(pc.dim(` Using wallet: ${account.address}`))
|
|
48
48
|
|
|
49
|
+
// The faucet tx receipt can land before the RPC's balance reads are
|
|
50
|
+
// consistent with it, so poll briefly for the funded balance to appear
|
|
51
|
+
// rather than racing straight into the charge.
|
|
52
|
+
const currency = (challenge.request as Record<string, unknown>).currency
|
|
53
|
+
if (typeof currency === 'string') {
|
|
54
|
+
for (let attempt = 0; attempt < 10; attempt++) {
|
|
55
|
+
const balance = await Actions.token
|
|
56
|
+
.getBalance(client, { account: account.address, token: currency as Address })
|
|
57
|
+
.catch(() => undefined)
|
|
58
|
+
if (balance && balance.amount > 0n) break
|
|
59
|
+
await new Promise((resolve) => setTimeout(resolve, 500))
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
49
63
|
const methods = [...tempoMethods({ account })]
|
|
50
64
|
return { methods }
|
|
51
65
|
} catch (error) {
|
|
@@ -198,7 +212,7 @@ export async function validatePaymentFlow(
|
|
|
198
212
|
const mppx = Mppx.create({ methods: provisioned.methods, polyfill: false })
|
|
199
213
|
const cred = await mppx.createCredential(fakeResp)
|
|
200
214
|
results.push(check('Payment: submitted', 'ephemeral testnet wallet'))
|
|
201
|
-
|
|
215
|
+
await sendAndValidateResponse(
|
|
202
216
|
results,
|
|
203
217
|
url,
|
|
204
218
|
endpoint,
|
|
@@ -210,17 +224,17 @@ export async function validatePaymentFlow(
|
|
|
210
224
|
)
|
|
211
225
|
} catch (error) {
|
|
212
226
|
results.push(fail('Payment: create credential', (error as Error).message))
|
|
213
|
-
return results
|
|
214
227
|
}
|
|
215
228
|
} else {
|
|
216
229
|
results.push(
|
|
217
230
|
fail('Payment: auto-provision wallet', 'Failed to create and fund testnet wallet'),
|
|
218
231
|
)
|
|
219
|
-
return results
|
|
220
232
|
}
|
|
233
|
+
options.onResults?.(results)
|
|
221
234
|
}
|
|
222
235
|
|
|
223
|
-
// Try each challenge method (
|
|
236
|
+
// Try each remaining challenge method (tempo testnet already handled above),
|
|
237
|
+
// so validate exercises every payment method the server offers, same as mainnet.
|
|
224
238
|
const loaded = await loadConfig().catch(() => undefined)
|
|
225
239
|
const isInteractive = options.interactive
|
|
226
240
|
const stripeKey = process.env.MPPX_STRIPE_SECRET_KEY ?? resolveStripeKey(verbose)
|
package/src/cli/validate.test.ts
CHANGED
|
@@ -707,6 +707,22 @@ describe('validate: multi-challenge', () => {
|
|
|
707
707
|
const { output } = await serve(['validate', server.url])
|
|
708
708
|
expect(output).toContain('Amount is valid integer string (Got: 1.50)')
|
|
709
709
|
})
|
|
710
|
+
|
|
711
|
+
test("tempo doesn't block other testnet methods", { timeout: 15_000 }, async () => {
|
|
712
|
+
// makeChallenge() defaults to a tempo testnet challenge (chainId 42431),
|
|
713
|
+
// which takes the ephemeral-wallet fast path. That path used to return
|
|
714
|
+
// immediately, so a server offering evm/stripe alongside tempo would
|
|
715
|
+
// never have those methods exercised. It should now fall through and
|
|
716
|
+
// try them too, same as it does for tempo mainnet challenges.
|
|
717
|
+
const server = await multiChallengeServer([makeChallenge(), makeEvmChallenge()])
|
|
718
|
+
const { output } = await serve(['validate', server.url, '--outputJson', '--yes'])
|
|
719
|
+
const jsonStart = output.indexOf('{')
|
|
720
|
+
const jsonEnd = output.lastIndexOf('}')
|
|
721
|
+
const result = JSON.parse(output.slice(jsonStart, jsonEnd + 1))
|
|
722
|
+
const paymentLabels = result.endpoints[0].payment.map((r: { label: string }) => r.label)
|
|
723
|
+
expect(paymentLabels).toContain('Payment: submitted')
|
|
724
|
+
expect(paymentLabels.some((l: string) => l.includes('[evm]'))).toBe(true)
|
|
725
|
+
})
|
|
710
726
|
})
|
|
711
727
|
|
|
712
728
|
describe('validate: payment methods coverage', () => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Account, Address } from 'viem'
|
|
2
2
|
import { describe, expectTypeOf, test } from 'vp/test'
|
|
3
3
|
|
|
4
|
+
import type * as Attestation from '../attestation/Types.js'
|
|
4
5
|
import * as Challenge from '../Challenge.js'
|
|
5
6
|
import type * as Mcp from '../Mcp.js'
|
|
6
7
|
import * as Method from '../Method.js'
|
|
@@ -73,6 +74,22 @@ describe('create.Config', () => {
|
|
|
73
74
|
expectTypeOf(mppx.fetch).toBeFunction()
|
|
74
75
|
})
|
|
75
76
|
|
|
77
|
+
test('accepts request attestation for HTTP transport only', () => {
|
|
78
|
+
const signer = {} as Attestation.Signer
|
|
79
|
+
const mppx = Mppx.create({
|
|
80
|
+
attestation: { webBotAuth: signer },
|
|
81
|
+
methods: [charge()],
|
|
82
|
+
})
|
|
83
|
+
expectTypeOf(mppx.fetch).toBeFunction()
|
|
84
|
+
|
|
85
|
+
Mppx.create({
|
|
86
|
+
// @ts-expect-error request attestation applies to HTTP transport only.
|
|
87
|
+
attestation: { webBotAuth: signer },
|
|
88
|
+
methods: [charge()],
|
|
89
|
+
transport: Transport.mcp(),
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
|
|
76
93
|
test('paymentPreferences callback exposes typed method keys', () => {
|
|
77
94
|
const mppx = Mppx.create({
|
|
78
95
|
methods: [tempo({ account: {} as Account })],
|
package/src/client/Mppx.test.ts
CHANGED
|
@@ -151,29 +151,29 @@ describe('createCredential', () => {
|
|
|
151
151
|
})
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
test('behavior: routes duplicate tempo/session client methods by
|
|
155
|
-
const
|
|
156
|
-
'
|
|
154
|
+
test('behavior: routes duplicate tempo/session client methods by challenge predicate', async () => {
|
|
155
|
+
const primary = taggedSessionMethod(
|
|
156
|
+
'primary',
|
|
157
157
|
({ challenge }) =>
|
|
158
158
|
(challenge.request.methodDetails as { sessionProtocol?: string } | undefined)
|
|
159
|
-
?.sessionProtocol === '
|
|
159
|
+
?.sessionProtocol === 'primary',
|
|
160
160
|
)
|
|
161
|
-
const
|
|
161
|
+
const fallback = taggedSessionMethod('fallback', ({ challenge }) => {
|
|
162
162
|
const sessionProtocol = (
|
|
163
163
|
challenge.request.methodDetails as { sessionProtocol?: string } | undefined
|
|
164
164
|
)?.sessionProtocol
|
|
165
|
-
return sessionProtocol === undefined || sessionProtocol === '
|
|
165
|
+
return sessionProtocol === undefined || sessionProtocol === 'fallback'
|
|
166
166
|
})
|
|
167
|
-
const mppx = Mppx.create({ polyfill: false, methods: [
|
|
167
|
+
const mppx = Mppx.create({ polyfill: false, methods: [primary, fallback] })
|
|
168
168
|
|
|
169
|
-
const [
|
|
170
|
-
mppx.createCredential(paymentRequiredResponse(sessionChallenge('
|
|
171
|
-
mppx.createCredential(paymentRequiredResponse(sessionChallenge('
|
|
172
|
-
mppx.createCredential(paymentRequiredResponse(sessionChallenge('
|
|
169
|
+
const [primaryCredential, fallbackCredential, unmarkedCredential] = await Promise.all([
|
|
170
|
+
mppx.createCredential(paymentRequiredResponse(sessionChallenge('primary', 'primary'))),
|
|
171
|
+
mppx.createCredential(paymentRequiredResponse(sessionChallenge('fallback', 'fallback'))),
|
|
172
|
+
mppx.createCredential(paymentRequiredResponse(sessionChallenge('unmarked'))),
|
|
173
173
|
])
|
|
174
|
-
expect(Credential.deserialize(
|
|
175
|
-
expect(Credential.deserialize(
|
|
176
|
-
expect(Credential.deserialize(
|
|
174
|
+
expect(Credential.deserialize(primaryCredential).payload).toEqual({ tag: 'primary' })
|
|
175
|
+
expect(Credential.deserialize(fallbackCredential).payload).toEqual({ tag: 'fallback' })
|
|
176
|
+
expect(Credential.deserialize(unmarkedCredential).payload).toEqual({ tag: 'fallback' })
|
|
177
177
|
})
|
|
178
178
|
|
|
179
179
|
test('behavior: rejects unknown tempo/session sessionProtocol', async () => {
|
package/src/client/Mppx.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as AttestationClient from '../attestation/Client.js'
|
|
2
|
+
import type * as Attestation from '../attestation/Types.js'
|
|
1
3
|
import type * as Challenge from '../Challenge.js'
|
|
2
4
|
import * as Expires from '../Expires.js'
|
|
3
5
|
import * as AcceptPayment from '../internal/AcceptPayment.js'
|
|
@@ -100,6 +102,7 @@ export function create<
|
|
|
100
102
|
>,
|
|
101
103
|
>(config: create.Config<methods, transport>): Mppx<methods, transport> {
|
|
102
104
|
const {
|
|
105
|
+
attestation,
|
|
103
106
|
maxPaymentRetries,
|
|
104
107
|
onChallenge,
|
|
105
108
|
orderChallenges,
|
|
@@ -111,6 +114,9 @@ export function create<
|
|
|
111
114
|
} = config
|
|
112
115
|
|
|
113
116
|
const rawFetch = config.fetch ?? globalThis.fetch
|
|
117
|
+
const attestedFetch = attestation
|
|
118
|
+
? createAttestedFetch(rawFetch, attestation as Attestation.SignerMap)
|
|
119
|
+
: rawFetch
|
|
114
120
|
const methods = config.methods.flat() as unknown as FlattenMethods<methods>
|
|
115
121
|
const acceptPayment = AcceptPayment.resolve(methods, config.paymentPreferences)
|
|
116
122
|
const events = Fetch.createEventDispatcher<FlattenMethods<methods>, EventResponseOf<transport>>()
|
|
@@ -121,7 +127,7 @@ export function create<
|
|
|
121
127
|
const config_fetch = {
|
|
122
128
|
acceptPayment,
|
|
123
129
|
acceptPaymentPolicy,
|
|
124
|
-
...(config.fetch && { fetch:
|
|
130
|
+
...((config.fetch || attestation) && { fetch: attestedFetch }),
|
|
125
131
|
eventDispatcher: events,
|
|
126
132
|
...(maxPaymentRetries !== undefined && { maxPaymentRetries }),
|
|
127
133
|
...(resolvedOnChallenge && { onChallenge: resolvedOnChallenge }),
|
|
@@ -188,9 +194,7 @@ export function create<
|
|
|
188
194
|
context?: unknown,
|
|
189
195
|
options?: createCredential.Options<FlattenMethods<methods>>,
|
|
190
196
|
) {
|
|
191
|
-
const challenges = transport.getChallenges
|
|
192
|
-
? await transport.getChallenges(response as never)
|
|
193
|
-
: [await transport.getChallenge(response as never)]
|
|
197
|
+
const challenges = await transport.getChallenges(response as never)
|
|
194
198
|
const preferences = resolveChallengePreferences(acceptPayment.entries, options?.acceptPayment)
|
|
195
199
|
|
|
196
200
|
let challenge: Challenge.Challenge | undefined
|
|
@@ -287,6 +291,10 @@ export declare namespace create {
|
|
|
287
291
|
methods extends Methods = Methods,
|
|
288
292
|
transport extends Transport.AnyTransport = Transport.Transport,
|
|
289
293
|
> = {
|
|
294
|
+
/** Request-attestation signers applied to every outbound HTTP attempt. */
|
|
295
|
+
attestation?: transport extends Transport.Transport<RequestInit, Response>
|
|
296
|
+
? Attestation.SignerMap | undefined
|
|
297
|
+
: never
|
|
290
298
|
/** Controls when `Accept-Payment` is injected. */
|
|
291
299
|
acceptPaymentPolicy?: Fetch.from.Config['acceptPaymentPolicy'] | undefined
|
|
292
300
|
/** Custom fetch function to wrap. Defaults to `globalThis.fetch`. */
|
|
@@ -315,6 +323,19 @@ export declare namespace create {
|
|
|
315
323
|
}
|
|
316
324
|
}
|
|
317
325
|
|
|
326
|
+
function createAttestedFetch(
|
|
327
|
+
fetch: typeof globalThis.fetch,
|
|
328
|
+
signers: Attestation.SignerMap,
|
|
329
|
+
): typeof globalThis.fetch {
|
|
330
|
+
const values = Object.values(signers)
|
|
331
|
+
if (values.length === 0)
|
|
332
|
+
throw new TypeError('Mppx client attestation must configure at least one signer.')
|
|
333
|
+
return AttestationClient.wrapFetch(
|
|
334
|
+
fetch,
|
|
335
|
+
AttestationClient.composeSigners(...(values as [Attestation.Signer, ...Attestation.Signer[]])),
|
|
336
|
+
)
|
|
337
|
+
}
|
|
338
|
+
|
|
318
339
|
/**
|
|
319
340
|
* Union of all context types from all methods that have context schemas.
|
|
320
341
|
* @internal
|