mppx 0.6.31 → 0.8.0
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 +50 -0
- package/README.md +20 -11
- package/dist/Challenge.d.ts.map +1 -1
- package/dist/Challenge.js +27 -13
- package/dist/Challenge.js.map +1 -1
- package/dist/Constants.d.ts +46 -0
- package/dist/Constants.d.ts.map +1 -0
- package/dist/Constants.js +46 -0
- package/dist/Constants.js.map +1 -0
- package/dist/Credential.d.ts.map +1 -1
- package/dist/Credential.js +5 -4
- package/dist/Credential.js.map +1 -1
- package/dist/Mcp.d.ts +3 -0
- package/dist/Mcp.d.ts.map +1 -1
- package/dist/Mcp.js +2 -0
- package/dist/Mcp.js.map +1 -1
- package/dist/Method.d.ts +32 -4
- package/dist/Method.d.ts.map +1 -1
- package/dist/Method.js +5 -2
- package/dist/Method.js.map +1 -1
- package/dist/PaymentRequest.d.ts +10 -10
- package/dist/PaymentRequest.js +8 -8
- package/dist/Receipt.d.ts.map +1 -1
- package/dist/Receipt.js +3 -2
- package/dist/Receipt.js.map +1 -1
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +19 -11
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/plugins/tempo.d.ts.map +1 -1
- package/dist/cli/plugins/tempo.js +17 -6
- package/dist/cli/plugins/tempo.js.map +1 -1
- package/dist/cli/utils.d.ts +5 -0
- package/dist/cli/utils.d.ts.map +1 -1
- package/dist/cli/utils.js +10 -0
- package/dist/cli/utils.js.map +1 -1
- package/dist/client/Methods.d.ts +5 -2
- package/dist/client/Methods.d.ts.map +1 -1
- package/dist/client/Methods.js +5 -2
- package/dist/client/Methods.js.map +1 -1
- package/dist/client/Mppx.js +2 -2
- package/dist/client/Mppx.js.map +1 -1
- package/dist/client/Transport.d.ts +11 -16
- package/dist/client/Transport.d.ts.map +1 -1
- package/dist/client/Transport.js +55 -76
- package/dist/client/Transport.js.map +1 -1
- package/dist/client/index.d.ts +5 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +3 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal/Fetch.d.ts.map +1 -1
- package/dist/client/internal/Fetch.js +60 -13
- package/dist/client/internal/Fetch.js.map +1 -1
- package/dist/client/internal/protocols/Mcp.d.ts +7 -0
- package/dist/client/internal/protocols/Mcp.d.ts.map +1 -0
- package/dist/client/internal/protocols/Mcp.js +159 -0
- package/dist/client/internal/protocols/Mcp.js.map +1 -0
- package/dist/client/internal/protocols/Mpp.d.ts +4 -0
- package/dist/client/internal/protocols/Mpp.d.ts.map +1 -0
- package/dist/client/internal/protocols/Mpp.js +18 -0
- package/dist/client/internal/protocols/Mpp.js.map +1 -0
- package/dist/client/internal/protocols/Protocol.d.ts +10 -0
- package/dist/client/internal/protocols/Protocol.d.ts.map +1 -0
- package/dist/client/internal/protocols/Protocol.js +2 -0
- package/dist/client/internal/protocols/Protocol.js.map +1 -0
- package/dist/client/internal/protocols/Shared.d.ts +5 -0
- package/dist/client/internal/protocols/Shared.d.ts.map +1 -0
- package/dist/client/internal/protocols/Shared.js +20 -0
- package/dist/client/internal/protocols/Shared.js.map +1 -0
- package/dist/client/internal/protocols/X402.d.ts +8 -0
- package/dist/client/internal/protocols/X402.d.ts.map +1 -0
- package/dist/client/internal/protocols/X402.js +39 -0
- package/dist/client/internal/protocols/X402.js.map +1 -0
- package/dist/evm/client/index.d.ts +1 -0
- package/dist/evm/client/index.d.ts.map +1 -1
- package/dist/evm/client/index.js +1 -0
- package/dist/evm/client/index.js.map +1 -1
- package/dist/evm/index.d.ts +2 -0
- package/dist/evm/index.d.ts.map +1 -1
- package/dist/evm/index.js +2 -0
- package/dist/evm/index.js.map +1 -1
- package/dist/evm/server/Methods.d.ts +1 -1
- package/dist/evm/server/Methods.d.ts.map +1 -1
- package/dist/evm/server/index.d.ts +1 -0
- package/dist/evm/server/index.d.ts.map +1 -1
- package/dist/evm/server/index.js +1 -0
- package/dist/evm/server/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/AcceptPayment.d.ts +3 -0
- package/dist/internal/AcceptPayment.d.ts.map +1 -1
- package/dist/internal/AcceptPayment.js +15 -11
- package/dist/internal/AcceptPayment.js.map +1 -1
- package/dist/mcp/client/McpClient.d.ts +101 -0
- package/dist/mcp/client/McpClient.d.ts.map +1 -0
- package/dist/mcp/client/McpClient.js +162 -0
- package/dist/mcp/client/McpClient.js.map +1 -0
- package/dist/mcp/client/index.d.ts.map +1 -0
- package/dist/mcp/client/index.js.map +1 -0
- package/dist/mcp/server/Transport.d.ts.map +1 -0
- package/dist/mcp/server/Transport.js.map +1 -0
- package/dist/mcp/server/index.d.ts.map +1 -0
- package/dist/mcp/server/index.js.map +1 -0
- package/dist/server/Mppx.d.ts +12 -4
- package/dist/server/Mppx.d.ts.map +1 -1
- package/dist/server/Mppx.js +85 -27
- package/dist/server/Mppx.js.map +1 -1
- package/dist/server/Response.d.ts.map +1 -1
- package/dist/server/Response.js +2 -1
- package/dist/server/Response.js.map +1 -1
- package/dist/server/Transport.d.ts +1 -1
- package/dist/server/Transport.d.ts.map +1 -1
- package/dist/server/Transport.js +5 -4
- package/dist/server/Transport.js.map +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -0
- package/dist/server/index.js.map +1 -1
- package/dist/stripe/client/Charge.d.ts +1 -1
- package/dist/stripe/client/Charge.d.ts.map +1 -1
- package/dist/stripe/client/Charge.js +3 -1
- package/dist/stripe/client/Charge.js.map +1 -1
- package/dist/stripe/server/Charge.d.ts +1 -1
- package/dist/stripe/server/Charge.d.ts.map +1 -1
- package/dist/stripe/server/Charge.js +9 -2
- package/dist/stripe/server/Charge.js.map +1 -1
- package/dist/stripe/server/Methods.d.ts +1 -1
- package/dist/stripe/server/Methods.d.ts.map +1 -1
- 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/tempo/Methods.d.ts +18 -0
- package/dist/tempo/Methods.d.ts.map +1 -1
- package/dist/tempo/Methods.js +16 -1
- package/dist/tempo/Methods.js.map +1 -1
- package/dist/tempo/Proof.d.ts +85 -1
- package/dist/tempo/Proof.d.ts.map +1 -1
- package/dist/tempo/Proof.js +35 -0
- package/dist/tempo/Proof.js.map +1 -1
- package/dist/tempo/client/Charge.d.ts +19 -1
- package/dist/tempo/client/Charge.d.ts.map +1 -1
- package/dist/tempo/client/Charge.js +47 -27
- package/dist/tempo/client/Charge.js.map +1 -1
- package/dist/tempo/client/Methods.d.ts +41 -10
- package/dist/tempo/client/Methods.d.ts.map +1 -1
- package/dist/tempo/client/Methods.js +16 -7
- package/dist/tempo/client/Methods.js.map +1 -1
- package/dist/tempo/client/ResolveAccount.d.ts +40 -0
- package/dist/tempo/client/ResolveAccount.d.ts.map +1 -0
- package/dist/tempo/client/ResolveAccount.js +2 -0
- package/dist/tempo/client/ResolveAccount.js.map +1 -0
- package/dist/tempo/client/index.d.ts +7 -4
- package/dist/tempo/client/index.d.ts.map +1 -1
- package/dist/tempo/client/index.js +5 -3
- package/dist/tempo/client/index.js.map +1 -1
- package/dist/tempo/index.d.ts +1 -0
- package/dist/tempo/index.d.ts.map +1 -1
- package/dist/tempo/index.js +1 -0
- package/dist/tempo/index.js.map +1 -1
- package/dist/tempo/internal/fee-payer.d.ts +29 -1
- package/dist/tempo/internal/fee-payer.d.ts.map +1 -1
- package/dist/tempo/internal/fee-payer.js +138 -4
- package/dist/tempo/internal/fee-payer.js.map +1 -1
- package/dist/tempo/internal/proof.d.ts +71 -5
- package/dist/tempo/internal/proof.d.ts.map +1 -1
- package/dist/tempo/internal/proof.js +42 -6
- package/dist/tempo/internal/proof.js.map +1 -1
- package/dist/tempo/{client → legacy/client}/ChannelOps.d.ts +19 -6
- package/dist/tempo/legacy/client/ChannelOps.d.ts.map +1 -0
- package/dist/tempo/{client → legacy/client}/ChannelOps.js +9 -3
- package/dist/tempo/legacy/client/ChannelOps.js.map +1 -0
- package/dist/tempo/{client → legacy/client}/Session.d.ts +23 -4
- package/dist/tempo/legacy/client/Session.d.ts.map +1 -0
- package/dist/tempo/{client → legacy/client}/Session.js +14 -7
- package/dist/tempo/legacy/client/Session.js.map +1 -0
- package/dist/tempo/{client → legacy/client}/SessionManager.d.ts +20 -5
- package/dist/tempo/legacy/client/SessionManager.d.ts.map +1 -0
- package/dist/tempo/{client → legacy/client}/SessionManager.js +30 -19
- package/dist/tempo/legacy/client/SessionManager.js.map +1 -0
- package/dist/tempo/legacy/client/index.d.ts +7 -0
- package/dist/tempo/legacy/client/index.d.ts.map +1 -0
- package/dist/tempo/legacy/client/index.js +5 -0
- package/dist/tempo/legacy/client/index.js.map +1 -0
- package/dist/tempo/legacy/index.d.ts +7 -0
- package/dist/tempo/legacy/index.d.ts.map +1 -0
- package/dist/tempo/legacy/index.js +7 -0
- package/dist/tempo/legacy/index.js.map +1 -0
- package/dist/tempo/{server → legacy/server}/Session.d.ts +28 -11
- package/dist/tempo/legacy/server/Session.d.ts.map +1 -0
- package/dist/tempo/{server → legacy/server}/Session.js +12 -10
- package/dist/tempo/legacy/server/Session.js.map +1 -0
- package/dist/tempo/legacy/server/index.d.ts +5 -0
- package/dist/tempo/legacy/server/index.d.ts.map +1 -0
- package/dist/tempo/legacy/server/index.js +5 -0
- package/dist/tempo/legacy/server/index.js.map +1 -0
- package/dist/tempo/{session → legacy/session}/Chain.d.ts +30 -23
- package/dist/tempo/legacy/session/Chain.d.ts.map +1 -0
- package/dist/tempo/{session → legacy/session}/Chain.js +12 -11
- package/dist/tempo/legacy/session/Chain.js.map +1 -0
- package/dist/tempo/{session → legacy/session}/Channel.d.ts +1 -0
- package/dist/tempo/legacy/session/Channel.d.ts.map +1 -0
- package/dist/tempo/legacy/session/Channel.js.map +1 -0
- package/dist/tempo/legacy/session/ChannelStore.d.ts +22 -0
- package/dist/tempo/legacy/session/ChannelStore.d.ts.map +1 -0
- package/dist/tempo/legacy/session/ChannelStore.js +6 -0
- package/dist/tempo/legacy/session/ChannelStore.js.map +1 -0
- package/dist/tempo/legacy/session/Types.d.ts +73 -0
- package/dist/tempo/legacy/session/Types.d.ts.map +1 -0
- package/dist/tempo/legacy/session/Types.js.map +1 -0
- package/dist/tempo/{session → legacy/session}/Voucher.d.ts +4 -4
- package/dist/tempo/legacy/session/Voucher.d.ts.map +1 -0
- package/dist/tempo/{session → legacy/session}/Voucher.js +1 -1
- package/dist/tempo/legacy/session/Voucher.js.map +1 -0
- package/dist/tempo/{session → legacy/session}/escrow.abi.d.ts +1 -0
- package/dist/tempo/{session → legacy/session}/escrow.abi.d.ts.map +1 -1
- package/dist/tempo/{session → legacy/session}/escrow.abi.js +1 -0
- package/dist/tempo/legacy/session/escrow.abi.js.map +1 -0
- package/dist/tempo/legacy/session/index.d.ts +9 -0
- package/dist/tempo/legacy/session/index.d.ts.map +1 -0
- package/dist/tempo/legacy/session/index.js +9 -0
- package/dist/tempo/legacy/session/index.js.map +1 -0
- package/dist/tempo/server/Charge.d.ts +1 -1
- package/dist/tempo/server/Charge.d.ts.map +1 -1
- package/dist/tempo/server/Charge.js +51 -30
- package/dist/tempo/server/Charge.js.map +1 -1
- package/dist/tempo/server/Methods.d.ts +67 -8
- package/dist/tempo/server/Methods.d.ts.map +1 -1
- package/dist/tempo/server/Methods.js +40 -10
- package/dist/tempo/server/Methods.js.map +1 -1
- package/dist/tempo/server/Subscription.d.ts +11 -1
- package/dist/tempo/server/Subscription.d.ts.map +1 -1
- package/dist/tempo/server/Subscription.js +135 -23
- package/dist/tempo/server/Subscription.js.map +1 -1
- package/dist/tempo/server/index.d.ts +6 -5
- package/dist/tempo/server/index.d.ts.map +1 -1
- package/dist/tempo/server/index.js +5 -5
- 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/request-body.d.ts +7 -2
- package/dist/tempo/server/internal/request-body.d.ts.map +1 -1
- package/dist/tempo/server/internal/request-body.js +20 -3
- package/dist/tempo/server/internal/request-body.js.map +1 -1
- package/dist/tempo/server/internal/transport.d.ts +8 -4
- package/dist/tempo/server/internal/transport.d.ts.map +1 -1
- package/dist/tempo/server/internal/transport.js +8 -7
- package/dist/tempo/server/internal/transport.js.map +1 -1
- package/dist/tempo/session/Snapshot.d.ts +32 -0
- package/dist/tempo/session/Snapshot.d.ts.map +1 -0
- package/dist/tempo/session/Snapshot.js +37 -0
- package/dist/tempo/session/Snapshot.js.map +1 -0
- package/dist/tempo/session/client/ChannelOps.d.ts +81 -0
- package/dist/tempo/session/client/ChannelOps.d.ts.map +1 -0
- package/dist/tempo/session/client/ChannelOps.js +201 -0
- package/dist/tempo/session/client/ChannelOps.js.map +1 -0
- package/dist/tempo/session/client/ChannelStore.d.ts +51 -0
- package/dist/tempo/session/client/ChannelStore.d.ts.map +1 -0
- package/dist/tempo/session/client/ChannelStore.js +63 -0
- package/dist/tempo/session/client/ChannelStore.js.map +1 -0
- package/dist/tempo/session/client/CredentialState.d.ts +245 -0
- package/dist/tempo/session/client/CredentialState.d.ts.map +1 -0
- package/dist/tempo/session/client/CredentialState.js +419 -0
- package/dist/tempo/session/client/CredentialState.js.map +1 -0
- package/dist/tempo/session/client/ReceiptCoordinator.d.ts +26 -0
- package/dist/tempo/session/client/ReceiptCoordinator.d.ts.map +1 -0
- package/dist/tempo/session/client/ReceiptCoordinator.js +61 -0
- package/dist/tempo/session/client/ReceiptCoordinator.js.map +1 -0
- package/dist/tempo/session/client/Runtime.d.ts +464 -0
- package/dist/tempo/session/client/Runtime.d.ts.map +1 -0
- package/dist/tempo/session/client/Runtime.js +499 -0
- package/dist/tempo/session/client/Runtime.js.map +1 -0
- package/dist/tempo/session/client/Session.d.ts +138 -0
- package/dist/tempo/session/client/Session.d.ts.map +1 -0
- package/dist/tempo/session/client/Session.js +69 -0
- package/dist/tempo/session/client/Session.js.map +1 -0
- package/dist/tempo/session/client/SessionManager.d.ts +84 -0
- package/dist/tempo/session/client/SessionManager.d.ts.map +1 -0
- package/dist/tempo/session/client/SessionManager.js +577 -0
- package/dist/tempo/session/client/SessionManager.js.map +1 -0
- package/dist/tempo/session/client/Transports.d.ts +449 -0
- package/dist/tempo/session/client/Transports.d.ts.map +1 -0
- package/dist/tempo/session/client/Transports.js +721 -0
- package/dist/tempo/session/client/Transports.js.map +1 -0
- package/dist/tempo/session/client/index.d.ts +11 -0
- package/dist/tempo/session/client/index.d.ts.map +1 -0
- package/dist/tempo/session/client/index.js +6 -0
- package/dist/tempo/session/client/index.js.map +1 -0
- package/dist/tempo/session/index.d.ts +7 -8
- package/dist/tempo/session/index.d.ts.map +1 -1
- package/dist/tempo/session/index.js +7 -8
- package/dist/tempo/session/index.js.map +1 -1
- package/dist/tempo/session/precompile/Chain.d.ts +319 -0
- package/dist/tempo/session/precompile/Chain.d.ts.map +1 -0
- package/dist/tempo/session/precompile/Chain.js +492 -0
- package/dist/tempo/session/precompile/Chain.js.map +1 -0
- package/dist/tempo/session/precompile/Channel.d.ts +46 -0
- package/dist/tempo/session/precompile/Channel.d.ts.map +1 -0
- package/dist/tempo/session/precompile/Channel.js +56 -0
- package/dist/tempo/session/precompile/Channel.js.map +1 -0
- package/dist/tempo/session/precompile/Protocol.d.ts +308 -0
- package/dist/tempo/session/precompile/Protocol.d.ts.map +1 -0
- package/dist/tempo/session/precompile/Protocol.js +264 -0
- package/dist/tempo/session/precompile/Protocol.js.map +1 -0
- package/dist/tempo/session/precompile/Voucher.d.ts +40 -0
- package/dist/tempo/session/precompile/Voucher.d.ts.map +1 -0
- package/dist/tempo/session/precompile/Voucher.js +125 -0
- package/dist/tempo/session/precompile/Voucher.js.map +1 -0
- package/dist/tempo/session/precompile/escrow.abi.d.ts +522 -0
- package/dist/tempo/session/precompile/escrow.abi.d.ts.map +1 -0
- package/dist/tempo/session/precompile/escrow.abi.js +224 -0
- package/dist/tempo/session/precompile/escrow.abi.js.map +1 -0
- package/dist/tempo/session/precompile/index.d.ts +24 -0
- package/dist/tempo/session/precompile/index.d.ts.map +1 -0
- package/dist/tempo/session/precompile/index.js +22 -0
- package/dist/tempo/session/precompile/index.js.map +1 -0
- package/dist/tempo/session/server/ChannelOps.d.ts +56 -0
- package/dist/tempo/session/server/ChannelOps.d.ts.map +1 -0
- package/dist/tempo/session/server/ChannelOps.js +91 -0
- package/dist/tempo/session/server/ChannelOps.js.map +1 -0
- package/dist/tempo/session/server/ChannelStore.d.ts +347 -0
- package/dist/tempo/session/server/ChannelStore.d.ts.map +1 -0
- package/dist/tempo/session/server/ChannelStore.js +404 -0
- package/dist/tempo/session/server/ChannelStore.js.map +1 -0
- package/dist/tempo/session/server/CredentialVerification.d.ts +85 -0
- package/dist/tempo/session/server/CredentialVerification.d.ts.map +1 -0
- package/dist/tempo/session/server/CredentialVerification.js +494 -0
- package/dist/tempo/session/server/CredentialVerification.js.map +1 -0
- package/dist/tempo/session/server/MeteredStream.d.ts +40 -0
- package/dist/tempo/session/server/MeteredStream.d.ts.map +1 -0
- package/dist/tempo/session/server/MeteredStream.js +42 -0
- package/dist/tempo/session/server/MeteredStream.js.map +1 -0
- package/dist/tempo/session/server/RequestState.d.ts +208 -0
- package/dist/tempo/session/server/RequestState.d.ts.map +1 -0
- package/dist/tempo/session/server/RequestState.js +252 -0
- package/dist/tempo/session/server/RequestState.js.map +1 -0
- package/dist/tempo/session/server/Session.d.ts +169 -0
- package/dist/tempo/session/server/Session.d.ts.map +1 -0
- package/dist/tempo/session/server/Session.js +351 -0
- package/dist/tempo/session/server/Session.js.map +1 -0
- package/dist/tempo/session/server/Settlement.d.ts +185 -0
- package/dist/tempo/session/server/Settlement.d.ts.map +1 -0
- package/dist/tempo/session/server/Settlement.js +252 -0
- package/dist/tempo/session/server/Settlement.js.map +1 -0
- package/dist/tempo/session/{Sse.d.ts → server/Sse.d.ts} +9 -56
- package/dist/tempo/session/server/Sse.d.ts.map +1 -0
- package/dist/tempo/session/server/Sse.js +184 -0
- package/dist/tempo/session/server/Sse.js.map +1 -0
- package/dist/tempo/session/server/Transports.d.ts +89 -0
- package/dist/tempo/session/server/Transports.d.ts.map +1 -0
- package/dist/tempo/session/server/Transports.js +149 -0
- package/dist/tempo/session/server/Transports.js.map +1 -0
- package/dist/tempo/session/server/Ws.d.ts +48 -0
- package/dist/tempo/session/server/Ws.d.ts.map +1 -0
- package/dist/tempo/session/server/Ws.js +244 -0
- package/dist/tempo/session/server/Ws.js.map +1 -0
- package/dist/tempo/session/server/index.d.ts +4 -0
- package/dist/tempo/session/server/index.d.ts.map +1 -0
- package/dist/tempo/session/server/index.js +2 -0
- package/dist/tempo/session/server/index.js.map +1 -0
- package/dist/tempo/subscription/KeyAuthorization.d.ts +712 -1
- package/dist/tempo/subscription/KeyAuthorization.d.ts.map +1 -1
- package/dist/tempo/subscription/Store.d.ts +2 -0
- package/dist/tempo/subscription/Store.d.ts.map +1 -1
- package/dist/tempo/subscription/Store.js +16 -1
- package/dist/tempo/subscription/Store.js.map +1 -1
- package/dist/x402/index.d.ts +1 -0
- package/dist/x402/index.d.ts.map +1 -1
- package/dist/x402/index.js +1 -0
- package/dist/x402/index.js.map +1 -1
- package/package.json +25 -9
- package/src/Challenge.test.ts +40 -0
- package/src/Challenge.ts +28 -13
- package/src/Constants.ts +58 -0
- package/src/Credential.ts +5 -4
- package/src/Mcp.ts +4 -0
- package/src/Method.ts +46 -5
- package/src/PaymentRequest.ts +10 -10
- package/src/Receipt.ts +3 -2
- package/src/cli/cli.test.ts +38 -43
- package/src/cli/cli.ts +23 -10
- package/src/cli/mcp.test.ts +21 -7
- package/src/cli/plugins/tempo.ts +21 -8
- package/src/cli/utils.test.ts +25 -1
- package/src/cli/utils.ts +10 -0
- package/src/client/Methods.ts +5 -2
- package/src/client/Mppx.test-d.ts +31 -1
- package/src/client/Mppx.test.ts +76 -1
- package/src/client/Mppx.ts +2 -2
- package/src/client/Transport.test.ts +225 -178
- package/src/client/Transport.ts +77 -84
- package/src/client/index.ts +25 -1
- package/src/client/internal/Fetch.test.ts +236 -6
- package/src/client/internal/Fetch.ts +69 -11
- package/src/client/internal/protocols/Mcp.test.ts +220 -0
- package/src/client/internal/protocols/Mcp.ts +162 -0
- package/src/client/internal/protocols/Mpp.ts +21 -0
- package/src/client/internal/protocols/Protocol.ts +10 -0
- package/src/client/internal/protocols/Shared.ts +25 -0
- package/src/client/internal/protocols/X402.ts +42 -0
- package/src/discovery/OpenApi.test.ts +1 -1
- package/src/env.d.ts +1 -1
- package/src/evm/PublicInterface.test-d.ts +1 -1
- package/src/evm/client/index.ts +1 -0
- package/src/evm/index.ts +2 -0
- package/src/evm/server/Charge.test.ts +1 -1
- package/src/evm/server/index.ts +1 -0
- package/src/index.ts +1 -0
- package/src/internal/AcceptPayment.test.ts +61 -0
- package/src/internal/AcceptPayment.ts +21 -14
- package/src/{mcp-sdk → mcp}/client/McpClient.integration.test.ts +18 -11
- package/src/{mcp-sdk → mcp}/client/McpClient.test-d.ts +45 -11
- package/src/{mcp-sdk → mcp}/client/McpClient.test.ts +211 -5
- package/src/mcp/client/McpClient.ts +307 -0
- package/src/mcp/client/McpClient.unit.test.ts +135 -0
- package/src/middlewares/elysia.test.ts +9 -5
- package/src/middlewares/express.test.ts +9 -5
- package/src/middlewares/hono.test.ts +5 -5
- package/src/middlewares/internal/mppx.test.ts +1 -1
- package/src/middlewares/nextjs.test.ts +9 -5
- package/src/proxy/Proxy.test.ts +9 -9
- package/src/proxy/services/anthropic.test.ts +1 -1
- package/src/proxy/services/openai.test.ts +1 -1
- package/src/proxy/services/stripe.test.ts +1 -1
- package/src/server/Mppx.authorize.test.ts +1 -1
- package/src/server/Mppx.test-d.ts +55 -1
- package/src/server/Mppx.test.ts +220 -9
- package/src/server/Mppx.ts +501 -407
- package/src/server/Response.ts +2 -1
- package/src/server/Transport.test.ts +6 -6
- package/src/server/Transport.ts +5 -4
- package/src/server/index.ts +1 -0
- package/src/stripe/Charge.integration.test.ts +1 -1
- package/src/stripe/client/Charge.test.ts +21 -6
- package/src/stripe/client/Charge.ts +6 -2
- package/src/stripe/server/Charge.test.ts +115 -2
- package/src/stripe/server/Charge.ts +13 -2
- package/src/stripe/server/internal/html/package.json +1 -1
- package/src/stripe/server/internal/html.gen.ts +1 -1
- package/src/tempo/AccessKeyAuthorization.test.ts +4 -94
- package/src/tempo/Methods.test.ts +45 -17
- package/src/tempo/Methods.ts +22 -0
- package/src/tempo/Proof.conformance.test.ts +146 -0
- package/src/tempo/Proof.test-d.ts +15 -0
- package/src/tempo/Proof.ts +52 -1
- package/src/tempo/PublicExports.test-d.ts +105 -0
- package/src/tempo/Subscription.integration.test.ts +1 -1
- package/src/tempo/client/Charge.test.ts +258 -0
- package/src/tempo/client/Charge.ts +84 -38
- package/src/tempo/client/Methods.ts +22 -8
- package/src/tempo/client/ResolveAccount.ts +46 -0
- package/src/tempo/client/index.ts +15 -4
- package/src/tempo/index.ts +1 -0
- package/src/tempo/internal/fee-payer.test.ts +296 -17
- package/src/tempo/internal/fee-payer.ts +186 -4
- package/src/tempo/internal/fee-token.test.ts +14 -9
- package/src/tempo/internal/proof.test.ts +12 -4
- package/src/tempo/internal/proof.ts +55 -6
- package/src/tempo/legacy/AccessKeyAuthorization.test.ts +162 -0
- package/src/tempo/legacy/README.md +9 -0
- package/src/tempo/{client → legacy/client}/ChannelOps.test.ts +6 -7
- package/src/tempo/{client → legacy/client}/ChannelOps.ts +22 -9
- package/src/tempo/{client → legacy/client}/Session.test.ts +51 -9
- package/src/tempo/{client → legacy/client}/Session.ts +25 -11
- package/src/tempo/{client → legacy/client}/SessionManager.test.ts +81 -9
- package/src/tempo/{client → legacy/client}/SessionManager.ts +52 -23
- package/src/tempo/legacy/client/index.ts +6 -0
- package/src/tempo/legacy/index.ts +6 -0
- package/src/tempo/{server → legacy/server}/Session.test.ts +136 -71
- package/src/tempo/{server → legacy/server}/Session.ts +32 -23
- package/src/tempo/legacy/server/index.ts +4 -0
- package/src/tempo/{session → legacy/session}/Chain.test.ts +3 -4
- package/src/tempo/{session → legacy/session}/Chain.ts +94 -63
- package/src/tempo/{session → legacy/session}/Channel.ts +1 -0
- package/src/tempo/legacy/session/ChannelStore.test.ts +58 -0
- package/src/tempo/legacy/session/ChannelStore.ts +39 -0
- package/src/tempo/legacy/session/Types.ts +91 -0
- package/src/tempo/{session → legacy/session}/Voucher.ts +12 -8
- package/src/tempo/{session → legacy/session}/escrow.abi.ts +1 -0
- package/src/tempo/legacy/session/index.ts +8 -0
- package/src/tempo/server/AtomicStore.test-d.ts +16 -11
- package/src/tempo/server/Charge.test.ts +480 -31
- package/src/tempo/server/Charge.ts +54 -30
- package/src/tempo/server/Methods.ts +58 -10
- package/src/tempo/server/Sse.test.ts +2 -2
- package/src/tempo/server/Subscription.test.ts +465 -3
- package/src/tempo/server/Subscription.ts +174 -19
- package/src/tempo/server/index.ts +6 -5
- package/src/tempo/server/internal/html/package.json +2 -2
- package/src/tempo/server/internal/html.gen.ts +1 -1
- package/src/tempo/server/internal/request-body.test.ts +37 -4
- package/src/tempo/server/internal/request-body.ts +25 -6
- package/src/tempo/server/internal/transport.test.ts +4 -4
- package/src/tempo/server/internal/transport.ts +19 -10
- package/src/tempo/session/Snapshot.test.ts +41 -0
- package/src/tempo/session/Snapshot.ts +74 -0
- package/src/tempo/session/client/ChannelOps.test.ts +163 -0
- package/src/tempo/session/client/ChannelOps.ts +330 -0
- package/src/tempo/session/client/ChannelStore.ts +111 -0
- package/src/tempo/session/client/CredentialState.test.ts +789 -0
- package/src/tempo/session/client/CredentialState.ts +799 -0
- package/src/tempo/session/client/ReceiptCoordinator.ts +95 -0
- package/src/tempo/session/client/Runtime.test.ts +1092 -0
- package/src/tempo/session/client/Runtime.ts +986 -0
- package/src/tempo/session/client/Session.test.ts +774 -0
- package/src/tempo/session/client/Session.ts +123 -0
- package/src/tempo/session/client/SessionManager.test.ts +1397 -0
- package/src/tempo/session/client/SessionManager.ts +751 -0
- package/src/tempo/session/client/Transports.test.ts +837 -0
- package/src/tempo/session/client/Transports.ts +1292 -0
- package/src/tempo/session/client/index.ts +40 -0
- package/src/tempo/session/index.ts +7 -8
- package/src/tempo/session/precompile/Chain.integration.test.ts +321 -0
- package/src/tempo/session/precompile/Chain.test.ts +1258 -0
- package/src/tempo/session/precompile/Chain.ts +979 -0
- package/src/tempo/session/precompile/Channel.test.ts +138 -0
- package/src/tempo/session/precompile/Channel.ts +103 -0
- package/src/tempo/session/precompile/Protocol.test.ts +358 -0
- package/src/tempo/session/precompile/Protocol.ts +520 -0
- package/src/tempo/session/precompile/Voucher.test.ts +354 -0
- package/src/tempo/session/precompile/Voucher.ts +162 -0
- package/src/tempo/session/precompile/escrow.abi.ts +226 -0
- package/src/tempo/session/precompile/index.ts +33 -0
- package/src/tempo/session/server/ChannelOps.test.ts +129 -0
- package/src/tempo/session/server/ChannelOps.ts +157 -0
- package/src/tempo/session/{ChannelStore.test.ts → server/ChannelStore.test.ts} +536 -29
- package/src/tempo/session/server/ChannelStore.ts +835 -0
- package/src/tempo/session/server/CredentialVerification.test.ts +146 -0
- package/src/tempo/session/server/CredentialVerification.ts +710 -0
- package/src/tempo/session/server/MeteredStream.ts +88 -0
- package/src/tempo/session/server/RequestState.test.ts +531 -0
- package/src/tempo/session/server/RequestState.ts +499 -0
- package/src/tempo/session/server/Session.integration.test.ts +444 -0
- package/src/tempo/session/server/Session.test.ts +3253 -0
- package/src/tempo/session/server/Session.ts +543 -0
- package/src/tempo/session/server/Settlement.test.ts +329 -0
- package/src/tempo/session/server/Settlement.ts +471 -0
- package/src/tempo/session/{Sse.test.ts → server/Sse.test.ts} +37 -3
- package/src/tempo/session/server/Sse.ts +254 -0
- package/src/tempo/session/server/Transports.test.ts +346 -0
- package/src/tempo/session/server/Transports.ts +255 -0
- package/src/tempo/session/{Ws.test.ts → server/Ws.test.ts} +4 -4
- package/src/tempo/session/server/Ws.ts +380 -0
- package/src/tempo/session/server/index.ts +8 -0
- package/src/tempo/subscription/Store.ts +27 -9
- package/src/x402/Exact.e2e.test.ts +1 -1
- package/src/x402/PublicInterface.test-d.ts +1 -1
- package/src/x402/index.ts +1 -0
- package/dist/mcp-sdk/client/McpClient.d.ts +0 -78
- package/dist/mcp-sdk/client/McpClient.d.ts.map +0 -1
- package/dist/mcp-sdk/client/McpClient.js +0 -105
- package/dist/mcp-sdk/client/McpClient.js.map +0 -1
- package/dist/mcp-sdk/client/index.d.ts.map +0 -1
- package/dist/mcp-sdk/client/index.js.map +0 -1
- package/dist/mcp-sdk/server/Transport.d.ts.map +0 -1
- package/dist/mcp-sdk/server/Transport.js.map +0 -1
- package/dist/mcp-sdk/server/index.d.ts.map +0 -1
- package/dist/mcp-sdk/server/index.js.map +0 -1
- package/dist/tempo/client/ChannelOps.d.ts.map +0 -1
- package/dist/tempo/client/ChannelOps.js.map +0 -1
- package/dist/tempo/client/Session.d.ts.map +0 -1
- package/dist/tempo/client/Session.js.map +0 -1
- package/dist/tempo/client/SessionManager.d.ts.map +0 -1
- package/dist/tempo/client/SessionManager.js.map +0 -1
- package/dist/tempo/server/Session.d.ts.map +0 -1
- package/dist/tempo/server/Session.js.map +0 -1
- package/dist/tempo/session/Chain.d.ts.map +0 -1
- package/dist/tempo/session/Chain.js.map +0 -1
- package/dist/tempo/session/Channel.d.ts.map +0 -1
- package/dist/tempo/session/Channel.js.map +0 -1
- package/dist/tempo/session/ChannelStore.d.ts +0 -117
- package/dist/tempo/session/ChannelStore.d.ts.map +0 -1
- package/dist/tempo/session/ChannelStore.js +0 -172
- package/dist/tempo/session/ChannelStore.js.map +0 -1
- package/dist/tempo/session/Receipt.d.ts +0 -22
- package/dist/tempo/session/Receipt.d.ts.map +0 -1
- package/dist/tempo/session/Receipt.js +0 -34
- package/dist/tempo/session/Receipt.js.map +0 -1
- package/dist/tempo/session/Sse.d.ts.map +0 -1
- package/dist/tempo/session/Sse.js +0 -363
- package/dist/tempo/session/Sse.js.map +0 -1
- package/dist/tempo/session/Types.d.ts +0 -78
- package/dist/tempo/session/Types.d.ts.map +0 -1
- package/dist/tempo/session/Types.js.map +0 -1
- package/dist/tempo/session/Voucher.d.ts.map +0 -1
- package/dist/tempo/session/Voucher.js.map +0 -1
- package/dist/tempo/session/Ws.d.ts +0 -87
- package/dist/tempo/session/Ws.d.ts.map +0 -1
- package/dist/tempo/session/Ws.js +0 -443
- package/dist/tempo/session/Ws.js.map +0 -1
- package/dist/tempo/session/escrow.abi.js.map +0 -1
- package/src/mcp-sdk/client/McpClient.ts +0 -196
- package/src/tempo/session/ChannelStore.ts +0 -308
- package/src/tempo/session/Receipt.test.ts +0 -89
- package/src/tempo/session/Receipt.ts +0 -46
- package/src/tempo/session/Sse.ts +0 -462
- package/src/tempo/session/Types.ts +0 -86
- package/src/tempo/session/Ws.ts +0 -576
- /package/dist/{mcp-sdk → mcp}/client/index.d.ts +0 -0
- /package/dist/{mcp-sdk → mcp}/client/index.js +0 -0
- /package/dist/{mcp-sdk → mcp}/server/Transport.d.ts +0 -0
- /package/dist/{mcp-sdk → mcp}/server/Transport.js +0 -0
- /package/dist/{mcp-sdk → mcp}/server/index.d.ts +0 -0
- /package/dist/{mcp-sdk → mcp}/server/index.js +0 -0
- /package/dist/tempo/{session → legacy/session}/Channel.js +0 -0
- /package/dist/tempo/{session → legacy/session}/Types.js +0 -0
- /package/src/{mcp-sdk → mcp}/client/index.ts +0 -0
- /package/src/{mcp-sdk → mcp}/server/Transport.test.ts +0 -0
- /package/src/{mcp-sdk → mcp}/server/Transport.ts +0 -0
- /package/src/{mcp-sdk → mcp}/server/index.ts +0 -0
- /package/src/tempo/{session → legacy/session}/Channel.test.ts +0 -0
- /package/src/tempo/{session → legacy/session}/Voucher.test.ts +0 -0
- /package/src/tempo/session/{Sse.fuzz.test.ts → server/Sse.fuzz.test.ts} +0 -0
|
@@ -0,0 +1,710 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isAddress,
|
|
3
|
+
isAddressEqual,
|
|
4
|
+
zeroAddress,
|
|
5
|
+
type Account as viem_Account,
|
|
6
|
+
type Address,
|
|
7
|
+
type Hex,
|
|
8
|
+
} from 'viem'
|
|
9
|
+
|
|
10
|
+
import type * as Challenge from '../../../Challenge.js'
|
|
11
|
+
import {
|
|
12
|
+
AmountExceedsDepositError,
|
|
13
|
+
ChannelClosedError,
|
|
14
|
+
ChannelNotFoundError,
|
|
15
|
+
InsufficientBalanceError,
|
|
16
|
+
InvalidSignatureError,
|
|
17
|
+
VerificationFailedError,
|
|
18
|
+
} from '../../../Errors.js'
|
|
19
|
+
import type * as FeePayer from '../../internal/fee-payer.js'
|
|
20
|
+
import * as Chain from '../precompile/Chain.js'
|
|
21
|
+
import { readChannelClosedReceiptFields } from '../precompile/Chain.js'
|
|
22
|
+
import * as Channel from '../precompile/Channel.js'
|
|
23
|
+
import {
|
|
24
|
+
createSessionReceipt,
|
|
25
|
+
uint96,
|
|
26
|
+
type ChannelDescriptor,
|
|
27
|
+
type SessionCredentialPayload,
|
|
28
|
+
type SessionReceipt,
|
|
29
|
+
} from '../precompile/Protocol.js'
|
|
30
|
+
import * as Voucher from '../precompile/Voucher.js'
|
|
31
|
+
import * as ChannelStore from './ChannelStore.js'
|
|
32
|
+
import { getChallengePaymentFields } from './RequestState.js'
|
|
33
|
+
import { assertSettlementSender, getClientAccount } from './Settlement.js'
|
|
34
|
+
|
|
35
|
+
/** Returns the effective voucher signer for a TIP-1034 descriptor. */
|
|
36
|
+
export function authorizedSigner(descriptor: Channel.ChannelDescriptor): Address {
|
|
37
|
+
return isAddressEqual(descriptor.authorizedSigner, zeroAddress)
|
|
38
|
+
? descriptor.payer
|
|
39
|
+
: descriptor.authorizedSigner
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Asserts that a credential payload includes a TIP-1034 descriptor. */
|
|
43
|
+
export function assertDescriptor(payload: {
|
|
44
|
+
descriptor?: Channel.ChannelDescriptor | undefined
|
|
45
|
+
}): asserts payload is { descriptor: Channel.ChannelDescriptor } {
|
|
46
|
+
if (!payload.descriptor)
|
|
47
|
+
throw new VerificationFailedError({
|
|
48
|
+
reason: 'descriptor required for TIP-1034 session action',
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Asserts that two TIP-1034 descriptors identify the same channel. */
|
|
53
|
+
export function assertSameDescriptor(a: Channel.ChannelDescriptor, b: Channel.ChannelDescriptor) {
|
|
54
|
+
if (
|
|
55
|
+
!isAddressEqual(a.payer, b.payer) ||
|
|
56
|
+
!isAddressEqual(a.payee, b.payee) ||
|
|
57
|
+
!isAddressEqual(a.operator, b.operator) ||
|
|
58
|
+
!isAddressEqual(a.token, b.token) ||
|
|
59
|
+
!isAddressEqual(a.authorizedSigner, b.authorizedSigner) ||
|
|
60
|
+
a.salt.toLowerCase() !== b.salt.toLowerCase() ||
|
|
61
|
+
a.expiringNonceHash.toLowerCase() !== b.expiringNonceHash.toLowerCase()
|
|
62
|
+
)
|
|
63
|
+
throw new VerificationFailedError({
|
|
64
|
+
reason: 'credential descriptor does not match stored channel',
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Validates a TIP-1034 descriptor against channel ID, server destination, and token.
|
|
70
|
+
*/
|
|
71
|
+
export function validateChannelDescriptor(
|
|
72
|
+
descriptor: Channel.ChannelDescriptor,
|
|
73
|
+
channelId: Address | `0x${string}`,
|
|
74
|
+
chainId: number,
|
|
75
|
+
escrow: Address,
|
|
76
|
+
recipient: Address,
|
|
77
|
+
currency: Address,
|
|
78
|
+
expectedOperator?: Address | undefined,
|
|
79
|
+
): void {
|
|
80
|
+
const computed = Channel.computeId({ ...descriptor, chainId, escrow })
|
|
81
|
+
if (computed.toLowerCase() !== channelId.toLowerCase()) {
|
|
82
|
+
throw new VerificationFailedError({ reason: 'channel descriptor does not match channelId' })
|
|
83
|
+
}
|
|
84
|
+
if (!isAddressEqual(descriptor.payee, recipient)) {
|
|
85
|
+
throw new VerificationFailedError({
|
|
86
|
+
reason: 'channel descriptor payee does not match server destination',
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
if (!isAddressEqual(descriptor.token, currency)) {
|
|
90
|
+
throw new VerificationFailedError({
|
|
91
|
+
reason: 'channel descriptor token does not match server token',
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
if (expectedOperator !== undefined && !isAddressEqual(descriptor.operator, expectedOperator)) {
|
|
95
|
+
throw new VerificationFailedError({
|
|
96
|
+
reason: 'channel descriptor operator does not match server operator',
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Validates on-chain channel state before accepting or charging a credential. */
|
|
102
|
+
export function validateChannelState(state: Chain.ChannelState, amount?: bigint): void {
|
|
103
|
+
if (state.deposit === 0n) {
|
|
104
|
+
throw new ChannelNotFoundError({ reason: 'channel not funded on-chain' })
|
|
105
|
+
}
|
|
106
|
+
if (state.closeRequestedAt !== 0) {
|
|
107
|
+
throw new ChannelClosedError({ reason: 'channel has a pending close request' })
|
|
108
|
+
}
|
|
109
|
+
if (amount !== undefined && state.deposit - state.settled < amount) {
|
|
110
|
+
throw new InsufficientBalanceError({
|
|
111
|
+
reason: 'channel available balance insufficient for requested amount',
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const sessionCredentialActions = [
|
|
117
|
+
'open',
|
|
118
|
+
'topUp',
|
|
119
|
+
'voucher',
|
|
120
|
+
'close',
|
|
121
|
+
] as const satisfies readonly SessionCredentialPayload['action'][]
|
|
122
|
+
const sessionCredentialActionSet = new Set<string>(sessionCredentialActions)
|
|
123
|
+
|
|
124
|
+
/** Shared action and channel fields required on every session credential payload. */
|
|
125
|
+
export type SessionCredentialPayloadHeader = {
|
|
126
|
+
/** Credential action discriminator. */
|
|
127
|
+
action: SessionCredentialPayload['action']
|
|
128
|
+
/** Channel ID the credential acts on. */
|
|
129
|
+
channelId: Hex
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
type SessionCredentialPayloadData = {
|
|
133
|
+
candidate: Record<string, unknown>
|
|
134
|
+
header: SessionCredentialPayloadHeader
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function isObject(value: unknown): value is Record<string, unknown> {
|
|
138
|
+
return value !== null && typeof value === 'object'
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function isSessionCredentialAction(value: unknown): value is SessionCredentialPayload['action'] {
|
|
142
|
+
return typeof value === 'string' && sessionCredentialActionSet.has(value)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function isHex(value: unknown): value is Hex {
|
|
146
|
+
return typeof value === 'string' && /^0x[0-9a-fA-F]*$/.test(value)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function isHash(value: unknown): value is Hex {
|
|
150
|
+
return typeof value === 'string' && /^0x[0-9a-fA-F]{64}$/.test(value)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function readAddress(value: unknown, field: string): Address {
|
|
154
|
+
if (typeof value === 'string' && isAddress(value, { strict: false })) return value
|
|
155
|
+
throw new VerificationFailedError({ reason: `invalid session credential ${field}` })
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function readHash(value: unknown, field: string): Hex {
|
|
159
|
+
if (isHash(value)) return value
|
|
160
|
+
throw new VerificationFailedError({ reason: `invalid session credential ${field}` })
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function readHex(value: unknown, field: string): Hex {
|
|
164
|
+
if (isHex(value)) return value
|
|
165
|
+
throw new VerificationFailedError({ reason: `invalid session credential ${field}` })
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function readRawAmount(value: unknown, field: string): string {
|
|
169
|
+
if (typeof value === 'string' && /^[0-9]+$/.test(value)) return value
|
|
170
|
+
throw new VerificationFailedError({ reason: `invalid session credential ${field}` })
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function readPayloadObject(payload: unknown): Record<string, unknown> {
|
|
174
|
+
if (!isObject(payload))
|
|
175
|
+
throw new VerificationFailedError({ reason: 'invalid session credential payload' })
|
|
176
|
+
return payload
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function readDescriptor(value: unknown): ChannelDescriptor {
|
|
180
|
+
if (value === undefined)
|
|
181
|
+
throw new VerificationFailedError({
|
|
182
|
+
reason: 'descriptor required for TIP-1034 session action',
|
|
183
|
+
})
|
|
184
|
+
const candidate = readPayloadObject(value)
|
|
185
|
+
return {
|
|
186
|
+
payer: readAddress(candidate.payer, 'descriptor.payer'),
|
|
187
|
+
payee: readAddress(candidate.payee, 'descriptor.payee'),
|
|
188
|
+
operator: readAddress(candidate.operator, 'descriptor.operator'),
|
|
189
|
+
token: readAddress(candidate.token, 'descriptor.token'),
|
|
190
|
+
salt: readHash(candidate.salt, 'descriptor.salt'),
|
|
191
|
+
authorizedSigner: readAddress(candidate.authorizedSigner, 'descriptor.authorizedSigner'),
|
|
192
|
+
expiringNonceHash: readHash(candidate.expiringNonceHash, 'descriptor.expiringNonceHash'),
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function readPayloadHeader(payload: unknown): SessionCredentialPayloadData {
|
|
197
|
+
const candidate = readPayloadObject(payload)
|
|
198
|
+
if (!isSessionCredentialAction(candidate.action)) {
|
|
199
|
+
throw new VerificationFailedError({ reason: 'invalid session credential action' })
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
candidate,
|
|
203
|
+
header: {
|
|
204
|
+
action: candidate.action,
|
|
205
|
+
channelId: ChannelStore.normalizeChannelId(readHash(candidate.channelId, 'channelId')),
|
|
206
|
+
},
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** Validates the action discriminator for a TIP-1034 session credential payload. */
|
|
211
|
+
export function requireSessionCredentialAction(
|
|
212
|
+
payload: unknown,
|
|
213
|
+
): SessionCredentialPayload['action'] {
|
|
214
|
+
const candidate = readPayloadObject(payload)
|
|
215
|
+
if (!isSessionCredentialAction(candidate.action)) {
|
|
216
|
+
throw new VerificationFailedError({ reason: 'invalid session credential action' })
|
|
217
|
+
}
|
|
218
|
+
return candidate.action
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** Validates the shared action and channel fields for a TIP-1034 session credential payload. */
|
|
222
|
+
export function requireSessionCredentialPayloadHeader(
|
|
223
|
+
payload: unknown,
|
|
224
|
+
): SessionCredentialPayloadHeader {
|
|
225
|
+
return readPayloadHeader(payload).header
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** Validates action-specific fields for a TIP-1034 session credential payload. */
|
|
229
|
+
export function requireSessionCredentialPayload(payload: unknown): SessionCredentialPayload {
|
|
230
|
+
const { candidate, header } = readPayloadHeader(payload)
|
|
231
|
+
switch (header.action) {
|
|
232
|
+
case 'open':
|
|
233
|
+
return {
|
|
234
|
+
action: 'open',
|
|
235
|
+
type: readTransactionType(candidate.type),
|
|
236
|
+
channelId: header.channelId,
|
|
237
|
+
transaction: readHex(candidate.transaction, 'transaction'),
|
|
238
|
+
signature: readHex(candidate.signature, 'signature'),
|
|
239
|
+
descriptor: readDescriptor(candidate.descriptor),
|
|
240
|
+
cumulativeAmount: readRawAmount(candidate.cumulativeAmount, 'cumulativeAmount'),
|
|
241
|
+
...(candidate.authorizedSigner === undefined
|
|
242
|
+
? {}
|
|
243
|
+
: {
|
|
244
|
+
authorizedSigner: readAddress(candidate.authorizedSigner, 'authorizedSigner'),
|
|
245
|
+
}),
|
|
246
|
+
}
|
|
247
|
+
case 'topUp':
|
|
248
|
+
return {
|
|
249
|
+
action: 'topUp',
|
|
250
|
+
type: readTransactionType(candidate.type),
|
|
251
|
+
channelId: header.channelId,
|
|
252
|
+
transaction: readHex(candidate.transaction, 'transaction'),
|
|
253
|
+
descriptor: readDescriptor(candidate.descriptor),
|
|
254
|
+
additionalDeposit: readRawAmount(candidate.additionalDeposit, 'additionalDeposit'),
|
|
255
|
+
}
|
|
256
|
+
case 'voucher':
|
|
257
|
+
return {
|
|
258
|
+
action: 'voucher',
|
|
259
|
+
channelId: header.channelId,
|
|
260
|
+
descriptor: readDescriptor(candidate.descriptor),
|
|
261
|
+
cumulativeAmount: readRawAmount(candidate.cumulativeAmount, 'cumulativeAmount'),
|
|
262
|
+
signature: readHex(candidate.signature, 'signature'),
|
|
263
|
+
}
|
|
264
|
+
case 'close':
|
|
265
|
+
return {
|
|
266
|
+
action: 'close',
|
|
267
|
+
channelId: header.channelId,
|
|
268
|
+
descriptor: readDescriptor(candidate.descriptor),
|
|
269
|
+
cumulativeAmount: readRawAmount(candidate.cumulativeAmount, 'cumulativeAmount'),
|
|
270
|
+
signature: readHex(candidate.signature, 'signature'),
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function readTransactionType(value: unknown): 'transaction' {
|
|
276
|
+
if (value === 'transaction') return value
|
|
277
|
+
throw new VerificationFailedError({ reason: 'invalid session credential transaction type' })
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/** Shared inputs required to verify a single precompile session credential payload. */
|
|
281
|
+
export type VerifyCredentialPayloadParameters = {
|
|
282
|
+
/** Optional account override used for payee-side close settlement. */
|
|
283
|
+
account?: viem_Account | undefined
|
|
284
|
+
/** Challenge echoed by the credential. */
|
|
285
|
+
challenge: Challenge.Challenge
|
|
286
|
+
/** Milliseconds before voucher verification refreshes on-chain channel state. */
|
|
287
|
+
channelStateTtl: number
|
|
288
|
+
/** Chain ID used for channel ID derivation and voucher domain separation. */
|
|
289
|
+
chainId: number
|
|
290
|
+
/** viem client used for precompile reads and transaction broadcasts. */
|
|
291
|
+
client: Chain.TransactionClient
|
|
292
|
+
/** TIP20EscrowChannel precompile address for this session method. */
|
|
293
|
+
escrow: Address
|
|
294
|
+
/** Operator address advertised in the HMAC-bound challenge details. */
|
|
295
|
+
expectedOperator?: Address | undefined
|
|
296
|
+
/** Optional fee-payer account for fee-sponsored management transactions. */
|
|
297
|
+
feePayer?: viem_Account | undefined
|
|
298
|
+
/** Optional policy for fee-sponsored close/open/top-up transactions. */
|
|
299
|
+
feePayerPolicy?: Partial<FeePayer.Policy> | undefined
|
|
300
|
+
/** Optional fee token override for close transactions. */
|
|
301
|
+
feeToken?: Address | undefined
|
|
302
|
+
/** Last successful on-chain refresh timestamp per channel ID. */
|
|
303
|
+
lastOnChainVerified: Map<Hex, number>
|
|
304
|
+
/** Minimum allowed voucher delta in raw units. */
|
|
305
|
+
minVoucherDelta: bigint
|
|
306
|
+
/** Discriminated session credential payload to verify. */
|
|
307
|
+
payload: SessionCredentialPayload
|
|
308
|
+
/** Server-side channel store. */
|
|
309
|
+
store: ChannelStore.ChannelStore
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/** Narrows shared credential verification inputs to one payload action. */
|
|
313
|
+
export type VerifyCredentialActionParameters<action extends SessionCredentialPayload['action']> =
|
|
314
|
+
Omit<VerifyCredentialPayloadParameters, 'payload'> & {
|
|
315
|
+
/** Credential payload for the selected action. */
|
|
316
|
+
payload: Extract<SessionCredentialPayload, { action: action }>
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/** Inputs for verifying an open transaction credential and initial voucher. */
|
|
320
|
+
export type OpenCredentialActionParameters = VerifyCredentialActionParameters<'open'>
|
|
321
|
+
|
|
322
|
+
/** Inputs for verifying a top-up transaction credential. */
|
|
323
|
+
export type TopUpCredentialActionParameters = VerifyCredentialActionParameters<'topUp'>
|
|
324
|
+
|
|
325
|
+
/** Inputs for verifying and accepting an incremental voucher credential. */
|
|
326
|
+
export type VoucherCredentialActionParameters = VerifyCredentialActionParameters<'voucher'>
|
|
327
|
+
|
|
328
|
+
/** Inputs for verifying and settling a cooperative close credential. */
|
|
329
|
+
export type CloseCredentialActionParameters = VerifyCredentialActionParameters<'close'>
|
|
330
|
+
|
|
331
|
+
const refreshOnChainVerificationCache = {
|
|
332
|
+
close: false,
|
|
333
|
+
open: true,
|
|
334
|
+
topUp: true,
|
|
335
|
+
voucher: false,
|
|
336
|
+
} satisfies Record<SessionCredentialPayload['action'], boolean>
|
|
337
|
+
|
|
338
|
+
/** Verifies a session credential payload and applies the action-specific state transition. */
|
|
339
|
+
export async function verifyCredentialPayload(
|
|
340
|
+
context: VerifyCredentialPayloadParameters,
|
|
341
|
+
): Promise<SessionReceipt> {
|
|
342
|
+
const receipt = await verifyCredentialAction(context)
|
|
343
|
+
if (refreshOnChainVerificationCache[context.payload.action])
|
|
344
|
+
context.lastOnChainVerified.set(receipt.channelId, Date.now())
|
|
345
|
+
return receipt
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function verifyCredentialAction(
|
|
349
|
+
context: VerifyCredentialPayloadParameters,
|
|
350
|
+
): Promise<SessionReceipt> {
|
|
351
|
+
const { payload } = context
|
|
352
|
+
switch (payload.action) {
|
|
353
|
+
case 'open':
|
|
354
|
+
return handleOpenCredential(actionContext(context, payload))
|
|
355
|
+
case 'topUp':
|
|
356
|
+
return handleTopUpCredential(actionContext(context, payload))
|
|
357
|
+
case 'voucher':
|
|
358
|
+
return handleVoucherCredential(actionContext(context, payload))
|
|
359
|
+
case 'close':
|
|
360
|
+
return handleCloseCredential(actionContext(context, payload))
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function actionContext<action extends SessionCredentialPayload['action']>(
|
|
365
|
+
context: VerifyCredentialPayloadParameters,
|
|
366
|
+
payload: Extract<SessionCredentialPayload, { action: action }>,
|
|
367
|
+
): VerifyCredentialActionParameters<action> {
|
|
368
|
+
return { ...context, payload }
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
async function handleOpenCredential(
|
|
372
|
+
parameters: OpenCredentialActionParameters,
|
|
373
|
+
): Promise<SessionReceipt> {
|
|
374
|
+
const { store, client, challenge, payload, chainId, escrow } = parameters
|
|
375
|
+
const request = getChallengePaymentFields(challenge)
|
|
376
|
+
const expectedOperator = parameters.expectedOperator ?? zeroAddress
|
|
377
|
+
const cumulativeAmount = uint96(BigInt(payload.cumulativeAmount))
|
|
378
|
+
assertDescriptor(payload)
|
|
379
|
+
if (
|
|
380
|
+
payload.authorizedSigner !== undefined &&
|
|
381
|
+
!isAddressEqual(payload.authorizedSigner, payload.descriptor.authorizedSigner)
|
|
382
|
+
)
|
|
383
|
+
throw new VerificationFailedError({
|
|
384
|
+
reason: 'credential authorizedSigner does not match descriptor',
|
|
385
|
+
})
|
|
386
|
+
const channelId = ChannelStore.normalizeChannelId(payload.channelId)
|
|
387
|
+
validateChannelDescriptor(
|
|
388
|
+
payload.descriptor,
|
|
389
|
+
channelId,
|
|
390
|
+
chainId,
|
|
391
|
+
escrow,
|
|
392
|
+
request.recipient,
|
|
393
|
+
request.currency,
|
|
394
|
+
expectedOperator,
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
const result = await Chain.broadcastOpenTransaction({
|
|
398
|
+
challengeExpires: challenge.expires,
|
|
399
|
+
chainId,
|
|
400
|
+
client,
|
|
401
|
+
escrowContract: escrow,
|
|
402
|
+
expectedAuthorizedSigner: payload.descriptor.authorizedSigner,
|
|
403
|
+
expectedChannelId: channelId,
|
|
404
|
+
expectedCurrency: request.currency,
|
|
405
|
+
expectedOperator,
|
|
406
|
+
expectedPayee: request.recipient,
|
|
407
|
+
expectedExpiringNonceHash: payload.descriptor.expiringNonceHash,
|
|
408
|
+
expectedPayer: payload.descriptor.payer,
|
|
409
|
+
feePayer: parameters.feePayer,
|
|
410
|
+
feePayerPolicy: parameters.feePayerPolicy,
|
|
411
|
+
serializedTransaction: payload.transaction,
|
|
412
|
+
async beforeBroadcast(prepared) {
|
|
413
|
+
assertSameDescriptor(prepared.descriptor, payload.descriptor)
|
|
414
|
+
if (cumulativeAmount > prepared.openDeposit)
|
|
415
|
+
throw new AmountExceedsDepositError({ reason: 'voucher amount exceeds open deposit' })
|
|
416
|
+
const valid = await Voucher.verifyVoucher(
|
|
417
|
+
escrow,
|
|
418
|
+
chainId,
|
|
419
|
+
{ channelId, cumulativeAmount: cumulativeAmount, signature: payload.signature },
|
|
420
|
+
authorizedSigner(prepared.descriptor),
|
|
421
|
+
)
|
|
422
|
+
if (!valid) throw new InvalidSignatureError({ reason: 'invalid voucher signature' })
|
|
423
|
+
},
|
|
424
|
+
})
|
|
425
|
+
const { descriptor, state } = result
|
|
426
|
+
assertSameDescriptor(descriptor, payload.descriptor)
|
|
427
|
+
validateChannelState(state, request.amount)
|
|
428
|
+
|
|
429
|
+
const updated = await store.updateChannel(channelId, (current) =>
|
|
430
|
+
ChannelStore.openChannelState({
|
|
431
|
+
authorizedSigner: authorizedSigner(descriptor),
|
|
432
|
+
chainId,
|
|
433
|
+
channelId,
|
|
434
|
+
current,
|
|
435
|
+
descriptor,
|
|
436
|
+
escrow,
|
|
437
|
+
expiringNonceHash: result.expiringNonceHash,
|
|
438
|
+
cumulativeAmount,
|
|
439
|
+
signature: payload.signature,
|
|
440
|
+
state,
|
|
441
|
+
}),
|
|
442
|
+
)
|
|
443
|
+
if (!updated) throw new VerificationFailedError({ reason: 'failed to create channel' })
|
|
444
|
+
return createSessionReceipt({
|
|
445
|
+
challengeId: challenge.id,
|
|
446
|
+
channelId,
|
|
447
|
+
acceptedCumulative: updated.highestVoucherAmount,
|
|
448
|
+
spent: updated.spent,
|
|
449
|
+
units: updated.units,
|
|
450
|
+
txHash: result.txHash,
|
|
451
|
+
})
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
async function handleTopUpCredential(
|
|
455
|
+
parameters: TopUpCredentialActionParameters,
|
|
456
|
+
): Promise<SessionReceipt> {
|
|
457
|
+
const { store, client, challenge, payload, chainId, escrow } = parameters
|
|
458
|
+
const request = getChallengePaymentFields(challenge)
|
|
459
|
+
const expectedOperator = parameters.expectedOperator ?? zeroAddress
|
|
460
|
+
const additionalDeposit = uint96(BigInt(payload.additionalDeposit))
|
|
461
|
+
assertDescriptor(payload)
|
|
462
|
+
const channelId = ChannelStore.normalizeChannelId(payload.channelId)
|
|
463
|
+
validateChannelDescriptor(
|
|
464
|
+
payload.descriptor,
|
|
465
|
+
channelId,
|
|
466
|
+
chainId,
|
|
467
|
+
escrow,
|
|
468
|
+
request.recipient,
|
|
469
|
+
request.currency,
|
|
470
|
+
expectedOperator,
|
|
471
|
+
)
|
|
472
|
+
const channel = await ChannelStore.loadPrecompileChannel({
|
|
473
|
+
descriptor: payload.descriptor,
|
|
474
|
+
channelId,
|
|
475
|
+
chainId,
|
|
476
|
+
escrow,
|
|
477
|
+
store,
|
|
478
|
+
validateDescriptor: true,
|
|
479
|
+
})
|
|
480
|
+
const result = await Chain.broadcastTopUpTransaction({
|
|
481
|
+
additionalDeposit,
|
|
482
|
+
challengeExpires: challenge.expires,
|
|
483
|
+
chainId,
|
|
484
|
+
client,
|
|
485
|
+
descriptor: channel.descriptor,
|
|
486
|
+
escrowContract: escrow,
|
|
487
|
+
expectedChannelId: channelId,
|
|
488
|
+
expectedCurrency: request.currency,
|
|
489
|
+
feePayer: parameters.feePayer,
|
|
490
|
+
feePayerPolicy: parameters.feePayerPolicy,
|
|
491
|
+
serializedTransaction: payload.transaction,
|
|
492
|
+
})
|
|
493
|
+
const { state } = result
|
|
494
|
+
validateChannelState(state)
|
|
495
|
+
|
|
496
|
+
const updated = await store.updateChannel(channelId, (current) =>
|
|
497
|
+
ChannelStore.topUpChannelState({ current, state }),
|
|
498
|
+
)
|
|
499
|
+
return createSessionReceipt({
|
|
500
|
+
challengeId: challenge.id,
|
|
501
|
+
channelId,
|
|
502
|
+
acceptedCumulative: updated?.highestVoucherAmount ?? channel.highestVoucherAmount,
|
|
503
|
+
spent: updated?.spent ?? channel.spent,
|
|
504
|
+
units: updated?.units ?? channel.units,
|
|
505
|
+
txHash: result.txHash,
|
|
506
|
+
})
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
async function handleVoucherCredential(
|
|
510
|
+
parameters: VoucherCredentialActionParameters,
|
|
511
|
+
): Promise<SessionReceipt> {
|
|
512
|
+
const {
|
|
513
|
+
store,
|
|
514
|
+
client,
|
|
515
|
+
challenge,
|
|
516
|
+
payload,
|
|
517
|
+
chainId,
|
|
518
|
+
escrow,
|
|
519
|
+
minVoucherDelta,
|
|
520
|
+
channelStateTtl,
|
|
521
|
+
lastOnChainVerified,
|
|
522
|
+
} = parameters
|
|
523
|
+
const request = getChallengePaymentFields(challenge)
|
|
524
|
+
const expectedOperator = parameters.expectedOperator ?? zeroAddress
|
|
525
|
+
const channelId = ChannelStore.normalizeChannelId(payload.channelId)
|
|
526
|
+
const voucher = Voucher.parseVoucherFromPayload(
|
|
527
|
+
channelId,
|
|
528
|
+
payload.cumulativeAmount,
|
|
529
|
+
payload.signature,
|
|
530
|
+
)
|
|
531
|
+
assertDescriptor(payload)
|
|
532
|
+
validateChannelDescriptor(
|
|
533
|
+
payload.descriptor,
|
|
534
|
+
channelId,
|
|
535
|
+
chainId,
|
|
536
|
+
escrow,
|
|
537
|
+
request.recipient,
|
|
538
|
+
request.currency,
|
|
539
|
+
expectedOperator,
|
|
540
|
+
)
|
|
541
|
+
const channel = await ChannelStore.loadPrecompileChannel({
|
|
542
|
+
descriptor: payload.descriptor,
|
|
543
|
+
channelId,
|
|
544
|
+
chainId,
|
|
545
|
+
escrow,
|
|
546
|
+
store,
|
|
547
|
+
validateDescriptor: true,
|
|
548
|
+
})
|
|
549
|
+
if (channel.finalized) throw new ChannelClosedError({ reason: 'channel is finalized' })
|
|
550
|
+
const isStale = Date.now() - (lastOnChainVerified.get(channelId) ?? 0) > channelStateTtl
|
|
551
|
+
const state = isStale ? await Chain.getChannelState(client, channelId, escrow) : undefined
|
|
552
|
+
if (state) lastOnChainVerified.set(channelId, Date.now())
|
|
553
|
+
const channelState = {
|
|
554
|
+
deposit: state?.deposit ?? uint96(channel.deposit),
|
|
555
|
+
settled: state?.settled ?? uint96(channel.settledOnChain),
|
|
556
|
+
closeRequestedAt: state?.closeRequestedAt ?? Number(channel.closeRequestedAt),
|
|
557
|
+
}
|
|
558
|
+
if (channelState.closeRequestedAt !== 0) {
|
|
559
|
+
await store.updateChannel(channelId, (current) =>
|
|
560
|
+
current
|
|
561
|
+
? {
|
|
562
|
+
...current,
|
|
563
|
+
closeRequestedAt:
|
|
564
|
+
BigInt(channelState.closeRequestedAt) > current.closeRequestedAt
|
|
565
|
+
? BigInt(channelState.closeRequestedAt)
|
|
566
|
+
: current.closeRequestedAt,
|
|
567
|
+
}
|
|
568
|
+
: current,
|
|
569
|
+
)
|
|
570
|
+
}
|
|
571
|
+
return ChannelStore.verifyAndAcceptVoucher({
|
|
572
|
+
store,
|
|
573
|
+
minVoucherDelta,
|
|
574
|
+
challenge,
|
|
575
|
+
channel,
|
|
576
|
+
voucher,
|
|
577
|
+
channelState,
|
|
578
|
+
methodDetails: { chainId, escrowContract: escrow },
|
|
579
|
+
})
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
async function handleCloseCredential(
|
|
583
|
+
parameters: CloseCredentialActionParameters,
|
|
584
|
+
): Promise<SessionReceipt> {
|
|
585
|
+
const { store, client, challenge, payload, chainId, escrow } = parameters
|
|
586
|
+
const request = getChallengePaymentFields(challenge)
|
|
587
|
+
const expectedOperator = parameters.expectedOperator ?? zeroAddress
|
|
588
|
+
const cumulativeAmount = uint96(BigInt(payload.cumulativeAmount))
|
|
589
|
+
const channelId = ChannelStore.normalizeChannelId(payload.channelId)
|
|
590
|
+
assertDescriptor(payload)
|
|
591
|
+
validateChannelDescriptor(
|
|
592
|
+
payload.descriptor,
|
|
593
|
+
channelId,
|
|
594
|
+
chainId,
|
|
595
|
+
escrow,
|
|
596
|
+
request.recipient,
|
|
597
|
+
request.currency,
|
|
598
|
+
expectedOperator,
|
|
599
|
+
)
|
|
600
|
+
const channel = await ChannelStore.loadPrecompileChannel({
|
|
601
|
+
descriptor: payload.descriptor,
|
|
602
|
+
channelId,
|
|
603
|
+
chainId,
|
|
604
|
+
escrow,
|
|
605
|
+
store,
|
|
606
|
+
})
|
|
607
|
+
if (channel.finalized) throw new ChannelClosedError({ reason: 'channel is already finalized' })
|
|
608
|
+
const state = await Chain.getChannelState(client, channelId, escrow)
|
|
609
|
+
if (state.closeRequestedAt !== 0)
|
|
610
|
+
throw new ChannelClosedError({ reason: 'channel has a pending close request' })
|
|
611
|
+
if (state.deposit === 0n && (cumulativeAmount !== 0n || channel.spent !== 0n))
|
|
612
|
+
throw new ChannelClosedError({ reason: 'channel deposit is zero (settled)' })
|
|
613
|
+
if (cumulativeAmount < channel.spent)
|
|
614
|
+
throw new VerificationFailedError({
|
|
615
|
+
reason: `close voucher amount must be >= ${channel.spent} (spent)`,
|
|
616
|
+
})
|
|
617
|
+
if (cumulativeAmount < state.settled)
|
|
618
|
+
throw new VerificationFailedError({
|
|
619
|
+
reason: `close voucher amount must be >= ${state.settled} (on-chain settled)`,
|
|
620
|
+
})
|
|
621
|
+
const valid = await Voucher.verifyVoucher(
|
|
622
|
+
escrow,
|
|
623
|
+
chainId,
|
|
624
|
+
{ channelId, cumulativeAmount: cumulativeAmount, signature: payload.signature },
|
|
625
|
+
channel.authorizedSigner,
|
|
626
|
+
)
|
|
627
|
+
if (!valid) throw new InvalidSignatureError({ reason: 'invalid voucher signature' })
|
|
628
|
+
let captureAmount = uint96(channel.spent > state.settled ? channel.spent : state.settled)
|
|
629
|
+
if (captureAmount > state.deposit)
|
|
630
|
+
throw new AmountExceedsDepositError({ reason: 'close capture amount exceeds on-chain deposit' })
|
|
631
|
+
const pendingCloseStartedAt = BigInt(Math.floor(Date.now() / 1000) || 1)
|
|
632
|
+
const previousCloseRequestedAt = channel.closeRequestedAt
|
|
633
|
+
let pendingCloseMarked = false
|
|
634
|
+
await store.updateChannel(channelId, (current) => {
|
|
635
|
+
const next = ChannelStore.markPendingClose({
|
|
636
|
+
closeRequestedAt: pendingCloseStartedAt,
|
|
637
|
+
cumulativeAmount,
|
|
638
|
+
current,
|
|
639
|
+
onChainDeposit: state.deposit,
|
|
640
|
+
onChainSettled: state.settled,
|
|
641
|
+
})
|
|
642
|
+
if (next.state) {
|
|
643
|
+
captureAmount = next.captureAmount
|
|
644
|
+
pendingCloseMarked = true
|
|
645
|
+
}
|
|
646
|
+
return next.state
|
|
647
|
+
})
|
|
648
|
+
const account = parameters.account ?? getClientAccount(client)
|
|
649
|
+
let txHash: Hex | undefined
|
|
650
|
+
let receipt: Awaited<ReturnType<typeof Chain.waitForSuccessfulReceipt>>
|
|
651
|
+
try {
|
|
652
|
+
assertSettlementSender({
|
|
653
|
+
operation: 'close',
|
|
654
|
+
channelId,
|
|
655
|
+
operator: channel.operator,
|
|
656
|
+
payee: channel.payee,
|
|
657
|
+
sender: account?.address,
|
|
658
|
+
})
|
|
659
|
+
txHash = await Chain.closeOnChain(
|
|
660
|
+
client,
|
|
661
|
+
channel.descriptor,
|
|
662
|
+
cumulativeAmount,
|
|
663
|
+
captureAmount,
|
|
664
|
+
payload.signature,
|
|
665
|
+
escrow,
|
|
666
|
+
account
|
|
667
|
+
? {
|
|
668
|
+
account,
|
|
669
|
+
...(parameters.feePayer ? { feePayer: parameters.feePayer } : {}),
|
|
670
|
+
...(parameters.feePayerPolicy ? { feePayerPolicy: parameters.feePayerPolicy } : {}),
|
|
671
|
+
...(parameters.feeToken ? { feeToken: parameters.feeToken } : {}),
|
|
672
|
+
candidateFeeTokens: [channel.token],
|
|
673
|
+
}
|
|
674
|
+
: undefined,
|
|
675
|
+
)
|
|
676
|
+
receipt = await Chain.waitForSuccessfulReceipt(client, txHash)
|
|
677
|
+
} catch (error) {
|
|
678
|
+
if (pendingCloseMarked) {
|
|
679
|
+
await store.updateChannel(channelId, (current) =>
|
|
680
|
+
current && current.closeRequestedAt === pendingCloseStartedAt
|
|
681
|
+
? { ...current, closeRequestedAt: previousCloseRequestedAt }
|
|
682
|
+
: current,
|
|
683
|
+
)
|
|
684
|
+
}
|
|
685
|
+
throw error
|
|
686
|
+
}
|
|
687
|
+
const closed = readChannelClosedReceiptFields(
|
|
688
|
+
Chain.getChannelEvent(receipt, 'ChannelClosed', channelId),
|
|
689
|
+
)
|
|
690
|
+
const { refundedToPayer, settledToPayee } = closed
|
|
691
|
+
if (settledToPayee > captureAmount || settledToPayee + refundedToPayer > state.deposit)
|
|
692
|
+
throw new VerificationFailedError({ reason: 'ChannelClosed amounts do not match state' })
|
|
693
|
+
const updated = await store.updateChannel(channelId, (current) =>
|
|
694
|
+
ChannelStore.finalizeClosedChannelState({
|
|
695
|
+
captureAmount,
|
|
696
|
+
channelId,
|
|
697
|
+
cumulativeAmount,
|
|
698
|
+
current,
|
|
699
|
+
signature: payload.signature,
|
|
700
|
+
}),
|
|
701
|
+
)
|
|
702
|
+
return createSessionReceipt({
|
|
703
|
+
challengeId: challenge.id,
|
|
704
|
+
channelId,
|
|
705
|
+
acceptedCumulative: cumulativeAmount,
|
|
706
|
+
spent: updated?.spent ?? channel.spent,
|
|
707
|
+
units: updated?.units ?? channel.units,
|
|
708
|
+
txHash,
|
|
709
|
+
})
|
|
710
|
+
}
|