mppx 0.6.26 → 0.6.28
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 +15 -0
- package/dist/Store.d.ts +32 -9
- package/dist/Store.d.ts.map +1 -1
- package/dist/Store.js +42 -10
- package/dist/Store.js.map +1 -1
- package/dist/cli/cli.js +1 -1
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/utils.js +2 -2
- package/dist/cli/utils.js.map +1 -1
- package/dist/proxy/internal/Headers.d.ts +13 -1
- package/dist/proxy/internal/Headers.d.ts.map +1 -1
- package/dist/proxy/internal/Headers.js +14 -1
- package/dist/proxy/internal/Headers.js.map +1 -1
- package/dist/stripe/server/Charge.d.ts +31 -1
- package/dist/stripe/server/Charge.d.ts.map +1 -1
- package/dist/stripe/server/Charge.js +88 -11
- package/dist/stripe/server/Charge.js.map +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/client/ChannelOps.d.ts.map +1 -1
- package/dist/tempo/client/ChannelOps.js +7 -2
- package/dist/tempo/client/ChannelOps.js.map +1 -1
- package/dist/tempo/client/Charge.d.ts.map +1 -1
- package/dist/tempo/client/Charge.js +6 -4
- package/dist/tempo/client/Charge.js.map +1 -1
- package/dist/tempo/client/Session.js +1 -1
- package/dist/tempo/client/Session.js.map +1 -1
- package/dist/tempo/client/Subscription.js +1 -1
- package/dist/tempo/client/Subscription.js.map +1 -1
- package/dist/tempo/server/Charge.d.ts +6 -0
- package/dist/tempo/server/Charge.d.ts.map +1 -1
- package/dist/tempo/server/Charge.js +8 -3
- package/dist/tempo/server/Charge.js.map +1 -1
- package/dist/tempo/server/Session.d.ts +6 -0
- package/dist/tempo/server/Session.d.ts.map +1 -1
- package/dist/tempo/server/Session.js +2 -2
- package/dist/tempo/server/Session.js.map +1 -1
- package/dist/tempo/server/Subscription.d.ts +6 -0
- package/dist/tempo/server/Subscription.d.ts.map +1 -1
- package/dist/tempo/server/Subscription.js +2 -2
- 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/Chain.d.ts.map +1 -1
- package/dist/tempo/session/Chain.js +6 -1
- package/dist/tempo/session/Chain.js.map +1 -1
- package/package.json +3 -3
- package/src/Store.test-d.ts +58 -0
- package/src/Store.test.ts +77 -0
- package/src/Store.ts +155 -74
- package/src/cli/cli.ts +1 -1
- package/src/cli/utils.test.ts +1 -1
- package/src/cli/utils.ts +2 -2
- package/src/proxy/internal/Headers.test.ts +18 -0
- package/src/proxy/internal/Headers.ts +14 -1
- package/src/stripe/server/Charge.test.ts +215 -1
- package/src/stripe/server/Charge.ts +150 -20
- package/src/stripe/server/internal/html.gen.ts +1 -1
- package/src/tempo/client/ChannelOps.ts +6 -2
- package/src/tempo/client/Charge.ts +5 -4
- package/src/tempo/client/Session.ts +1 -1
- package/src/tempo/client/Subscription.ts +1 -1
- package/src/tempo/server/Charge.test.ts +22 -1
- package/src/tempo/server/Charge.ts +17 -3
- package/src/tempo/server/Session.ts +10 -2
- package/src/tempo/server/Subscription.test.ts +1 -1
- package/src/tempo/server/Subscription.ts +8 -2
- package/src/tempo/server/internal/html/main.ts +1 -1
- package/src/tempo/server/internal/html/package.json +1 -1
- package/src/tempo/server/internal/html.gen.ts +1 -1
- package/src/tempo/session/Chain.test.ts +16 -8
- package/src/tempo/session/Chain.ts +6 -1
- package/src/tempo/session/ChannelStore.test.ts +21 -0
- package/src/tempo/subscription/Store.test.ts +55 -0
- package/src/viem/Account.test.ts +1 -1
- package/src/viem/Client.test.ts +1 -1
|
@@ -157,6 +157,7 @@ export async function createOpenPayload(
|
|
|
157
157
|
functionName: 'open',
|
|
158
158
|
args: [payee, currency, deposit, salt, authorizedSigner],
|
|
159
159
|
})
|
|
160
|
+
const validBefore = Math.floor(Date.now() / 1_000) + 25
|
|
160
161
|
|
|
161
162
|
const prepared = await prepareTransactionRequest(client, {
|
|
162
163
|
account,
|
|
@@ -164,10 +165,13 @@ export async function createOpenPayload(
|
|
|
164
165
|
{ to: currency, data: approveData },
|
|
165
166
|
{ to: escrowContract, data: openData },
|
|
166
167
|
],
|
|
167
|
-
...(feePayer && { feePayer: true }),
|
|
168
168
|
feeToken: currency,
|
|
169
|
+
...(feePayer ? { nonceKey: 'expiring', validBefore } : {}),
|
|
169
170
|
} as never)
|
|
170
|
-
|
|
171
|
+
// Estimate before enabling fee-payer mode so Tempo includes sender
|
|
172
|
+
// signature and access-key verification costs in the gas budget.
|
|
173
|
+
prepared.gas = (prepared.gas ?? 0n) + 5_000n
|
|
174
|
+
if (feePayer) (prepared as Record<string, unknown>).feePayer = true
|
|
171
175
|
const transaction = (await signTransaction(client, prepared as never)) as Hex.Hex
|
|
172
176
|
|
|
173
177
|
const signature = await signVoucher(
|
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
signTypedData,
|
|
7
7
|
signTransaction,
|
|
8
8
|
} from 'viem/actions'
|
|
9
|
-
import { tempo as tempo_chain } from 'viem/chains'
|
|
10
9
|
import { Actions } from 'viem/tempo'
|
|
10
|
+
import { tempo as tempo_chain } from 'viem/tempo/chains'
|
|
11
11
|
|
|
12
12
|
import * as Credential from '../../Credential.js'
|
|
13
13
|
import * as Method from '../../Method.js'
|
|
@@ -163,12 +163,13 @@ export function charge(parameters: charge.Parameters = {}) {
|
|
|
163
163
|
const prepared = await prepareTransactionRequest(client, {
|
|
164
164
|
account,
|
|
165
165
|
calls,
|
|
166
|
-
...(methodDetails?.feePayer && { feePayer: true }),
|
|
167
166
|
nonceKey: 'expiring',
|
|
168
167
|
validBefore,
|
|
169
168
|
} as never)
|
|
170
|
-
//
|
|
171
|
-
|
|
169
|
+
// Estimate before enabling fee-payer mode so Tempo includes sender
|
|
170
|
+
// signature and access-key verification costs in the gas budget.
|
|
171
|
+
prepared.gas = (prepared.gas ?? 0n) + 5_000n
|
|
172
|
+
if (methodDetails?.feePayer) (prepared as Record<string, unknown>).feePayer = true
|
|
172
173
|
const signature = await signTransaction(client, prepared as never)
|
|
173
174
|
|
|
174
175
|
return Credential.serialize({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Hex } from 'ox'
|
|
2
2
|
import { type Address, parseUnits, type Account as viem_Account } from 'viem'
|
|
3
|
-
import { tempo as tempo_chain } from 'viem/chains'
|
|
3
|
+
import { tempo as tempo_chain } from 'viem/tempo/chains'
|
|
4
4
|
|
|
5
5
|
import type * as Challenge from '../../Challenge.js'
|
|
6
6
|
import * as Method from '../../Method.js'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Hex } from 'ox'
|
|
2
2
|
import { KeyAuthorization } from 'ox/tempo'
|
|
3
3
|
import { isAddressEqual, type Address } from 'viem'
|
|
4
|
-
import { tempo as tempo_chain } from 'viem/chains'
|
|
4
|
+
import { tempo as tempo_chain } from 'viem/tempo/chains'
|
|
5
5
|
|
|
6
6
|
import * as Credential from '../../Credential.js'
|
|
7
7
|
import type { MaybePromise } from '../../internal/types.js'
|
|
@@ -286,6 +286,7 @@ describe('tempo', () => {
|
|
|
286
286
|
})
|
|
287
287
|
|
|
288
288
|
test('behavior: rejects replayed transaction hash', async () => {
|
|
289
|
+
const dedupStore = Store.memory()
|
|
289
290
|
const dedupServer = Mppx_server.create({
|
|
290
291
|
methods: [
|
|
291
292
|
tempo_server.charge({
|
|
@@ -294,7 +295,8 @@ describe('tempo', () => {
|
|
|
294
295
|
},
|
|
295
296
|
currency: asset,
|
|
296
297
|
account: accounts[0],
|
|
297
|
-
store:
|
|
298
|
+
store: dedupStore,
|
|
299
|
+
storeKeyPrefix: 'tenant:',
|
|
298
300
|
}),
|
|
299
301
|
],
|
|
300
302
|
realm,
|
|
@@ -336,6 +338,8 @@ describe('tempo', () => {
|
|
|
336
338
|
})
|
|
337
339
|
expect(response.status).toBe(200)
|
|
338
340
|
}
|
|
341
|
+
expect(await dedupStore.get(`tenant:mppx:charge:${receipt.transactionHash}`)).not.toBeNull()
|
|
342
|
+
expect(await dedupStore.get(`mppx:charge:${receipt.transactionHash}`)).toBeNull()
|
|
339
343
|
|
|
340
344
|
const response2 = await fetch(httpServer.url)
|
|
341
345
|
expect(response2.status).toBe(402)
|
|
@@ -1616,6 +1620,7 @@ describe('tempo', () => {
|
|
|
1616
1620
|
currency: asset,
|
|
1617
1621
|
account: accounts[0],
|
|
1618
1622
|
store: sponsoredStore,
|
|
1623
|
+
storeKeyPrefix: 'tenant:',
|
|
1619
1624
|
}),
|
|
1620
1625
|
],
|
|
1621
1626
|
realm,
|
|
@@ -1661,6 +1666,16 @@ describe('tempo', () => {
|
|
|
1661
1666
|
|
|
1662
1667
|
const first = fetch(httpServer.url, { headers: { Authorization: credential1 } })
|
|
1663
1668
|
await simulationStarted
|
|
1669
|
+
expect(
|
|
1670
|
+
await sponsoredStore.get(
|
|
1671
|
+
`tenant:mppx:charge:sponsor:${chain.id}:${accounts[1].address.toLowerCase()}`,
|
|
1672
|
+
),
|
|
1673
|
+
).not.toBeNull()
|
|
1674
|
+
expect(
|
|
1675
|
+
await sponsoredStore.get(
|
|
1676
|
+
`mppx:charge:sponsor:${chain.id}:${accounts[1].address.toLowerCase()}`,
|
|
1677
|
+
),
|
|
1678
|
+
).toBeNull()
|
|
1664
1679
|
const second = fetch(httpServer.url, { headers: { Authorization: credential2 } })
|
|
1665
1680
|
|
|
1666
1681
|
try {
|
|
@@ -2870,6 +2885,7 @@ describe('tempo', () => {
|
|
|
2870
2885
|
|
|
2871
2886
|
test('behavior: store keys proof replay protection by challenge ID', async () => {
|
|
2872
2887
|
const replayStore = Store.memory()
|
|
2888
|
+
const storeKeyPrefix = 'tenant:'
|
|
2873
2889
|
const server_ = Mppx_server.create({
|
|
2874
2890
|
methods: [
|
|
2875
2891
|
tempo_server.charge({
|
|
@@ -2879,6 +2895,7 @@ describe('tempo', () => {
|
|
|
2879
2895
|
currency: asset,
|
|
2880
2896
|
account: accounts[0],
|
|
2881
2897
|
store: replayStore,
|
|
2898
|
+
storeKeyPrefix,
|
|
2882
2899
|
}),
|
|
2883
2900
|
],
|
|
2884
2901
|
realm,
|
|
@@ -2918,6 +2935,10 @@ describe('tempo', () => {
|
|
|
2918
2935
|
headers: { Authorization: Credential.serialize(credential1) },
|
|
2919
2936
|
})
|
|
2920
2937
|
expect(response2.status).toBe(200)
|
|
2938
|
+
expect(
|
|
2939
|
+
await replayStore.get(`${storeKeyPrefix}mppx:charge:proof:${challenge1.id}`),
|
|
2940
|
+
).not.toBeNull()
|
|
2941
|
+
expect(await replayStore.get(`mppx:charge:proof:${challenge1.id}`)).toBeNull()
|
|
2921
2942
|
|
|
2922
2943
|
const response3 = await fetch(httpServer.url)
|
|
2923
2944
|
expect(response3.status).toBe(402)
|
|
@@ -15,8 +15,8 @@ import {
|
|
|
15
15
|
verifyTypedData,
|
|
16
16
|
call as viem_call,
|
|
17
17
|
} from 'viem/actions'
|
|
18
|
-
import { tempo as tempo_chain } from 'viem/chains'
|
|
19
18
|
import { Abis, Actions, Transaction } from 'viem/tempo'
|
|
19
|
+
import { tempo as tempo_chain } from 'viem/tempo/chains'
|
|
20
20
|
|
|
21
21
|
import { PaymentError, VerificationFailedError } from '../../Errors.js'
|
|
22
22
|
import * as Expires from '../../Expires.js'
|
|
@@ -66,8 +66,16 @@ export function charge<const parameters extends charge.Parameters>(
|
|
|
66
66
|
validateSender,
|
|
67
67
|
waitForConfirmation = true,
|
|
68
68
|
} = parameters
|
|
69
|
-
const
|
|
70
|
-
const
|
|
69
|
+
const storeKeyPrefix = parameters.storeKeyPrefix ?? ''
|
|
70
|
+
const store = Store.from(
|
|
71
|
+
(parameters.store ?? Store.memory()) as Store.AtomicStore<charge.StoreItemMap>,
|
|
72
|
+
{ keyPrefix: storeKeyPrefix },
|
|
73
|
+
)
|
|
74
|
+
const proofStore = parameters.store
|
|
75
|
+
? Store.from(parameters.store as Store.AtomicStore<charge.StoreItemMap>, {
|
|
76
|
+
keyPrefix: storeKeyPrefix,
|
|
77
|
+
})
|
|
78
|
+
: undefined
|
|
71
79
|
|
|
72
80
|
const { recipient, feePayer, feePayerUrl } = Account.resolve(parameters)
|
|
73
81
|
|
|
@@ -539,6 +547,12 @@ export declare namespace charge {
|
|
|
539
547
|
* memo binding, transaction success, and replay protection.
|
|
540
548
|
*/
|
|
541
549
|
validateSender?: ValidateSender | undefined
|
|
550
|
+
/**
|
|
551
|
+
* Prefix prepended to charge replay-protection store keys.
|
|
552
|
+
*
|
|
553
|
+
* By default, no prefix is applied.
|
|
554
|
+
*/
|
|
555
|
+
storeKeyPrefix?: string | undefined
|
|
542
556
|
/**
|
|
543
557
|
* Whether to wait for the charge transaction to confirm on-chain before
|
|
544
558
|
* responding. @default true
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
type Account as viem_Account,
|
|
19
19
|
type Client as viem_Client,
|
|
20
20
|
} from 'viem'
|
|
21
|
-
import { tempo as tempo_chain } from 'viem/chains'
|
|
21
|
+
import { tempo as tempo_chain } from 'viem/tempo/chains'
|
|
22
22
|
|
|
23
23
|
import {
|
|
24
24
|
AmountExceedsDepositError,
|
|
@@ -104,7 +104,9 @@ export function session<const parameters extends session.Parameters>(
|
|
|
104
104
|
|
|
105
105
|
const lastOnChainVerified = new Map<Hex, number>()
|
|
106
106
|
|
|
107
|
-
const store = ChannelStore.fromStore(
|
|
107
|
+
const store = ChannelStore.fromStore(
|
|
108
|
+
Store.from(rawStore, { keyPrefix: parameters.storeKeyPrefix }),
|
|
109
|
+
)
|
|
108
110
|
|
|
109
111
|
const { account, recipient, feePayer, feePayerUrl } = Account.resolve(parameters)
|
|
110
112
|
|
|
@@ -357,6 +359,12 @@ export declare namespace session {
|
|
|
357
359
|
* local single-process usage.
|
|
358
360
|
*/
|
|
359
361
|
store?: Store.AtomicStore | undefined
|
|
362
|
+
/**
|
|
363
|
+
* Prefix prepended to channel state store keys.
|
|
364
|
+
*
|
|
365
|
+
* By default, no prefix is applied.
|
|
366
|
+
*/
|
|
367
|
+
storeKeyPrefix?: string | undefined
|
|
360
368
|
/**
|
|
361
369
|
* Enable SSE streaming.
|
|
362
370
|
*
|
|
@@ -3,7 +3,7 @@ import { Mppx } from 'mppx/server'
|
|
|
3
3
|
import { KeyAuthorization } from 'ox/tempo'
|
|
4
4
|
import { createClient, custom } from 'viem'
|
|
5
5
|
import { privateKeyToAccount } from 'viem/accounts'
|
|
6
|
-
import { tempo as tempo_chain } from 'viem/chains'
|
|
6
|
+
import { tempo as tempo_chain } from 'viem/tempo/chains'
|
|
7
7
|
import { describe, expect, test } from 'vp/test'
|
|
8
8
|
|
|
9
9
|
import * as Store from '../../Store.js'
|
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
sendRawTransactionSync,
|
|
9
9
|
signTransaction,
|
|
10
10
|
} from 'viem/actions'
|
|
11
|
-
import { tempo as tempo_chain } from 'viem/chains'
|
|
12
11
|
import { Abis, Account as TempoAccount, Transaction } from 'viem/tempo'
|
|
12
|
+
import { tempo as tempo_chain } from 'viem/tempo/chains'
|
|
13
13
|
|
|
14
14
|
import { VerificationFailedError } from '../../Errors.js'
|
|
15
15
|
import type { LooseOmit, MaybePromise, NoExtraKeys } from '../../internal/types.js'
|
|
@@ -72,7 +72,7 @@ export function subscription<const parameters extends subscription.Parameters>(
|
|
|
72
72
|
|
|
73
73
|
const { recipient } = Account.resolve(parameters)
|
|
74
74
|
const context = createContext(parameters, {
|
|
75
|
-
store: rawStore,
|
|
75
|
+
store: Store.from(rawStore, { keyPrefix: parameters.storeKeyPrefix }),
|
|
76
76
|
options: {
|
|
77
77
|
activationTimeoutMs: parameters.activationTimeoutMs,
|
|
78
78
|
renewalTimeoutMs: parameters.renewalTimeoutMs,
|
|
@@ -1110,6 +1110,12 @@ export declare namespace subscription {
|
|
|
1110
1110
|
subscription: SubscriptionRecord
|
|
1111
1111
|
}) => Promise<RenewalResult>
|
|
1112
1112
|
store?: Store.AtomicStore<Record<string, unknown>> | undefined
|
|
1113
|
+
/**
|
|
1114
|
+
* Prefix prepended to all subscription store keys.
|
|
1115
|
+
*
|
|
1116
|
+
* By default, no prefix is applied.
|
|
1117
|
+
*/
|
|
1118
|
+
storeKeyPrefix?: string | undefined
|
|
1113
1119
|
testnet?: boolean | undefined
|
|
1114
1120
|
waitForConfirmation?: boolean | undefined
|
|
1115
1121
|
} & Defaults
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { local, Provider } from 'accounts'
|
|
2
2
|
import { createClient, custom, http } from 'viem'
|
|
3
|
-
import { tempoModerato, tempoLocalnet } from 'viem/chains'
|
|
3
|
+
import { tempoModerato, tempoLocalnet } from 'viem/tempo/chains'
|
|
4
4
|
|
|
5
5
|
import { tempo } from '../../../../client/index.js'
|
|
6
6
|
import * as Html from '../../../../Html.js'
|