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
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
serializeSnapshot as serializeSessionSnapshot,
|
|
32
32
|
} from '../Snapshot.js'
|
|
33
33
|
import * as ChannelStore from './ChannelStore.js'
|
|
34
|
-
import {
|
|
34
|
+
import { broadcastCredentialPayload, validateCredentialPayload } from './CredentialVerification.js'
|
|
35
35
|
import { requireSessionCredentialPayload } from './CredentialVerification.js'
|
|
36
36
|
import {
|
|
37
37
|
type ResolveSessionChannelId,
|
|
@@ -42,13 +42,18 @@ import {
|
|
|
42
42
|
type SessionPaymentRequestInput,
|
|
43
43
|
} from './RequestState.js'
|
|
44
44
|
import { respondToSessionCredential } from './RequestState.js'
|
|
45
|
-
import {
|
|
46
|
-
|
|
45
|
+
import {
|
|
46
|
+
applyVerifiedHttpAccounting,
|
|
47
|
+
chargeSessionChannel,
|
|
48
|
+
type SettleChargedSessionChannel,
|
|
49
|
+
} from './Settlement.js'
|
|
50
|
+
import { isSettlementDue, maybeSettleScheduled } from './Settlement.js'
|
|
47
51
|
import {
|
|
48
52
|
resolveSettlementSchedule,
|
|
49
53
|
type OnSessionSettlement,
|
|
50
54
|
type SettlementSchedule,
|
|
51
55
|
} from './Settlement.js'
|
|
56
|
+
import * as Ws from './Ws.js'
|
|
52
57
|
|
|
53
58
|
/** Server-side automatic settlement schedule. */
|
|
54
59
|
export type { SettlementSchedule } from './Settlement.js'
|
|
@@ -330,6 +335,26 @@ export function session<const parameters extends session.Parameters>(
|
|
|
330
335
|
getClient: parameters.getClient,
|
|
331
336
|
rpcUrl: defaults.rpcUrl,
|
|
332
337
|
})
|
|
338
|
+
const settleScheduled: SettleChargedSessionChannel = async (channel) => {
|
|
339
|
+
if (!isSettlementDue(channel, settlementSchedule)) return undefined
|
|
340
|
+
return maybeSettleScheduled({
|
|
341
|
+
account,
|
|
342
|
+
channel,
|
|
343
|
+
client: await getClient({ chainId: channel.chainId }),
|
|
344
|
+
...(feePayer ? { feePayer } : {}),
|
|
345
|
+
feePayerPolicy: parameters.feePayerPolicy,
|
|
346
|
+
feeToken: parameters.feeToken,
|
|
347
|
+
onSessionSettlement,
|
|
348
|
+
schedule: settlementSchedule,
|
|
349
|
+
store,
|
|
350
|
+
})
|
|
351
|
+
}
|
|
352
|
+
const serveWebSocket: session.Extensions['serveWebSocket'] = (options) =>
|
|
353
|
+
Ws.serve({
|
|
354
|
+
...options,
|
|
355
|
+
onChargeCommitted: settleScheduled,
|
|
356
|
+
store,
|
|
357
|
+
})
|
|
333
358
|
const bootstrapCharge = ChargeServer.charge({
|
|
334
359
|
account,
|
|
335
360
|
chainId: parameters.chainId,
|
|
@@ -341,16 +366,123 @@ export function session<const parameters extends session.Parameters>(
|
|
|
341
366
|
store: rawStore,
|
|
342
367
|
})
|
|
343
368
|
|
|
344
|
-
type
|
|
369
|
+
type SessionTransport = parameters['sse'] extends false | undefined ? undefined : Transport.Sse
|
|
345
370
|
const transport = parameters.sse
|
|
346
371
|
? Transport.sse({
|
|
372
|
+
settleCharged: settleScheduled,
|
|
347
373
|
store,
|
|
348
374
|
...(typeof parameters.sse === 'object' ? parameters.sse : undefined),
|
|
349
375
|
})
|
|
350
376
|
: undefined
|
|
351
377
|
|
|
378
|
+
const validateCredential: Method.ValidateFn<typeof Methods.session> = async ({
|
|
379
|
+
credential,
|
|
380
|
+
request,
|
|
381
|
+
}) => {
|
|
382
|
+
const payload = requireSessionCredentialPayload(credential.payload)
|
|
383
|
+
const context = await resolveCredentialVerificationContext({
|
|
384
|
+
decimals,
|
|
385
|
+
feePayer: configuredFeePayer,
|
|
386
|
+
getClient,
|
|
387
|
+
minVoucherDelta: parameters.minVoucherDelta,
|
|
388
|
+
request,
|
|
389
|
+
})
|
|
390
|
+
|
|
391
|
+
const details = await validateCredentialPayload({
|
|
392
|
+
account,
|
|
393
|
+
challenge: credential.challenge,
|
|
394
|
+
channelStateTtl,
|
|
395
|
+
chainId: context.chainId,
|
|
396
|
+
client: context.client,
|
|
397
|
+
credentialSource: credential.source,
|
|
398
|
+
escrow: context.escrow,
|
|
399
|
+
expectedOperator: context.methodDetails.operator,
|
|
400
|
+
feePayer: context.feePayer,
|
|
401
|
+
feePayerPolicy: parameters.feePayerPolicy,
|
|
402
|
+
lastOnChainVerified,
|
|
403
|
+
minVoucherDelta: context.minVoucherDelta,
|
|
404
|
+
payload,
|
|
405
|
+
store,
|
|
406
|
+
})
|
|
407
|
+
|
|
408
|
+
return {
|
|
409
|
+
challenge: credential.challenge,
|
|
410
|
+
credential: { ...credential, payload },
|
|
411
|
+
details,
|
|
412
|
+
intent: 'session' as const,
|
|
413
|
+
method: 'tempo' as const,
|
|
414
|
+
request: context.request,
|
|
415
|
+
source: credential.source,
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const broadcastCredential: Method.BroadcastFn<typeof Methods.session> = async ({
|
|
420
|
+
credential,
|
|
421
|
+
envelope,
|
|
422
|
+
request,
|
|
423
|
+
}) => {
|
|
424
|
+
const { challenge } = credential
|
|
425
|
+
const payload = requireSessionCredentialPayload(credential.payload)
|
|
426
|
+
const context = await resolveCredentialVerificationContext({
|
|
427
|
+
decimals,
|
|
428
|
+
feePayer: configuredFeePayer,
|
|
429
|
+
getClient,
|
|
430
|
+
minVoucherDelta: parameters.minVoucherDelta,
|
|
431
|
+
request,
|
|
432
|
+
})
|
|
433
|
+
|
|
434
|
+
const sessionReceipt = await broadcastCredentialPayload({
|
|
435
|
+
account,
|
|
436
|
+
challenge,
|
|
437
|
+
channelStateTtl,
|
|
438
|
+
chainId: context.chainId,
|
|
439
|
+
client: context.client,
|
|
440
|
+
credentialSource: credential.source,
|
|
441
|
+
escrow: context.escrow,
|
|
442
|
+
expectedOperator: context.methodDetails.operator,
|
|
443
|
+
feePayer: context.feePayer,
|
|
444
|
+
feePayerPolicy: parameters.feePayerPolicy,
|
|
445
|
+
feeToken: parameters.feeToken,
|
|
446
|
+
lastOnChainVerified,
|
|
447
|
+
minVoucherDelta: context.minVoucherDelta,
|
|
448
|
+
onSessionSettlement,
|
|
449
|
+
payload,
|
|
450
|
+
store,
|
|
451
|
+
})
|
|
452
|
+
|
|
453
|
+
return applyVerifiedHttpAccounting({
|
|
454
|
+
capturedRequest: envelope?.capturedRequest,
|
|
455
|
+
payloadAction: payload.action,
|
|
456
|
+
receipt: sessionReceipt,
|
|
457
|
+
getRequestAmount: () => BigInt(context.request.amount ?? challenge.request.amount),
|
|
458
|
+
sseEnabled: Boolean(parameters.sse),
|
|
459
|
+
markPrepaidReceipt: Transport.markPrepaidSessionTick,
|
|
460
|
+
charge: (channelId, requestAmount) =>
|
|
461
|
+
chargeSessionChannel({ store, channelId, amount: requestAmount }),
|
|
462
|
+
settleCharged: (channel) =>
|
|
463
|
+
maybeSettleScheduled({
|
|
464
|
+
account,
|
|
465
|
+
client: context.client,
|
|
466
|
+
...(typeof context.feePayer === 'object' ? { feePayer: context.feePayer } : {}),
|
|
467
|
+
feePayerPolicy: parameters.feePayerPolicy,
|
|
468
|
+
feeToken: parameters.feeToken,
|
|
469
|
+
onSessionSettlement,
|
|
470
|
+
schedule: settlementSchedule,
|
|
471
|
+
store,
|
|
472
|
+
channel,
|
|
473
|
+
}),
|
|
474
|
+
})
|
|
475
|
+
}
|
|
476
|
+
|
|
352
477
|
type Defaults = session.DeriveDefaults<parameters>
|
|
353
|
-
|
|
478
|
+
const method = Method.toServer<
|
|
479
|
+
typeof Methods.session,
|
|
480
|
+
Defaults,
|
|
481
|
+
SessionTransport,
|
|
482
|
+
session.Extensions
|
|
483
|
+
>(Methods.session, {
|
|
484
|
+
canOffer: parameters.canOffer,
|
|
485
|
+
onPaymentSuccess: parameters.onPaymentSuccess,
|
|
354
486
|
defaults: deriveServerDefaults<parameters>({
|
|
355
487
|
amount,
|
|
356
488
|
currency,
|
|
@@ -361,6 +493,8 @@ export function session<const parameters extends session.Parameters>(
|
|
|
361
493
|
unitType,
|
|
362
494
|
}),
|
|
363
495
|
|
|
496
|
+
extensions: { serveWebSocket, settleScheduled },
|
|
497
|
+
|
|
364
498
|
transport: deriveTransport<parameters>(transport),
|
|
365
499
|
|
|
366
500
|
preflight: parameters.bootstrap
|
|
@@ -406,59 +540,8 @@ export function session<const parameters extends session.Parameters>(
|
|
|
406
540
|
}
|
|
407
541
|
},
|
|
408
542
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
const payload = requireSessionCredentialPayload(credential.payload)
|
|
412
|
-
const context = await resolveCredentialVerificationContext({
|
|
413
|
-
decimals,
|
|
414
|
-
feePayer: configuredFeePayer,
|
|
415
|
-
getClient,
|
|
416
|
-
minVoucherDelta: parameters.minVoucherDelta,
|
|
417
|
-
request,
|
|
418
|
-
})
|
|
419
|
-
|
|
420
|
-
const sessionReceipt = await verifyCredentialPayload({
|
|
421
|
-
account,
|
|
422
|
-
challenge,
|
|
423
|
-
channelStateTtl,
|
|
424
|
-
chainId: context.chainId,
|
|
425
|
-
client: context.client,
|
|
426
|
-
credentialSource: credential.source,
|
|
427
|
-
escrow: context.escrow,
|
|
428
|
-
expectedOperator: context.methodDetails.operator,
|
|
429
|
-
feePayer: context.feePayer,
|
|
430
|
-
feePayerPolicy: parameters.feePayerPolicy,
|
|
431
|
-
feeToken: parameters.feeToken,
|
|
432
|
-
lastOnChainVerified,
|
|
433
|
-
minVoucherDelta: context.minVoucherDelta,
|
|
434
|
-
onSessionSettlement,
|
|
435
|
-
payload,
|
|
436
|
-
store,
|
|
437
|
-
})
|
|
438
|
-
|
|
439
|
-
return applyVerifiedHttpAccounting({
|
|
440
|
-
capturedRequest: envelope?.capturedRequest,
|
|
441
|
-
payloadAction: payload.action,
|
|
442
|
-
receipt: sessionReceipt,
|
|
443
|
-
getRequestAmount: () => BigInt(context.request.amount ?? challenge.request.amount),
|
|
444
|
-
sseEnabled: Boolean(parameters.sse),
|
|
445
|
-
markPrepaidReceipt: Transport.markPrepaidSessionTick,
|
|
446
|
-
charge: (channelId, requestAmount) =>
|
|
447
|
-
chargeSessionChannel({ store, channelId, amount: requestAmount }),
|
|
448
|
-
settleCharged: (channel) =>
|
|
449
|
-
maybeSettleScheduled({
|
|
450
|
-
account,
|
|
451
|
-
client: context.client,
|
|
452
|
-
...(typeof context.feePayer === 'object' ? { feePayer: context.feePayer } : {}),
|
|
453
|
-
feePayerPolicy: parameters.feePayerPolicy,
|
|
454
|
-
feeToken: parameters.feeToken,
|
|
455
|
-
onSessionSettlement,
|
|
456
|
-
schedule: settlementSchedule,
|
|
457
|
-
store,
|
|
458
|
-
channel,
|
|
459
|
-
}),
|
|
460
|
-
})
|
|
461
|
-
},
|
|
543
|
+
validate: validateCredential,
|
|
544
|
+
broadcast: broadcastCredential,
|
|
462
545
|
|
|
463
546
|
// This hook acts as a gate: when it returns a Response, `withReceipt()`
|
|
464
547
|
// in Mppx.ts short-circuits and returns that response directly without
|
|
@@ -478,12 +561,27 @@ export function session<const parameters extends session.Parameters>(
|
|
|
478
561
|
})
|
|
479
562
|
},
|
|
480
563
|
})
|
|
564
|
+
return method
|
|
481
565
|
}
|
|
482
566
|
|
|
483
567
|
export namespace session {
|
|
484
568
|
export const serializeSnapshot = serializeSessionSnapshot
|
|
485
569
|
export const deserializeSnapshot = deserializeSessionSnapshot
|
|
486
570
|
|
|
571
|
+
/** Extensions attached to the Tempo session method handler. */
|
|
572
|
+
export type Extensions = {
|
|
573
|
+
/** Applies the configured automatic settlement policy to a committed channel charge. */
|
|
574
|
+
settleScheduled: SettleChargedSessionChannel
|
|
575
|
+
/** Serves a WebSocket route from this handler using its configured store and settlement policy. */
|
|
576
|
+
serveWebSocket: (options: ServeWebSocketOptions) => Promise<void>
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/** WebSocket server options supplied after the session binds shared dependencies. */
|
|
580
|
+
export type ServeWebSocketOptions = Omit<
|
|
581
|
+
Ws.serve.Options,
|
|
582
|
+
'onChargeCommitted' | 'settleScheduled' | 'store'
|
|
583
|
+
>
|
|
584
|
+
|
|
487
585
|
/** Request defaults inferred from the Tempo session method schema. */
|
|
488
586
|
export type Defaults = LooseOmit<
|
|
489
587
|
Method.RequestDefaults<typeof Methods.session>,
|
|
@@ -526,7 +624,7 @@ export namespace session {
|
|
|
526
624
|
store?: Store.AtomicStore | undefined
|
|
527
625
|
/** Enable SSE streaming. Pass `true` for defaults or an options object to configure SSE. */
|
|
528
626
|
sse?: boolean | Transport.sse.Options | undefined
|
|
529
|
-
/** Tempo chain ID used for TIP-1034 channel escrow challenges. Defaults to the resolved client chain ID.
|
|
627
|
+
/** Tempo chain ID used for TIP-1034 channel escrow challenges. Defaults to the resolved client chain ID. */
|
|
530
628
|
chainId?: number | undefined
|
|
531
629
|
/** TIP20EscrowChannel precompile address override. */
|
|
532
630
|
escrowContract?: Address | undefined
|
|
@@ -539,7 +637,8 @@ export namespace session {
|
|
|
539
637
|
feeToken?: Address | undefined
|
|
540
638
|
} & Account.resolve.Parameters &
|
|
541
639
|
Client.getResolver.Parameters &
|
|
542
|
-
Defaults
|
|
640
|
+
Defaults &
|
|
641
|
+
Method.ComposableHooks<typeof Methods.session>
|
|
543
642
|
|
|
544
643
|
/** Defaults derived from `session()` parameters for handler type inference. */
|
|
545
644
|
export type DeriveDefaults<parameters extends Parameters> = types.DeriveDefaults<
|
|
@@ -260,6 +260,7 @@ describe('serve', () => {
|
|
|
260
260
|
|
|
261
261
|
test('uses a prepaid unit for the first generated value', async () => {
|
|
262
262
|
const storage = memoryStore()
|
|
263
|
+
const committed: Array<{ spent: bigint; units: number }> = []
|
|
263
264
|
await seedChannel(storage, 3000000n)
|
|
264
265
|
await storage.updateChannel(channelId, (current) =>
|
|
265
266
|
current ? { ...current, spent: 1000000n, units: 1 } : current,
|
|
@@ -271,6 +272,9 @@ describe('serve', () => {
|
|
|
271
272
|
challengeId,
|
|
272
273
|
tickCost: 1000000n,
|
|
273
274
|
generate: generate(['hello', 'world']),
|
|
275
|
+
onChargeCommitted(channel) {
|
|
276
|
+
committed.push({ spent: channel.spent, units: channel.units })
|
|
277
|
+
},
|
|
274
278
|
prepaidUnits: 1,
|
|
275
279
|
})
|
|
276
280
|
|
|
@@ -281,6 +285,79 @@ describe('serve', () => {
|
|
|
281
285
|
const channel = await storage.getChannel(channelId)
|
|
282
286
|
expect(channel!.spent).toBe(2000000n)
|
|
283
287
|
expect(channel!.units).toBe(2)
|
|
288
|
+
expect(committed).toEqual([{ spent: 2000000n, units: 2 }])
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
test('runs the post-commit hook before emitting each charged value', async () => {
|
|
292
|
+
const storage = memoryStore()
|
|
293
|
+
const committed: Array<{ spent: bigint; units: number }> = []
|
|
294
|
+
await seedChannel(storage, 2000000n)
|
|
295
|
+
|
|
296
|
+
const output = await readStream(
|
|
297
|
+
serve({
|
|
298
|
+
store: storage,
|
|
299
|
+
channelId,
|
|
300
|
+
challengeId,
|
|
301
|
+
tickCost: 1000000n,
|
|
302
|
+
generate: generate(['first', 'second']),
|
|
303
|
+
onChargeCommitted(channel) {
|
|
304
|
+
committed.push({ spent: channel.spent, units: channel.units })
|
|
305
|
+
},
|
|
306
|
+
}),
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
expect(output).toContain('event: message\ndata: first\n\n')
|
|
310
|
+
expect(output).toContain('event: message\ndata: second\n\n')
|
|
311
|
+
expect(committed).toEqual([
|
|
312
|
+
{ spent: 1000000n, units: 1 },
|
|
313
|
+
{ spent: 2000000n, units: 2 },
|
|
314
|
+
])
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
test('does not emit a charged value when the post-commit hook fails', async () => {
|
|
318
|
+
const storage = memoryStore()
|
|
319
|
+
await seedChannel(storage, 1000000n)
|
|
320
|
+
|
|
321
|
+
const reader = serve({
|
|
322
|
+
store: storage,
|
|
323
|
+
channelId,
|
|
324
|
+
challengeId,
|
|
325
|
+
tickCost: 1000000n,
|
|
326
|
+
generate: generate(['blocked']),
|
|
327
|
+
onChargeCommitted() {
|
|
328
|
+
throw new Error('settlement failed')
|
|
329
|
+
},
|
|
330
|
+
}).getReader()
|
|
331
|
+
|
|
332
|
+
await expect(reader.read()).rejects.toThrow('settlement failed')
|
|
333
|
+
const channel = await storage.getChannel(channelId)
|
|
334
|
+
expect(channel).toMatchObject({ spent: 1000000n, units: 1 })
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
test('does not run the post-commit hook for an unconsumed reservation', async () => {
|
|
338
|
+
const storage = memoryStore()
|
|
339
|
+
let commits = 0
|
|
340
|
+
await seedChannel(storage, 1000000n)
|
|
341
|
+
|
|
342
|
+
await readStream(
|
|
343
|
+
serve({
|
|
344
|
+
store: storage,
|
|
345
|
+
channelId,
|
|
346
|
+
challengeId,
|
|
347
|
+
tickCost: 1000000n,
|
|
348
|
+
generate: async function* (stream) {
|
|
349
|
+
await stream.charge()
|
|
350
|
+
yield* []
|
|
351
|
+
},
|
|
352
|
+
onChargeCommitted() {
|
|
353
|
+
commits++
|
|
354
|
+
},
|
|
355
|
+
}),
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
expect(commits).toBe(0)
|
|
359
|
+
const channel = await storage.getChannel(channelId)
|
|
360
|
+
expect(channel).toMatchObject({ spent: 0n, units: 0 })
|
|
284
361
|
})
|
|
285
362
|
|
|
286
363
|
test('emits multiline message values as a single SSE message event', async () => {
|
|
@@ -12,7 +12,11 @@ import {
|
|
|
12
12
|
requireSessionCredentialContext,
|
|
13
13
|
} from '../precompile/Protocol.js'
|
|
14
14
|
import * as ChannelStore from './ChannelStore.js'
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
meterIterable,
|
|
17
|
+
type MeteredStreamOptions,
|
|
18
|
+
type SessionController,
|
|
19
|
+
} from './MeteredStream.js'
|
|
16
20
|
|
|
17
21
|
/**
|
|
18
22
|
* SSE (Server-Sent Events) utilities for metered streaming payments.
|
|
@@ -81,6 +85,7 @@ export function serve(options: serve.Options): ReadableStream<Uint8Array> {
|
|
|
81
85
|
channelId,
|
|
82
86
|
tickCost,
|
|
83
87
|
generate,
|
|
88
|
+
onChargeCommitted: options.onChargeCommitted,
|
|
84
89
|
pollIntervalMs,
|
|
85
90
|
prepaidUnits: options.prepaidUnits,
|
|
86
91
|
signal,
|
|
@@ -121,6 +126,8 @@ export declare namespace serve {
|
|
|
121
126
|
challengeId: string
|
|
122
127
|
tickCost: bigint
|
|
123
128
|
generate: AsyncIterable<string> | ((stream: SessionController) => AsyncIterable<string>)
|
|
129
|
+
/** Callback invoked after each nonzero stream charge is committed. */
|
|
130
|
+
onChargeCommitted?: MeteredStreamOptions['onChargeCommitted']
|
|
124
131
|
pollIntervalMs?: number | undefined
|
|
125
132
|
prepaidUnits?: number | undefined
|
|
126
133
|
signal?: AbortSignal | undefined
|
|
@@ -86,7 +86,7 @@ export async function reserveChargeOrWait(options: ReserveChargeParameters): Pro
|
|
|
86
86
|
/** Atomically commits previously reserved stream charges to channel spend and unit counters. */
|
|
87
87
|
export async function commitReservedCharges(
|
|
88
88
|
options: CommitReservedChargesParameters,
|
|
89
|
-
): Promise<
|
|
89
|
+
): Promise<ChannelStore.State | undefined> {
|
|
90
90
|
const { amount, channelId, store, units } = options
|
|
91
91
|
if (amount === 0n || units === 0) return
|
|
92
92
|
|
|
@@ -107,6 +107,7 @@ export async function commitReservedCharges(
|
|
|
107
107
|
if (!channel) throw new Error('channel not found')
|
|
108
108
|
throwIfChannelClosed(channel)
|
|
109
109
|
if (!committed) throw new Error('reserved voucher coverage is no longer available')
|
|
110
|
+
return channel
|
|
110
111
|
}
|
|
111
112
|
|
|
112
113
|
/** Throws when a channel can no longer be used for streaming charges. */
|
|
@@ -124,6 +124,27 @@ function seedChannel(
|
|
|
124
124
|
}))
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
+
function acceptingRoute(acceptedCumulative: bigint): Ws.serve.Options['route'] {
|
|
128
|
+
return async () => ({
|
|
129
|
+
status: 200,
|
|
130
|
+
withReceipt(response = new Response(null, { status: 204 })) {
|
|
131
|
+
response.headers.set(
|
|
132
|
+
'Payment-Receipt',
|
|
133
|
+
serializeSessionReceipt(
|
|
134
|
+
createSessionReceipt({
|
|
135
|
+
challengeId: challenge.id,
|
|
136
|
+
channelId,
|
|
137
|
+
acceptedCumulative,
|
|
138
|
+
spent: 0n,
|
|
139
|
+
units: 0,
|
|
140
|
+
}),
|
|
141
|
+
),
|
|
142
|
+
)
|
|
143
|
+
return response
|
|
144
|
+
},
|
|
145
|
+
})
|
|
146
|
+
}
|
|
147
|
+
|
|
127
148
|
describe('parseMessage', () => {
|
|
128
149
|
test('rejects non-object data in payment-receipt', () => {
|
|
129
150
|
expect(Ws.parseMessage('{"mpp":"payment-receipt","data":true}')).toBeNull()
|
|
@@ -348,6 +369,7 @@ describe('isows', () => {
|
|
|
348
369
|
test('drops reserved charges when the stream ends without delivering a chunk', async () => {
|
|
349
370
|
const socket = new MockSocket()
|
|
350
371
|
const store = memoryChannelStore()
|
|
372
|
+
let commits = 0
|
|
351
373
|
await seedChannel(store, 1n)
|
|
352
374
|
|
|
353
375
|
await Ws.serve({
|
|
@@ -376,6 +398,9 @@ describe('isows', () => {
|
|
|
376
398
|
await stream.charge()
|
|
377
399
|
yield* []
|
|
378
400
|
},
|
|
401
|
+
onChargeCommitted() {
|
|
402
|
+
commits++
|
|
403
|
+
},
|
|
379
404
|
})
|
|
380
405
|
|
|
381
406
|
socket.receive(
|
|
@@ -406,6 +431,7 @@ describe('isows', () => {
|
|
|
406
431
|
const channel = await store.getChannel(channelId)
|
|
407
432
|
expect(channel?.spent).toBe(0n)
|
|
408
433
|
expect(channel?.units).toBe(0)
|
|
434
|
+
expect(commits).toBe(0)
|
|
409
435
|
})
|
|
410
436
|
|
|
411
437
|
test('aborts a blocked application generator before sending close-ready', async () => {
|
|
@@ -521,6 +547,151 @@ describe('isows', () => {
|
|
|
521
547
|
expect(socket.sent.some((message) => message.includes('priced-response'))).toBe(true)
|
|
522
548
|
})
|
|
523
549
|
|
|
550
|
+
test.each(['onChargeCommitted', 'settleScheduled'] as const)(
|
|
551
|
+
'runs %s after each committed charge and before emitting its message',
|
|
552
|
+
async (hookName) => {
|
|
553
|
+
const socket = new MockSocket()
|
|
554
|
+
const store = memoryChannelStore()
|
|
555
|
+
const committed: Array<{ emitted: number; spent: bigint; units: number }> = []
|
|
556
|
+
await seedChannel(store, 2n)
|
|
557
|
+
|
|
558
|
+
const hook = async (channel: ChannelStore.State) => {
|
|
559
|
+
committed.push({
|
|
560
|
+
emitted: socket.sent.filter((message) => Ws.parseMessage(message)?.mpp === 'message')
|
|
561
|
+
.length,
|
|
562
|
+
spent: channel.spent,
|
|
563
|
+
units: channel.units,
|
|
564
|
+
})
|
|
565
|
+
return undefined
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
await Ws.serve({
|
|
569
|
+
socket,
|
|
570
|
+
store,
|
|
571
|
+
url: 'ws://example.test/stream',
|
|
572
|
+
route: acceptingRoute(2n),
|
|
573
|
+
generate: (async function* () {
|
|
574
|
+
yield 'first'
|
|
575
|
+
yield 'second'
|
|
576
|
+
})(),
|
|
577
|
+
...(hookName === 'onChargeCommitted'
|
|
578
|
+
? { onChargeCommitted: hook }
|
|
579
|
+
: { settleScheduled: hook }),
|
|
580
|
+
})
|
|
581
|
+
|
|
582
|
+
socket.receive(
|
|
583
|
+
Ws.formatAuthorizationMessage(
|
|
584
|
+
makeCredential({
|
|
585
|
+
action: 'open',
|
|
586
|
+
channelId,
|
|
587
|
+
cumulativeAmount: '2',
|
|
588
|
+
signature: `0x${'77'.repeat(65)}`,
|
|
589
|
+
transaction: '0x01',
|
|
590
|
+
type: 'transaction',
|
|
591
|
+
}),
|
|
592
|
+
),
|
|
593
|
+
)
|
|
594
|
+
|
|
595
|
+
await sleep(10)
|
|
596
|
+
|
|
597
|
+
expect(committed).toEqual([
|
|
598
|
+
{ emitted: 0, spent: 1n, units: 1 },
|
|
599
|
+
{ emitted: 1, spent: 2n, units: 2 },
|
|
600
|
+
])
|
|
601
|
+
expect(
|
|
602
|
+
socket.sent
|
|
603
|
+
.map((message) => Ws.parseMessage(message))
|
|
604
|
+
.filter((message) => message?.mpp === 'message')
|
|
605
|
+
.map((message) => (message?.mpp === 'message' ? message.data : undefined)),
|
|
606
|
+
).toEqual(['first', 'second'])
|
|
607
|
+
},
|
|
608
|
+
)
|
|
609
|
+
|
|
610
|
+
test('prefers onChargeCommitted over the deprecated settlement callback', async () => {
|
|
611
|
+
const socket = new MockSocket()
|
|
612
|
+
const store = memoryChannelStore()
|
|
613
|
+
const callbacks: string[] = []
|
|
614
|
+
await seedChannel(store, 1n)
|
|
615
|
+
|
|
616
|
+
await Ws.serve({
|
|
617
|
+
socket,
|
|
618
|
+
store,
|
|
619
|
+
url: 'ws://example.test/stream',
|
|
620
|
+
route: acceptingRoute(1n),
|
|
621
|
+
generate: (async function* () {
|
|
622
|
+
yield 'message'
|
|
623
|
+
})(),
|
|
624
|
+
onChargeCommitted() {
|
|
625
|
+
callbacks.push('current')
|
|
626
|
+
},
|
|
627
|
+
async settleScheduled() {
|
|
628
|
+
callbacks.push('deprecated')
|
|
629
|
+
return undefined
|
|
630
|
+
},
|
|
631
|
+
})
|
|
632
|
+
|
|
633
|
+
socket.receive(
|
|
634
|
+
Ws.formatAuthorizationMessage(
|
|
635
|
+
makeCredential({
|
|
636
|
+
action: 'open',
|
|
637
|
+
channelId,
|
|
638
|
+
cumulativeAmount: '1',
|
|
639
|
+
signature: `0x${'77'.repeat(65)}`,
|
|
640
|
+
transaction: '0x01',
|
|
641
|
+
type: 'transaction',
|
|
642
|
+
}),
|
|
643
|
+
),
|
|
644
|
+
)
|
|
645
|
+
|
|
646
|
+
await sleep(10)
|
|
647
|
+
|
|
648
|
+
expect(callbacks).toEqual(['current'])
|
|
649
|
+
})
|
|
650
|
+
|
|
651
|
+
test('closes without emitting a charged message when the post-commit hook fails', async () => {
|
|
652
|
+
const socket = new MockSocket()
|
|
653
|
+
const store = memoryChannelStore()
|
|
654
|
+
await seedChannel(store, 1n)
|
|
655
|
+
|
|
656
|
+
await Ws.serve({
|
|
657
|
+
socket,
|
|
658
|
+
store,
|
|
659
|
+
url: 'ws://example.test/stream',
|
|
660
|
+
route: acceptingRoute(1n),
|
|
661
|
+
generate: (async function* () {
|
|
662
|
+
yield 'blocked'
|
|
663
|
+
})(),
|
|
664
|
+
onChargeCommitted() {
|
|
665
|
+
throw new Error('settlement failed')
|
|
666
|
+
},
|
|
667
|
+
})
|
|
668
|
+
|
|
669
|
+
socket.receive(
|
|
670
|
+
Ws.formatAuthorizationMessage(
|
|
671
|
+
makeCredential({
|
|
672
|
+
action: 'open',
|
|
673
|
+
channelId,
|
|
674
|
+
cumulativeAmount: '1',
|
|
675
|
+
signature: `0x${'77'.repeat(65)}`,
|
|
676
|
+
transaction: '0x01',
|
|
677
|
+
type: 'transaction',
|
|
678
|
+
}),
|
|
679
|
+
),
|
|
680
|
+
)
|
|
681
|
+
|
|
682
|
+
await sleep(10)
|
|
683
|
+
|
|
684
|
+
expect(socket.closed).toBe(true)
|
|
685
|
+
expect(socket.sent.some((message) => message.includes('settlement failed'))).toBe(true)
|
|
686
|
+
expect(
|
|
687
|
+
socket.sent.some((message) => {
|
|
688
|
+
const parsed = Ws.parseMessage(message)
|
|
689
|
+
return parsed?.mpp === 'message' && parsed.data === 'blocked'
|
|
690
|
+
}),
|
|
691
|
+
).toBe(false)
|
|
692
|
+
expect(await store.getChannel(channelId)).toMatchObject({ spent: 1n, units: 1 })
|
|
693
|
+
})
|
|
694
|
+
|
|
524
695
|
test('does not meter or emit application messages after close is requested on-chain', async () => {
|
|
525
696
|
const socket = new MockSocket()
|
|
526
697
|
const store = memoryChannelStore()
|
|
@@ -15,7 +15,8 @@ import {
|
|
|
15
15
|
type SessionReceipt,
|
|
16
16
|
} from '../precompile/Protocol.js'
|
|
17
17
|
import * as ChannelStore from './ChannelStore.js'
|
|
18
|
-
import type { SessionController } from './MeteredStream.js'
|
|
18
|
+
import type { MeteredStreamOptions, SessionController } from './MeteredStream.js'
|
|
19
|
+
import type { SettleChargedSessionChannel } from './Settlement.js'
|
|
19
20
|
export type { SessionController } from './MeteredStream.js'
|
|
20
21
|
export type { Socket } from './Transports.js'
|
|
21
22
|
import { meterIterable } from './MeteredStream.js'
|
|
@@ -152,6 +153,7 @@ export async function serve(options: serve.Options): Promise<void> {
|
|
|
152
153
|
channelId: context.channelId,
|
|
153
154
|
tickCost: context.tickCost,
|
|
154
155
|
generate,
|
|
156
|
+
onChargeCommitted: options.onChargeCommitted ?? options.settleScheduled,
|
|
155
157
|
pollIntervalMs,
|
|
156
158
|
signal: abortController.signal,
|
|
157
159
|
emitNeedVoucher: (message) => send(socket, message),
|
|
@@ -332,6 +334,10 @@ export declare namespace serve {
|
|
|
332
334
|
/** Payment route handler. Receives synthetic `POST` requests with only
|
|
333
335
|
* the `Authorization` header — no cookies, bodies, or upgrade headers. */
|
|
334
336
|
route: SessionRoute
|
|
337
|
+
/** Optional low-level hook invoked after each committed stream charge. */
|
|
338
|
+
onChargeCommitted?: MeteredStreamOptions['onChargeCommitted']
|
|
339
|
+
/** @deprecated Use `onChargeCommitted`. */
|
|
340
|
+
settleScheduled?: SettleChargedSessionChannel | undefined
|
|
335
341
|
socket: Socket
|
|
336
342
|
store: ChannelStore.ChannelStore | import('../../../Store.js').Store
|
|
337
343
|
url: string | URL
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Constants as HttpMessageSignature } from '../attestation/internal/HttpMessageSignature.js'
|
|
2
|
+
|
|
3
|
+
/** Web Bot Auth values for the supported HTTPS-directory signature profile. */
|
|
4
|
+
export const Constants = {
|
|
5
|
+
/** Stable identifier for Web Bot Auth signers and replay storage. */
|
|
6
|
+
protocol: 'web-bot-auth',
|
|
7
|
+
/** Web Bot Auth discovery type supported by this adapter. */
|
|
8
|
+
discoveryType: 'directory',
|
|
9
|
+
/** RFC 9421 signature label used when no label is configured. */
|
|
10
|
+
label: 'webbot',
|
|
11
|
+
/** Tag identifying a Web Bot Auth request signature. */
|
|
12
|
+
tag: 'web-bot-auth',
|
|
13
|
+
/** Structured HTTP header linking a bot signature to its HTTPS directory origin. */
|
|
14
|
+
signatureAgentHeader: 'Signature-Agent',
|
|
15
|
+
/** Default lifetime, in seconds, for a bot request signature. */
|
|
16
|
+
defaultSignatureLifetime: 60,
|
|
17
|
+
/** Default verifier limit, following the draft's recommended 24-hour maximum. */
|
|
18
|
+
defaultMaximumSignatureLifetime: 24 * 60 * 60,
|
|
19
|
+
/** HTTP components required by this directory profile. */
|
|
20
|
+
requiredComponents: [
|
|
21
|
+
HttpMessageSignature.components.authority,
|
|
22
|
+
HttpMessageSignature.components.signatureAgent,
|
|
23
|
+
],
|
|
24
|
+
} as const
|