mppx 0.8.15 → 0.8.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/dist/Challenge.d.ts.map +1 -1
- package/dist/Challenge.js +40 -35
- package/dist/Challenge.js.map +1 -1
- package/dist/Constants.d.ts +17 -17
- package/dist/Constants.d.ts.map +1 -1
- package/dist/Credential.d.ts.map +1 -1
- package/dist/Errors.d.ts +3 -3
- package/dist/Errors.d.ts.map +1 -1
- package/dist/Errors.js.map +1 -1
- package/dist/Method.d.ts +35 -5
- package/dist/Method.d.ts.map +1 -1
- package/dist/Method.js +7 -22
- package/dist/Method.js.map +1 -1
- package/dist/Store.d.ts +19 -0
- package/dist/Store.d.ts.map +1 -1
- package/dist/Store.js +43 -0
- package/dist/Store.js.map +1 -1
- package/dist/attestation/Client.d.ts +17 -0
- package/dist/attestation/Client.d.ts.map +1 -0
- package/dist/attestation/Client.js +28 -0
- package/dist/attestation/Client.js.map +1 -0
- package/dist/attestation/Constants.d.ts +15 -0
- package/dist/attestation/Constants.d.ts.map +1 -0
- package/dist/attestation/Constants.js +15 -0
- package/dist/attestation/Constants.js.map +1 -0
- package/dist/attestation/Server.d.ts +4 -0
- package/dist/attestation/Server.d.ts.map +1 -0
- package/dist/attestation/Server.js +8 -0
- package/dist/attestation/Server.js.map +1 -0
- package/dist/attestation/Types.d.ts +76 -0
- package/dist/attestation/Types.d.ts.map +1 -0
- package/dist/attestation/Types.js +2 -0
- package/dist/attestation/Types.js.map +1 -0
- package/dist/attestation/index.d.ts +6 -0
- package/dist/attestation/index.d.ts.map +1 -0
- package/dist/attestation/index.js +6 -0
- package/dist/attestation/index.js.map +1 -0
- package/dist/attestation/internal/HttpMessageSignature.d.ts +73 -0
- package/dist/attestation/internal/HttpMessageSignature.d.ts.map +1 -0
- package/dist/attestation/internal/HttpMessageSignature.js +320 -0
- package/dist/attestation/internal/HttpMessageSignature.js.map +1 -0
- package/dist/attestation/internal/SigningContext.d.ts +4 -0
- package/dist/attestation/internal/SigningContext.d.ts.map +1 -0
- package/dist/attestation/internal/SigningContext.js +11 -0
- package/dist/attestation/internal/SigningContext.js.map +1 -0
- package/dist/cli/account.d.ts +14 -14
- package/dist/cli/account.d.ts.map +1 -1
- package/dist/cli/cli.d.ts +6 -6
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +1 -0
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/plugins/tempo.js.map +1 -1
- package/dist/cli/sessions/commands.d.ts +4 -4
- package/dist/cli/sessions/commands.d.ts.map +1 -1
- package/dist/cli/sessions/commands.js.map +1 -1
- package/dist/cli/sessions/store.d.ts.map +1 -1
- package/dist/cli/sessions/store.js.map +1 -1
- package/dist/cli/utils.d.ts +1 -1
- package/dist/cli/utils.d.ts.map +1 -1
- package/dist/cli/utils.js.map +1 -1
- package/dist/cli/validate/discovery.js.map +1 -1
- package/dist/cli/validate/index.d.ts +3 -3
- package/dist/cli/validate/index.d.ts.map +1 -1
- package/dist/client/Mppx.d.ts +3 -0
- package/dist/client/Mppx.d.ts.map +1 -1
- package/dist/client/Mppx.js +13 -5
- package/dist/client/Mppx.js.map +1 -1
- package/dist/client/Transport.d.ts +3 -5
- package/dist/client/Transport.d.ts.map +1 -1
- package/dist/client/Transport.js +1 -17
- package/dist/client/Transport.js.map +1 -1
- package/dist/client/internal/Fetch.d.ts.map +1 -1
- package/dist/client/internal/Fetch.js +2 -6
- package/dist/client/internal/Fetch.js.map +1 -1
- package/dist/client/node.js.map +1 -1
- package/dist/discovery/OpenApi.d.ts +3 -5
- package/dist/discovery/OpenApi.d.ts.map +1 -1
- package/dist/discovery/OpenApi.js +13 -34
- package/dist/discovery/OpenApi.js.map +1 -1
- package/dist/discovery/internal/Metadata.d.ts +20 -0
- package/dist/discovery/internal/Metadata.d.ts.map +1 -0
- package/dist/discovery/internal/Metadata.js +36 -0
- package/dist/discovery/internal/Metadata.js.map +1 -0
- package/dist/evm/Methods.d.ts +11 -11
- package/dist/evm/Methods.d.ts.map +1 -1
- package/dist/evm/Types.d.ts +17 -17
- package/dist/evm/Types.d.ts.map +1 -1
- package/dist/evm/client/Charge.d.ts +11 -11
- package/dist/evm/client/Methods.d.ts +11 -11
- package/dist/evm/server/Charge.d.ts +1 -1
- package/dist/evm/server/Charge.d.ts.map +1 -1
- package/dist/evm/server/Charge.js +2 -0
- package/dist/evm/server/Charge.js.map +1 -1
- package/dist/evm/server/Methods.d.ts +11 -11
- package/dist/internal/HeaderCodec.d.ts +2 -2
- package/dist/internal/HeaderCodec.d.ts.map +1 -1
- package/dist/internal/types.d.ts +6 -0
- package/dist/internal/types.d.ts.map +1 -1
- package/dist/middlewares/elysia.js.map +1 -1
- package/dist/middlewares/express.js.map +1 -1
- package/dist/middlewares/hono.js.map +1 -1
- package/dist/middlewares/nextjs.js.map +1 -1
- package/dist/proxy/Proxy.d.ts +2 -0
- package/dist/proxy/Proxy.d.ts.map +1 -1
- package/dist/proxy/Proxy.js +117 -9
- package/dist/proxy/Proxy.js.map +1 -1
- package/dist/proxy/Service.d.ts +36 -1
- package/dist/proxy/Service.d.ts.map +1 -1
- package/dist/proxy/Service.js +9 -8
- package/dist/proxy/Service.js.map +1 -1
- package/dist/proxy/services/anthropic.d.ts.map +1 -1
- package/dist/proxy/services/anthropic.js +1 -0
- package/dist/proxy/services/anthropic.js.map +1 -1
- package/dist/proxy/services/openai.d.ts.map +1 -1
- package/dist/proxy/services/openai.js +1 -0
- package/dist/proxy/services/openai.js.map +1 -1
- package/dist/proxy/services/stripe.d.ts.map +1 -1
- package/dist/proxy/services/stripe.js +1 -0
- package/dist/proxy/services/stripe.js.map +1 -1
- package/dist/server/Mppx.d.ts +75 -13
- package/dist/server/Mppx.d.ts.map +1 -1
- package/dist/server/Mppx.js +201 -23
- package/dist/server/Mppx.js.map +1 -1
- package/dist/server/internal/html/config.d.ts +9 -9
- package/dist/server/internal/html/config.d.ts.map +1 -1
- package/dist/server/internal/html/constants.d.ts +17 -17
- package/dist/server/internal/html/constants.d.ts.map +1 -1
- package/dist/stripe/Methods.d.ts +10 -10
- package/dist/stripe/Methods.d.ts.map +1 -1
- package/dist/stripe/client/Charge.d.ts +10 -10
- package/dist/stripe/client/Methods.d.ts +10 -10
- package/dist/stripe/internal/constants.d.ts +1 -1
- package/dist/stripe/internal/constants.js +1 -1
- package/dist/stripe/internal/types.d.ts +1 -0
- package/dist/stripe/internal/types.d.ts.map +1 -1
- package/dist/stripe/server/Charge.d.ts +11 -11
- package/dist/stripe/server/Charge.d.ts.map +1 -1
- package/dist/stripe/server/Charge.js +49 -1
- package/dist/stripe/server/Charge.js.map +1 -1
- package/dist/stripe/server/Methods.d.ts +137 -48
- package/dist/stripe/server/Methods.d.ts.map +1 -1
- package/dist/stripe/server/Methods.js +259 -4
- package/dist/stripe/server/Methods.js.map +1 -1
- package/dist/stripe/server/internal/deposit-address.d.ts +13 -0
- package/dist/stripe/server/internal/deposit-address.d.ts.map +1 -0
- package/dist/stripe/server/internal/deposit-address.js +28 -0
- package/dist/stripe/server/internal/deposit-address.js.map +1 -0
- package/dist/stripe/server/internal/html.gen.d.ts +1 -1
- package/dist/stripe/server/internal/html.gen.d.ts.map +1 -1
- package/dist/stripe/server/internal/html.gen.js +1 -1
- package/dist/stripe/server/internal/html.gen.js.map +1 -1
- package/dist/stripe/server/internal/record-payment.d.ts +15 -0
- package/dist/stripe/server/internal/record-payment.d.ts.map +1 -0
- package/dist/stripe/server/internal/record-payment.js +42 -0
- package/dist/stripe/server/internal/record-payment.js.map +1 -0
- package/dist/stripe/server/internal/request.d.ts +25 -0
- package/dist/stripe/server/internal/request.d.ts.map +1 -0
- package/dist/stripe/server/internal/request.js +29 -0
- package/dist/stripe/server/internal/request.js.map +1 -0
- package/dist/tap/Constants.d.ts +28 -0
- package/dist/tap/Constants.d.ts.map +1 -0
- package/dist/tap/Constants.js +32 -0
- package/dist/tap/Constants.js.map +1 -0
- package/dist/tap/Types.d.ts +11 -0
- package/dist/tap/Types.d.ts.map +1 -0
- package/dist/tap/Types.js +2 -0
- package/dist/tap/Types.js.map +1 -0
- package/dist/tap/client/index.d.ts +26 -0
- package/dist/tap/client/index.d.ts.map +1 -0
- package/dist/tap/client/index.js +33 -0
- package/dist/tap/client/index.js.map +1 -0
- package/dist/tap/index.d.ts +5 -0
- package/dist/tap/index.d.ts.map +1 -0
- package/dist/tap/index.js +5 -0
- package/dist/tap/index.js.map +1 -0
- package/dist/tap/server/index.d.ts +20 -0
- package/dist/tap/server/index.d.ts.map +1 -0
- package/dist/tap/server/index.js +36 -0
- package/dist/tap/server/index.js.map +1 -0
- package/dist/tempo/Attribution.d.ts +1 -1
- package/dist/tempo/Methods.d.ts +60 -60
- package/dist/tempo/Methods.d.ts.map +1 -1
- package/dist/tempo/Proof.d.ts +16 -16
- package/dist/tempo/client/Charge.d.ts +19 -19
- package/dist/tempo/client/Charge.d.ts.map +1 -1
- package/dist/tempo/client/Charge.js +1 -7
- package/dist/tempo/client/Charge.js.map +1 -1
- package/dist/tempo/client/Methods.d.ts +38 -38
- package/dist/tempo/client/Methods.js.map +1 -1
- package/dist/tempo/client/Subscription.d.ts +23 -23
- package/dist/tempo/client/Subscription.js.map +1 -1
- package/dist/tempo/internal/address.d.ts +2 -1
- package/dist/tempo/internal/address.d.ts.map +1 -1
- package/dist/tempo/internal/address.js +3 -1
- package/dist/tempo/internal/address.js.map +1 -1
- package/dist/tempo/internal/auto-swap.d.ts.map +1 -1
- package/dist/tempo/internal/auto-swap.js +4 -19
- package/dist/tempo/internal/auto-swap.js.map +1 -1
- package/dist/tempo/internal/defaults.d.ts +6 -6
- package/dist/tempo/internal/defaults.d.ts.map +1 -1
- package/dist/tempo/internal/fee-payer.d.ts +12 -12
- package/dist/tempo/internal/fee-payer.d.ts.map +1 -1
- package/dist/tempo/internal/fee-payer.js.map +1 -1
- package/dist/tempo/internal/proof.d.ts +17 -17
- package/dist/tempo/internal/proof.d.ts.map +1 -1
- package/dist/tempo/legacy/client/Session.d.ts +20 -20
- package/dist/tempo/legacy/client/Session.js.map +1 -1
- package/dist/tempo/legacy/client/SessionManager.js.map +1 -1
- package/dist/tempo/legacy/index.d.ts +1 -3
- package/dist/tempo/legacy/index.d.ts.map +1 -1
- package/dist/tempo/legacy/index.js +1 -3
- package/dist/tempo/legacy/index.js.map +1 -1
- package/dist/tempo/legacy/session/escrow.abi.d.ts +374 -374
- package/dist/tempo/legacy/session/escrow.abi.d.ts.map +1 -1
- package/dist/tempo/server/Charge.d.ts +25 -11
- package/dist/tempo/server/Charge.d.ts.map +1 -1
- package/dist/tempo/server/Charge.js +44 -39
- package/dist/tempo/server/Charge.js.map +1 -1
- package/dist/tempo/server/Methods.d.ts +37 -52
- package/dist/tempo/server/Methods.d.ts.map +1 -1
- package/dist/tempo/server/Methods.js +0 -14
- package/dist/tempo/server/Methods.js.map +1 -1
- package/dist/tempo/server/Relay.d.ts +1 -1
- package/dist/tempo/server/Relay.d.ts.map +1 -1
- package/dist/tempo/server/Relay.js +2 -2
- package/dist/tempo/server/Relay.js.map +1 -1
- package/dist/tempo/server/Subscription.d.ts +25 -25
- package/dist/tempo/server/Subscription.d.ts.map +1 -1
- package/dist/tempo/server/Subscription.js +2 -0
- package/dist/tempo/server/Subscription.js.map +1 -1
- package/dist/tempo/server/index.d.ts +1 -1
- package/dist/tempo/server/index.d.ts.map +1 -1
- package/dist/tempo/server/index.js +1 -1
- package/dist/tempo/server/index.js.map +1 -1
- package/dist/tempo/server/internal/html.gen.d.ts +1 -1
- package/dist/tempo/server/internal/html.gen.d.ts.map +1 -1
- package/dist/tempo/server/internal/html.gen.js +1 -1
- package/dist/tempo/server/internal/html.gen.js.map +1 -1
- package/dist/tempo/server/internal/transport.d.ts +2 -0
- package/dist/tempo/server/internal/transport.d.ts.map +1 -1
- package/dist/tempo/server/internal/transport.js +9 -2
- package/dist/tempo/server/internal/transport.js.map +1 -1
- package/dist/tempo/session/client/ChannelOps.js.map +1 -1
- package/dist/tempo/session/client/CredentialState.d.ts +1 -1
- package/dist/tempo/session/client/CredentialState.js.map +1 -1
- package/dist/tempo/session/client/ReceiptCoordinator.js.map +1 -1
- package/dist/tempo/session/client/Runtime.js.map +1 -1
- package/dist/tempo/session/client/Session.d.ts +19 -19
- package/dist/tempo/session/client/Session.js.map +1 -1
- package/dist/tempo/session/client/SessionManager.js.map +1 -1
- package/dist/tempo/session/client/Transports.d.ts.map +1 -1
- package/dist/tempo/session/precompile/Chain.d.ts +27 -0
- package/dist/tempo/session/precompile/Chain.d.ts.map +1 -1
- package/dist/tempo/session/precompile/Chain.js +68 -7
- package/dist/tempo/session/precompile/Chain.js.map +1 -1
- package/dist/tempo/session/precompile/Protocol.js.map +1 -1
- package/dist/tempo/session/precompile/Voucher.d.ts +4 -4
- package/dist/tempo/session/precompile/Voucher.d.ts.map +1 -1
- package/dist/tempo/session/precompile/escrow.abi.d.ts +306 -306
- package/dist/tempo/session/precompile/escrow.abi.d.ts.map +1 -1
- package/dist/tempo/session/server/ChannelStore.d.ts +9 -0
- package/dist/tempo/session/server/ChannelStore.d.ts.map +1 -1
- package/dist/tempo/session/server/ChannelStore.js +16 -8
- package/dist/tempo/session/server/ChannelStore.js.map +1 -1
- package/dist/tempo/session/server/CredentialVerification.d.ts +30 -13
- package/dist/tempo/session/server/CredentialVerification.d.ts.map +1 -1
- package/dist/tempo/session/server/CredentialVerification.js +207 -13
- package/dist/tempo/session/server/CredentialVerification.js.map +1 -1
- package/dist/tempo/session/server/MeteredStream.d.ts +3 -0
- package/dist/tempo/session/server/MeteredStream.d.ts.map +1 -1
- package/dist/tempo/session/server/MeteredStream.js +3 -1
- package/dist/tempo/session/server/MeteredStream.js.map +1 -1
- package/dist/tempo/session/server/Session.d.ts +32 -21
- package/dist/tempo/session/server/Session.d.ts.map +1 -1
- package/dist/tempo/session/server/Session.js +116 -53
- package/dist/tempo/session/server/Session.js.map +1 -1
- package/dist/tempo/session/server/Sse.d.ts +3 -1
- package/dist/tempo/session/server/Sse.d.ts.map +1 -1
- package/dist/tempo/session/server/Sse.js +2 -1
- package/dist/tempo/session/server/Sse.js.map +1 -1
- package/dist/tempo/session/server/Transports.d.ts +1 -1
- package/dist/tempo/session/server/Transports.d.ts.map +1 -1
- package/dist/tempo/session/server/Transports.js +1 -0
- package/dist/tempo/session/server/Transports.js.map +1 -1
- package/dist/tempo/session/server/Ws.d.ts +6 -1
- package/dist/tempo/session/server/Ws.d.ts.map +1 -1
- package/dist/tempo/session/server/Ws.js +1 -0
- package/dist/tempo/session/server/Ws.js.map +1 -1
- package/dist/tempo/subscription/KeyAuthorization.d.ts +39 -39
- package/dist/tempo/subscription/KeyAuthorization.d.ts.map +1 -1
- package/dist/viem/Account.d.ts.map +1 -1
- package/dist/viem/Account.js.map +1 -1
- package/dist/web-bot-auth/Constants.d.ts +20 -0
- package/dist/web-bot-auth/Constants.d.ts.map +1 -0
- package/dist/web-bot-auth/Constants.js +24 -0
- package/dist/web-bot-auth/Constants.js.map +1 -0
- package/dist/web-bot-auth/Types.d.ts +10 -0
- package/dist/web-bot-auth/Types.d.ts.map +1 -0
- package/dist/web-bot-auth/Types.js +2 -0
- package/dist/web-bot-auth/Types.js.map +1 -0
- package/dist/web-bot-auth/client/index.d.ts +29 -0
- package/dist/web-bot-auth/client/index.d.ts.map +1 -0
- package/dist/web-bot-auth/client/index.js +64 -0
- package/dist/web-bot-auth/client/index.js.map +1 -0
- package/dist/web-bot-auth/index.d.ts +7 -0
- package/dist/web-bot-auth/index.d.ts.map +1 -0
- package/dist/web-bot-auth/index.js +7 -0
- package/dist/web-bot-auth/index.js.map +1 -0
- package/dist/web-bot-auth/internal/JwkThumbprint.d.ts +5 -0
- package/dist/web-bot-auth/internal/JwkThumbprint.d.ts.map +1 -0
- package/dist/web-bot-auth/internal/JwkThumbprint.js +20 -0
- package/dist/web-bot-auth/internal/JwkThumbprint.js.map +1 -0
- package/dist/web-bot-auth/internal/SignatureAgent.d.ts +3 -0
- package/dist/web-bot-auth/internal/SignatureAgent.d.ts.map +1 -0
- package/dist/web-bot-auth/internal/SignatureAgent.js +18 -0
- package/dist/web-bot-auth/internal/SignatureAgent.js.map +1 -0
- package/dist/web-bot-auth/server/index.d.ts +35 -0
- package/dist/web-bot-auth/server/index.d.ts.map +1 -0
- package/dist/web-bot-auth/server/index.js +88 -0
- package/dist/web-bot-auth/server/index.js.map +1 -0
- package/dist/x402/Assets.d.ts.map +1 -1
- package/dist/x402/Types.d.ts +6 -6
- package/dist/x402/Types.d.ts.map +1 -1
- package/dist/x402/server/EvmCharge.d.ts.map +1 -1
- package/dist/x402/server/EvmCharge.js +32 -20
- package/dist/x402/server/EvmCharge.js.map +1 -1
- package/package.json +19 -3
- package/src/Challenge.fuzz.test.ts +80 -47
- package/src/Challenge.test.ts +65 -0
- package/src/Challenge.ts +39 -35
- package/src/Method.ts +82 -68
- package/src/Store.test-d.ts +16 -0
- package/src/Store.test.ts +50 -0
- package/src/Store.ts +68 -0
- package/src/attestation/Attestation.integration.test.ts +208 -0
- package/src/attestation/Client.test.ts +83 -0
- package/src/attestation/Client.ts +34 -0
- package/src/attestation/Constants.ts +15 -0
- package/src/attestation/Server.test.ts +60 -0
- package/src/attestation/Server.ts +12 -0
- package/src/attestation/Types.test-d.ts +54 -0
- package/src/attestation/Types.ts +77 -0
- package/src/attestation/index.ts +5 -0
- package/src/attestation/internal/HttpMessageSignature.test.ts +101 -0
- package/src/attestation/internal/HttpMessageSignature.ts +429 -0
- package/src/attestation/internal/SigningContext.ts +13 -0
- package/src/bin.js +2 -0
- package/src/cli/cli.ts +1 -0
- package/src/client/Mppx.test-d.ts +17 -0
- package/src/client/Mppx.test.ts +14 -14
- package/src/client/Mppx.ts +25 -4
- package/src/client/Transport.test.ts +12 -45
- package/src/client/Transport.ts +3 -24
- package/src/client/internal/Fetch.ts +2 -6
- package/src/discovery/OpenApi.test.ts +170 -0
- package/src/discovery/OpenApi.ts +16 -48
- package/src/discovery/internal/Metadata.ts +51 -0
- package/src/evm/server/Charge.ts +6 -1
- package/src/internal/AcceptPayment.test.ts +12 -8
- package/src/internal/types.ts +9 -0
- package/src/mcp/client/McpClient.integration.test.ts +19 -32
- package/src/middlewares/elysia.test.ts +2 -12
- package/src/middlewares/express.test.ts +2 -12
- package/src/middlewares/hono.test.ts +6 -9
- package/src/middlewares/nextjs.test.ts +2 -12
- package/src/proxy/Proxy.test.ts +26 -19
- package/src/proxy/Proxy.ts +147 -9
- package/src/proxy/Proxy.upstreamError.test.ts +364 -0
- package/src/proxy/Service.test.ts +73 -3
- package/src/proxy/Service.ts +50 -23
- package/src/proxy/services/anthropic.ts +1 -0
- package/src/proxy/services/hooks.test-d.ts +14 -0
- package/src/proxy/services/hooks.test.ts +44 -0
- package/src/proxy/services/openai.ts +1 -0
- package/src/proxy/services/stripe.ts +1 -0
- package/src/server/Methods.test-d.ts +88 -0
- package/src/server/Methods.test.ts +69 -0
- package/src/server/Mppx.test-d.ts +141 -7
- package/src/server/Mppx.test.ts +1017 -119
- package/src/server/Mppx.ts +350 -54
- package/src/stripe/internal/constants.ts +1 -1
- package/src/stripe/internal/types.ts +1 -0
- package/src/stripe/server/Charge.test-d.ts +16 -1
- package/src/stripe/server/Charge.test.ts +79 -0
- package/src/stripe/server/Charge.ts +54 -1
- package/src/stripe/server/Methods.test-d.ts +157 -0
- package/src/stripe/server/Methods.test.ts +403 -0
- package/src/stripe/server/Methods.ts +423 -6
- package/src/stripe/server/internal/deposit-address.ts +57 -0
- package/src/stripe/server/internal/html/node_modules/.bin/mppx +3 -3
- package/src/stripe/server/internal/html/package.json +1 -1
- package/src/stripe/server/internal/html.gen.ts +1 -1
- package/src/stripe/server/internal/record-payment.ts +66 -0
- package/src/stripe/server/internal/request.ts +49 -0
- package/src/tap/Constants.ts +32 -0
- package/src/tap/Tap.test.ts +125 -0
- package/src/tap/Types.ts +11 -0
- package/src/tap/client/index.ts +54 -0
- package/src/tap/index.ts +4 -0
- package/src/tap/server/index.ts +48 -0
- package/src/tempo/PublicExports.test-d.ts +3 -3
- package/src/tempo/client/Charge.ts +1 -19
- package/src/tempo/internal/address.test.ts +42 -0
- package/src/tempo/internal/address.ts +3 -3
- package/src/tempo/internal/auto-swap.test.ts +4 -4
- package/src/tempo/internal/auto-swap.ts +7 -50
- package/src/tempo/legacy/README.md +5 -5
- package/src/tempo/legacy/index.ts +1 -3
- package/src/tempo/server/AtomicStore.test-d.ts +13 -0
- package/src/tempo/server/Charge.test.ts +19 -84
- package/src/tempo/server/Charge.ts +83 -55
- package/src/tempo/server/Methods.ts +0 -20
- package/src/tempo/server/Relay.test.ts +5 -5
- package/src/tempo/server/Relay.ts +2 -2
- package/src/tempo/server/Subscription.ts +4 -1
- package/src/tempo/server/index.ts +1 -1
- package/src/tempo/server/internal/html/node_modules/.bin/mppx +3 -3
- package/src/tempo/server/internal/html/package.json +1 -1
- package/src/tempo/server/internal/html.gen.ts +1 -1
- package/src/tempo/server/internal/transport.test.ts +22 -3
- package/src/tempo/server/internal/transport.ts +15 -3
- package/src/tempo/session/README.md +112 -0
- package/src/tempo/session/precompile/Chain.ts +131 -11
- package/src/tempo/session/server/ChannelStore.ts +33 -12
- package/src/tempo/session/server/CredentialVerification.test.ts +4 -4
- package/src/tempo/session/server/CredentialVerification.ts +340 -28
- package/src/tempo/session/server/MeteredStream.ts +5 -1
- package/src/tempo/session/server/Session.test.ts +428 -43
- package/src/tempo/session/server/Session.ts +159 -60
- package/src/tempo/session/server/Sse.test.ts +77 -0
- package/src/tempo/session/server/Sse.ts +8 -1
- package/src/tempo/session/server/Transports.ts +2 -1
- package/src/tempo/session/server/Ws.test.ts +171 -0
- package/src/tempo/session/server/Ws.ts +7 -1
- package/src/web-bot-auth/Constants.ts +24 -0
- package/src/web-bot-auth/Types.ts +9 -0
- package/src/web-bot-auth/WebBotAuth.test.ts +182 -0
- package/src/web-bot-auth/client/index.ts +84 -0
- package/src/web-bot-auth/index.ts +6 -0
- package/src/web-bot-auth/internal/JwkThumbprint.ts +21 -0
- package/src/web-bot-auth/internal/SignatureAgent.ts +18 -0
- package/src/web-bot-auth/server/index.ts +113 -0
- package/src/x402/Exact.e2e.test.ts +121 -81
- package/src/x402/Exact.localnet.test.ts +1 -1
- package/src/x402/server/EvmCharge.ts +35 -19
- package/dist/tempo/legacy/server/Session.d.ts +0 -208
- package/dist/tempo/legacy/server/Session.d.ts.map +0 -1
- package/dist/tempo/legacy/server/Session.js +0 -698
- package/dist/tempo/legacy/server/Session.js.map +0 -1
- package/dist/tempo/legacy/server/index.d.ts +0 -5
- package/dist/tempo/legacy/server/index.d.ts.map +0 -1
- package/dist/tempo/legacy/server/index.js +0 -5
- package/dist/tempo/legacy/server/index.js.map +0 -1
- package/dist/tempo/legacy/session/ChannelStore.d.ts +0 -22
- package/dist/tempo/legacy/session/ChannelStore.d.ts.map +0 -1
- package/dist/tempo/legacy/session/ChannelStore.js +0 -6
- package/dist/tempo/legacy/session/ChannelStore.js.map +0 -1
- package/src/tempo/legacy/server/Defaults.test-d.ts +0 -9
- package/src/tempo/legacy/server/Session.test.ts +0 -6370
- package/src/tempo/legacy/server/Session.ts +0 -1024
- package/src/tempo/legacy/server/index.ts +0 -4
- package/src/tempo/legacy/session/ChannelStore.test.ts +0 -58
- package/src/tempo/legacy/session/ChannelStore.ts +0 -39
|
@@ -738,8 +738,15 @@ describe('sse transport', () => {
|
|
|
738
738
|
|
|
739
739
|
test('respondReceipt with non-SSE upstream Response still deducts from channel', async () => {
|
|
740
740
|
const store = memoryStore()
|
|
741
|
+
const settled: Array<{ spent: bigint; units: number }> = []
|
|
741
742
|
await seedChannel(store, 10000000n)
|
|
742
|
-
const transport = sse({
|
|
743
|
+
const transport = sse({
|
|
744
|
+
store,
|
|
745
|
+
async settleCharged(channel) {
|
|
746
|
+
settled.push({ spent: channel.spent, units: channel.units })
|
|
747
|
+
return undefined
|
|
748
|
+
},
|
|
749
|
+
})
|
|
743
750
|
const request = new Request('https://test.example.com/session', {
|
|
744
751
|
body: JSON.stringify({ prompt: 'hello' }),
|
|
745
752
|
headers: makeAuthorizedRequest().headers,
|
|
@@ -768,6 +775,7 @@ describe('sse transport', () => {
|
|
|
768
775
|
expect(channel!.units).toBe(1)
|
|
769
776
|
expect(receipt.spent).toBe('1000000')
|
|
770
777
|
expect(receipt.units).toBe(1)
|
|
778
|
+
expect(settled).toEqual([{ spent: 1000000n, units: 1 }])
|
|
771
779
|
|
|
772
780
|
expect(JSON.parse(body)).toEqual({ content: 'hello' })
|
|
773
781
|
expect(response.headers.get('Content-Type')).toBe('application/json')
|
|
@@ -806,8 +814,18 @@ describe('sse transport', () => {
|
|
|
806
814
|
|
|
807
815
|
test('respondReceipt with 204 content response still deducts from channel', async () => {
|
|
808
816
|
const store = memoryStore()
|
|
817
|
+
let resolveSettlement!: (channel: ChannelStore.State) => void
|
|
818
|
+
const settlement = new Promise<ChannelStore.State>((resolve) => {
|
|
819
|
+
resolveSettlement = resolve
|
|
820
|
+
})
|
|
809
821
|
await seedChannel(store, 10000000n)
|
|
810
|
-
const transport = sse({
|
|
822
|
+
const transport = sse({
|
|
823
|
+
store,
|
|
824
|
+
async settleCharged(channel) {
|
|
825
|
+
resolveSettlement(channel)
|
|
826
|
+
return undefined
|
|
827
|
+
},
|
|
828
|
+
})
|
|
811
829
|
const request = new Request('https://test.example.com/session', {
|
|
812
830
|
body: JSON.stringify({ prompt: 'hello' }),
|
|
813
831
|
headers: makeAuthorizedRequest().headers,
|
|
@@ -827,11 +845,12 @@ describe('sse transport', () => {
|
|
|
827
845
|
expect(await response.text()).toBe('')
|
|
828
846
|
const receipt = deserializeSessionReceipt(response.headers.get('Payment-Receipt')!)
|
|
829
847
|
|
|
830
|
-
await
|
|
848
|
+
const settled = await settlement
|
|
831
849
|
|
|
832
850
|
const channel = await store.getChannel(channelId)
|
|
833
851
|
expect(channel!.spent).toBe(1000000n)
|
|
834
852
|
expect(channel!.units).toBe(1)
|
|
853
|
+
expect(settled).toMatchObject({ spent: 1000000n, units: 1 })
|
|
835
854
|
expect(receipt.spent).toBe('1000000')
|
|
836
855
|
expect(receipt.units).toBe(1)
|
|
837
856
|
})
|
|
@@ -12,6 +12,7 @@ import * as Transport from '../../../server/Transport.js'
|
|
|
12
12
|
import type { SessionReceipt } from '../../session/precompile/Protocol.js'
|
|
13
13
|
import { requireSessionCredentialContext } from '../../session/precompile/Protocol.js'
|
|
14
14
|
import * as ChannelStore from '../../session/server/ChannelStore.js'
|
|
15
|
+
import type { SettleChargedSessionChannel } from '../../session/server/Settlement.js'
|
|
15
16
|
import * as Sse_core from '../../session/server/Sse.js'
|
|
16
17
|
import { captureRequestBodyProbe, shouldChargePlainResponse } from './request-body.js'
|
|
17
18
|
|
|
@@ -48,7 +49,12 @@ function hasPrepaidSessionTick(receipt: SessionReceipt): boolean {
|
|
|
48
49
|
* - Auto-detection of upstream SSE responses
|
|
49
50
|
* - Fallback to standard HTTP receipt handling for plain Response
|
|
50
51
|
*/
|
|
51
|
-
export function sse(
|
|
52
|
+
export function sse(
|
|
53
|
+
options: sse.Options & {
|
|
54
|
+
settleCharged?: SettleChargedSessionChannel | undefined
|
|
55
|
+
store: ChannelStore.ChannelStore
|
|
56
|
+
},
|
|
57
|
+
): Sse {
|
|
52
58
|
const { pollingInterval, poll } = options
|
|
53
59
|
|
|
54
60
|
// When `poll` is true, strip `waitForUpdate` so the SSE charge loop
|
|
@@ -117,6 +123,7 @@ export function sse(options: sse.Options & { store: ChannelStore.ChannelStore })
|
|
|
117
123
|
tickCost,
|
|
118
124
|
pollIntervalMs: pollingInterval,
|
|
119
125
|
generate,
|
|
126
|
+
onChargeCommitted: options.settleCharged,
|
|
120
127
|
prepaidUnits: hasPrepaidSessionTick(receipt as SessionReceipt) ? 1 : 0,
|
|
121
128
|
signal: input.signal,
|
|
122
129
|
})
|
|
@@ -174,20 +181,25 @@ export function sse(options: sse.Options & { store: ChannelStore.ChannelStore })
|
|
|
174
181
|
response: response as Response,
|
|
175
182
|
challengeId: verifiedChallengeId,
|
|
176
183
|
})
|
|
184
|
+
const chargePlainResponse = async () => {
|
|
185
|
+
const result = await ChannelStore.deductFromChannel(store, channelId, tickCost)
|
|
186
|
+
if (result.ok) await options.settleCharged?.(result.channel)
|
|
187
|
+
return result
|
|
188
|
+
}
|
|
177
189
|
|
|
178
190
|
// Non-SSE response (e.g. upstream returned JSON instead of event-stream).
|
|
179
191
|
// Need to deduct tickCost so request isn't free.
|
|
180
192
|
// For null-body statuses, the request shape determines whether the
|
|
181
193
|
// response is management (no charge) or plain content (charge one tick).
|
|
182
194
|
if (isNullBodyStatus(chargedResponse.status)) {
|
|
183
|
-
void
|
|
195
|
+
void chargePlainResponse()
|
|
184
196
|
return chargedResponse
|
|
185
197
|
}
|
|
186
198
|
|
|
187
199
|
const stream = new ReadableStream<Uint8Array>({
|
|
188
200
|
async start(controller) {
|
|
189
201
|
// deduction completes before consumer reads
|
|
190
|
-
const result = await
|
|
202
|
+
const result = await chargePlainResponse()
|
|
191
203
|
if (!result.ok) {
|
|
192
204
|
controller.error(
|
|
193
205
|
new Errors.InsufficientBalanceError({
|
|
@@ -186,6 +186,118 @@ sequenceDiagram
|
|
|
186
186
|
The initial SSE POST is excluded from default HTTP charging to prevent double
|
|
187
187
|
counting. Stream accounting remains owned by the transport driver.
|
|
188
188
|
|
|
189
|
+
## Server transport configuration
|
|
190
|
+
|
|
191
|
+
A session method owns the account, channel store, verification policy, and
|
|
192
|
+
settlement schedule. Routes add prices and application content. HTTP and SSE
|
|
193
|
+
run through configured route handlers; WebSocket uses a session-bound helper
|
|
194
|
+
because its application messages no longer pass through HTTP.
|
|
195
|
+
|
|
196
|
+
| Server shape | Session option | Content API | Charging |
|
|
197
|
+
| ---------------------- | -------------- | ----------------------------------- | ----------------------------------- |
|
|
198
|
+
| HTTP only | Omit `sse` | `result.withReceipt(Response)` | Once per billable request |
|
|
199
|
+
| SSE only | `sse: true` | `result.withReceipt(AsyncIterable)` | Each `stream.charge()` |
|
|
200
|
+
| WebSocket only | Omit `sse` | `mppx.session.serveWebSocket(...)` | Each `stream.charge()` |
|
|
201
|
+
| HTTP + SSE + WebSocket | `sse: true` | All three APIs | Selected by route and response type |
|
|
202
|
+
|
|
203
|
+
All transports for one session service must share the same configured session
|
|
204
|
+
method and store. `serveWebSocket` is bound to both the store and settlement
|
|
205
|
+
policy, so callers pass neither dependency again. `tempo.Ws.serve` remains the
|
|
206
|
+
low-level adapter for custom integrations.
|
|
207
|
+
|
|
208
|
+
### Shared method configuration
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
const session = tempo.session({
|
|
212
|
+
account,
|
|
213
|
+
currency,
|
|
214
|
+
getClient: () => client,
|
|
215
|
+
settlementSchedule: { units: 100 },
|
|
216
|
+
store,
|
|
217
|
+
// Include when this instance serves any SSE route.
|
|
218
|
+
sse: true,
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
const mppx = Mppx.create({ methods: [session], secretKey })
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
`sse: true` enables async-iterable responses without changing ordinary
|
|
225
|
+
`Response` handling, so a mixed server uses one session method.
|
|
226
|
+
|
|
227
|
+
### HTTP
|
|
228
|
+
|
|
229
|
+
```ts
|
|
230
|
+
const httpRoute = mppx.session({ amount: '0.01', unitType: 'request' })
|
|
231
|
+
const result = await httpRoute(request)
|
|
232
|
+
|
|
233
|
+
if (result.status === 402) return result.challenge
|
|
234
|
+
return result.withReceipt(Response.json({ ok: true }))
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
HTTP accounting charges the configured route amount before application content
|
|
238
|
+
runs. A plain `Response` selects normal HTTP handling even when `sse: true`.
|
|
239
|
+
|
|
240
|
+
### SSE
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
const sseRoute = mppx.session({ amount: '0.001', unitType: 'token' })
|
|
244
|
+
const result = await sseRoute(request)
|
|
245
|
+
|
|
246
|
+
if (result.status === 402) return result.challenge
|
|
247
|
+
return result.withReceipt(async function* (stream) {
|
|
248
|
+
for await (const token of generateTokens()) {
|
|
249
|
+
await stream.charge()
|
|
250
|
+
yield token
|
|
251
|
+
}
|
|
252
|
+
})
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
SSE requires `sse: true` on the shared session method. The async iterable
|
|
256
|
+
selects SSE framing and transport-owned metering.
|
|
257
|
+
|
|
258
|
+
### WebSocket
|
|
259
|
+
|
|
260
|
+
```ts
|
|
261
|
+
const wsRoute = mppx.session({ amount: '0.001', unitType: 'token' })
|
|
262
|
+
|
|
263
|
+
webSocketServer.on('connection', (socket, request) => {
|
|
264
|
+
void mppx.session.serveWebSocket({
|
|
265
|
+
generate: async function* (stream) {
|
|
266
|
+
for await (const token of generateTokens()) {
|
|
267
|
+
await stream.charge()
|
|
268
|
+
yield token
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
route: wsRoute,
|
|
272
|
+
socket,
|
|
273
|
+
url: new URL(request.url!, `ws://${request.headers.host}`),
|
|
274
|
+
})
|
|
275
|
+
})
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
The application still exposes `wsRoute` over HTTP for the initial challenge
|
|
279
|
+
probe. The bound helper reuses the session store and automatic settlement
|
|
280
|
+
schedule for in-band WebSocket vouchers and charges.
|
|
281
|
+
|
|
282
|
+
### Mixed server
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
const httpRoute = mppx.session({ amount: '0.01', unitType: 'request' })
|
|
286
|
+
const sseRoute = mppx.session({ amount: '0.001', unitType: 'token' })
|
|
287
|
+
const wsRoute = mppx.session({ amount: '0.001', unitType: 'token' })
|
|
288
|
+
|
|
289
|
+
async function handler(request: Request) {
|
|
290
|
+
const pathname = new URL(request.url).pathname
|
|
291
|
+
if (pathname === '/api/data') return serveHttp(httpRoute, request)
|
|
292
|
+
if (pathname === '/api/events') return serveSse(sseRoute, request)
|
|
293
|
+
if (pathname === '/ws') return serveWebSocketProbe(wsRoute, request)
|
|
294
|
+
return new Response('Not found', { status: 404 })
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Each route can choose its own price and unit type. Verification, channel state,
|
|
299
|
+
and settlement policy remain shared through the single session method.
|
|
300
|
+
|
|
189
301
|
## Extension boundaries
|
|
190
302
|
|
|
191
303
|
| Change | Preserve |
|
|
@@ -522,6 +522,55 @@ async function simulateTempoTransaction(client: Client, request: unknown) {
|
|
|
522
522
|
await call(client, request as never)
|
|
523
523
|
}
|
|
524
524
|
|
|
525
|
+
/** Simulates an unsponsored client-signed session transaction without broadcasting it. */
|
|
526
|
+
export async function simulateCredentialTransaction(parameters: {
|
|
527
|
+
/** viem client used for the read-only execution simulation. */
|
|
528
|
+
client: TransactionClient
|
|
529
|
+
/** Fee-payer configuration for the eventual broadcast. Sponsored transactions are simulated after completion. */
|
|
530
|
+
feePayer?: Account | true | undefined
|
|
531
|
+
/** Parsed client-signed Tempo transaction. */
|
|
532
|
+
transaction: ReturnType<(typeof Transaction)['deserialize']>
|
|
533
|
+
}): Promise<void> {
|
|
534
|
+
if (parameters.feePayer) return
|
|
535
|
+
await simulateTempoTransaction(
|
|
536
|
+
parameters.client,
|
|
537
|
+
FeePayer.simulationTransaction(parameters.transaction, { feePayer: false }),
|
|
538
|
+
)
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
function validateCredentialSponsorship(parameters: {
|
|
542
|
+
allowedFeeTokens: readonly Address[]
|
|
543
|
+
challengeExpires?: string | undefined
|
|
544
|
+
chainId: number
|
|
545
|
+
details: Record<string, string>
|
|
546
|
+
feePayer?: Account | true | undefined
|
|
547
|
+
feePayerPolicy?: Partial<FeePayer.Policy> | undefined
|
|
548
|
+
transaction: ReturnType<(typeof Transaction)['deserialize']>
|
|
549
|
+
}) {
|
|
550
|
+
const {
|
|
551
|
+
allowedFeeTokens,
|
|
552
|
+
challengeExpires,
|
|
553
|
+
chainId,
|
|
554
|
+
details,
|
|
555
|
+
feePayer,
|
|
556
|
+
feePayerPolicy,
|
|
557
|
+
transaction,
|
|
558
|
+
} = parameters
|
|
559
|
+
if (!feePayer || feePayer === true) return
|
|
560
|
+
FeePayer.prepareSponsoredTransaction({
|
|
561
|
+
account: feePayer,
|
|
562
|
+
allowedFeeTokens,
|
|
563
|
+
challengeExpires,
|
|
564
|
+
chainId,
|
|
565
|
+
details,
|
|
566
|
+
policy: feePayerPolicy,
|
|
567
|
+
transaction: {
|
|
568
|
+
...transaction,
|
|
569
|
+
...(allowedFeeTokens[0] ? { feeToken: transaction.feeToken ?? allowedFeeTokens[0] } : {}),
|
|
570
|
+
},
|
|
571
|
+
})
|
|
572
|
+
}
|
|
573
|
+
|
|
525
574
|
async function signTempoTransaction(client: Client, transaction: unknown): Promise<Hex> {
|
|
526
575
|
return (await signTransaction(client, transaction as never)) as Hex
|
|
527
576
|
}
|
|
@@ -874,10 +923,25 @@ export type BroadcastOpenTransactionParameters = {
|
|
|
874
923
|
serializedTransaction: Hex
|
|
875
924
|
}
|
|
876
925
|
|
|
877
|
-
/**
|
|
878
|
-
export
|
|
879
|
-
|
|
880
|
-
|
|
926
|
+
/** Inputs for validating a client-signed TIP-1034 open transaction without broadcasting it. */
|
|
927
|
+
export type ValidateOpenCredentialTransactionParameters = Omit<
|
|
928
|
+
BroadcastOpenTransactionParameters,
|
|
929
|
+
'beforeBroadcast' | 'client'
|
|
930
|
+
>
|
|
931
|
+
|
|
932
|
+
/** Validated fields recovered from a client-signed TIP-1034 open transaction. */
|
|
933
|
+
export type ValidatedOpenCredentialTransaction = Omit<
|
|
934
|
+
BroadcastOpenTransactionResult,
|
|
935
|
+
'state' | 'txHash'
|
|
936
|
+
> & {
|
|
937
|
+
/** Parsed client-signed transaction, reused by simulation and broadcast. */
|
|
938
|
+
transaction: ReturnType<(typeof Transaction)['deserialize']>
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
/** Validates the immutable fields of a client-signed TIP-1034 open transaction. */
|
|
942
|
+
export function validateOpenCredentialTransaction(
|
|
943
|
+
parameters: ValidateOpenCredentialTransactionParameters,
|
|
944
|
+
): ValidatedOpenCredentialTransaction {
|
|
881
945
|
const { transaction, call, prefixCalls } = parsePrecompileCredentialTransaction({
|
|
882
946
|
escrowContract: parameters.escrowContract,
|
|
883
947
|
feePayer: parameters.feePayer,
|
|
@@ -909,6 +973,19 @@ export async function broadcastOpenTransaction(
|
|
|
909
973
|
channelId: parameters.expectedChannelId,
|
|
910
974
|
})
|
|
911
975
|
if (parameters.feePayer) assertSenderSigned(transaction)
|
|
976
|
+
validateCredentialSponsorship({
|
|
977
|
+
allowedFeeTokens: [parameters.expectedCurrency],
|
|
978
|
+
challengeExpires: parameters.challengeExpires,
|
|
979
|
+
chainId: parameters.chainId,
|
|
980
|
+
details: {
|
|
981
|
+
channelId: parameters.expectedChannelId,
|
|
982
|
+
currency: parameters.expectedCurrency,
|
|
983
|
+
recipient: parameters.expectedPayee,
|
|
984
|
+
},
|
|
985
|
+
feePayer: parameters.feePayer,
|
|
986
|
+
feePayerPolicy: parameters.feePayerPolicy,
|
|
987
|
+
transaction,
|
|
988
|
+
})
|
|
912
989
|
const expiringNonceHash = ChannelUtils.computeExpiringNonceHash(
|
|
913
990
|
ChannelUtils.transactionForExpiringNonceHash({
|
|
914
991
|
feePayer: parameters.feePayer,
|
|
@@ -920,10 +997,19 @@ export async function broadcastOpenTransaction(
|
|
|
920
997
|
throw new VerificationFailedError({
|
|
921
998
|
reason: 'credential expiringNonceHash does not match transaction',
|
|
922
999
|
})
|
|
1000
|
+
return { descriptor, expiringNonceHash, openDeposit: open.deposit, transaction }
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
/** Broadcast and validate a client-signed TIP-1034 open transaction. */
|
|
1004
|
+
export async function broadcastOpenTransaction(
|
|
1005
|
+
parameters: BroadcastOpenTransactionParameters,
|
|
1006
|
+
): Promise<BroadcastOpenTransactionResult> {
|
|
1007
|
+
const { descriptor, expiringNonceHash, openDeposit, transaction } =
|
|
1008
|
+
validateOpenCredentialTransaction(parameters)
|
|
923
1009
|
await parameters.beforeBroadcast?.({
|
|
924
1010
|
descriptor,
|
|
925
1011
|
expiringNonceHash,
|
|
926
|
-
openDeposit
|
|
1012
|
+
openDeposit,
|
|
927
1013
|
})
|
|
928
1014
|
const receipt = await sendCredentialTransaction({
|
|
929
1015
|
challengeExpires: parameters.challengeExpires,
|
|
@@ -952,7 +1038,7 @@ export async function broadcastOpenTransaction(
|
|
|
952
1038
|
emittedExpiringNonceHash: opened.expiringNonceHash,
|
|
953
1039
|
escrow: parameters.escrowContract,
|
|
954
1040
|
expectedChannelId: parameters.expectedChannelId,
|
|
955
|
-
openDeposit
|
|
1041
|
+
openDeposit,
|
|
956
1042
|
})
|
|
957
1043
|
const chainChannel = await readbackWithRetry(() =>
|
|
958
1044
|
getChannel(parameters.client, descriptor, parameters.escrowContract, receipt.blockNumber),
|
|
@@ -964,7 +1050,7 @@ export async function broadcastOpenTransaction(
|
|
|
964
1050
|
descriptor,
|
|
965
1051
|
state,
|
|
966
1052
|
expiringNonceHash: opened.expiringNonceHash,
|
|
967
|
-
openDeposit
|
|
1053
|
+
openDeposit,
|
|
968
1054
|
}
|
|
969
1055
|
}
|
|
970
1056
|
|
|
@@ -1004,10 +1090,22 @@ export type BroadcastTopUpTransactionParameters = {
|
|
|
1004
1090
|
serializedTransaction: Hex
|
|
1005
1091
|
}
|
|
1006
1092
|
|
|
1007
|
-
/**
|
|
1008
|
-
export
|
|
1009
|
-
|
|
1010
|
-
|
|
1093
|
+
/** Inputs for validating a client-signed TIP-1034 top-up transaction without broadcasting it. */
|
|
1094
|
+
export type ValidateTopUpCredentialTransactionParameters = Omit<
|
|
1095
|
+
BroadcastTopUpTransactionParameters,
|
|
1096
|
+
'client'
|
|
1097
|
+
>
|
|
1098
|
+
|
|
1099
|
+
/** Validated fields recovered from a client-signed TIP-1034 top-up transaction. */
|
|
1100
|
+
export type ValidatedTopUpCredentialTransaction = {
|
|
1101
|
+
/** Parsed client-signed transaction, reused by simulation and broadcast. */
|
|
1102
|
+
transaction: ReturnType<(typeof Transaction)['deserialize']>
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
/** Validates the immutable fields of a client-signed TIP-1034 top-up transaction. */
|
|
1106
|
+
export function validateTopUpCredentialTransaction(
|
|
1107
|
+
parameters: ValidateTopUpCredentialTransactionParameters,
|
|
1108
|
+
): ValidatedTopUpCredentialTransaction {
|
|
1011
1109
|
const { transaction, call, prefixCalls } = parsePrecompileCredentialTransaction({
|
|
1012
1110
|
escrowContract: parameters.escrowContract,
|
|
1013
1111
|
feePayer: parameters.feePayer,
|
|
@@ -1027,6 +1125,28 @@ export async function broadcastTopUpTransaction(
|
|
|
1027
1125
|
label: 'topUp',
|
|
1028
1126
|
prefixCalls,
|
|
1029
1127
|
})
|
|
1128
|
+
if (parameters.feePayer) assertSenderSigned(transaction)
|
|
1129
|
+
validateCredentialSponsorship({
|
|
1130
|
+
allowedFeeTokens: [parameters.expectedCurrency],
|
|
1131
|
+
challengeExpires: parameters.challengeExpires,
|
|
1132
|
+
chainId: parameters.chainId,
|
|
1133
|
+
details: {
|
|
1134
|
+
additionalDeposit: parameters.additionalDeposit.toString(),
|
|
1135
|
+
channelId: parameters.expectedChannelId,
|
|
1136
|
+
currency: parameters.expectedCurrency,
|
|
1137
|
+
},
|
|
1138
|
+
feePayer: parameters.feePayer,
|
|
1139
|
+
feePayerPolicy: parameters.feePayerPolicy,
|
|
1140
|
+
transaction,
|
|
1141
|
+
})
|
|
1142
|
+
return { transaction }
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
/** Broadcast and validate a client-signed TIP-1034 top-up transaction. */
|
|
1146
|
+
export async function broadcastTopUpTransaction(
|
|
1147
|
+
parameters: BroadcastTopUpTransactionParameters,
|
|
1148
|
+
): Promise<BroadcastTopUpTransactionResult> {
|
|
1149
|
+
const { transaction } = validateTopUpCredentialTransaction(parameters)
|
|
1030
1150
|
const receipt = await sendCredentialTransaction({
|
|
1031
1151
|
challengeExpires: parameters.challengeExpires,
|
|
1032
1152
|
chainId: parameters.chainId,
|
|
@@ -240,6 +240,18 @@ export type VerifyAndAcceptVoucherParameters = {
|
|
|
240
240
|
voucher: SignedVoucher
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
+
/** Inputs for validating a cumulative voucher without recording it. */
|
|
244
|
+
export type ValidateVoucherParameters = Omit<
|
|
245
|
+
VerifyAndAcceptVoucherParameters,
|
|
246
|
+
'challenge' | 'store'
|
|
247
|
+
>
|
|
248
|
+
|
|
249
|
+
/** Result of validating a cumulative voucher against persisted channel state. */
|
|
250
|
+
export type VoucherValidation = {
|
|
251
|
+
/** Whether the voucher was already accepted at the same cumulative amount. */
|
|
252
|
+
alreadyAccepted: boolean
|
|
253
|
+
}
|
|
254
|
+
|
|
243
255
|
/** Channel backend-specific fields. */
|
|
244
256
|
export type BackendState = CompatibilityBackendState | PrecompileBackendState
|
|
245
257
|
|
|
@@ -520,12 +532,11 @@ export async function loadPrecompileChannel(
|
|
|
520
532
|
return channel
|
|
521
533
|
}
|
|
522
534
|
|
|
523
|
-
/** Verifies a cumulative voucher
|
|
524
|
-
export async function
|
|
525
|
-
parameters:
|
|
526
|
-
): Promise<
|
|
527
|
-
const {
|
|
528
|
-
parameters
|
|
535
|
+
/** Verifies a cumulative voucher without changing persisted channel state. */
|
|
536
|
+
export async function validateVoucher(
|
|
537
|
+
parameters: ValidateVoucherParameters,
|
|
538
|
+
): Promise<VoucherValidation> {
|
|
539
|
+
const { minVoucherDelta, channel, voucher, channelState, methodDetails } = parameters
|
|
529
540
|
|
|
530
541
|
validateChannelState(channelState)
|
|
531
542
|
if (voucher.cumulativeAmount > channelState.deposit)
|
|
@@ -546,7 +557,22 @@ export async function verifyAndAcceptVoucher(
|
|
|
546
557
|
throw new VerificationFailedError({
|
|
547
558
|
reason: 'voucher cumulativeAmount is below on-chain settled amount',
|
|
548
559
|
})
|
|
549
|
-
if (voucher.cumulativeAmount === channel.highestVoucherAmount)
|
|
560
|
+
if (voucher.cumulativeAmount === channel.highestVoucherAmount) return { alreadyAccepted: true }
|
|
561
|
+
const delta = voucher.cumulativeAmount - channel.highestVoucherAmount
|
|
562
|
+
if (delta < minVoucherDelta)
|
|
563
|
+
throw new DeltaTooSmallError({
|
|
564
|
+
reason: `voucher delta ${delta} below minimum ${minVoucherDelta}`,
|
|
565
|
+
})
|
|
566
|
+
return { alreadyAccepted: false }
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
/** Verifies a cumulative voucher and returns a session receipt after store reconciliation. */
|
|
570
|
+
export async function verifyAndAcceptVoucher(
|
|
571
|
+
parameters: VerifyAndAcceptVoucherParameters,
|
|
572
|
+
): Promise<SessionReceipt> {
|
|
573
|
+
const { store, challenge, channel, voucher, channelState } = parameters
|
|
574
|
+
const validation = await validateVoucher(parameters)
|
|
575
|
+
if (validation.alreadyAccepted)
|
|
550
576
|
return createSessionReceipt({
|
|
551
577
|
challengeId: challenge.id,
|
|
552
578
|
channelId: voucher.channelId,
|
|
@@ -554,11 +580,6 @@ export async function verifyAndAcceptVoucher(
|
|
|
554
580
|
spent: channel.spent,
|
|
555
581
|
units: channel.units,
|
|
556
582
|
})
|
|
557
|
-
const delta = voucher.cumulativeAmount - channel.highestVoucherAmount
|
|
558
|
-
if (delta < minVoucherDelta)
|
|
559
|
-
throw new DeltaTooSmallError({
|
|
560
|
-
reason: `voucher delta ${delta} below minimum ${minVoucherDelta}`,
|
|
561
|
-
})
|
|
562
583
|
const updated = await store.updateChannel(voucher.channelId, (current) =>
|
|
563
584
|
acceptVoucherStateUpdate({ channelState, current, voucher }),
|
|
564
585
|
)
|
|
@@ -9,11 +9,11 @@ import * as Voucher from '../precompile/Voucher.js'
|
|
|
9
9
|
import * as ChannelStore from './ChannelStore.js'
|
|
10
10
|
import {
|
|
11
11
|
assertOpenCredentialCoversRequest,
|
|
12
|
+
broadcastCredentialPayload,
|
|
12
13
|
requireSessionCredentialAction,
|
|
13
14
|
requireSessionCredentialPayload,
|
|
14
15
|
requireSessionCredentialPayloadHeader,
|
|
15
16
|
validateChannelDescriptor,
|
|
16
|
-
verifyCredentialPayload,
|
|
17
17
|
} from './CredentialVerification.js'
|
|
18
18
|
|
|
19
19
|
describe('SessionCredentialGuards', () => {
|
|
@@ -190,7 +190,7 @@ describe('SessionCredentialGuards', () => {
|
|
|
190
190
|
})
|
|
191
191
|
})
|
|
192
192
|
|
|
193
|
-
describe('
|
|
193
|
+
describe('broadcastCredentialPayload', () => {
|
|
194
194
|
const escrow = '0x4D50500000000000000000000000000000000000' as Address
|
|
195
195
|
const testChainId = chainIds.testnet
|
|
196
196
|
const computedChannelId = Channel.computeId({ ...descriptor, chainId: testChainId, escrow })
|
|
@@ -246,7 +246,7 @@ describe('SessionCredentialGuards', () => {
|
|
|
246
246
|
const verifyVoucher = vi.spyOn(Voucher, 'verifyVoucher').mockResolvedValue(true)
|
|
247
247
|
|
|
248
248
|
await expect(
|
|
249
|
-
|
|
249
|
+
broadcastCredentialPayload({
|
|
250
250
|
challenge,
|
|
251
251
|
channelStateTtl: 60_000,
|
|
252
252
|
chainId: testChainId,
|
|
@@ -274,7 +274,7 @@ describe('SessionCredentialGuards', () => {
|
|
|
274
274
|
const verifyVoucher = vi.spyOn(Voucher, 'verifyVoucher').mockResolvedValue(true)
|
|
275
275
|
|
|
276
276
|
await expect(
|
|
277
|
-
|
|
277
|
+
broadcastCredentialPayload({
|
|
278
278
|
challenge,
|
|
279
279
|
channelStateTtl: 60_000,
|
|
280
280
|
chainId: testChainId,
|