mppx 0.8.18 → 0.9.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 +22 -0
- package/README.md +0 -6
- package/dist/Challenge.d.ts +7 -0
- package/dist/Challenge.js +32 -6
- package/dist/Constants.d.ts +1 -0
- package/dist/Constants.js +1 -0
- package/dist/Credential.d.ts +11 -5
- package/dist/Credential.js +8 -8
- package/dist/Html.js +1 -1
- package/dist/cli/THIRD-PARTY-LICENSES.txt +1 -1
- package/dist/cli/cli.d.ts +2 -2
- package/dist/cli/cli.js +134 -134
- package/dist/cli/plugins/index.js +13 -13
- package/dist/cli/sessions/Manager.js +4 -6
- package/dist/cli/sessions/commands.d.ts +1 -1
- package/dist/cli/sessions/store.js +13 -19
- package/dist/cli/validate/index.d.ts +2 -2
- package/dist/client/Mppx.d.ts +39 -2
- package/dist/client/Mppx.js +102 -46
- package/dist/client/Transport.js +1 -1
- package/dist/client/internal/protocols/Mpp.d.ts +1 -1
- package/dist/client/internal/protocols/Mpp.js +5 -3
- package/dist/client/internal/protocols/Protocol.d.ts +3 -1
- package/dist/client/internal/protocols/Shared.js +5 -1
- package/dist/integrations/x402/Evm.d.ts +29 -0
- package/dist/integrations/x402/Evm.js +150 -0
- package/dist/integrations/x402/Negotiator.d.ts +36 -0
- package/dist/integrations/x402/Negotiator.js +165 -0
- package/dist/mcp/internal/Credential.d.ts +9 -0
- package/dist/mcp/internal/Credential.js +16 -0
- package/dist/mcp/server/Transport.js +2 -4
- package/dist/middlewares/express.js +5 -12
- package/dist/middlewares/internal/express.d.ts +8 -0
- package/dist/middlewares/internal/express.js +24 -0
- package/dist/middlewares/internal/node.d.ts +10 -0
- package/dist/middlewares/internal/node.js +34 -0
- package/dist/proxy/Proxy.js +15 -9
- package/dist/server/Mppx.d.ts +2 -0
- package/dist/server/Mppx.js +17 -14
- package/dist/server/Transport.d.ts +8 -2
- package/dist/server/Transport.js +6 -3
- package/dist/server/internal/SecretKey.d.ts +3 -0
- package/dist/server/internal/SecretKey.js +9 -0
- package/dist/server/internal/html/serviceWorker.client.d.ts +1 -1
- package/dist/server/internal/html/serviceWorker.client.js +2 -2
- package/dist/server/internal/html/serviceWorker.gen.d.ts +1 -1
- package/dist/server/internal/html/serviceWorker.gen.js +1 -1
- package/dist/stripe/server/internal/html.gen.d.ts +1 -1
- package/dist/stripe/server/internal/html.gen.js +1 -1
- package/dist/tempo/Methods.d.ts +0 -10
- package/dist/tempo/Methods.js +3 -12
- package/dist/tempo/client/Charge.d.ts +0 -3
- package/dist/tempo/client/Charge.js +3 -13
- package/dist/tempo/client/Methods.d.ts +0 -10
- package/dist/tempo/internal/account.d.ts +15 -6
- package/dist/tempo/internal/account.js +17 -26
- package/dist/tempo/internal/defaults.d.ts +0 -11
- package/dist/tempo/internal/defaults.js +0 -11
- package/dist/tempo/internal/fee-payer.d.ts +21 -3
- package/dist/tempo/internal/fee-payer.js +10 -19
- package/dist/tempo/internal/remote-fee-payer.d.ts +12 -0
- package/dist/tempo/internal/remote-fee-payer.js +17 -0
- package/dist/tempo/legacy/client/Session.d.ts +0 -7
- package/dist/tempo/server/Charge.d.ts +0 -3
- package/dist/tempo/server/Charge.js +26 -68
- package/dist/tempo/server/Methods.d.ts +4 -18
- package/dist/tempo/server/Methods.js +4 -8
- package/dist/tempo/server/internal/html.gen.d.ts +1 -1
- package/dist/tempo/server/internal/html.gen.js +1 -1
- package/dist/tempo/session/client/ChannelOps.d.ts +0 -14
- package/dist/tempo/session/client/ChannelOps.js +0 -22
- package/dist/tempo/session/client/ChannelStore.d.ts +5 -0
- package/dist/tempo/session/client/ChannelStore.js +2 -2
- package/dist/tempo/session/client/CredentialState.d.ts +2 -12
- package/dist/tempo/session/client/CredentialState.js +75 -73
- package/dist/tempo/session/client/Session.d.ts +2 -9
- package/dist/tempo/session/client/Session.js +71 -176
- package/dist/tempo/session/client/SessionManager.js +9 -28
- package/dist/tempo/session/precompile/Chain.d.ts +0 -4
- package/dist/tempo/session/precompile/Chain.js +2 -29
- package/dist/tempo/session/precompile/Protocol.d.ts +0 -13
- package/dist/tempo/session/precompile/Voucher.d.ts +1 -3
- package/dist/tempo/session/precompile/Voucher.js +12 -6
- package/dist/tempo/session/server/ChannelStore.d.ts +0 -6
- package/dist/tempo/session/server/ChannelStore.js +4 -11
- package/dist/tempo/session/server/CredentialVerification.d.ts +7 -9
- package/dist/tempo/session/server/CredentialVerification.js +118 -184
- package/dist/tempo/session/server/RequestState.d.ts +0 -17
- package/dist/tempo/session/server/RequestState.js +15 -59
- package/dist/tempo/session/server/Session.d.ts +0 -9
- package/dist/tempo/session/server/Session.js +8 -37
- package/dist/tempo/session/server/Settlement.d.ts +0 -7
- package/dist/tempo/session/server/Settlement.js +16 -50
- package/dist/viem/Client.d.ts +7 -2
- package/dist/viem/Client.js +17 -5
- package/dist/x402/Types.d.ts +2 -0
- package/dist/x402/Types.js +2 -0
- package/dist/x402/mcp.d.ts +20 -0
- package/dist/x402/mcp.js +153 -0
- package/dist/x402/middlewares/express.d.ts +23 -0
- package/dist/x402/middlewares/express.js +49 -0
- package/dist/x402/middlewares/hono.d.ts +13 -0
- package/dist/x402/middlewares/hono.js +36 -0
- package/dist/x402/middlewares/next.d.ts +17 -0
- package/dist/x402/middlewares/next.js +58 -0
- package/package.json +41 -1
- package/dist/tempo/internal/machine-token-charge.d.ts +0 -51
- package/dist/tempo/internal/machine-token-charge.js +0 -113
- package/dist/tempo/internal/machine-token-session.d.ts +0 -88
- package/dist/tempo/internal/machine-token-session.js +0 -173
- package/dist/tempo/internal/signature-envelope.d.ts +0 -14
- package/dist/tempo/internal/signature-envelope.js +0 -28
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parseUnits } from 'viem';
|
|
2
2
|
import { tempo as tempo_chain } from 'viem/chains';
|
|
3
3
|
import * as MethodChallenge from '../../../client/internal/MethodChallenge.js';
|
|
4
4
|
import * as MethodResponse from '../../../client/internal/MethodResponse.js';
|
|
@@ -9,15 +9,13 @@ import * as Account from '../../../viem/Account.js';
|
|
|
9
9
|
import * as Client from '../../../viem/Client.js';
|
|
10
10
|
import * as AutoSwap from '../../internal/auto-swap.js';
|
|
11
11
|
import * as defaults from '../../internal/defaults.js';
|
|
12
|
-
import * as MachineTokenSession from '../../internal/machine-token-session.js';
|
|
13
12
|
import * as Methods from '../../Methods.js';
|
|
14
|
-
import * as Chain from '../precompile/Chain.js';
|
|
15
13
|
import * as Channel from '../precompile/Channel.js';
|
|
16
|
-
import { deserializeSessionReceipt, isEventStream, readSessionChallengeAmount, requireSessionCredentialContext,
|
|
17
|
-
import {
|
|
14
|
+
import { deserializeSessionReceipt, isEventStream, readSessionChallengeAmount, requireSessionCredentialContext, } from '../precompile/Protocol.js';
|
|
15
|
+
import { serializeCredential } from './ChannelOps.js';
|
|
18
16
|
import { createChannelStore, entryKey } from './ChannelStore.js';
|
|
19
|
-
import { canSignDescriptor, executeCredentialPlan, hasSessionAction, planCredential,
|
|
20
|
-
import { assertWithinMaxDeposit, resolveAutomaticTopUp
|
|
17
|
+
import { canSignDescriptor, executeCredentialPlan, hasSessionAction, planCredential, resolveChallengeContext, resolveRecoverContext, sessionContextSchema, } from './CredentialState.js';
|
|
18
|
+
import { assertWithinMaxDeposit, resolveAutomaticTopUp } from './Runtime.js';
|
|
21
19
|
import { getSessionSnapshot, handleSseNeedVoucher, isTip1034SessionChallenge, postTopUp, wrapSseResponse, } from './Transports.js';
|
|
22
20
|
export { sessionContextSchema } from './CredentialState.js';
|
|
23
21
|
/** Tail promise for each payment scope, used to serialize automatic opens per store. */
|
|
@@ -71,42 +69,6 @@ function acknowledgesOpen(outcome, challenge, opened) {
|
|
|
71
69
|
return matchesOpen(opened, getSessionSnapshot(candidate));
|
|
72
70
|
}) ?? false);
|
|
73
71
|
}
|
|
74
|
-
function applyMachineTokenRoute(resolved, route) {
|
|
75
|
-
const snapshotDescriptor = resolved.snapshot?.descriptor;
|
|
76
|
-
const snapshotMatches = snapshotDescriptor &&
|
|
77
|
-
isAddressEqual(snapshotDescriptor.payee, route.payee) &&
|
|
78
|
-
isAddressEqual(snapshotDescriptor.operator, route.operator) &&
|
|
79
|
-
isAddressEqual(snapshotDescriptor.token, route.token);
|
|
80
|
-
return {
|
|
81
|
-
...resolved,
|
|
82
|
-
operator: route.operator,
|
|
83
|
-
payee: route.payee,
|
|
84
|
-
paymentScope: { payee: resolved.payee, token: resolved.token },
|
|
85
|
-
snapshot: snapshotMatches ? resolved.snapshot : undefined,
|
|
86
|
-
token: route.token,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
async function resolveMachineContext(resolved, context) {
|
|
90
|
-
const descriptor = context?.descriptor ?? resolved.snapshot?.descriptor;
|
|
91
|
-
if (!descriptor)
|
|
92
|
-
return undefined;
|
|
93
|
-
if (!MachineTokenSession.matchDeployment({ chainId: resolved.chainId, descriptor }))
|
|
94
|
-
return undefined;
|
|
95
|
-
const closing = context?.action === 'close';
|
|
96
|
-
if ((!closing && !MachineTokenSession.isEnabledChallenge(resolved.challenge)) ||
|
|
97
|
-
!isAddressEqual(resolved.escrow, tip20ChannelEscrow))
|
|
98
|
-
return undefined;
|
|
99
|
-
const route = await MachineTokenSession.matchRoute(resolved.client, {
|
|
100
|
-
active: !closing,
|
|
101
|
-
chainId: resolved.chainId,
|
|
102
|
-
descriptor,
|
|
103
|
-
merchant: resolved.payee,
|
|
104
|
-
targetToken: resolved.token,
|
|
105
|
-
});
|
|
106
|
-
if (!route)
|
|
107
|
-
throw new Error('Machine-token channel is not bound to this merchant session challenge.');
|
|
108
|
-
return applyMachineTokenRoute(resolved, route);
|
|
109
|
-
}
|
|
110
72
|
/**
|
|
111
73
|
* Creates the low-level TIP-1034 session payment method for use with `Mppx.create()`.
|
|
112
74
|
*
|
|
@@ -125,15 +87,7 @@ export function session(parameters = {}) {
|
|
|
125
87
|
const maxDeposit = maxDepositParameter !== undefined ? parseUnits(maxDepositParameter, decimals) : undefined;
|
|
126
88
|
const topUpAmount = topUpAmountParameter !== undefined ? parseUnits(topUpAmountParameter, decimals) : undefined;
|
|
127
89
|
const store = channelStore ?? createChannelStore();
|
|
128
|
-
const
|
|
129
|
-
if (!entry)
|
|
130
|
-
return;
|
|
131
|
-
if (entry.opened)
|
|
132
|
-
await store.set(entry);
|
|
133
|
-
else
|
|
134
|
-
await store.delete(entryKey(entry));
|
|
135
|
-
onChannelUpdate?.(entry);
|
|
136
|
-
};
|
|
90
|
+
const sink = { store, notifyUpdate: (entry) => onChannelUpdate?.(entry) };
|
|
137
91
|
const resolveCredentialAccount = async (resolved, context, entry) => {
|
|
138
92
|
const defaultAccount = getAccount(resolved.client, context);
|
|
139
93
|
const descriptor = context?.action
|
|
@@ -149,132 +103,67 @@ export function session(parameters = {}) {
|
|
|
149
103
|
},
|
|
150
104
|
})) ?? defaultAccount);
|
|
151
105
|
};
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
106
|
+
const resolveCredentialPlan = async (resolved, context, entry) => planCredential({
|
|
107
|
+
account: await resolveCredentialAccount(resolved, context, entry),
|
|
108
|
+
entry,
|
|
109
|
+
context,
|
|
110
|
+
decimals,
|
|
111
|
+
maxDeposit,
|
|
112
|
+
resolved,
|
|
157
113
|
});
|
|
158
|
-
/** Selects one rail for this channel lifecycle before any credential is signed. */
|
|
159
|
-
const resolveRail = async (direct, context) => {
|
|
160
|
-
let account;
|
|
161
|
-
const descriptor = context?.descriptor ?? direct.snapshot?.descriptor;
|
|
162
|
-
if (descriptor || hasSessionAction(context)) {
|
|
163
|
-
const machine = descriptor ? await resolveMachineContext(direct, context) : undefined;
|
|
164
|
-
const resolved = machine ?? direct;
|
|
165
|
-
return {
|
|
166
|
-
account,
|
|
167
|
-
entry: await store.get(resolved.key),
|
|
168
|
-
machine: machine !== undefined,
|
|
169
|
-
resolved,
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
const directEntry = await store.get(direct.key);
|
|
173
|
-
if (directEntry?.opened) {
|
|
174
|
-
if (!MachineTokenSession.matchDeployment({
|
|
175
|
-
chainId: direct.chainId,
|
|
176
|
-
descriptor: directEntry.descriptor,
|
|
177
|
-
}))
|
|
178
|
-
return { account, entry: directEntry, machine: false, resolved: direct };
|
|
179
|
-
const machine = await resolveMachineContext(direct, { descriptor: directEntry.descriptor });
|
|
180
|
-
if (!machine)
|
|
181
|
-
throw new Error('Machine-token channel is not bound to this merchant session challenge.');
|
|
182
|
-
return { account, entry: directEntry, machine: true, resolved: machine };
|
|
183
|
-
}
|
|
184
|
-
if (!MachineTokenSession.isEnabledChallenge(direct.challenge) ||
|
|
185
|
-
!isAddressEqual(direct.escrow, tip20ChannelEscrow))
|
|
186
|
-
return { account, entry: undefined, machine: false, resolved: direct };
|
|
187
|
-
const route = await MachineTokenSession.resolveRoute(direct.client, {
|
|
188
|
-
chainId: direct.chainId,
|
|
189
|
-
merchant: direct.payee,
|
|
190
|
-
targetToken: direct.token,
|
|
191
|
-
}).catch(() => undefined);
|
|
192
|
-
if (!route)
|
|
193
|
-
return { account, entry: undefined, machine: false, resolved: direct };
|
|
194
|
-
const machine = applyMachineTokenRoute(direct, route);
|
|
195
|
-
account = await resolveCredentialAccount(machine, context, undefined);
|
|
196
|
-
const openingDeposit = resolveOpeningDeposit({
|
|
197
|
-
contextDepositRaw: context?.depositRaw,
|
|
198
|
-
maxDeposit,
|
|
199
|
-
requestAmount: direct.amount,
|
|
200
|
-
suggestedDepositRaw: direct.suggestedDepositRaw,
|
|
201
|
-
});
|
|
202
|
-
const funded = await MachineTokenSession.hasSufficientBalance(machine.client, {
|
|
203
|
-
account: account.address,
|
|
204
|
-
amount: openingDeposit,
|
|
205
|
-
token: machine.token,
|
|
206
|
-
});
|
|
207
|
-
return funded
|
|
208
|
-
? { account, entry: undefined, machine: true, resolved: machine }
|
|
209
|
-
: { account, entry: undefined, machine: false, resolved: direct };
|
|
210
|
-
};
|
|
211
114
|
const method = Method.toClient(Methods.session, {
|
|
212
115
|
canHandleChallenge: ({ challenge }) => isTip1034SessionChallenge(challenge),
|
|
213
116
|
context: sessionContextSchema,
|
|
214
117
|
async createCredential(parameters) {
|
|
215
118
|
const { challenge, context } = parameters;
|
|
119
|
+
const resolved = await resolveChallengeContext({
|
|
120
|
+
allowCustomEscrow,
|
|
121
|
+
challenge,
|
|
122
|
+
escrowOverride,
|
|
123
|
+
getClient,
|
|
124
|
+
});
|
|
216
125
|
const attempt = MethodResponse.getAttempt(parameters);
|
|
217
126
|
let release = () => { };
|
|
218
127
|
try {
|
|
219
|
-
const
|
|
220
|
-
if (
|
|
221
|
-
release = await lockChannel(store,
|
|
222
|
-
if (attempt && (await store.get(
|
|
128
|
+
const automatic = !hasSessionAction(context) && context?.descriptor === undefined;
|
|
129
|
+
if (automatic) {
|
|
130
|
+
release = await lockChannel(store, resolved.key);
|
|
131
|
+
if (attempt && (await store.get(resolved.key))?.opened)
|
|
223
132
|
await attempt.prepare();
|
|
224
133
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
if (!(await MachineTokenSession.hasSufficientBalance(plan.resolved.client, {
|
|
238
|
-
account: plan.account.address,
|
|
239
|
-
amount: additionalDeposit,
|
|
240
|
-
token: plan.resolved.token,
|
|
241
|
-
})))
|
|
242
|
-
throw new Error('Insufficient machine-token balance for session top-up.');
|
|
243
|
-
}
|
|
244
|
-
const feeToken = MachineTokenSession.resolveFeeToken({
|
|
245
|
-
chainId: resolved.chainId,
|
|
246
|
-
override: resolved.feeToken,
|
|
247
|
-
paymentToken: resolved.token,
|
|
248
|
-
});
|
|
249
|
-
const result = await executeCredentialPlan(plan, AutoSwap.resolve(context?.autoSwap ?? autoSwapParameter, AutoSwap.defaultCurrencies), feeToken);
|
|
250
|
-
let { payload } = result;
|
|
251
|
-
if (machine && payload.action !== 'topUp') {
|
|
252
|
-
if (payload.action === 'close') {
|
|
253
|
-
const state = await Chain.getChannelState(plan.resolved.client, payload.channelId, plan.resolved.escrow);
|
|
254
|
-
if (state.deposit === 0n)
|
|
255
|
-
throw new Error('Cannot authorize a machine-token refund for an empty channel.');
|
|
256
|
-
// The refund authorization covers the full on-chain deposit, while
|
|
257
|
-
// the close voucher remains the exact amount the merchant captures.
|
|
258
|
-
const depositSignature = BigInt(payload.cumulativeAmount) === state.deposit
|
|
259
|
-
? payload.signature
|
|
260
|
-
: (await createVoucherPayload(plan.resolved.client, plan.account, payload.descriptor, state.deposit, plan.resolved.chainId, plan.resolved.escrow)).signature;
|
|
261
|
-
payload = { ...payload, refundSignature: depositSignature };
|
|
134
|
+
let entry = await store.get(resolved.key);
|
|
135
|
+
let plan = await resolveCredentialPlan(resolved, context, entry);
|
|
136
|
+
if (!automatic && attempt && plan.type === 'open') {
|
|
137
|
+
release = await lockChannel(store, resolved.key);
|
|
138
|
+
const nextEntry = await store.get(resolved.key);
|
|
139
|
+
if (nextEntry?.channelId !== entry?.channelId) {
|
|
140
|
+
entry = nextEntry;
|
|
141
|
+
if (entry?.opened) {
|
|
142
|
+
await attempt.prepare();
|
|
143
|
+
entry = await store.get(resolved.key);
|
|
144
|
+
}
|
|
145
|
+
plan = await resolveCredentialPlan(resolved, context, entry);
|
|
262
146
|
}
|
|
263
|
-
const authorizationSignature = await MachineTokenSession.signAuthorization(plan.resolved.client, plan.account, {
|
|
264
|
-
authorization: {
|
|
265
|
-
channelId: payload.channelId,
|
|
266
|
-
cumulativeAmount: BigInt(payload.cumulativeAmount),
|
|
267
|
-
},
|
|
268
|
-
chainId: plan.resolved.chainId,
|
|
269
|
-
router: plan.resolved.operator,
|
|
270
|
-
});
|
|
271
|
-
payload = { ...payload, authorizationSignature };
|
|
272
147
|
}
|
|
273
|
-
|
|
274
|
-
|
|
148
|
+
let pendingOpen;
|
|
149
|
+
// Defer opens only when low-level Fetch owns the response lifecycle.
|
|
150
|
+
// SessionManager unregisters this hook and keeps its existing transaction boundary.
|
|
151
|
+
const credentialSink = attempt && plan.type === 'open'
|
|
152
|
+
? {
|
|
153
|
+
store: {
|
|
154
|
+
get: (key) => store.get(key),
|
|
155
|
+
async set(next) {
|
|
156
|
+
pendingOpen = next;
|
|
157
|
+
},
|
|
158
|
+
delete: (key) => store.delete(key),
|
|
159
|
+
},
|
|
160
|
+
notifyUpdate() { },
|
|
161
|
+
}
|
|
162
|
+
: sink;
|
|
163
|
+
const payload = await executeCredentialPlan(plan, credentialSink, AutoSwap.resolve(context?.autoSwap ?? autoSwapParameter, AutoSwap.defaultCurrencies));
|
|
275
164
|
const credential = await serializeCredential(challenge, payload, resolved.chainId, plan.account);
|
|
276
|
-
if (attempt &&
|
|
277
|
-
const opened =
|
|
165
|
+
if (attempt && pendingOpen) {
|
|
166
|
+
const opened = pendingOpen;
|
|
278
167
|
attempt.settle = async (outcome) => {
|
|
279
168
|
const accepted = outcome.status === 'accepted' || acknowledgesOpen(outcome, challenge, opened);
|
|
280
169
|
if (!accepted && outcome.status === 'pending')
|
|
@@ -284,7 +173,8 @@ export function session(parameters = {}) {
|
|
|
284
173
|
const current = await store.get(resolved.key);
|
|
285
174
|
if (!current?.opened ||
|
|
286
175
|
current.channelId.toLowerCase() !== opened.channelId.toLowerCase()) {
|
|
287
|
-
await
|
|
176
|
+
await store.set(opened);
|
|
177
|
+
sink.notifyUpdate(opened);
|
|
288
178
|
}
|
|
289
179
|
}
|
|
290
180
|
return true;
|
|
@@ -335,7 +225,7 @@ export function session(parameters = {}) {
|
|
|
335
225
|
deposit: latest.deposit > nextDeposit ? latest.deposit : nextDeposit,
|
|
336
226
|
};
|
|
337
227
|
await store.set(updated);
|
|
338
|
-
|
|
228
|
+
sink.notifyUpdate(updated);
|
|
339
229
|
};
|
|
340
230
|
MethodChallenge.register(method, async ({ challenge, context, fetch, input }) => {
|
|
341
231
|
if (!isTip1034SessionChallenge(challenge))
|
|
@@ -343,11 +233,13 @@ export function session(parameters = {}) {
|
|
|
343
233
|
const sessionContext = context === undefined ? undefined : sessionContextSchema.parse(context);
|
|
344
234
|
if (hasSessionAction(sessionContext))
|
|
345
235
|
return;
|
|
346
|
-
const
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
236
|
+
const resolved = await resolveChallengeContext({
|
|
237
|
+
allowCustomEscrow,
|
|
238
|
+
challenge,
|
|
239
|
+
escrowOverride,
|
|
240
|
+
getClient,
|
|
241
|
+
});
|
|
242
|
+
const channel = await store.get(resolved.key);
|
|
351
243
|
if (!channel?.opened)
|
|
352
244
|
return;
|
|
353
245
|
const snapshot = resolved.snapshot?.channelId.toLowerCase() === channel.channelId.toLowerCase()
|
|
@@ -375,17 +267,20 @@ export function session(parameters = {}) {
|
|
|
375
267
|
return MethodResponse.register(method, async ({ challenge, credential, fetch, headers, input, refetch, response, signal }) => {
|
|
376
268
|
if (!isTip1034SessionChallenge(challenge))
|
|
377
269
|
return response;
|
|
378
|
-
const credentialContext = requireSessionCredentialContext(Credential.deserialize(credential).payload);
|
|
379
270
|
if (!isEventStream(response)) {
|
|
271
|
+
const credentialContext = requireSessionCredentialContext(Credential.deserialize(credential).payload);
|
|
380
272
|
if (credentialContext.action === 'open' &&
|
|
381
273
|
headers.get('accept')?.toLowerCase().includes('text/event-stream'))
|
|
382
274
|
return (await refetch?.()) ?? response;
|
|
383
275
|
return response;
|
|
384
276
|
}
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
277
|
+
const channelKey = (await resolveChallengeContext({
|
|
278
|
+
allowCustomEscrow,
|
|
279
|
+
challenge,
|
|
280
|
+
escrowOverride,
|
|
281
|
+
getClient,
|
|
282
|
+
})).key;
|
|
283
|
+
let channel = await store.get(channelKey);
|
|
389
284
|
const driver = {
|
|
390
285
|
assertVoucherWithinLocalLimit: (cumulativeAmount) => assertWithinMaxDeposit(cumulativeAmount, maxDeposit),
|
|
391
286
|
createSessionCredential: (challenge, context) => method.createCredential({ challenge, context }),
|
|
@@ -9,7 +9,6 @@ import * as Account from '../../../viem/Account.js';
|
|
|
9
9
|
import * as Client from '../../../viem/Client.js';
|
|
10
10
|
import { charge as chargePlugin } from '../../client/Charge.js';
|
|
11
11
|
import * as defaults from '../../internal/defaults.js';
|
|
12
|
-
import { hasRewrittenScope, isMachineChannel } from '../client/ChannelOps.js';
|
|
13
12
|
import { createChannelStore, entryKey } from '../client/ChannelStore.js';
|
|
14
13
|
import { hydrateSessionSnapshot } from '../client/CredentialState.js';
|
|
15
14
|
import { session as sessionPlugin } from '../client/Session.js';
|
|
@@ -274,7 +273,7 @@ export function sessionManager(parameters) {
|
|
|
274
273
|
});
|
|
275
274
|
}
|
|
276
275
|
/** Persists a server snapshot into the channel store and returns the entry. */
|
|
277
|
-
async function storeSnapshotHeader(response
|
|
276
|
+
async function storeSnapshotHeader(response) {
|
|
278
277
|
const header = response.headers.get(Constants.Headers.paymentSessionSnapshot);
|
|
279
278
|
if (!header)
|
|
280
279
|
return undefined;
|
|
@@ -289,14 +288,11 @@ export function sessionManager(parameters) {
|
|
|
289
288
|
kind: 'authorizePaymentChannel',
|
|
290
289
|
},
|
|
291
290
|
})) ?? defaultAccount;
|
|
292
|
-
const
|
|
293
|
-
const entry = paymentScope && hasRewrittenScope({ descriptor: hydrated.entry.descriptor, paymentScope })
|
|
294
|
-
? { ...hydrated.entry, paymentScope }
|
|
295
|
-
: hydrated.entry;
|
|
291
|
+
const { entry, spent } = await hydrateSessionSnapshot({ account, client, snapshot });
|
|
296
292
|
assertVoucherWithinLocalLimit(entry.cumulativeAmount);
|
|
297
293
|
await Promise.resolve(store.set(entry)).catch(() => undefined);
|
|
298
294
|
runtime.channel = entry;
|
|
299
|
-
runtime.spent =
|
|
295
|
+
runtime.spent = spent;
|
|
300
296
|
return entry;
|
|
301
297
|
}
|
|
302
298
|
async function bootstrapSession(input, init) {
|
|
@@ -337,10 +333,7 @@ export function sessionManager(parameters) {
|
|
|
337
333
|
},
|
|
338
334
|
});
|
|
339
335
|
if (response.ok)
|
|
340
|
-
return await storeSnapshotHeader(response
|
|
341
|
-
payee: challenge.request.recipient,
|
|
342
|
-
token: challenge.request.currency,
|
|
343
|
-
});
|
|
336
|
+
return await storeSnapshotHeader(response);
|
|
344
337
|
return undefined;
|
|
345
338
|
}
|
|
346
339
|
catch {
|
|
@@ -381,9 +374,8 @@ export function sessionManager(parameters) {
|
|
|
381
374
|
throw new Error('close snapshot payment scope does not match local session');
|
|
382
375
|
}
|
|
383
376
|
const acceptedCumulative = BigInt(snapshot.acceptedCumulative);
|
|
384
|
-
const settled = BigInt(snapshot.settled);
|
|
385
377
|
const snapshotSpent = BigInt(snapshot.spent);
|
|
386
|
-
if (acceptedCumulative < 0n ||
|
|
378
|
+
if (acceptedCumulative < 0n || snapshotSpent < 0n) {
|
|
387
379
|
throw new Error('close snapshot amounts must not be negative');
|
|
388
380
|
}
|
|
389
381
|
if (snapshotSpent > acceptedCumulative) {
|
|
@@ -392,7 +384,7 @@ export function sessionManager(parameters) {
|
|
|
392
384
|
if (acceptedCumulative > channel.cumulativeAmount) {
|
|
393
385
|
throw new Error('close snapshot accepted cumulative exceeds local voucher state');
|
|
394
386
|
}
|
|
395
|
-
return { acceptedCumulative,
|
|
387
|
+
return { acceptedCumulative, spent: snapshotSpent };
|
|
396
388
|
}
|
|
397
389
|
function applyCloseSnapshot(target, challenge) {
|
|
398
390
|
const snapshot = validateCloseSnapshot(target.channel, challenge);
|
|
@@ -410,14 +402,7 @@ export function sessionManager(parameters) {
|
|
|
410
402
|
const snapshot = applySnapshot
|
|
411
403
|
? applyCloseSnapshot(target, challenge)
|
|
412
404
|
: validateCloseSnapshot(target.channel, challenge);
|
|
413
|
-
const
|
|
414
|
-
const closeAmount = snapshot
|
|
415
|
-
? machineSession
|
|
416
|
-
? snapshot.spent > snapshot.settled
|
|
417
|
-
? snapshot.spent
|
|
418
|
-
: snapshot.settled
|
|
419
|
-
: snapshot.acceptedCumulative
|
|
420
|
-
: getFallbackCloseAmount(challenge, target.channelId);
|
|
405
|
+
const closeAmount = snapshot?.acceptedCumulative ?? getFallbackCloseAmount(challenge, target.channelId);
|
|
421
406
|
if (closeAmount > target.channel.cumulativeAmount) {
|
|
422
407
|
throw new Error('fallback close amount exceeds local voucher state');
|
|
423
408
|
}
|
|
@@ -545,10 +530,11 @@ export function sessionManager(parameters) {
|
|
|
545
530
|
trackCreates: false,
|
|
546
531
|
};
|
|
547
532
|
channelUse = use;
|
|
533
|
+
// Cold starts resume from `channelStore` after the 402 reveals the scope.
|
|
534
|
+
const liveHint = runtime.channel?.opened ? runtime.channel.channelId : undefined;
|
|
548
535
|
try {
|
|
549
536
|
await bootstrapSession(input, init);
|
|
550
537
|
use.trackCreates = true;
|
|
551
|
-
const liveHint = runtime.channel?.opened ? runtime.channel.channelId : undefined;
|
|
552
538
|
let effectiveInit = requestInitWithSessionHint(input, init, liveHint);
|
|
553
539
|
// Stored channels may be stale, so retry once after evicting the resumed entry.
|
|
554
540
|
let canRetryResumed = !previous.channel?.opened;
|
|
@@ -556,11 +542,6 @@ export function sessionManager(parameters) {
|
|
|
556
542
|
const resumed = use.resumed;
|
|
557
543
|
if (!canRetryResumed || !resumed)
|
|
558
544
|
return false;
|
|
559
|
-
// A machine-token entry holds the only local copy of its channel
|
|
560
|
-
// descriptor; evicting it would strand the deposit, so fail loudly
|
|
561
|
-
// instead of retrying without it.
|
|
562
|
-
if (resumed.opened && (isMachineChannel(resumed) || hasRewrittenScope(resumed)))
|
|
563
|
-
return false;
|
|
564
545
|
canRetryResumed = false;
|
|
565
546
|
await ignoreChannel(resumed);
|
|
566
547
|
effectiveInit = requestInitWithSessionHint(input, init, undefined);
|
|
@@ -197,8 +197,6 @@ export declare function simulateCredentialTransaction(parameters: {
|
|
|
197
197
|
* Submit a settle transaction on-chain.
|
|
198
198
|
*/
|
|
199
199
|
export declare function settleOnChain(client: Client, descriptor: ChannelDescriptor, cumulativeAmount: bigint, signature: Hex, escrow?: Address, options?: ChannelTransactionOptions): Promise<Hex>;
|
|
200
|
-
/** Submit a settle transaction through the first-party machine-token session router. */
|
|
201
|
-
export declare function settleMachineSessionOnChain(client: Client, descriptor: ChannelDescriptor, cumulativeAmount: bigint, signature: Hex, authorizationSignature: Hex, router: Address, options?: ChannelTransactionOptions): Promise<Hex>;
|
|
202
200
|
/**
|
|
203
201
|
* Submit a top-up transaction on-chain.
|
|
204
202
|
*/
|
|
@@ -215,8 +213,6 @@ export declare function withdrawOnChain(client: Client, descriptor: ChannelDescr
|
|
|
215
213
|
* Submit a close transaction on-chain.
|
|
216
214
|
*/
|
|
217
215
|
export declare function closeOnChain(client: Client, descriptor: ChannelDescriptor, cumulativeAmount: bigint, captureAmount: bigint, signature: Hex, escrow?: Address, options?: ChannelTransactionOptions): Promise<Hex>;
|
|
218
|
-
/** Submit a cooperative close through the first-party machine-token session router. */
|
|
219
|
-
export declare function closeMachineSessionOnChain(client: Client, descriptor: ChannelDescriptor, cumulativeAmount: bigint, signature: Hex, authorizationSignature: Hex, refundSignature: Hex, router: Address, options?: ChannelTransactionOptions): Promise<Hex>;
|
|
220
216
|
/** Receipt event shape emitted by TIP20EscrowChannel precompile management calls. */
|
|
221
217
|
export type ChannelReceiptEvent = {
|
|
222
218
|
args: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { decodeFunctionData, encodeFunctionData, isAddressEqual,
|
|
1
|
+
import { decodeFunctionData, encodeFunctionData, isAddressEqual, parseEventLogs } from 'viem';
|
|
2
2
|
import { call, prepareTransactionRequest, readContract, sendRawTransaction, sendRawTransactionSync, sendTransaction as sendViemTransaction, signTransaction, waitForTransactionReceipt, } from 'viem/actions';
|
|
3
3
|
import { Abis, Addresses, Transaction } from 'viem/tempo';
|
|
4
4
|
import { BadRequestError, VerificationFailedError } from '../../../Errors.js';
|
|
@@ -8,10 +8,6 @@ import * as ChannelOps from '../server/ChannelOps.js';
|
|
|
8
8
|
import * as ChannelUtils from './Channel.js';
|
|
9
9
|
import { escrowAbi } from './escrow.abi.js';
|
|
10
10
|
import { tip20ChannelEscrow } from './Protocol.js';
|
|
11
|
-
const machineSessionAbi = parseAbi([
|
|
12
|
-
'function settleSession((address payer,address payee,address operator,address token,bytes32 salt,address authorizedSigner,bytes32 expiringNonceHash) descriptor,uint96 cumulativeAmount,bytes signature,bytes authorizationSignature)',
|
|
13
|
-
'function closeSession((address payer,address payee,address operator,address token,bytes32 salt,address authorizedSigner,bytes32 expiringNonceHash) descriptor,uint96 cumulativeAmount,bytes signature,bytes authorizationSignature,bytes refundSignature)',
|
|
14
|
-
]);
|
|
15
11
|
const uint96Max = 2n ** 96n - 1n;
|
|
16
12
|
function readBytes32(value, label) {
|
|
17
13
|
if (typeof value === 'string' && /^0x[0-9a-fA-F]{64}$/.test(value))
|
|
@@ -345,26 +341,6 @@ export async function settleOnChain(client, descriptor, cumulativeAmount, signat
|
|
|
345
341
|
const args = [descriptorTuple(descriptor), cumulativeAmount, signature];
|
|
346
342
|
return sendPrecompileTransaction(client, escrow, encodeFunctionData({ abi: escrowAbi, functionName: 'settle', args }), 'settle', options);
|
|
347
343
|
}
|
|
348
|
-
function encodeMachineSessionCall(descriptor, cumulativeAmount, signature, authorizationSignature, refundSignature) {
|
|
349
|
-
assertUint96(cumulativeAmount);
|
|
350
|
-
const args = [
|
|
351
|
-
descriptorTuple(descriptor),
|
|
352
|
-
cumulativeAmount,
|
|
353
|
-
signature,
|
|
354
|
-
authorizationSignature,
|
|
355
|
-
];
|
|
356
|
-
return refundSignature === undefined
|
|
357
|
-
? encodeFunctionData({ abi: machineSessionAbi, functionName: 'settleSession', args })
|
|
358
|
-
: encodeFunctionData({
|
|
359
|
-
abi: machineSessionAbi,
|
|
360
|
-
functionName: 'closeSession',
|
|
361
|
-
args: [...args, refundSignature],
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
/** Submit a settle transaction through the first-party machine-token session router. */
|
|
365
|
-
export async function settleMachineSessionOnChain(client, descriptor, cumulativeAmount, signature, authorizationSignature, router, options) {
|
|
366
|
-
return sendPrecompileTransaction(client, router, encodeMachineSessionCall(descriptor, cumulativeAmount, signature, authorizationSignature), 'settle machine-token session', options);
|
|
367
|
-
}
|
|
368
344
|
/**
|
|
369
345
|
* Submit a top-up transaction on-chain.
|
|
370
346
|
*/
|
|
@@ -396,10 +372,6 @@ export async function closeOnChain(client, descriptor, cumulativeAmount, capture
|
|
|
396
372
|
const args = [descriptorTuple(descriptor), cumulativeAmount, captureAmount, signature];
|
|
397
373
|
return sendPrecompileTransaction(client, escrow, encodeFunctionData({ abi: escrowAbi, functionName: 'close', args }), 'close', options);
|
|
398
374
|
}
|
|
399
|
-
/** Submit a cooperative close through the first-party machine-token session router. */
|
|
400
|
-
export async function closeMachineSessionOnChain(client, descriptor, cumulativeAmount, signature, authorizationSignature, refundSignature, router, options) {
|
|
401
|
-
return sendPrecompileTransaction(client, router, encodeMachineSessionCall(descriptor, cumulativeAmount, signature, authorizationSignature, refundSignature), 'close machine-token session', options);
|
|
402
|
-
}
|
|
403
375
|
/**
|
|
404
376
|
* Asserts that a deserialized transaction has an existing sender signature.
|
|
405
377
|
*/
|
|
@@ -682,6 +654,7 @@ async function sendPrecompileTransaction(client, to, data, label, options) {
|
|
|
682
654
|
account,
|
|
683
655
|
data,
|
|
684
656
|
feePayer: true,
|
|
657
|
+
feeToken: options.feeToken,
|
|
685
658
|
to,
|
|
686
659
|
});
|
|
687
660
|
}
|
|
@@ -57,8 +57,6 @@ export type OpenCredentialPayload = {
|
|
|
57
57
|
transaction: Hex;
|
|
58
58
|
/** Voucher signature for `cumulativeAmount`. */
|
|
59
59
|
signature: Hex;
|
|
60
|
-
/** Machine-token-only router-domain guard for `cumulativeAmount`. */
|
|
61
|
-
authorizationSignature?: Hex | undefined;
|
|
62
60
|
/** Descriptor needed to recover and verify the channel. */
|
|
63
61
|
descriptor: ChannelDescriptor;
|
|
64
62
|
/** Initial cumulative spend authorized by the opening voucher, as raw units. */
|
|
@@ -94,8 +92,6 @@ export type VoucherCredentialPayload = {
|
|
|
94
92
|
cumulativeAmount: RawAmountString;
|
|
95
93
|
/** Voucher signature for `cumulativeAmount`. */
|
|
96
94
|
signature: Hex;
|
|
97
|
-
/** Machine-token-only router-domain guard for `cumulativeAmount`. */
|
|
98
|
-
authorizationSignature?: Hex | undefined;
|
|
99
95
|
};
|
|
100
96
|
/**
|
|
101
97
|
* Credential payload that cooperatively closes a channel at final cumulative spend.
|
|
@@ -110,13 +106,6 @@ export type CloseCredentialPayload = {
|
|
|
110
106
|
cumulativeAmount: RawAmountString;
|
|
111
107
|
/** Voucher signature for `cumulativeAmount`. */
|
|
112
108
|
signature: Hex;
|
|
113
|
-
/** Machine-token-only router-domain guard for `cumulativeAmount`. */
|
|
114
|
-
authorizationSignature?: Hex | undefined;
|
|
115
|
-
/**
|
|
116
|
-
* Machine-token-only signature for the full on-chain deposit. It lets the trusted router
|
|
117
|
-
* return policy-restricted principal without increasing the merchant's authorized capture.
|
|
118
|
-
*/
|
|
119
|
-
refundSignature?: Hex | undefined;
|
|
120
109
|
};
|
|
121
110
|
/**
|
|
122
111
|
* TIP20EscrowChannel precompile session credential payload (discriminated union).
|
|
@@ -135,8 +124,6 @@ export interface SessionVoucher {
|
|
|
135
124
|
*/
|
|
136
125
|
export interface SessionSignedVoucher extends SessionVoucher {
|
|
137
126
|
signature: Hex;
|
|
138
|
-
/** Router-domain guard retained for scheduled machine-token settlement. */
|
|
139
|
-
authorizationSignature?: Hex | undefined;
|
|
140
127
|
}
|
|
141
128
|
/**
|
|
142
129
|
* Management action names shared by session credential payloads.
|
|
@@ -36,7 +36,5 @@ export declare function verifyVoucher(escrowContract: Address, chainId: number,
|
|
|
36
36
|
/**
|
|
37
37
|
* Parse a voucher from credential payload.
|
|
38
38
|
*/
|
|
39
|
-
export declare function parseVoucherFromPayload(channelId: Hex, cumulativeAmount: string, signature: Hex
|
|
40
|
-
authorizationSignature?: Hex | undefined;
|
|
41
|
-
};
|
|
39
|
+
export declare function parseVoucherFromPayload(channelId: Hex, cumulativeAmount: string, signature: Hex): SignedVoucher;
|
|
42
40
|
//# sourceMappingURL=Voucher.d.ts.map
|
|
@@ -3,7 +3,6 @@ import { hashTypedData } from 'viem';
|
|
|
3
3
|
import { signTypedData } from 'viem/actions';
|
|
4
4
|
import { Account as TempoAccount } from 'viem/tempo';
|
|
5
5
|
import * as TempoAddress from '../../internal/address.js';
|
|
6
|
-
import { parseCanonicalEnvelope, serializeCanonicalEnvelope, } from '../../internal/signature-envelope.js';
|
|
7
6
|
import { uint96 } from './Protocol.js';
|
|
8
7
|
/** Must match the on-chain TIP-20 channel reserve DOMAIN_SEPARATOR name. */
|
|
9
8
|
const DOMAIN_NAME = 'TIP20 Channel Reserve';
|
|
@@ -50,6 +49,9 @@ function getVoucherPayload(verifyingContract, chainId, voucher) {
|
|
|
50
49
|
},
|
|
51
50
|
});
|
|
52
51
|
}
|
|
52
|
+
function isPrimitiveEnvelope(type) {
|
|
53
|
+
return type === 'secp256k1' || type === 'p256' || type === 'webAuthn';
|
|
54
|
+
}
|
|
53
55
|
function signCanonicalTempoVoucher(account, parameters) {
|
|
54
56
|
// viem/tempo's canonical TIP-1034 voucher signer accepts Tempo account
|
|
55
57
|
// extensions that are wider than viem's base Account type. Keep that
|
|
@@ -83,7 +85,10 @@ export async function signVoucher(client, account, voucher, verifyingContract, c
|
|
|
83
85
|
message: voucher,
|
|
84
86
|
});
|
|
85
87
|
})();
|
|
86
|
-
|
|
88
|
+
const envelope = SignatureEnvelope.from(signature);
|
|
89
|
+
if (!isPrimitiveEnvelope(envelope.type))
|
|
90
|
+
throw new Error(`TIP-1034 vouchers require a TIP-1020 primitive signature; received "${envelope.type}".`);
|
|
91
|
+
return SignatureEnvelope.serialize(envelope);
|
|
87
92
|
}
|
|
88
93
|
/**
|
|
89
94
|
* Verify a voucher signature matches the expected signer.
|
|
@@ -93,8 +98,10 @@ export async function signVoucher(client, account, voucher, verifyingContract, c
|
|
|
93
98
|
*/
|
|
94
99
|
export function verifyVoucher(escrowContract, chainId, voucher, expectedSigner) {
|
|
95
100
|
try {
|
|
96
|
-
const envelope =
|
|
97
|
-
if (!envelope)
|
|
101
|
+
const envelope = SignatureEnvelope.from(voucher.signature);
|
|
102
|
+
if (!isPrimitiveEnvelope(envelope.type))
|
|
103
|
+
return false;
|
|
104
|
+
if (SignatureEnvelope.serialize(envelope).toLowerCase() !== voucher.signature.toLowerCase())
|
|
98
105
|
return false;
|
|
99
106
|
const payload = getVoucherPayload(escrowContract, chainId, voucher);
|
|
100
107
|
const signer = SignatureEnvelope.extractAddress({ payload, signature: envelope });
|
|
@@ -108,12 +115,11 @@ export function verifyVoucher(escrowContract, chainId, voucher, expectedSigner)
|
|
|
108
115
|
/**
|
|
109
116
|
* Parse a voucher from credential payload.
|
|
110
117
|
*/
|
|
111
|
-
export function parseVoucherFromPayload(channelId, cumulativeAmount, signature
|
|
118
|
+
export function parseVoucherFromPayload(channelId, cumulativeAmount, signature) {
|
|
112
119
|
return {
|
|
113
120
|
channelId,
|
|
114
121
|
cumulativeAmount: uint96(BigInt(cumulativeAmount)),
|
|
115
122
|
signature,
|
|
116
|
-
...(authorizationSignature ? { authorizationSignature } : {}),
|
|
117
123
|
};
|
|
118
124
|
}
|
|
119
125
|
//# sourceMappingURL=Voucher.js.map
|
|
@@ -54,8 +54,6 @@ export type HighestVoucherParameters = {
|
|
|
54
54
|
cumulativeAmount: bigint;
|
|
55
55
|
/** Candidate voucher signature. */
|
|
56
56
|
signature: Hex;
|
|
57
|
-
/** Optional router-domain authorization retained for machine-token settlement. */
|
|
58
|
-
authorizationSignature?: Hex | undefined;
|
|
59
57
|
};
|
|
60
58
|
/** Highest accepted voucher amount plus signed voucher payload. */
|
|
61
59
|
export type HighestVoucher = {
|
|
@@ -95,8 +93,6 @@ export type OpenChannelStateParameters = {
|
|
|
95
93
|
cumulativeAmount: bigint;
|
|
96
94
|
/** Voucher signature for `cumulativeAmount`. */
|
|
97
95
|
signature: Hex;
|
|
98
|
-
/** Optional router-domain authorization for the initial machine-token voucher. */
|
|
99
|
-
authorizationSignature?: Hex | undefined;
|
|
100
96
|
/** Latest on-chain channel state read after open. */
|
|
101
97
|
state: Chain.ChannelState;
|
|
102
98
|
};
|
|
@@ -138,8 +134,6 @@ export type PendingCloseUpdate = {
|
|
|
138
134
|
};
|
|
139
135
|
/** Inputs for finalizing local state after a successful close transaction. */
|
|
140
136
|
export type FinalizeClosedChannelParameters = {
|
|
141
|
-
/** Router authorization paired with the close voucher on machine channels. */
|
|
142
|
-
authorizationSignature?: Hex | undefined;
|
|
143
137
|
/** Amount captured to payee during close. */
|
|
144
138
|
captureAmount: bigint;
|
|
145
139
|
/** Normalized channel ID. */
|