mppx 0.5.13 → 0.5.16

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.
Files changed (83) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/Method.d.ts +5 -2
  3. package/dist/Method.d.ts.map +1 -1
  4. package/dist/Method.js.map +1 -1
  5. package/dist/mcp-sdk/server/Transport.d.ts.map +1 -1
  6. package/dist/mcp-sdk/server/Transport.js +8 -2
  7. package/dist/mcp-sdk/server/Transport.js.map +1 -1
  8. package/dist/server/Mppx.d.ts.map +1 -1
  9. package/dist/server/Mppx.js +17 -10
  10. package/dist/server/Mppx.js.map +1 -1
  11. package/dist/server/Request.js +5 -1
  12. package/dist/server/Request.js.map +1 -1
  13. package/dist/server/Transport.d.ts.map +1 -1
  14. package/dist/server/Transport.js +4 -0
  15. package/dist/server/Transport.js.map +1 -1
  16. package/dist/stripe/server/internal/html.gen.d.ts +1 -1
  17. package/dist/stripe/server/internal/html.gen.d.ts.map +1 -1
  18. package/dist/stripe/server/internal/html.gen.js +1 -1
  19. package/dist/stripe/server/internal/html.gen.js.map +1 -1
  20. package/dist/tempo/Methods.d.ts.map +1 -1
  21. package/dist/tempo/Methods.js +4 -2
  22. package/dist/tempo/Methods.js.map +1 -1
  23. package/dist/tempo/client/SessionManager.d.ts.map +1 -1
  24. package/dist/tempo/client/SessionManager.js +20 -10
  25. package/dist/tempo/client/SessionManager.js.map +1 -1
  26. package/dist/tempo/internal/fee-payer.d.ts +4 -1
  27. package/dist/tempo/internal/fee-payer.d.ts.map +1 -1
  28. package/dist/tempo/internal/fee-payer.js +99 -23
  29. package/dist/tempo/internal/fee-payer.js.map +1 -1
  30. package/dist/tempo/server/Charge.d.ts.map +1 -1
  31. package/dist/tempo/server/Charge.js +6 -0
  32. package/dist/tempo/server/Charge.js.map +1 -1
  33. package/dist/tempo/server/Session.d.ts +4 -0
  34. package/dist/tempo/server/Session.d.ts.map +1 -1
  35. package/dist/tempo/server/Session.js +79 -48
  36. package/dist/tempo/server/Session.js.map +1 -1
  37. package/dist/tempo/server/internal/html.gen.d.ts +1 -1
  38. package/dist/tempo/server/internal/html.gen.d.ts.map +1 -1
  39. package/dist/tempo/server/internal/html.gen.js +1 -1
  40. package/dist/tempo/server/internal/html.gen.js.map +1 -1
  41. package/dist/tempo/server/internal/transport.d.ts +0 -7
  42. package/dist/tempo/server/internal/transport.d.ts.map +1 -1
  43. package/dist/tempo/server/internal/transport.js +84 -13
  44. package/dist/tempo/server/internal/transport.js.map +1 -1
  45. package/dist/tempo/session/Chain.d.ts +5 -0
  46. package/dist/tempo/session/Chain.d.ts.map +1 -1
  47. package/dist/tempo/session/Chain.js +202 -63
  48. package/dist/tempo/session/Chain.js.map +1 -1
  49. package/dist/tempo/session/ChannelStore.d.ts +1 -0
  50. package/dist/tempo/session/ChannelStore.d.ts.map +1 -1
  51. package/dist/tempo/session/ChannelStore.js +38 -15
  52. package/dist/tempo/session/ChannelStore.js.map +1 -1
  53. package/package.json +2 -2
  54. package/src/Method.ts +5 -2
  55. package/src/internal/changeset.test.ts +106 -0
  56. package/src/mcp-sdk/client/McpClient.integration.test.ts +634 -0
  57. package/src/mcp-sdk/server/Transport.test.ts +1 -0
  58. package/src/mcp-sdk/server/Transport.ts +10 -2
  59. package/src/proxy/Proxy.test.ts +149 -1
  60. package/src/server/Mppx.test.ts +120 -0
  61. package/src/server/Mppx.ts +27 -11
  62. package/src/server/Request.test.ts +46 -1
  63. package/src/server/Request.ts +6 -1
  64. package/src/server/Transport.test.ts +2 -0
  65. package/src/server/Transport.ts +4 -0
  66. package/src/stripe/server/internal/html.gen.ts +1 -1
  67. package/src/tempo/Methods.test.ts +13 -0
  68. package/src/tempo/Methods.ts +23 -16
  69. package/src/tempo/client/SessionManager.ts +32 -9
  70. package/src/tempo/internal/fee-payer.test.ts +88 -16
  71. package/src/tempo/internal/fee-payer.ts +118 -23
  72. package/src/tempo/server/Charge.test.ts +73 -0
  73. package/src/tempo/server/Charge.ts +6 -0
  74. package/src/tempo/server/Session.test.ts +934 -47
  75. package/src/tempo/server/Session.ts +100 -52
  76. package/src/tempo/server/internal/html.gen.ts +1 -1
  77. package/src/tempo/server/internal/transport.test.ts +321 -10
  78. package/src/tempo/server/internal/transport.ts +101 -14
  79. package/src/tempo/session/Chain.test.ts +225 -2
  80. package/src/tempo/session/Chain.ts +250 -65
  81. package/src/tempo/session/ChannelStore.test.ts +23 -0
  82. package/src/tempo/session/ChannelStore.ts +46 -13
  83. package/src/viem/Client.test.ts +52 -1
@@ -109,6 +109,18 @@ export type ChannelStore = {
109
109
 
110
110
  export type DeductResult = { ok: true; channel: State } | { ok: false; channel: State }
111
111
 
112
+ export function normalizeChannelId(channelId: Hex): Hex {
113
+ return channelId.toLowerCase() as Hex
114
+ }
115
+
116
+ function normalizeState(channelId: Hex, state: State): State {
117
+ return state.channelId === channelId ? state : { ...state, channelId }
118
+ }
119
+
120
+ function normalizeMaybeState(channelId: Hex, state: State | null): State | null {
121
+ return state ? normalizeState(channelId, state) : null
122
+ }
123
+
112
124
  /**
113
125
  * Atomically deduct `amount` from a channel's available balance.
114
126
  *
@@ -208,54 +220,75 @@ export function fromStore(store: Store.Store | Store.AtomicStore): ChannelStore
208
220
  channelId: Hex,
209
221
  fn: (current: State | null) => Store.Change<State, result>,
210
222
  ): Promise<result> {
223
+ const normalizedChannelId = normalizeChannelId(channelId)
211
224
  let change: Store.Change<State, result> | undefined
212
225
 
213
226
  if (atomicUpdate) {
214
- const result = await atomicUpdate(channelId, (current) => {
215
- change = fn((current as State | null) ?? null)
227
+ const result = await atomicUpdate(normalizedChannelId, (current) => {
228
+ change = fn(normalizeMaybeState(normalizedChannelId, (current as State | null) ?? null))
229
+ if (change.op === 'set') {
230
+ change = {
231
+ ...change,
232
+ value: normalizeState(normalizedChannelId, change.value),
233
+ }
234
+ }
216
235
  if (change.op !== 'set') return change
217
236
  return { ...change, value: change.value as never }
218
237
  })
219
- if (change?.op !== 'noop') notify(channelId)
238
+ if (change?.op !== 'noop') notify(normalizedChannelId)
220
239
  return result
221
240
  }
222
241
 
223
- while (locks.has(channelId)) await locks.get(channelId)
242
+ while (locks.has(normalizedChannelId)) await locks.get(normalizedChannelId)
224
243
 
225
244
  let release!: () => void
226
245
  locks.set(
227
- channelId,
246
+ normalizedChannelId,
228
247
  new Promise<void>((r) => {
229
248
  release = r
230
249
  }),
231
250
  )
232
251
 
233
252
  try {
234
- const current = (await store.get(channelId)) as State | null
253
+ const current = normalizeMaybeState(
254
+ normalizedChannelId,
255
+ (await store.get(normalizedChannelId)) as State | null,
256
+ )
235
257
  change = fn(current)
236
- if (change.op === 'set') await store.put(channelId, change.value as never)
237
- if (change.op === 'delete') await store.delete(channelId)
238
- if (change.op !== 'noop') notify(channelId)
258
+ if (change.op === 'set') {
259
+ change = {
260
+ ...change,
261
+ value: normalizeState(normalizedChannelId, change.value),
262
+ }
263
+ await store.put(normalizedChannelId, change.value as never)
264
+ }
265
+ if (change.op === 'delete') await store.delete(normalizedChannelId)
266
+ if (change.op !== 'noop') notify(normalizedChannelId)
239
267
  return change.result
240
268
  } finally {
241
- locks.delete(channelId)
269
+ locks.delete(normalizedChannelId)
242
270
  release()
243
271
  }
244
272
  }
245
273
 
246
274
  const cs: ChannelStore = {
247
275
  async getChannel(channelId) {
248
- return (await store.get(channelId)) as State | null
276
+ const normalizedChannelId = normalizeChannelId(channelId)
277
+ return normalizeMaybeState(
278
+ normalizedChannelId,
279
+ (await store.get(normalizedChannelId)) as State | null,
280
+ )
249
281
  },
250
282
  async updateChannel(channelId, fn) {
251
283
  return update(channelId, fn)
252
284
  },
253
285
  waitForUpdate(channelId) {
254
286
  return new Promise<void>((resolve) => {
255
- let set = waiters.get(channelId)
287
+ const normalizedChannelId = normalizeChannelId(channelId)
288
+ let set = waiters.get(normalizedChannelId)
256
289
  if (!set) {
257
290
  set = new Set()
258
- waiters.set(channelId, set)
291
+ waiters.set(normalizedChannelId, set)
259
292
  }
260
293
  set.add(resolve)
261
294
  })
@@ -2,7 +2,7 @@ import { createClient, custom, defineChain, type Hex } from 'viem'
2
2
  import { privateKeyToAccount } from 'viem/accounts'
3
3
  import { signTransaction } from 'viem/actions'
4
4
  import { tempoLocalnet } from 'viem/chains'
5
- import { Transaction } from 'viem/tempo'
5
+ import { Account as TempoAccount, Transaction } from 'viem/tempo'
6
6
  import { describe, expect, test } from 'vp/test'
7
7
 
8
8
  import * as Client from './Client.js'
@@ -168,6 +168,57 @@ describe('feePayer transaction serialization', () => {
168
168
  } as never)
169
169
  expect(serverSigned).toMatch(/^0x7[68]/)
170
170
  })
171
+
172
+ test('behavior: deserialized + re-signed tx preserves keyAuthorization', async () => {
173
+ const rootAccount = TempoAccount.fromSecp256k1(
174
+ '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80',
175
+ )
176
+ const accessKey = TempoAccount.fromSecp256k1(
177
+ '0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d',
178
+ { access: rootAccount },
179
+ )
180
+ const feePayerAccount = privateKeyToAccount(
181
+ '0x5de4111afa1a4b94908f83103f52c5de640f0e4f465f975fa6d6640d3c5e3b48',
182
+ )
183
+ const accessKeyClient = createClient({
184
+ account: accessKey,
185
+ chain: tempoLocalnet,
186
+ transport: mockTransport,
187
+ })
188
+
189
+ const keyAuthorization = await rootAccount.signKeyAuthorization(
190
+ {
191
+ accessKeyAddress: accessKey.accessKeyAddress,
192
+ keyType: accessKey.keyType,
193
+ },
194
+ {
195
+ chainId: BigInt(tempoLocalnet.id),
196
+ },
197
+ )
198
+
199
+ const clientSigned = await signTransaction(accessKeyClient, {
200
+ account: accessKey,
201
+ ...feePayer_prepared,
202
+ keyAuthorization,
203
+ } as never)
204
+ const deserialized = Transaction.deserialize(
205
+ clientSigned as Transaction.TransactionSerializedTempo,
206
+ )
207
+
208
+ expect(deserialized.keyAuthorization).toEqual(keyAuthorization)
209
+
210
+ const serverSigned = await signTransaction(tempoClient, {
211
+ ...deserialized,
212
+ account: feePayerAccount,
213
+ feePayer: feePayerAccount,
214
+ feeToken: '0x20c0000000000000000000000000000000000001' as const,
215
+ } as never)
216
+ const serverDeserialized = Transaction.deserialize(
217
+ serverSigned as Transaction.TransactionSerializedTempo,
218
+ )
219
+
220
+ expect(serverDeserialized.keyAuthorization).toEqual(keyAuthorization)
221
+ })
171
222
  })
172
223
 
173
224
  describe('getResolver serializer injection', () => {