mppx 0.6.2 → 0.6.5
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 +20 -0
- package/dist/Credential.d.ts +4 -0
- package/dist/Credential.d.ts.map +1 -1
- package/dist/Credential.js +18 -2
- package/dist/Credential.js.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/bin.js.map +1 -1
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +166 -54
- package/dist/cli/cli.js.map +1 -1
- package/dist/discovery/Discovery.d.ts +234 -18
- package/dist/discovery/Discovery.d.ts.map +1 -1
- package/dist/discovery/Discovery.js +24 -2
- package/dist/discovery/Discovery.js.map +1 -1
- package/dist/discovery/OpenApi.d.ts +1 -1
- package/dist/discovery/OpenApi.d.ts.map +1 -1
- package/dist/discovery/OpenApi.js +2 -1
- package/dist/discovery/OpenApi.js.map +1 -1
- package/dist/discovery/Validate.d.ts.map +1 -1
- package/dist/discovery/Validate.js +2 -1
- package/dist/discovery/Validate.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/client/Charge.js +1 -1
- package/dist/tempo/client/Charge.js.map +1 -1
- package/dist/tempo/client/SessionManager.d.ts.map +1 -1
- package/dist/tempo/client/SessionManager.js +15 -1
- package/dist/tempo/client/SessionManager.js.map +1 -1
- package/dist/tempo/internal/proof.d.ts +6 -2
- package/dist/tempo/internal/proof.d.ts.map +1 -1
- package/dist/tempo/internal/proof.js +7 -4
- package/dist/tempo/internal/proof.js.map +1 -1
- package/dist/tempo/server/Charge.d.ts.map +1 -1
- package/dist/tempo/server/Charge.js +4 -3
- package/dist/tempo/server/Charge.js.map +1 -1
- package/dist/tempo/server/Session.d.ts.map +1 -1
- package/dist/tempo/server/Session.js +23 -0
- package/dist/tempo/server/Session.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/Chain.d.ts.map +1 -1
- package/dist/tempo/session/Chain.js +29 -0
- package/dist/tempo/session/Chain.js.map +1 -1
- package/package.json +1 -1
- package/src/Challenge.test.ts +45 -0
- package/src/Credential.test.ts +66 -0
- package/src/Credential.ts +23 -3
- package/src/bin.ts +1 -1
- package/src/cli/cli.ts +194 -58
- package/src/cli/mcp.test.ts +233 -0
- package/src/discovery/Discovery.test.ts +66 -4
- package/src/discovery/Discovery.ts +40 -7
- package/src/discovery/OpenApi.test.ts +61 -33
- package/src/discovery/OpenApi.ts +2 -2
- package/src/discovery/Validate.test.ts +117 -0
- package/src/discovery/Validate.ts +2 -1
- 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/nextjs.test.ts +1 -1
- package/src/proxy/Proxy.test.ts +3 -3
- package/src/stripe/server/internal/html.gen.ts +1 -1
- package/src/tempo/client/Charge.ts +1 -1
- package/src/tempo/client/SessionManager.ts +13 -1
- package/src/tempo/internal/proof.test.ts +11 -5
- package/src/tempo/internal/proof.ts +7 -4
- package/src/tempo/server/Charge.test.ts +51 -15
- package/src/tempo/server/Charge.ts +5 -3
- package/src/tempo/server/Session.test.ts +265 -3
- package/src/tempo/server/Session.ts +30 -0
- package/src/tempo/server/internal/html.gen.ts +1 -1
- package/src/tempo/session/Chain.ts +55 -0
|
@@ -244,13 +244,14 @@ export function charge<const parameters extends charge.Parameters>(
|
|
|
244
244
|
domain: Proof.domain(resolvedChainId),
|
|
245
245
|
types: Proof.types,
|
|
246
246
|
primaryType: 'Proof',
|
|
247
|
-
message: Proof.message(challenge.id),
|
|
247
|
+
message: Proof.message(challenge.id, challenge.realm),
|
|
248
248
|
signature: payload.signature as `0x${string}`,
|
|
249
249
|
})
|
|
250
250
|
if (!valid) {
|
|
251
251
|
const proofSigner = recoverAuthorizedProofSigner({
|
|
252
252
|
chainId: resolvedChainId,
|
|
253
253
|
challengeId: challenge.id,
|
|
254
|
+
realm: challenge.realm,
|
|
254
255
|
signature: payload.signature as `0x${string}`,
|
|
255
256
|
sourceAddress: source.address,
|
|
256
257
|
})
|
|
@@ -712,10 +713,11 @@ async function markProofUsed(
|
|
|
712
713
|
function recoverAuthorizedProofSigner(parameters: {
|
|
713
714
|
chainId: number
|
|
714
715
|
challengeId: string
|
|
716
|
+
realm: string
|
|
715
717
|
signature: `0x${string}`
|
|
716
718
|
sourceAddress: `0x${string}`
|
|
717
719
|
}): `0x${string}` | null {
|
|
718
|
-
const { chainId, challengeId, signature, sourceAddress } = parameters
|
|
720
|
+
const { chainId, challengeId, realm, signature, sourceAddress } = parameters
|
|
719
721
|
|
|
720
722
|
try {
|
|
721
723
|
const envelope = SignatureEnvelope.from(signature)
|
|
@@ -723,7 +725,7 @@ function recoverAuthorizedProofSigner(parameters: {
|
|
|
723
725
|
domain: Proof.domain(chainId),
|
|
724
726
|
types: Proof.types,
|
|
725
727
|
primaryType: 'Proof',
|
|
726
|
-
message: Proof.message(challengeId),
|
|
728
|
+
message: Proof.message(challengeId, realm),
|
|
727
729
|
})
|
|
728
730
|
|
|
729
731
|
if (envelope.type === 'keychain') {
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
Transport as ServerTransport,
|
|
8
8
|
tempo as tempo_server,
|
|
9
9
|
} from 'mppx/server'
|
|
10
|
-
import { Base64 } from 'ox'
|
|
10
|
+
import { Base64, Secp256k1 } from 'ox'
|
|
11
11
|
import {
|
|
12
12
|
type Address,
|
|
13
13
|
createClient,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
signatureToCompactSignature,
|
|
18
18
|
} from 'viem'
|
|
19
19
|
import { waitForTransactionReceipt } from 'viem/actions'
|
|
20
|
-
import { Addresses } from 'viem/tempo'
|
|
20
|
+
import { Account as TempoAccount, Actions, Addresses } from 'viem/tempo'
|
|
21
21
|
import { beforeAll, beforeEach, describe, expect, expectTypeOf, test } from 'vp/test'
|
|
22
22
|
import { WebSocketServer } from 'ws'
|
|
23
23
|
import { nodeEnv } from '~test/config.js'
|
|
@@ -50,7 +50,8 @@ import {
|
|
|
50
50
|
import type * as Methods from '../Methods.js'
|
|
51
51
|
import * as ChannelStore from '../session/ChannelStore.js'
|
|
52
52
|
import { deserializeSessionReceipt } from '../session/Receipt.js'
|
|
53
|
-
import
|
|
53
|
+
import { serializeSessionReceipt } from '../session/Receipt.js'
|
|
54
|
+
import type { SessionCredentialPayload, SessionReceipt } from '../session/Types.js'
|
|
54
55
|
import { signVoucher } from '../session/Voucher.js'
|
|
55
56
|
import * as TempoWs from '../session/Ws.js'
|
|
56
57
|
import { charge, session, settle } from './Session.js'
|
|
@@ -1886,6 +1887,77 @@ describe.runIf(isLocalnet)('session', () => {
|
|
|
1886
1887
|
expect(ch!.settledOnChain).toBe(5000000n)
|
|
1887
1888
|
})
|
|
1888
1889
|
|
|
1890
|
+
test('accepts a Tempo access-key account for settlement', async () => {
|
|
1891
|
+
const { channelId, serializedTransaction } = await createSignedOpenTransaction(10000000n)
|
|
1892
|
+
const server = createServer()
|
|
1893
|
+
|
|
1894
|
+
await server.verify({
|
|
1895
|
+
credential: {
|
|
1896
|
+
challenge: makeChallenge({ id: 'settle-access-key-open', channelId }),
|
|
1897
|
+
payload: {
|
|
1898
|
+
action: 'open' as const,
|
|
1899
|
+
type: 'transaction' as const,
|
|
1900
|
+
channelId,
|
|
1901
|
+
transaction: serializedTransaction,
|
|
1902
|
+
cumulativeAmount: '5000000',
|
|
1903
|
+
signature: await signTestVoucher(channelId, 5000000n),
|
|
1904
|
+
},
|
|
1905
|
+
},
|
|
1906
|
+
request: makeRequest(),
|
|
1907
|
+
})
|
|
1908
|
+
|
|
1909
|
+
const privateKey = Secp256k1.randomPrivateKey()
|
|
1910
|
+
const accessKey = TempoAccount.fromSecp256k1(privateKey, {
|
|
1911
|
+
access: recipientAccount,
|
|
1912
|
+
})
|
|
1913
|
+
|
|
1914
|
+
await Actions.accessKey.authorizeSync(client, {
|
|
1915
|
+
account: recipientAccount,
|
|
1916
|
+
accessKey,
|
|
1917
|
+
feeToken: currency,
|
|
1918
|
+
})
|
|
1919
|
+
|
|
1920
|
+
const settleTxHash = await settle(store, client, channelId, {
|
|
1921
|
+
escrowContract,
|
|
1922
|
+
account: accessKey,
|
|
1923
|
+
})
|
|
1924
|
+
expect(settleTxHash).toMatch(/^0x/)
|
|
1925
|
+
|
|
1926
|
+
const ch = await store.getChannel(channelId)
|
|
1927
|
+
expect(ch!.settledOnChain).toBe(5000000n)
|
|
1928
|
+
})
|
|
1929
|
+
|
|
1930
|
+
test('rejects a raw delegated key account with a helpful error', async () => {
|
|
1931
|
+
const { channelId, serializedTransaction } = await createSignedOpenTransaction(10000000n)
|
|
1932
|
+
const server = createServer()
|
|
1933
|
+
|
|
1934
|
+
await server.verify({
|
|
1935
|
+
credential: {
|
|
1936
|
+
challenge: makeChallenge({ id: 'settle-raw-access-key-open', channelId }),
|
|
1937
|
+
payload: {
|
|
1938
|
+
action: 'open' as const,
|
|
1939
|
+
type: 'transaction' as const,
|
|
1940
|
+
channelId,
|
|
1941
|
+
transaction: serializedTransaction,
|
|
1942
|
+
cumulativeAmount: '5000000',
|
|
1943
|
+
signature: await signTestVoucher(channelId, 5000000n),
|
|
1944
|
+
},
|
|
1945
|
+
},
|
|
1946
|
+
request: makeRequest(),
|
|
1947
|
+
})
|
|
1948
|
+
|
|
1949
|
+
const rawAccessKey = TempoAccount.fromSecp256k1(Secp256k1.randomPrivateKey())
|
|
1950
|
+
|
|
1951
|
+
await expect(
|
|
1952
|
+
settle(store, client, channelId, {
|
|
1953
|
+
escrowContract,
|
|
1954
|
+
account: rawAccessKey,
|
|
1955
|
+
}),
|
|
1956
|
+
).rejects.toThrow(
|
|
1957
|
+
`Cannot settle channel ${channelId}: tx sender ${rawAccessKey.address} is not the channel payee ${recipientAccount.address}. If using an access key, pass a Tempo access-key account whose address is the payee wallet, not the raw delegated key address.`,
|
|
1958
|
+
)
|
|
1959
|
+
})
|
|
1960
|
+
|
|
1889
1961
|
test('settle rejects when no channel found', async () => {
|
|
1890
1962
|
const fakeChannelId =
|
|
1891
1963
|
'0x0000000000000000000000000000000000000000000000000000000000000000' as Hex
|
|
@@ -1895,6 +1967,196 @@ describe.runIf(isLocalnet)('session', () => {
|
|
|
1895
1967
|
})
|
|
1896
1968
|
})
|
|
1897
1969
|
|
|
1970
|
+
describe('close account shapes', () => {
|
|
1971
|
+
test('root payee account closes successfully', async () => {
|
|
1972
|
+
const { channelId, serializedTransaction } = await createSignedOpenTransaction(10000000n)
|
|
1973
|
+
const server = createServer()
|
|
1974
|
+
await server.verify({
|
|
1975
|
+
credential: {
|
|
1976
|
+
challenge: makeChallenge({ id: 'close-root-payee-open', channelId }),
|
|
1977
|
+
payload: {
|
|
1978
|
+
action: 'open' as const,
|
|
1979
|
+
type: 'transaction' as const,
|
|
1980
|
+
channelId,
|
|
1981
|
+
transaction: serializedTransaction,
|
|
1982
|
+
cumulativeAmount: '1000000',
|
|
1983
|
+
signature: await signTestVoucher(channelId, 1000000n),
|
|
1984
|
+
},
|
|
1985
|
+
},
|
|
1986
|
+
request: makeRequest(),
|
|
1987
|
+
})
|
|
1988
|
+
|
|
1989
|
+
const closeReceipt = await server.verify({
|
|
1990
|
+
credential: {
|
|
1991
|
+
challenge: makeChallenge({ id: 'close-root-payee', channelId }),
|
|
1992
|
+
payload: {
|
|
1993
|
+
action: 'close' as const,
|
|
1994
|
+
channelId,
|
|
1995
|
+
cumulativeAmount: '1000000',
|
|
1996
|
+
signature: await signTestVoucher(channelId, 1000000n),
|
|
1997
|
+
},
|
|
1998
|
+
},
|
|
1999
|
+
request: makeRequest(),
|
|
2000
|
+
})
|
|
2001
|
+
|
|
2002
|
+
expect(closeReceipt.status).toBe('success')
|
|
2003
|
+
expect((await store.getChannel(channelId))?.finalized).toBe(true)
|
|
2004
|
+
})
|
|
2005
|
+
|
|
2006
|
+
test('payee access-key account closes successfully', async () => {
|
|
2007
|
+
const accessKey = TempoAccount.fromSecp256k1(Secp256k1.randomPrivateKey(), {
|
|
2008
|
+
access: recipientAccount,
|
|
2009
|
+
})
|
|
2010
|
+
|
|
2011
|
+
await Actions.accessKey.authorizeSync(client, {
|
|
2012
|
+
account: recipientAccount,
|
|
2013
|
+
accessKey,
|
|
2014
|
+
feeToken: currency,
|
|
2015
|
+
})
|
|
2016
|
+
|
|
2017
|
+
const { channelId, serializedTransaction } = await createSignedOpenTransaction(10000000n)
|
|
2018
|
+
const server = createServer({ account: accessKey })
|
|
2019
|
+
await server.verify({
|
|
2020
|
+
credential: {
|
|
2021
|
+
challenge: makeChallenge({ id: 'close-access-key-open', channelId }),
|
|
2022
|
+
payload: {
|
|
2023
|
+
action: 'open' as const,
|
|
2024
|
+
type: 'transaction' as const,
|
|
2025
|
+
channelId,
|
|
2026
|
+
transaction: serializedTransaction,
|
|
2027
|
+
cumulativeAmount: '1000000',
|
|
2028
|
+
signature: await signTestVoucher(channelId, 1000000n),
|
|
2029
|
+
},
|
|
2030
|
+
},
|
|
2031
|
+
request: makeRequest(),
|
|
2032
|
+
})
|
|
2033
|
+
|
|
2034
|
+
const closeReceipt = await server.verify({
|
|
2035
|
+
credential: {
|
|
2036
|
+
challenge: makeChallenge({ id: 'close-access-key', channelId }),
|
|
2037
|
+
payload: {
|
|
2038
|
+
action: 'close' as const,
|
|
2039
|
+
channelId,
|
|
2040
|
+
cumulativeAmount: '1000000',
|
|
2041
|
+
signature: await signTestVoucher(channelId, 1000000n),
|
|
2042
|
+
},
|
|
2043
|
+
},
|
|
2044
|
+
request: makeRequest(),
|
|
2045
|
+
})
|
|
2046
|
+
|
|
2047
|
+
expect(closeReceipt.status).toBe('success')
|
|
2048
|
+
expect((await store.getChannel(channelId))?.finalized).toBe(true)
|
|
2049
|
+
})
|
|
2050
|
+
|
|
2051
|
+
test('raw delegated server key fails clearly during close', async () => {
|
|
2052
|
+
const rawAccessKey = TempoAccount.fromSecp256k1(Secp256k1.randomPrivateKey())
|
|
2053
|
+
const { channelId, serializedTransaction } = await createSignedOpenTransaction(10000000n)
|
|
2054
|
+
const server = createServer({ account: rawAccessKey, recipient })
|
|
2055
|
+
await server.verify({
|
|
2056
|
+
credential: {
|
|
2057
|
+
challenge: makeChallenge({ id: 'close-raw-access-key-open', channelId }),
|
|
2058
|
+
payload: {
|
|
2059
|
+
action: 'open' as const,
|
|
2060
|
+
type: 'transaction' as const,
|
|
2061
|
+
channelId,
|
|
2062
|
+
transaction: serializedTransaction,
|
|
2063
|
+
cumulativeAmount: '1000000',
|
|
2064
|
+
signature: await signTestVoucher(channelId, 1000000n),
|
|
2065
|
+
},
|
|
2066
|
+
},
|
|
2067
|
+
request: makeRequest(),
|
|
2068
|
+
})
|
|
2069
|
+
|
|
2070
|
+
await expect(
|
|
2071
|
+
server.verify({
|
|
2072
|
+
credential: {
|
|
2073
|
+
challenge: makeChallenge({ id: 'close-raw-access-key', channelId }),
|
|
2074
|
+
payload: {
|
|
2075
|
+
action: 'close' as const,
|
|
2076
|
+
channelId,
|
|
2077
|
+
cumulativeAmount: '1000000',
|
|
2078
|
+
signature: await signTestVoucher(channelId, 1000000n),
|
|
2079
|
+
},
|
|
2080
|
+
},
|
|
2081
|
+
request: makeRequest(),
|
|
2082
|
+
}),
|
|
2083
|
+
).rejects.toThrow(
|
|
2084
|
+
`Cannot close channel ${channelId}: tx sender ${rawAccessKey.address} is not the channel payee ${recipientAccount.address}. If using an access key, pass a Tempo access-key account whose address is the payee wallet, not the raw delegated key address.`,
|
|
2085
|
+
)
|
|
2086
|
+
})
|
|
2087
|
+
|
|
2088
|
+
test('sessionManager.close surfaces problem details from HTTP close failures', async () => {
|
|
2089
|
+
const challenge = makeChallenge({
|
|
2090
|
+
id: 'close-http-failure',
|
|
2091
|
+
channelId: '0x0000000000000000000000000000000000000000000000000000000000000001' as Hex,
|
|
2092
|
+
})
|
|
2093
|
+
let requests = 0
|
|
2094
|
+
|
|
2095
|
+
const fetch = async (_input: RequestInfo | URL, init?: RequestInit) => {
|
|
2096
|
+
requests++
|
|
2097
|
+
|
|
2098
|
+
const authorization = new Headers(init?.headers).get('Authorization')
|
|
2099
|
+
if (!authorization) {
|
|
2100
|
+
return new Response(null, {
|
|
2101
|
+
status: 402,
|
|
2102
|
+
headers: { 'WWW-Authenticate': Challenge.serialize(challenge) },
|
|
2103
|
+
})
|
|
2104
|
+
}
|
|
2105
|
+
|
|
2106
|
+
const credential = Credential.deserialize<SessionCredentialPayload>(authorization)
|
|
2107
|
+
if (credential.payload.action === 'open') {
|
|
2108
|
+
return new Response('ok', {
|
|
2109
|
+
status: 200,
|
|
2110
|
+
headers: {
|
|
2111
|
+
'Payment-Receipt': serializeSessionReceipt({
|
|
2112
|
+
method: 'tempo',
|
|
2113
|
+
intent: 'session',
|
|
2114
|
+
status: 'success',
|
|
2115
|
+
timestamp: new Date().toISOString(),
|
|
2116
|
+
reference: credential.payload.channelId,
|
|
2117
|
+
challengeId: credential.challenge.id,
|
|
2118
|
+
channelId: credential.payload.channelId,
|
|
2119
|
+
acceptedCumulative: credential.payload.cumulativeAmount,
|
|
2120
|
+
spent: credential.payload.cumulativeAmount,
|
|
2121
|
+
units: 1,
|
|
2122
|
+
}),
|
|
2123
|
+
},
|
|
2124
|
+
})
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
if (credential.payload.action === 'close') {
|
|
2128
|
+
return new Response(
|
|
2129
|
+
JSON.stringify({ detail: 'raw delegated key is not the payee wallet' }),
|
|
2130
|
+
{
|
|
2131
|
+
status: 400,
|
|
2132
|
+
headers: { 'Content-Type': 'application/problem+json' },
|
|
2133
|
+
},
|
|
2134
|
+
)
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
throw new Error(
|
|
2138
|
+
`unexpected payment action ${(credential.payload as { action: string }).action}`,
|
|
2139
|
+
)
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2142
|
+
const manager = sessionManager({
|
|
2143
|
+
account: payer,
|
|
2144
|
+
client,
|
|
2145
|
+
escrowContract,
|
|
2146
|
+
fetch,
|
|
2147
|
+
maxDeposit: '1',
|
|
2148
|
+
})
|
|
2149
|
+
|
|
2150
|
+
const response = await manager.fetch('https://api.example.com/resource')
|
|
2151
|
+
expect(response.status).toBe(200)
|
|
2152
|
+
|
|
2153
|
+
await expect(manager.close()).rejects.toThrow(
|
|
2154
|
+
'Close request failed with status 400: raw delegated key is not the payee wallet',
|
|
2155
|
+
)
|
|
2156
|
+
expect(requests).toBe(3)
|
|
2157
|
+
})
|
|
2158
|
+
})
|
|
2159
|
+
|
|
1898
2160
|
describe('non-persistent storage recovery', () => {
|
|
1899
2161
|
test('open on existing on-chain channel initializes settledOnChain from chain', async () => {
|
|
1900
2162
|
const { channelId, serializedTransaction } = await createSignedOpenTransaction(10000000n)
|
|
@@ -369,6 +369,22 @@ export declare namespace session {
|
|
|
369
369
|
}
|
|
370
370
|
}
|
|
371
371
|
|
|
372
|
+
function assertSettlementSender(parameters: {
|
|
373
|
+
operation: 'close' | 'settle'
|
|
374
|
+
channelId: Hex
|
|
375
|
+
payee: Address
|
|
376
|
+
sender: Address | undefined
|
|
377
|
+
}) {
|
|
378
|
+
const { operation, channelId, payee, sender } = parameters
|
|
379
|
+
if (!sender) return
|
|
380
|
+
if (sender.toLowerCase() === payee.toLowerCase()) return
|
|
381
|
+
throw new BadRequestError({
|
|
382
|
+
reason:
|
|
383
|
+
`Cannot ${operation} channel ${channelId}: tx sender ${sender} is not the channel payee ${payee}. ` +
|
|
384
|
+
'If using an access key, pass a Tempo access-key account whose address is the payee wallet, not the raw delegated key address.',
|
|
385
|
+
})
|
|
386
|
+
}
|
|
387
|
+
|
|
372
388
|
/**
|
|
373
389
|
* One-shot settle: reads highest voucher from store and submits on-chain.
|
|
374
390
|
*/
|
|
@@ -393,6 +409,13 @@ export async function settle(
|
|
|
393
409
|
defaults.escrowContract[chainId as keyof typeof defaults.escrowContract]
|
|
394
410
|
if (!resolvedEscrow) throw new Error(`No escrow contract for chainId ${chainId}.`)
|
|
395
411
|
|
|
412
|
+
assertSettlementSender({
|
|
413
|
+
operation: 'settle',
|
|
414
|
+
channelId,
|
|
415
|
+
payee: channel.payee,
|
|
416
|
+
sender: options?.account?.address ?? client.account?.address,
|
|
417
|
+
})
|
|
418
|
+
|
|
396
419
|
const settledAmount = channel.highestVoucher.cumulativeAmount
|
|
397
420
|
const txHash = await settleOnChain(client, resolvedEscrow, channel.highestVoucher, {
|
|
398
421
|
...(options?.feePayer && options?.account
|
|
@@ -891,6 +914,13 @@ async function handleClose(
|
|
|
891
914
|
throw new InvalidSignatureError({ reason: 'invalid voucher signature' })
|
|
892
915
|
}
|
|
893
916
|
|
|
917
|
+
assertSettlementSender({
|
|
918
|
+
operation: 'close',
|
|
919
|
+
channelId: payload.channelId,
|
|
920
|
+
payee: onChain.payee,
|
|
921
|
+
sender: account?.address ?? client.account?.address,
|
|
922
|
+
})
|
|
923
|
+
|
|
894
924
|
const txHash = await closeOnChain(client, methodDetails.escrowContract, voucher, {
|
|
895
925
|
...(feePayer && account ? { feePayer, account } : { account }),
|
|
896
926
|
})
|