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
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
resolveEscrow,
|
|
26
26
|
type ChannelEntry,
|
|
27
27
|
} from './ChannelOps.js'
|
|
28
|
+
import { channelKey, entryKey, type ChannelSink } from './ChannelStore.js'
|
|
28
29
|
import { assertWithinMaxDeposit, resolveOpeningDeposit } from './Runtime.js'
|
|
29
30
|
|
|
30
31
|
/** Credential payload variants that carry cumulative voucher authorization. */
|
|
@@ -33,39 +34,6 @@ export type CumulativeCredentialPayload = Extract<
|
|
|
33
34
|
{ cumulativeAmount: string }
|
|
34
35
|
>
|
|
35
36
|
|
|
36
|
-
/** In-memory client channel cache used by automatic precompile session credential planning. */
|
|
37
|
-
export type ChannelCache = {
|
|
38
|
-
/** Maps reusable channel keys to cached channel metadata. */
|
|
39
|
-
channels: Map<string, ChannelEntry>
|
|
40
|
-
/** Maps channel IDs back to reusable channel keys for manual credential cache updates. */
|
|
41
|
-
channelIdToKey: Map<string, string>
|
|
42
|
-
/** Emits cache updates to the public `onChannelUpdate` callback. */
|
|
43
|
-
notifyUpdate(entry: ChannelEntry): void
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** Creates an empty client channel cache with an optional update callback. */
|
|
47
|
-
export function createChannelCache(
|
|
48
|
-
onUpdate?: ((entry: ChannelEntry) => void) | undefined,
|
|
49
|
-
): ChannelCache {
|
|
50
|
-
return {
|
|
51
|
-
channels: new Map(),
|
|
52
|
-
channelIdToKey: new Map(),
|
|
53
|
-
notifyUpdate: (entry) => onUpdate?.(entry),
|
|
54
|
-
} satisfies ChannelCache
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/** Returns the cache key for a reusable payer session channel. */
|
|
58
|
-
export function channelKey(payee: Address, token: Address, escrow: Address): string {
|
|
59
|
-
return `${payee.toLowerCase()}:${token.toLowerCase()}:${escrow.toLowerCase()}`
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/** Stores a channel entry and notifies observers. */
|
|
63
|
-
export function storeChannelEntry(cache: ChannelCache, key: string, entry: ChannelEntry): void {
|
|
64
|
-
cache.channels.set(key, entry)
|
|
65
|
-
cache.channelIdToKey.set(entry.channelId, key)
|
|
66
|
-
cache.notifyUpdate(entry)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
37
|
/** Returns whether a credential payload carries cumulative voucher authorization. */
|
|
70
38
|
export function hasCredentialCumulativeAmount(
|
|
71
39
|
payload: SessionCredentialPayload,
|
|
@@ -81,21 +49,32 @@ export function readCredentialCumulativeAmount(
|
|
|
81
49
|
return BigInt(payload.cumulativeAmount)
|
|
82
50
|
}
|
|
83
51
|
|
|
84
|
-
/**
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Persists a channel entry through the sink and notifies observers. Closed
|
|
54
|
+
* channels are removed from the store but still reported to observers so callers
|
|
55
|
+
* can react to the close.
|
|
56
|
+
*/
|
|
57
|
+
async function storeChannelEntry(sink: ChannelSink, entry: ChannelEntry): Promise<void> {
|
|
58
|
+
if (entry.opened) await sink.store.set(entry)
|
|
59
|
+
else await sink.store.delete(entryKey(entry))
|
|
60
|
+
sink.notifyUpdate(entry)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Applies a credential payload's cumulative amount to the stored channel at `key`. */
|
|
64
|
+
async function applyCumulative(
|
|
65
|
+
sink: ChannelSink,
|
|
66
|
+
key: string,
|
|
88
67
|
payload: SessionCredentialPayload,
|
|
89
|
-
): void {
|
|
90
|
-
const key = cache.channelIdToKey.get(channelId)
|
|
68
|
+
): Promise<void> {
|
|
91
69
|
const cumulativeAmount = readCredentialCumulativeAmount(payload)
|
|
92
|
-
if (
|
|
93
|
-
const entry =
|
|
70
|
+
if (cumulativeAmount === undefined) return
|
|
71
|
+
const entry = await sink.store.get(key)
|
|
94
72
|
if (!entry) return
|
|
73
|
+
if (entry.channelId.toLowerCase() !== payload.channelId.toLowerCase()) return
|
|
95
74
|
entry.cumulativeAmount =
|
|
96
75
|
entry.cumulativeAmount > cumulativeAmount ? entry.cumulativeAmount : cumulativeAmount
|
|
97
76
|
if (payload.action === 'close') entry.opened = false
|
|
98
|
-
|
|
77
|
+
await storeChannelEntry(sink, entry)
|
|
99
78
|
}
|
|
100
79
|
|
|
101
80
|
const hexSchema = z.custom<Hex>(
|
|
@@ -252,7 +231,7 @@ export type ReusableChannelExpectation = {
|
|
|
252
231
|
payee: Address
|
|
253
232
|
/** Payer address controlled by the local account. */
|
|
254
233
|
payer: Address
|
|
255
|
-
/** Voucher
|
|
234
|
+
/** Voucher authority resolved from the local account. */
|
|
256
235
|
authorizedSigner: Address
|
|
257
236
|
/** Token expected by the current challenge. */
|
|
258
237
|
token: Address
|
|
@@ -300,8 +279,8 @@ export type ChallengeContext = {
|
|
|
300
279
|
/** Inputs used to choose the next client-side session credential operation. */
|
|
301
280
|
export type PlanCredentialParameters = {
|
|
302
281
|
account: ViemAccount
|
|
303
|
-
|
|
304
|
-
|
|
282
|
+
/** Channel previously stored for this challenge scope, fetched by the caller. */
|
|
283
|
+
entry: ChannelEntry | undefined
|
|
305
284
|
context?: SessionContext | undefined
|
|
306
285
|
decimals: number
|
|
307
286
|
maxDeposit?: bigint | undefined
|
|
@@ -336,7 +315,6 @@ export type CredentialPlan =
|
|
|
336
315
|
| {
|
|
337
316
|
type: 'open'
|
|
338
317
|
account: ViemAccount
|
|
339
|
-
authorizedSigner?: Address | undefined
|
|
340
318
|
context?: SessionContext | undefined
|
|
341
319
|
maxDeposit?: bigint | undefined
|
|
342
320
|
resolved: ChallengeContext
|
|
@@ -345,7 +323,6 @@ export type CredentialPlan =
|
|
|
345
323
|
| {
|
|
346
324
|
type: 'recover'
|
|
347
325
|
account: ViemAccount
|
|
348
|
-
authorizedSigner?: Address | undefined
|
|
349
326
|
context: DescriptorSessionContext
|
|
350
327
|
decimals: number
|
|
351
328
|
maxDeposit?: bigint | undefined
|
|
@@ -363,7 +340,6 @@ export type CredentialPlan =
|
|
|
363
340
|
| {
|
|
364
341
|
type: 'manual'
|
|
365
342
|
account: ViemAccount
|
|
366
|
-
authorizedSigner?: Address | undefined
|
|
367
343
|
context: ManualSessionDescriptorContext
|
|
368
344
|
decimals: number
|
|
369
345
|
resolved: ChallengeContext
|
|
@@ -436,7 +412,7 @@ export async function resolveChallengeContext(
|
|
|
436
412
|
client,
|
|
437
413
|
escrow,
|
|
438
414
|
feePayer: methodDetails.feePayer,
|
|
439
|
-
key: channelKey(payee, token, escrow),
|
|
415
|
+
key: channelKey({ payee, token, escrow, chainId }),
|
|
440
416
|
operator: methodDetails.operator,
|
|
441
417
|
payee,
|
|
442
418
|
snapshot: methodDetails.sessionSnapshot,
|
|
@@ -533,9 +509,21 @@ export function resolveRecoveredCumulative(
|
|
|
533
509
|
return settled + requestAmount
|
|
534
510
|
}
|
|
535
511
|
|
|
512
|
+
/** Returns whether `account` can satisfy the descriptor's voucher authority. */
|
|
513
|
+
export function canSignDescriptor(
|
|
514
|
+
account: ViemAccount,
|
|
515
|
+
descriptor: Channel.ChannelDescriptor,
|
|
516
|
+
): boolean {
|
|
517
|
+
// Only the payer can deposit into and voucher against its own channel.
|
|
518
|
+
if (!isSameAddress(account.address, descriptor.payer)) return false
|
|
519
|
+
const authority = descriptor.authorizedSigner
|
|
520
|
+
if (BigInt(authority) === 0n || isSameAddress(authority, descriptor.payer)) return true
|
|
521
|
+
return isSameAddress(resolveAuthorizedSigner(account), authority)
|
|
522
|
+
}
|
|
523
|
+
|
|
536
524
|
/** Chooses the next credential plan from local channel cache and optional caller context. */
|
|
537
525
|
export function planCredential(parameters: PlanCredentialParameters): CredentialPlan {
|
|
538
|
-
const { account,
|
|
526
|
+
const { account, entry, context, decimals, maxDeposit, resolved } = parameters
|
|
539
527
|
|
|
540
528
|
if (hasSessionAction(context)) {
|
|
541
529
|
if (!hasManualSessionDescriptor(context))
|
|
@@ -543,54 +531,52 @@ export function planCredential(parameters: PlanCredentialParameters): Credential
|
|
|
543
531
|
return {
|
|
544
532
|
type: 'manual',
|
|
545
533
|
account,
|
|
546
|
-
authorizedSigner,
|
|
547
534
|
context,
|
|
548
535
|
decimals,
|
|
549
536
|
resolved,
|
|
550
537
|
}
|
|
551
538
|
}
|
|
552
539
|
|
|
553
|
-
const entry = cache.channels.get(resolved.key)
|
|
554
540
|
if (!entry && context?.channelId && !context.descriptor)
|
|
555
541
|
throw new Error('descriptor required to reuse TIP-1034 channel')
|
|
556
542
|
const recoverContext = resolveRecoverContext({ context, snapshot: resolved.snapshot })
|
|
557
|
-
if (!entry && recoverContext) {
|
|
543
|
+
if (!entry && recoverContext && canSignDescriptor(account, recoverContext.descriptor)) {
|
|
558
544
|
return {
|
|
559
545
|
type: 'recover',
|
|
560
546
|
account,
|
|
561
|
-
authorizedSigner,
|
|
562
547
|
context: recoverContext,
|
|
563
548
|
decimals,
|
|
564
549
|
maxDeposit,
|
|
565
550
|
resolved,
|
|
566
551
|
}
|
|
567
552
|
}
|
|
568
|
-
if (entry?.opened
|
|
569
|
-
|
|
553
|
+
if (entry?.opened && canSignDescriptor(account, entry.descriptor))
|
|
554
|
+
return { type: 'voucher', account, entry, maxDeposit, resolved }
|
|
555
|
+
return { type: 'open', account, context, maxDeposit, resolved }
|
|
570
556
|
}
|
|
571
557
|
|
|
572
558
|
/** Executes a credential plan and returns the concrete session credential payload. */
|
|
573
559
|
export async function executeCredentialPlan(
|
|
574
560
|
plan: CredentialPlan,
|
|
575
|
-
|
|
561
|
+
sink: ChannelSink,
|
|
576
562
|
): Promise<SessionCredentialPayload> {
|
|
577
563
|
switch (plan.type) {
|
|
578
564
|
case 'open':
|
|
579
|
-
return open(plan,
|
|
565
|
+
return open(plan, sink)
|
|
580
566
|
case 'recover':
|
|
581
|
-
return recover(plan,
|
|
567
|
+
return recover(plan, sink)
|
|
582
568
|
case 'voucher':
|
|
583
|
-
return voucher(plan,
|
|
569
|
+
return voucher(plan, sink)
|
|
584
570
|
case 'manual':
|
|
585
|
-
return manual(plan,
|
|
571
|
+
return manual(plan, sink)
|
|
586
572
|
}
|
|
587
573
|
}
|
|
588
574
|
|
|
589
575
|
async function open(
|
|
590
576
|
plan: Extract<CredentialPlan, { type: 'open' }>,
|
|
591
|
-
|
|
577
|
+
sink: ChannelSink,
|
|
592
578
|
): Promise<SessionCredentialPayload> {
|
|
593
|
-
const { account,
|
|
579
|
+
const { account, resolved } = plan
|
|
594
580
|
const deposit = resolveOpeningDeposit({
|
|
595
581
|
contextDepositRaw: plan.context?.depositRaw,
|
|
596
582
|
maxDeposit: plan.maxDeposit,
|
|
@@ -598,7 +584,6 @@ async function open(
|
|
|
598
584
|
suggestedDepositRaw: resolved.suggestedDepositRaw,
|
|
599
585
|
})
|
|
600
586
|
const payload = await createOpenPayload(resolved.client, account, {
|
|
601
|
-
authorizedSigner,
|
|
602
587
|
chainId: resolved.chainId,
|
|
603
588
|
deposit,
|
|
604
589
|
escrow: resolved.escrow,
|
|
@@ -608,7 +593,7 @@ async function open(
|
|
|
608
593
|
payee: resolved.payee,
|
|
609
594
|
token: resolved.token,
|
|
610
595
|
})
|
|
611
|
-
storeChannelEntry(
|
|
596
|
+
await storeChannelEntry(sink, {
|
|
612
597
|
channelId: payload.channelId,
|
|
613
598
|
cumulativeAmount: resolved.amount,
|
|
614
599
|
deposit,
|
|
@@ -622,7 +607,7 @@ async function open(
|
|
|
622
607
|
|
|
623
608
|
async function recover(
|
|
624
609
|
plan: Extract<CredentialPlan, { type: 'recover' }>,
|
|
625
|
-
|
|
610
|
+
sink: ChannelSink,
|
|
626
611
|
): Promise<SessionCredentialPayload> {
|
|
627
612
|
const { account, context, decimals, maxDeposit, resolved } = plan
|
|
628
613
|
const { descriptor } = context
|
|
@@ -635,7 +620,7 @@ async function recover(
|
|
|
635
620
|
escrow: resolved.escrow,
|
|
636
621
|
payee: resolved.payee,
|
|
637
622
|
payer: account.address,
|
|
638
|
-
authorizedSigner: resolveAuthorizedSigner(account
|
|
623
|
+
authorizedSigner: resolveAuthorizedSigner(account),
|
|
639
624
|
token: resolved.token,
|
|
640
625
|
},
|
|
641
626
|
})
|
|
@@ -657,7 +642,7 @@ async function recover(
|
|
|
657
642
|
resolved.chainId,
|
|
658
643
|
resolved.escrow,
|
|
659
644
|
)
|
|
660
|
-
storeChannelEntry(
|
|
645
|
+
await storeChannelEntry(sink, {
|
|
661
646
|
channelId: reusable.channelId,
|
|
662
647
|
cumulativeAmount,
|
|
663
648
|
deposit: reusable.state.deposit,
|
|
@@ -671,7 +656,7 @@ async function recover(
|
|
|
671
656
|
|
|
672
657
|
async function voucher(
|
|
673
658
|
plan: Extract<CredentialPlan, { type: 'voucher' }>,
|
|
674
|
-
|
|
659
|
+
sink: ChannelSink,
|
|
675
660
|
): Promise<SessionCredentialPayload> {
|
|
676
661
|
const { account, entry, resolved } = plan
|
|
677
662
|
const cumulativeAmount = entry.cumulativeAmount + resolved.amount
|
|
@@ -685,13 +670,13 @@ async function voucher(
|
|
|
685
670
|
resolved.escrow,
|
|
686
671
|
)
|
|
687
672
|
entry.cumulativeAmount = cumulativeAmount
|
|
688
|
-
|
|
673
|
+
await storeChannelEntry(sink, entry)
|
|
689
674
|
return payload
|
|
690
675
|
}
|
|
691
676
|
|
|
692
677
|
async function manual(
|
|
693
678
|
plan: Extract<CredentialPlan, { type: 'manual' }>,
|
|
694
|
-
|
|
679
|
+
sink: ChannelSink,
|
|
695
680
|
): Promise<SessionCredentialPayload> {
|
|
696
681
|
const { account, context, decimals, resolved } = plan
|
|
697
682
|
const { descriptor } = context
|
|
@@ -706,7 +691,7 @@ async function manual(
|
|
|
706
691
|
expectedChannelId: channelId,
|
|
707
692
|
payee: resolved.payee,
|
|
708
693
|
payer: account.address,
|
|
709
|
-
authorizedSigner: resolveAuthorizedSigner(account
|
|
694
|
+
authorizedSigner: resolveAuthorizedSigner(account),
|
|
710
695
|
token: resolved.token,
|
|
711
696
|
})
|
|
712
697
|
|
|
@@ -718,7 +703,7 @@ async function manual(
|
|
|
718
703
|
descriptor,
|
|
719
704
|
resolved,
|
|
720
705
|
})
|
|
721
|
-
|
|
706
|
+
await applyCumulative(sink, resolved.key, payload)
|
|
722
707
|
return payload
|
|
723
708
|
}
|
|
724
709
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Address, createClient, custom, decodeFunctionData, encodeFunctionResult } from 'viem'
|
|
2
2
|
import { privateKeyToAccount } from 'viem/accounts'
|
|
3
|
-
import { Transaction } from 'viem/tempo'
|
|
3
|
+
import { Account as TempoAccount, Secp256k1, Transaction } from 'viem/tempo'
|
|
4
4
|
import { describe, expect, test } from 'vp/test'
|
|
5
5
|
|
|
6
6
|
import type { Challenge } from '../../../Challenge.js'
|
|
@@ -286,6 +286,46 @@ describe('precompile client session', () => {
|
|
|
286
286
|
expect(updates).toEqual([100n, 200n])
|
|
287
287
|
})
|
|
288
288
|
|
|
289
|
+
test('passes existing channel authority to resolveAccount before reusing session channel', async () => {
|
|
290
|
+
const accessKey = TempoAccount.fromSecp256k1(Secp256k1.randomPrivateKey(), {
|
|
291
|
+
access: account,
|
|
292
|
+
})
|
|
293
|
+
const calls: session.ResolveAccountInfo[] = []
|
|
294
|
+
const method = session({
|
|
295
|
+
account,
|
|
296
|
+
decimals: 0,
|
|
297
|
+
maxDeposit: '1000',
|
|
298
|
+
getClient: () => client,
|
|
299
|
+
resolveAccount(info) {
|
|
300
|
+
calls.push(info)
|
|
301
|
+
return accessKey
|
|
302
|
+
},
|
|
303
|
+
})
|
|
304
|
+
const first = deserializeCredential(
|
|
305
|
+
await method.createCredential({ challenge: makeChallenge(), context: {} }),
|
|
306
|
+
)
|
|
307
|
+
const second = deserializeCredential(
|
|
308
|
+
await method.createCredential({ challenge: makeChallenge(), context: {} }),
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
expect(calls).toHaveLength(2)
|
|
312
|
+
expect(calls[0]!.account.address).toBe(account.address)
|
|
313
|
+
expect(calls[0]!.operation).toEqual({ kind: 'authorizePaymentChannel' })
|
|
314
|
+
expect(calls[1]!.operation).toEqual({
|
|
315
|
+
kind: 'authorizePaymentChannel',
|
|
316
|
+
authority: accessKey.accessKeyAddress,
|
|
317
|
+
})
|
|
318
|
+
expect(first.source).toBe(`did:pkh:eip155:${chainId}:${account.address}`)
|
|
319
|
+
expect(second.source).toBe(`did:pkh:eip155:${chainId}:${account.address}`)
|
|
320
|
+
expect(first.payload.action).toBe('open')
|
|
321
|
+
if (first.payload.action !== 'open' || second.payload.action !== 'voucher')
|
|
322
|
+
throw new Error('expected open then voucher payloads')
|
|
323
|
+
expect(first.payload.descriptor.payer).toBe(account.address)
|
|
324
|
+
expect(first.payload.descriptor.authorizedSigner).toBe(accessKey.accessKeyAddress)
|
|
325
|
+
expect(second.payload.channelId).toBe(first.payload.channelId)
|
|
326
|
+
expect(second.payload.cumulativeAmount).toBe('200')
|
|
327
|
+
})
|
|
328
|
+
|
|
289
329
|
test('enforces maxDeposit when reusing a cached auto-mode channel', async () => {
|
|
290
330
|
const updates: bigint[] = []
|
|
291
331
|
const method = session({
|
|
@@ -5,15 +5,20 @@ import * as Constants from '../../../Constants.js'
|
|
|
5
5
|
import * as Method from '../../../Method.js'
|
|
6
6
|
import * as Account from '../../../viem/Account.js'
|
|
7
7
|
import * as Client from '../../../viem/Client.js'
|
|
8
|
+
import type {
|
|
9
|
+
ResolveAccount as ResolveAccount_,
|
|
10
|
+
ResolveAccountInfo as ResolveAccountInfo_,
|
|
11
|
+
} from '../../client/ResolveAccount.js'
|
|
8
12
|
import * as defaults from '../../internal/defaults.js'
|
|
9
13
|
import * as Methods from '../../Methods.js'
|
|
10
14
|
import { serializeCredential, type ChannelEntry } from './ChannelOps.js'
|
|
11
|
-
import {
|
|
15
|
+
import { createChannelStore, type ChannelStore } from './ChannelStore.js'
|
|
12
16
|
import {
|
|
13
|
-
createChannelCache,
|
|
14
17
|
executeCredentialPlan,
|
|
15
18
|
planCredential,
|
|
16
19
|
resolveChallengeContext,
|
|
20
|
+
resolveRecoverContext,
|
|
21
|
+
sessionContextSchema,
|
|
17
22
|
} from './CredentialState.js'
|
|
18
23
|
|
|
19
24
|
export { sessionContextSchema, type SessionContext } from './CredentialState.js'
|
|
@@ -28,12 +33,13 @@ export { sessionContextSchema, type SessionContext } from './CredentialState.js'
|
|
|
28
33
|
export function session(parameters: session.Parameters = {}) {
|
|
29
34
|
const {
|
|
30
35
|
account,
|
|
31
|
-
|
|
36
|
+
channelStore,
|
|
32
37
|
decimals = defaults.decimals,
|
|
33
38
|
escrow: escrowOverride,
|
|
34
39
|
getClient: getClientParameter,
|
|
35
40
|
maxDeposit: maxDepositParameter,
|
|
36
41
|
onChannelUpdate,
|
|
42
|
+
resolveAccount,
|
|
37
43
|
} = parameters
|
|
38
44
|
const getClient = Client.getResolver({
|
|
39
45
|
chain: tempo_chain,
|
|
@@ -43,7 +49,8 @@ export function session(parameters: session.Parameters = {}) {
|
|
|
43
49
|
const getAccount = Account.getResolver({ account })
|
|
44
50
|
const maxDeposit =
|
|
45
51
|
maxDepositParameter !== undefined ? parseUnits(maxDepositParameter, decimals) : undefined
|
|
46
|
-
const
|
|
52
|
+
const store = channelStore ?? createChannelStore()
|
|
53
|
+
const sink = { store, notifyUpdate: (entry: ChannelEntry) => onChannelUpdate?.(entry) }
|
|
47
54
|
|
|
48
55
|
return Method.toClient(Methods.session, {
|
|
49
56
|
canHandleChallenge({ challenge }) {
|
|
@@ -61,18 +68,32 @@ export function session(parameters: session.Parameters = {}) {
|
|
|
61
68
|
escrowOverride,
|
|
62
69
|
getClient,
|
|
63
70
|
})
|
|
64
|
-
const
|
|
71
|
+
const defaultAccount = getAccount(resolved.client, context)
|
|
72
|
+
const entry = await store.get(resolved.key)
|
|
73
|
+
// Resolve recovery hints early so account selection can satisfy an existing channel authority.
|
|
74
|
+
const recoverContext = resolveRecoverContext({ context, snapshot: resolved.snapshot })
|
|
75
|
+
const descriptor = context?.action
|
|
76
|
+
? context.descriptor
|
|
77
|
+
: (entry?.descriptor ?? recoverContext?.descriptor)
|
|
78
|
+
const account =
|
|
79
|
+
(await resolveAccount?.({
|
|
80
|
+
account: defaultAccount,
|
|
81
|
+
chainId: resolved.chainId,
|
|
82
|
+
operation: {
|
|
83
|
+
kind: 'authorizePaymentChannel',
|
|
84
|
+
...(descriptor ? { authority: descriptor.authorizedSigner } : {}),
|
|
85
|
+
},
|
|
86
|
+
})) ?? defaultAccount
|
|
65
87
|
const payload = await executeCredentialPlan(
|
|
66
88
|
planCredential({
|
|
67
89
|
account,
|
|
68
|
-
|
|
69
|
-
cache,
|
|
90
|
+
entry,
|
|
70
91
|
context,
|
|
71
92
|
decimals,
|
|
72
93
|
maxDeposit,
|
|
73
94
|
resolved,
|
|
74
95
|
}),
|
|
75
|
-
|
|
96
|
+
sink,
|
|
76
97
|
)
|
|
77
98
|
return serializeCredential(challenge, payload, resolved.chainId, account)
|
|
78
99
|
},
|
|
@@ -81,10 +102,13 @@ export function session(parameters: session.Parameters = {}) {
|
|
|
81
102
|
|
|
82
103
|
/** Type helpers for the low-level TIP-1034 session client method. */
|
|
83
104
|
export declare namespace session {
|
|
105
|
+
type ResolveAccount = ResolveAccount_
|
|
106
|
+
type ResolveAccountInfo = ResolveAccountInfo_
|
|
107
|
+
|
|
84
108
|
type Parameters = Account.getResolver.Parameters &
|
|
85
109
|
Client.getResolver.Parameters & {
|
|
86
|
-
/**
|
|
87
|
-
|
|
110
|
+
/** Pluggable persistence for reusable channels. Defaults to an in-memory store. */
|
|
111
|
+
channelStore?: ChannelStore | undefined
|
|
88
112
|
/** Token decimals for parsing human-readable amounts (default: 6). */
|
|
89
113
|
decimals?: number | undefined
|
|
90
114
|
/** TIP20EscrowChannel address override. */
|
|
@@ -93,5 +117,7 @@ export declare namespace session {
|
|
|
93
117
|
maxDeposit?: string | undefined
|
|
94
118
|
/** Called whenever channel state changes. */
|
|
95
119
|
onChannelUpdate?: ((entry: ChannelEntry) => void) | undefined
|
|
120
|
+
/** Selects the account that signs this session credential after the challenge is known. */
|
|
121
|
+
resolveAccount?: ResolveAccount | undefined
|
|
96
122
|
}
|
|
97
123
|
}
|