mppx 0.7.0 → 0.8.1
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 +41 -0
- package/README.md +20 -11
- package/dist/Challenge.d.ts.map +1 -1
- package/dist/Challenge.js +18 -6
- package/dist/Challenge.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/PaymentRequest.d.ts +10 -10
- package/dist/PaymentRequest.js +8 -8
- package/dist/cli/internal.d.ts +1 -0
- package/dist/cli/internal.d.ts.map +1 -1
- package/dist/cli/internal.js +1 -15
- package/dist/cli/internal.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 -75
- package/dist/client/Transport.js.map +1 -1
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal/Fetch.d.ts.map +1 -1
- package/dist/client/internal/Fetch.js +46 -7
- 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/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/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 +1 -1
- package/dist/server/Mppx.d.ts.map +1 -1
- package/dist/server/Mppx.js +9 -0
- package/dist/server/Mppx.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 +1 -1
- package/dist/server/Transport.js.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/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 +13 -1
- package/dist/tempo/client/Charge.d.ts.map +1 -1
- package/dist/tempo/client/Charge.js +38 -25
- package/dist/tempo/client/Charge.js.map +1 -1
- package/dist/tempo/client/Methods.d.ts +5 -3
- package/dist/tempo/client/Methods.d.ts.map +1 -1
- package/dist/tempo/client/Methods.js +4 -2
- 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/internal/fee-payer.d.ts +26 -1
- package/dist/tempo/internal/fee-payer.d.ts.map +1 -1
- package/dist/tempo/internal/fee-payer.js +83 -30
- 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/legacy/client/SessionManager.d.ts.map +1 -1
- package/dist/tempo/legacy/client/SessionManager.js +10 -3
- package/dist/tempo/legacy/client/SessionManager.js.map +1 -1
- package/dist/tempo/server/Charge.d.ts.map +1 -1
- package/dist/tempo/server/Charge.js +46 -18
- package/dist/tempo/server/Charge.js.map +1 -1
- package/dist/tempo/server/Methods.d.ts +4 -2
- package/dist/tempo/server/Methods.d.ts.map +1 -1
- package/dist/tempo/server/Methods.js +4 -2
- package/dist/tempo/server/Methods.js.map +1 -1
- package/dist/tempo/server/Subscription.d.ts +10 -0
- 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/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/session/client/ChannelOps.d.ts +2 -3
- package/dist/tempo/session/client/ChannelOps.d.ts.map +1 -1
- package/dist/tempo/session/client/ChannelOps.js +7 -10
- package/dist/tempo/session/client/ChannelOps.js.map +1 -1
- 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 +7 -24
- package/dist/tempo/session/client/CredentialState.d.ts.map +1 -1
- package/dist/tempo/session/client/CredentialState.js +51 -49
- package/dist/tempo/session/client/CredentialState.js.map +1 -1
- package/dist/tempo/session/client/Session.d.ts +8 -2
- package/dist/tempo/session/client/Session.d.ts.map +1 -1
- package/dist/tempo/session/client/Session.js +22 -8
- package/dist/tempo/session/client/Session.js.map +1 -1
- package/dist/tempo/session/client/SessionManager.d.ts +4 -40
- package/dist/tempo/session/client/SessionManager.d.ts.map +1 -1
- package/dist/tempo/session/client/SessionManager.js +124 -174
- package/dist/tempo/session/client/SessionManager.js.map +1 -1
- package/dist/tempo/session/client/index.d.ts +3 -4
- package/dist/tempo/session/client/index.d.ts.map +1 -1
- package/dist/tempo/session/client/index.js +1 -0
- package/dist/tempo/session/client/index.js.map +1 -1
- package/dist/tempo/session/precompile/Voucher.d.ts +3 -3
- package/dist/tempo/session/precompile/Voucher.d.ts.map +1 -1
- package/dist/tempo/session/precompile/Voucher.js +24 -25
- package/dist/tempo/session/precompile/Voucher.js.map +1 -1
- package/dist/tempo/session/server/CredentialVerification.d.ts +6 -0
- package/dist/tempo/session/server/CredentialVerification.d.ts.map +1 -1
- package/dist/tempo/session/server/CredentialVerification.js +13 -0
- package/dist/tempo/session/server/CredentialVerification.js.map +1 -1
- package/dist/tempo/session/server/Settlement.d.ts.map +1 -1
- package/dist/tempo/session/server/Settlement.js +4 -2
- package/dist/tempo/session/server/Settlement.js.map +1 -1
- package/dist/tempo/session/server/Sse.d.ts.map +1 -1
- package/dist/tempo/session/server/Sse.js.map +1 -1
- package/dist/tempo/session/server/Ws.d.ts.map +1 -1
- package/dist/tempo/session/server/Ws.js.map +1 -1
- 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 +21 -10
- package/src/Challenge.test.ts +40 -0
- package/src/Challenge.ts +19 -6
- package/src/Mcp.ts +4 -0
- package/src/PaymentRequest.ts +10 -10
- package/src/cli/cli.test.ts +15 -15
- package/src/cli/config.test.ts +13 -7
- package/src/cli/internal.ts +1 -16
- package/src/client/Mppx.test-d.ts +21 -1
- package/src/client/Mppx.test.ts +1 -1
- package/src/client/Mppx.ts +2 -2
- package/src/client/Transport.test.ts +225 -178
- package/src/client/Transport.ts +77 -83
- package/src/client/index.ts +14 -0
- package/src/client/internal/Fetch.test.ts +207 -2
- package/src/client/internal/Fetch.ts +52 -6
- 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/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/{mcp-sdk → mcp}/client/McpClient.integration.test.ts +10 -4
- package/src/{mcp-sdk → mcp}/client/McpClient.test-d.ts +45 -18
- package/src/{mcp-sdk → mcp}/client/McpClient.test.ts +211 -5
- package/src/mcp/client/McpClient.ts +307 -0
- package/src/{mcp-sdk → mcp}/client/McpClient.unit.test.ts +9 -5
- package/src/middlewares/elysia.test.ts +1 -1
- package/src/middlewares/express.test.ts +1 -1
- package/src/middlewares/hono.test.ts +1 -1
- package/src/middlewares/internal/mppx.test.ts +1 -1
- package/src/middlewares/nextjs.test.ts +1 -1
- package/src/proxy/Proxy.test.ts +1 -1
- 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 +1 -1
- package/src/server/Mppx.test.ts +20 -2
- package/src/server/Mppx.ts +14 -1
- package/src/server/Transport.test.ts +6 -6
- package/src/server/Transport.ts +1 -1
- package/src/stripe/Charge.integration.test.ts +1 -1
- package/src/stripe/client/Charge.test.ts +1 -1
- package/src/stripe/server/Charge.test.ts +1 -1
- package/src/stripe/server/internal/html/package.json +1 -1
- package/src/stripe/server/internal/html.gen.ts +1 -1
- 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/Subscription.integration.test.ts +1 -1
- package/src/tempo/client/Charge.test.ts +173 -0
- package/src/tempo/client/Charge.ts +65 -36
- package/src/tempo/client/Methods.ts +4 -2
- package/src/tempo/client/ResolveAccount.ts +46 -0
- package/src/tempo/internal/fee-payer.test.ts +89 -10
- package/src/tempo/internal/fee-payer.ts +128 -41
- package/src/tempo/internal/proof.test.ts +12 -4
- package/src/tempo/internal/proof.ts +55 -6
- package/src/tempo/legacy/client/SessionManager.ts +11 -3
- package/src/tempo/legacy/server/Session.test.ts +91 -26
- package/src/tempo/server/Charge.test.ts +388 -17
- package/src/tempo/server/Charge.ts +50 -24
- package/src/tempo/server/Methods.ts +4 -2
- package/src/tempo/server/Subscription.test.ts +465 -3
- package/src/tempo/server/Subscription.ts +174 -19
- package/src/tempo/server/internal/html/package.json +2 -2
- package/src/tempo/server/internal/html.gen.ts +1 -1
- package/src/tempo/session/client/ChannelOps.ts +5 -19
- package/src/tempo/session/client/ChannelStore.ts +111 -0
- package/src/tempo/session/client/CredentialState.test.ts +206 -62
- package/src/tempo/session/client/CredentialState.ts +58 -73
- package/src/tempo/session/client/Session.test.ts +41 -1
- package/src/tempo/session/client/Session.ts +36 -10
- package/src/tempo/session/client/SessionManager.test.ts +154 -65
- package/src/tempo/session/client/SessionManager.ts +141 -235
- package/src/tempo/session/client/index.ts +8 -5
- package/src/tempo/session/precompile/Voucher.test.ts +45 -7
- package/src/tempo/session/precompile/Voucher.ts +27 -25
- package/src/tempo/session/server/CredentialVerification.test.ts +36 -0
- package/src/tempo/session/server/CredentialVerification.ts +18 -0
- package/src/tempo/session/server/Session.test.ts +4 -4
- package/src/tempo/session/server/Settlement.test.ts +88 -1
- package/src/tempo/session/server/Settlement.ts +2 -1
- package/src/tempo/session/server/Sse.ts +0 -2
- package/src/tempo/session/server/Ws.ts +0 -4
- 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 -85
- package/dist/mcp-sdk/client/McpClient.d.ts.map +0 -1
- package/dist/mcp-sdk/client/McpClient.js +0 -118
- 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/src/mcp-sdk/client/McpClient.ts +0 -228
- /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/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
|
@@ -8,9 +8,9 @@ import type * as Account from '../../../viem/Account.js'
|
|
|
8
8
|
import type * as Client from '../../../viem/Client.js'
|
|
9
9
|
import { charge as chargePlugin } from '../../client/Charge.js'
|
|
10
10
|
import type { ChannelEntry } from '../client/ChannelOps.js'
|
|
11
|
+
import { createChannelStore, entryKey, type ChannelStore } from '../client/ChannelStore.js'
|
|
11
12
|
import type { SessionContext } from '../client/CredentialState.js'
|
|
12
13
|
import { session as sessionPlugin } from '../client/Session.js'
|
|
13
|
-
import type { ChannelDescriptor } from '../precompile/Protocol.js'
|
|
14
14
|
import { deserializeSessionReceipt } from '../precompile/Protocol.js'
|
|
15
15
|
import { readSessionChallengeAmount, type SessionReceipt } from '../precompile/Protocol.js'
|
|
16
16
|
import {
|
|
@@ -34,7 +34,6 @@ import {
|
|
|
34
34
|
import { closeSocketSession } from './Runtime.js'
|
|
35
35
|
import {
|
|
36
36
|
closeHttpSession,
|
|
37
|
-
getSessionSnapshot,
|
|
38
37
|
isTempoSessionChallenge,
|
|
39
38
|
managementInput,
|
|
40
39
|
postTopUp,
|
|
@@ -98,36 +97,6 @@ export type PaymentResponse = Response & {
|
|
|
98
97
|
cumulative: bigint
|
|
99
98
|
}
|
|
100
99
|
|
|
101
|
-
/** Serializable client-side channel snapshot stored between manager instances. */
|
|
102
|
-
export type StoredSessionChannel = {
|
|
103
|
-
/** Latest known channel ID. Used as the next request's channel hint. */
|
|
104
|
-
channelId: Hex.Hex
|
|
105
|
-
/** Latest local cumulative voucher authorization in raw token units. */
|
|
106
|
-
cumulativeAmount: string
|
|
107
|
-
/** Latest known deposit in raw token units. */
|
|
108
|
-
deposit: string
|
|
109
|
-
/** TIP-1034 channel descriptor, used as a fallback when the server cannot snapshot. */
|
|
110
|
-
descriptor: ChannelDescriptor
|
|
111
|
-
/** Escrow address used to derive the channel ID. */
|
|
112
|
-
escrow: Address
|
|
113
|
-
/** Chain ID used to derive the channel ID. */
|
|
114
|
-
chainId: number
|
|
115
|
-
/** Whether the channel was open when stored. Closed channels are not used as hints. */
|
|
116
|
-
opened: boolean
|
|
117
|
-
/** Client timestamp for debugging or app-level eviction. */
|
|
118
|
-
updatedAt: number
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/** Optional per-manager store for channel hints and restart recovery. */
|
|
122
|
-
export type SessionStore = {
|
|
123
|
-
/** Reads the latest stored channel snapshot for this manager scope. */
|
|
124
|
-
get(): Promise<StoredSessionChannel | null | undefined> | StoredSessionChannel | null | undefined
|
|
125
|
-
/** Persists the latest channel snapshot. */
|
|
126
|
-
set(channel: StoredSessionChannel): Promise<void> | void
|
|
127
|
-
/** Deletes the stored snapshot when a channel is closed, when supported. */
|
|
128
|
-
delete?(): Promise<void> | void
|
|
129
|
-
}
|
|
130
|
-
|
|
131
100
|
/** Normalized runtime dependencies derived from `sessionManager()` parameters. */
|
|
132
101
|
type SessionManagerConfig = {
|
|
133
102
|
/** Decimal precision used when parsing human-readable manager amounts. */
|
|
@@ -156,65 +125,16 @@ function isZeroAmountChargeChallenge(challenge: Challenge.Challenge) {
|
|
|
156
125
|
}
|
|
157
126
|
}
|
|
158
127
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
channelId: entry.channelId,
|
|
162
|
-
cumulativeAmount: entry.cumulativeAmount.toString(),
|
|
163
|
-
deposit: entry.deposit.toString(),
|
|
164
|
-
descriptor: entry.descriptor,
|
|
165
|
-
escrow: entry.escrow,
|
|
166
|
-
chainId: entry.chainId,
|
|
167
|
-
opened: entry.opened,
|
|
168
|
-
updatedAt: Date.now(),
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function storedChannelContext(channel: StoredSessionChannel): SessionContext {
|
|
173
|
-
return {
|
|
174
|
-
channelId: channel.channelId,
|
|
175
|
-
cumulativeAmountRaw: channel.cumulativeAmount,
|
|
176
|
-
descriptor: channel.descriptor,
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
function storedChannelFromSnapshot(
|
|
181
|
-
snapshot: ReturnType<typeof deserializeSessionSnapshot>,
|
|
182
|
-
): StoredSessionChannel {
|
|
128
|
+
/** Builds a reusable channel entry from a server session snapshot header. */
|
|
129
|
+
function entryFromSnapshot(snapshot: ReturnType<typeof deserializeSessionSnapshot>): ChannelEntry {
|
|
183
130
|
return {
|
|
184
131
|
channelId: snapshot.channelId,
|
|
185
|
-
cumulativeAmount: snapshot.acceptedCumulative,
|
|
186
|
-
deposit: snapshot.deposit,
|
|
132
|
+
cumulativeAmount: BigInt(snapshot.acceptedCumulative),
|
|
133
|
+
deposit: BigInt(snapshot.deposit),
|
|
187
134
|
descriptor: snapshot.descriptor,
|
|
188
135
|
escrow: snapshot.escrow,
|
|
189
136
|
chainId: snapshot.chainId,
|
|
190
137
|
opened: true,
|
|
191
|
-
updatedAt: Date.now(),
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
type CredentialContextResolution = {
|
|
196
|
-
context: SessionContext
|
|
197
|
-
usedStoredChannel: boolean
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
function resolveCredentialContext(parameters: {
|
|
201
|
-
channel: ChannelEntry | null
|
|
202
|
-
challenge: TempoSessionChallenge
|
|
203
|
-
context: SessionContext
|
|
204
|
-
storedChannel: StoredSessionChannel | null
|
|
205
|
-
}): CredentialContextResolution {
|
|
206
|
-
const { channel, challenge, context, storedChannel } = parameters
|
|
207
|
-
if (
|
|
208
|
-
context.action ||
|
|
209
|
-
channel?.opened ||
|
|
210
|
-
!storedChannel?.opened ||
|
|
211
|
-
getSessionSnapshot(challenge)
|
|
212
|
-
) {
|
|
213
|
-
return { context, usedStoredChannel: false }
|
|
214
|
-
}
|
|
215
|
-
return {
|
|
216
|
-
context: { ...context, ...storedChannelContext(storedChannel) },
|
|
217
|
-
usedStoredChannel: true,
|
|
218
138
|
}
|
|
219
139
|
}
|
|
220
140
|
|
|
@@ -267,40 +187,71 @@ function resolveSessionManagerConfig(parameters: sessionManager.Parameters): Ses
|
|
|
267
187
|
* channel state management and credential creation, and to `Fetch.from`
|
|
268
188
|
* for the 402 challenge/retry flow.
|
|
269
189
|
*
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
* The manager only keeps active client transport state in memory. Channel
|
|
273
|
-
* descriptors and cumulative voucher state are hydrated from server snapshots
|
|
274
|
-
* when challenges include them; otherwise the next request opens a fresh
|
|
275
|
-
* TIP-1034 channel. `maxDeposit` remains the local cap for all automatic
|
|
276
|
-
* voucher and top-up decisions.
|
|
190
|
+
* `channelStore` can persist reusable channels between manager instances.
|
|
277
191
|
*/
|
|
278
192
|
export function sessionManager(parameters: sessionManager.Parameters): SessionManager {
|
|
279
193
|
const config = resolveSessionManagerConfig(parameters)
|
|
280
|
-
const sessionStore = parameters.sessionStore
|
|
281
|
-
let storedChannel: StoredSessionChannel | null = null
|
|
282
|
-
let bootstrapChannelId: Hex.Hex | null = null
|
|
283
|
-
const ignoredStoredChannelIds = new Set<Hex.Hex>()
|
|
284
194
|
const runtime = createSessionManagerRuntime()
|
|
285
195
|
const receipts = createSessionReceiptCoordinator({
|
|
286
196
|
getSocketSession: () => runtime.socketSession,
|
|
287
197
|
})
|
|
288
198
|
|
|
199
|
+
const backing = parameters.channelStore ?? createChannelStore()
|
|
200
|
+
const ignoredChannelIds = new Set<Hex.Hex>()
|
|
201
|
+
|
|
202
|
+
// Tracks one fetch's channel reuse so stale stored entries can be evicted once.
|
|
203
|
+
type ChannelUse = {
|
|
204
|
+
seenExisting: Set<string>
|
|
205
|
+
createdKeys: Set<string>
|
|
206
|
+
resumed: ChannelEntry | undefined
|
|
207
|
+
}
|
|
208
|
+
let channelUse: ChannelUse | undefined
|
|
209
|
+
|
|
210
|
+
/** Returns the backing entry for `key` only when it is open and not ignored. */
|
|
211
|
+
async function getReusable(key: string): Promise<ChannelEntry | undefined> {
|
|
212
|
+
const entry = await backing.get(key)
|
|
213
|
+
if (entry?.opened && !ignoredChannelIds.has(entry.channelId)) return entry
|
|
214
|
+
return undefined
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const store: ChannelStore = {
|
|
218
|
+
async get(key) {
|
|
219
|
+
const entry = await getReusable(key)
|
|
220
|
+
if (entry && channelUse) {
|
|
221
|
+
channelUse.seenExisting.add(key)
|
|
222
|
+
if (!channelUse.createdKeys.has(key)) channelUse.resumed ??= entry
|
|
223
|
+
}
|
|
224
|
+
return entry
|
|
225
|
+
},
|
|
226
|
+
async set(entry) {
|
|
227
|
+
const key = entryKey(entry)
|
|
228
|
+
if (entry.opened) ignoredChannelIds.delete(entry.channelId)
|
|
229
|
+
if (channelUse && !channelUse.seenExisting.has(key)) channelUse.createdKeys.add(key)
|
|
230
|
+
await backing.set(entry)
|
|
231
|
+
},
|
|
232
|
+
delete: (key) => backing.delete(key),
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/** Removes a failed channel from candidacy for the rest of this manager's life. */
|
|
236
|
+
async function ignoreChannel(entry: ChannelEntry) {
|
|
237
|
+
ignoredChannelIds.add(entry.channelId)
|
|
238
|
+
await Promise.resolve(backing.delete(entryKey(entry))).catch(() => undefined)
|
|
239
|
+
}
|
|
240
|
+
|
|
289
241
|
function dispatch(event: Parameters<typeof dispatchSessionEvent>[1]) {
|
|
290
242
|
return dispatchSessionEvent(runtime, event)
|
|
291
243
|
}
|
|
292
244
|
|
|
293
245
|
const method = sessionPlugin({
|
|
294
246
|
account: parameters.account,
|
|
295
|
-
authorizedSigner: parameters.authorizedSigner,
|
|
296
247
|
getClient: parameters.client ? () => parameters.client! : parameters.getClient,
|
|
297
248
|
escrow: parameters.escrow,
|
|
298
249
|
decimals: config.decimals,
|
|
299
250
|
maxDeposit: parameters.maxDeposit,
|
|
251
|
+
channelStore: store,
|
|
300
252
|
onChannelUpdate(entry) {
|
|
301
253
|
if (entry.channelId !== runtime.channel?.channelId) runtime.spent = 0n
|
|
302
254
|
runtime.channel = entry
|
|
303
|
-
persistStoredChannel(entry)
|
|
304
255
|
if (runtime.lastChallenge) {
|
|
305
256
|
dispatch({
|
|
306
257
|
type: 'activated',
|
|
@@ -335,28 +286,12 @@ export function sessionManager(parameters: sessionManager.Parameters): SessionMa
|
|
|
335
286
|
requiredCumulative,
|
|
336
287
|
})
|
|
337
288
|
}
|
|
338
|
-
const resolved = resolveCredentialContext({
|
|
339
|
-
challenge,
|
|
340
|
-
channel: runtime.channel,
|
|
341
|
-
context: {},
|
|
342
|
-
storedChannel,
|
|
343
|
-
})
|
|
344
|
-
if (resolved.usedStoredChannel) return _helpers.createCredential(resolved.context)
|
|
345
289
|
return undefined
|
|
346
290
|
},
|
|
347
291
|
})
|
|
348
292
|
|
|
349
293
|
function createSessionCredential(challenge: TempoSessionChallenge, context: SessionContext) {
|
|
350
|
-
|
|
351
|
-
challenge,
|
|
352
|
-
channel: runtime.channel,
|
|
353
|
-
context,
|
|
354
|
-
storedChannel,
|
|
355
|
-
})
|
|
356
|
-
return method.createCredential({
|
|
357
|
-
challenge,
|
|
358
|
-
context: resolved.context,
|
|
359
|
-
})
|
|
294
|
+
return method.createCredential({ challenge, context })
|
|
360
295
|
}
|
|
361
296
|
|
|
362
297
|
function updateSpentFromReceipt(receipt: SessionReceipt | null | undefined) {
|
|
@@ -386,50 +321,21 @@ export function sessionManager(parameters: sessionManager.Parameters): SessionMa
|
|
|
386
321
|
})
|
|
387
322
|
}
|
|
388
323
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
if (storedChannel) return storedChannel
|
|
392
|
-
const channel = await sessionStore.get()
|
|
393
|
-
storedChannel =
|
|
394
|
-
channel?.opened && !ignoredStoredChannelIds.has(channel.channelId) ? channel : null
|
|
395
|
-
return storedChannel
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
async function clearStoredChannel() {
|
|
399
|
-
if (!sessionStore) {
|
|
400
|
-
storedChannel = null
|
|
401
|
-
bootstrapChannelId = null
|
|
402
|
-
return
|
|
403
|
-
}
|
|
404
|
-
const channel = storedChannel
|
|
405
|
-
if (channel) ignoredStoredChannelIds.add(channel.channelId)
|
|
406
|
-
storedChannel = null
|
|
407
|
-
bootstrapChannelId = null
|
|
408
|
-
if (sessionStore.delete) {
|
|
409
|
-
await Promise.resolve(sessionStore.delete()).catch(() => undefined)
|
|
410
|
-
return
|
|
411
|
-
}
|
|
412
|
-
if (channel) {
|
|
413
|
-
await Promise.resolve(
|
|
414
|
-
sessionStore.set({ ...channel, opened: false, updatedAt: Date.now() }),
|
|
415
|
-
).catch(() => undefined)
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
async function storeSnapshotHeader(response: Response) {
|
|
324
|
+
/** Persists a server snapshot into the channel store and returns the entry. */
|
|
325
|
+
async function storeSnapshotHeader(response: Response): Promise<ChannelEntry | undefined> {
|
|
420
326
|
const header = response.headers.get(Constants.Headers.paymentSessionSnapshot)
|
|
421
|
-
if (!header) return
|
|
422
|
-
const
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
storedChannel = channel
|
|
426
|
-
if (sessionStore) await Promise.resolve(sessionStore.set(channel)).catch(() => undefined)
|
|
327
|
+
if (!header) return undefined
|
|
328
|
+
const entry = entryFromSnapshot(deserializeSessionSnapshot(header))
|
|
329
|
+
await Promise.resolve(store.set(entry)).catch(() => undefined)
|
|
330
|
+
return entry
|
|
427
331
|
}
|
|
428
332
|
|
|
429
|
-
async function bootstrapSession(
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
333
|
+
async function bootstrapSession(
|
|
334
|
+
input: RequestInfo | URL,
|
|
335
|
+
init?: RequestInit | undefined,
|
|
336
|
+
): Promise<ChannelEntry | undefined> {
|
|
337
|
+
if (!parameters.bootstrap) return undefined
|
|
338
|
+
if (runtime.channel?.opened) return undefined
|
|
433
339
|
|
|
434
340
|
const requestHeaders = input instanceof Request ? input.headers : undefined
|
|
435
341
|
const { body: _body, method: _method, ...bootstrapInit } = init ?? {}
|
|
@@ -446,13 +352,10 @@ export function sessionManager(parameters: sessionManager.Parameters): SessionMa
|
|
|
446
352
|
|
|
447
353
|
try {
|
|
448
354
|
const challengeResponse = await config.fetch(bootstrapInput, headInit)
|
|
449
|
-
if (challengeResponse.status !== 402)
|
|
450
|
-
await storeSnapshotHeader(challengeResponse)
|
|
451
|
-
return
|
|
452
|
-
}
|
|
355
|
+
if (challengeResponse.status !== 402) return await storeSnapshotHeader(challengeResponse)
|
|
453
356
|
const challenge = Challenge.fromResponseList(challengeResponse).find(isTempoChargeChallenge)
|
|
454
|
-
if (!challenge) return
|
|
455
|
-
if (!isZeroAmountChargeChallenge(challenge)) return
|
|
357
|
+
if (!challenge) return undefined
|
|
358
|
+
if (!isZeroAmountChargeChallenge(challenge)) return undefined
|
|
456
359
|
const credential = await chargeMethod.createCredential({
|
|
457
360
|
challenge: challenge as never,
|
|
458
361
|
context: {},
|
|
@@ -464,22 +367,13 @@ export function sessionManager(parameters: sessionManager.Parameters): SessionMa
|
|
|
464
367
|
[Constants.Headers.authorization]: credential,
|
|
465
368
|
},
|
|
466
369
|
})
|
|
467
|
-
if (response.ok) await storeSnapshotHeader(response)
|
|
370
|
+
if (response.ok) return await storeSnapshotHeader(response)
|
|
371
|
+
return undefined
|
|
468
372
|
} catch {
|
|
469
|
-
return
|
|
373
|
+
return undefined
|
|
470
374
|
}
|
|
471
375
|
}
|
|
472
376
|
|
|
473
|
-
function persistStoredChannel(entry: ChannelEntry) {
|
|
474
|
-
if (!sessionStore) return
|
|
475
|
-
const channel = storedChannelFromEntry(entry)
|
|
476
|
-
ignoredStoredChannelIds.delete(channel.channelId)
|
|
477
|
-
const operation =
|
|
478
|
-
entry.opened || !sessionStore.delete ? sessionStore.set(channel) : sessionStore.delete()
|
|
479
|
-
void Promise.resolve(operation).catch(() => undefined)
|
|
480
|
-
storedChannel = entry.opened ? channel : null
|
|
481
|
-
}
|
|
482
|
-
|
|
483
377
|
function getFallbackCloseAmount(challenge: TempoSessionChallenge, channelId: Hex.Hex): bigint {
|
|
484
378
|
const currentSocket = runtime.socketSession
|
|
485
379
|
return computeFallbackCloseAmount({
|
|
@@ -597,68 +491,83 @@ export function sessionManager(parameters: sessionManager.Parameters): SessionMa
|
|
|
597
491
|
}
|
|
598
492
|
|
|
599
493
|
async function doFetch(input: RequestInfo | URL, init?: RequestInit): Promise<PaymentResponse> {
|
|
494
|
+
// The manager drives one shared `runtime` state machine, so requests are
|
|
495
|
+
// single-flight. Reject overlap loudly instead of letting concurrent calls
|
|
496
|
+
// corrupt each other's runtime and channel tracking.
|
|
497
|
+
if (channelUse)
|
|
498
|
+
throw new Error(
|
|
499
|
+
'SessionManager: a request is already in flight; concurrent requests on one manager are not supported',
|
|
500
|
+
)
|
|
501
|
+
const use: ChannelUse = { seenExisting: new Set(), createdKeys: new Set(), resumed: undefined }
|
|
502
|
+
channelUse = use
|
|
503
|
+
|
|
600
504
|
runtime.lastUrl = input
|
|
601
|
-
|
|
602
|
-
await bootstrapSession(input, init)
|
|
603
|
-
const hintedInit = requestInitWithSessionHint(
|
|
604
|
-
input,
|
|
605
|
-
init,
|
|
606
|
-
(await getStoredChannel())?.channelId ?? bootstrapChannelId ?? stored?.channelId,
|
|
607
|
-
)
|
|
505
|
+
|
|
608
506
|
const previous = captureRuntimeStateSnapshot({
|
|
609
507
|
channel: runtime.channel,
|
|
610
508
|
spent: runtime.spent,
|
|
611
509
|
state: runtime.state,
|
|
612
510
|
})
|
|
613
511
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
512
|
+
// Cold starts resume from `channelStore` after the 402 reveals the scope.
|
|
513
|
+
const liveHint = runtime.channel?.opened ? runtime.channel.channelId : undefined
|
|
514
|
+
|
|
515
|
+
try {
|
|
516
|
+
await bootstrapSession(input, init)
|
|
517
|
+
|
|
518
|
+
let effectiveInit = requestInitWithSessionHint(input, init, liveHint)
|
|
519
|
+
// Stored channels may be stale, so retry once after evicting the resumed entry.
|
|
520
|
+
let canRetryResumed = !previous.channel?.opened
|
|
521
|
+
|
|
522
|
+
async function retryWithoutResumed(): Promise<boolean> {
|
|
523
|
+
const resumed = use.resumed
|
|
524
|
+
if (!canRetryResumed || !resumed) return false
|
|
525
|
+
canRetryResumed = false
|
|
526
|
+
await ignoreChannel(resumed)
|
|
527
|
+
effectiveInit = requestInitWithSessionHint(input, init, undefined)
|
|
528
|
+
return true
|
|
629
529
|
}
|
|
630
530
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
fetch: config.fetch,
|
|
640
|
-
getChannel: () => runtime.channel,
|
|
641
|
-
restoreCumulative,
|
|
642
|
-
setChallenge(challenge) {
|
|
643
|
-
runtime.lastChallenge = challenge
|
|
644
|
-
},
|
|
645
|
-
topUpIfNeeded,
|
|
646
|
-
})
|
|
647
|
-
if (retry) {
|
|
648
|
-
attemptedHttpManagement = true
|
|
649
|
-
paymentResponse = toPaymentResponse(retry)
|
|
531
|
+
for (;;) {
|
|
532
|
+
let response: Response
|
|
533
|
+
try {
|
|
534
|
+
response = await wrappedFetch(input, effectiveInit)
|
|
535
|
+
} catch (error) {
|
|
536
|
+
restoreRuntime(previous)
|
|
537
|
+
if (await retryWithoutResumed()) continue
|
|
538
|
+
throw error
|
|
650
539
|
}
|
|
540
|
+
|
|
541
|
+
let paymentResponse = toPaymentResponse(response)
|
|
542
|
+
let attemptedHttpManagement = false
|
|
543
|
+
if (paymentResponse.status === 402) {
|
|
544
|
+
const retry = await retryHttpPaymentRequired({
|
|
545
|
+
input,
|
|
546
|
+
init: effectiveInit,
|
|
547
|
+
response: paymentResponse,
|
|
548
|
+
createSessionCredential,
|
|
549
|
+
fetch: config.fetch,
|
|
550
|
+
getChannel: () => runtime.channel,
|
|
551
|
+
restoreCumulative,
|
|
552
|
+
setChallenge(challenge) {
|
|
553
|
+
runtime.lastChallenge = challenge
|
|
554
|
+
},
|
|
555
|
+
topUpIfNeeded,
|
|
556
|
+
})
|
|
557
|
+
if (retry) {
|
|
558
|
+
attemptedHttpManagement = true
|
|
559
|
+
paymentResponse = toPaymentResponse(retry)
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
if (!attemptedHttpManagement && !paymentResponse.ok && !paymentResponse.receipt) {
|
|
563
|
+
restoreRuntime(previous)
|
|
564
|
+
if (await retryWithoutResumed()) continue
|
|
565
|
+
return paymentResponse
|
|
566
|
+
}
|
|
567
|
+
return paymentResponse
|
|
651
568
|
}
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
if (!canRetryWithoutStoredHint) return paymentResponse
|
|
655
|
-
canRetryWithoutStoredHint = false
|
|
656
|
-
await clearStoredChannel()
|
|
657
|
-
await bootstrapSession(input, init)
|
|
658
|
-
effectiveInit = requestInitWithSessionHint(input, init, bootstrapChannelId ?? undefined)
|
|
659
|
-
continue
|
|
660
|
-
}
|
|
661
|
-
return paymentResponse
|
|
569
|
+
} finally {
|
|
570
|
+
channelUse = undefined
|
|
662
571
|
}
|
|
663
572
|
}
|
|
664
573
|
|
|
@@ -741,7 +650,10 @@ export function sessionManager(parameters: sessionManager.Parameters): SessionMa
|
|
|
741
650
|
)
|
|
742
651
|
}
|
|
743
652
|
const probeUrl = webSocketProbeUrl(input)
|
|
744
|
-
|
|
653
|
+
const signalInit = init?.signal ? { signal: init.signal } : undefined
|
|
654
|
+
await bootstrapSession(probeUrl, signalInit)
|
|
655
|
+
// Cold starts resume from `channelStore` after the probe's 402.
|
|
656
|
+
const liveHint = runtime.channel?.opened ? runtime.channel.channelId : undefined
|
|
745
657
|
|
|
746
658
|
const prepared = await prepareWebSocketSession({
|
|
747
659
|
createSessionCredential,
|
|
@@ -750,11 +662,7 @@ export function sessionManager(parameters: sessionManager.Parameters): SessionMa
|
|
|
750
662
|
onProbeUrl(httpUrl) {
|
|
751
663
|
runtime.lastUrl = httpUrl.toString()
|
|
752
664
|
},
|
|
753
|
-
probeInit: requestInitWithSessionHint(
|
|
754
|
-
probeUrl,
|
|
755
|
-
init?.signal ? { signal: init.signal } : undefined,
|
|
756
|
-
(await getStoredChannel())?.channelId ?? bootstrapChannelId ?? undefined,
|
|
757
|
-
),
|
|
665
|
+
probeInit: requestInitWithSessionHint(probeUrl, signalInit, liveHint),
|
|
758
666
|
signal: init?.signal,
|
|
759
667
|
})
|
|
760
668
|
const { challenge, credential, httpUrl, wsUrl } = prepared
|
|
@@ -823,8 +731,6 @@ export namespace sessionManager {
|
|
|
823
731
|
|
|
824
732
|
export type Parameters = Account.getResolver.Parameters &
|
|
825
733
|
Client.getResolver.Parameters & {
|
|
826
|
-
/** Address authorized to sign vouchers. Defaults to the account access key address when available, otherwise the account address. */
|
|
827
|
-
authorizedSigner?: Address | undefined
|
|
828
734
|
/** Enables same-route HEAD bootstrap from a server session snapshot before opening a new channel. */
|
|
829
735
|
bootstrap?: boolean | undefined
|
|
830
736
|
/** Viem client instance. Shorthand for `getClient: () => client`. */
|
|
@@ -837,8 +743,8 @@ export namespace sessionManager {
|
|
|
837
743
|
fetch?: typeof globalThis.fetch | undefined
|
|
838
744
|
/** Maximum deposit in human-readable units (e.g. `'10'` for 10 tokens). Converted to raw units via `decimals`. */
|
|
839
745
|
maxDeposit?: string | undefined
|
|
840
|
-
/**
|
|
841
|
-
|
|
746
|
+
/** Store for reusable session channels. Defaults to in-memory. */
|
|
747
|
+
channelStore?: ChannelStore | undefined
|
|
842
748
|
/** Optional websocket constructor for runtimes without a global WebSocket. */
|
|
843
749
|
webSocket?: WebSocketConstructor | undefined
|
|
844
750
|
}
|
|
@@ -2,18 +2,20 @@ export { session } from './Session.js'
|
|
|
2
2
|
export { sessionManager } from './SessionManager.js'
|
|
3
3
|
export * as Machine from './Runtime.js'
|
|
4
4
|
export { deserializeSnapshot, serializeSnapshot } from '../Snapshot.js'
|
|
5
|
-
|
|
5
|
+
export {
|
|
6
|
+
createChannelStore,
|
|
7
|
+
createJsonChannelStore,
|
|
8
|
+
entryKey,
|
|
9
|
+
type ChannelStore,
|
|
10
|
+
type JsonChannelKv,
|
|
11
|
+
} from './ChannelStore.js'
|
|
6
12
|
export type {
|
|
7
13
|
PaymentResponse,
|
|
8
|
-
SessionStore,
|
|
9
14
|
SessionManager,
|
|
10
15
|
SessionManagerSseOptions,
|
|
11
16
|
SessionManagerWebSocketOptions,
|
|
12
|
-
StoredSessionChannel,
|
|
13
17
|
} from './SessionManager.js'
|
|
14
|
-
/** Public managed WebSocket facade returned by `sessionManager().ws()`. */
|
|
15
18
|
export type { SessionManagedWebSocket } from './Transports.js'
|
|
16
|
-
/** Public pure state-machine types. */
|
|
17
19
|
export type {
|
|
18
20
|
ActiveSessionState,
|
|
19
21
|
ChallengedSessionState,
|
|
@@ -35,3 +37,4 @@ export type {
|
|
|
35
37
|
WithdrawableSessionState,
|
|
36
38
|
} from './Runtime.js'
|
|
37
39
|
export type { SessionSnapshot } from '../Snapshot.js'
|
|
40
|
+
export type { ResolveAccount, ResolveAccountInfo } from '../../client/ResolveAccount.js'
|
|
@@ -271,7 +271,7 @@ describe('Precompile Voucher', () => {
|
|
|
271
271
|
).toBe(false)
|
|
272
272
|
})
|
|
273
273
|
|
|
274
|
-
test('
|
|
274
|
+
test('signs and verifies p256 access-key vouchers as primitives', async () => {
|
|
275
275
|
const rootAccount = TempoAccount.fromSecp256k1(Secp256k1.randomPrivateKey())
|
|
276
276
|
const accessKey = TempoAccount.fromP256(P256.randomPrivateKey(), {
|
|
277
277
|
access: rootAccount,
|
|
@@ -281,16 +281,54 @@ describe('Precompile Voucher', () => {
|
|
|
281
281
|
transport: http('http://127.0.0.1'),
|
|
282
282
|
})
|
|
283
283
|
|
|
284
|
-
await
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
284
|
+
const signature = await signVoucher(
|
|
285
|
+
accessKeyClient,
|
|
286
|
+
accessKey,
|
|
287
|
+
{ channelId, cumulativeAmount },
|
|
288
|
+
escrowContract,
|
|
289
|
+
chainId,
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
const envelope = SignatureEnvelope.from(signature as SignatureEnvelope.Serialized)
|
|
293
|
+
expect(envelope.type).toBe('p256')
|
|
294
|
+
expect(
|
|
295
|
+
verifyVoucher(
|
|
289
296
|
escrowContract,
|
|
290
297
|
chainId,
|
|
298
|
+
{ channelId, cumulativeAmount, signature },
|
|
291
299
|
accessKey.accessKeyAddress,
|
|
292
300
|
),
|
|
293
|
-
).
|
|
301
|
+
).toBe(true)
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
test('signs and verifies webAuthn root vouchers as primitives', async () => {
|
|
305
|
+
const webAuthnAccount = TempoAccount.fromHeadlessWebAuthn(P256.randomPrivateKey(), {
|
|
306
|
+
origin: 'https://example.com',
|
|
307
|
+
rpId: 'example.com',
|
|
308
|
+
})
|
|
309
|
+
const webAuthnClient = createClient({
|
|
310
|
+
account: webAuthnAccount,
|
|
311
|
+
transport: http('http://127.0.0.1'),
|
|
312
|
+
})
|
|
313
|
+
|
|
314
|
+
const signature = await signVoucher(
|
|
315
|
+
webAuthnClient,
|
|
316
|
+
webAuthnAccount,
|
|
317
|
+
{ channelId, cumulativeAmount },
|
|
318
|
+
escrowContract,
|
|
319
|
+
chainId,
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
const envelope = SignatureEnvelope.from(signature as SignatureEnvelope.Serialized)
|
|
323
|
+
expect(envelope.type).toBe('webAuthn')
|
|
324
|
+
expect(
|
|
325
|
+
verifyVoucher(
|
|
326
|
+
escrowContract,
|
|
327
|
+
chainId,
|
|
328
|
+
{ channelId, cumulativeAmount, signature },
|
|
329
|
+
webAuthnAccount.address,
|
|
330
|
+
),
|
|
331
|
+
).toBe(true)
|
|
294
332
|
})
|
|
295
333
|
|
|
296
334
|
test('domain and type match TIP-1034', () => {
|