mppx 0.8.12 → 0.8.13

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 (193) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +16 -1
  3. package/dist/cli/account.d.ts +88 -0
  4. package/dist/cli/account.d.ts.map +1 -1
  5. package/dist/cli/account.js +39 -9
  6. package/dist/cli/account.js.map +1 -1
  7. package/dist/cli/cli.d.ts +2 -1
  8. package/dist/cli/cli.d.ts.map +1 -1
  9. package/dist/cli/cli.js +59 -2
  10. package/dist/cli/cli.js.map +1 -1
  11. package/dist/cli/sessions/Manager.d.ts +31 -0
  12. package/dist/cli/sessions/Manager.d.ts.map +1 -0
  13. package/dist/cli/sessions/Manager.js +56 -0
  14. package/dist/cli/sessions/Manager.js.map +1 -0
  15. package/dist/cli/sessions/commands.d.ts +36 -0
  16. package/dist/cli/sessions/commands.d.ts.map +1 -0
  17. package/dist/cli/sessions/commands.js +407 -0
  18. package/dist/cli/sessions/commands.js.map +1 -0
  19. package/dist/cli/sessions/request.d.ts +35 -0
  20. package/dist/cli/sessions/request.d.ts.map +1 -0
  21. package/dist/cli/sessions/request.js +271 -0
  22. package/dist/cli/sessions/request.js.map +1 -0
  23. package/dist/cli/sessions/store.d.ts +134 -0
  24. package/dist/cli/sessions/store.d.ts.map +1 -0
  25. package/dist/cli/sessions/store.js +723 -0
  26. package/dist/cli/sessions/store.js.map +1 -0
  27. package/dist/cli/utils.d.ts +2 -0
  28. package/dist/cli/utils.d.ts.map +1 -1
  29. package/dist/cli/utils.js +12 -0
  30. package/dist/cli/utils.js.map +1 -1
  31. package/dist/cli/validate/index.d.ts.map +1 -1
  32. package/dist/cli/validate/index.js +12 -6
  33. package/dist/cli/validate/index.js.map +1 -1
  34. package/dist/cli/validate/messages.d.ts +2 -0
  35. package/dist/cli/validate/messages.d.ts.map +1 -0
  36. package/dist/cli/validate/messages.js +8 -0
  37. package/dist/cli/validate/messages.js.map +1 -0
  38. package/dist/client/node.d.ts +29 -0
  39. package/dist/client/node.d.ts.map +1 -0
  40. package/dist/client/node.js +177 -0
  41. package/dist/client/node.js.map +1 -0
  42. package/dist/internal/types.d.ts +24 -0
  43. package/dist/internal/types.d.ts.map +1 -1
  44. package/dist/stripe/server/Charge.d.ts +8 -4
  45. package/dist/stripe/server/Charge.d.ts.map +1 -1
  46. package/dist/stripe/server/Charge.js.map +1 -1
  47. package/dist/stripe/server/internal/html.gen.d.ts +1 -1
  48. package/dist/stripe/server/internal/html.gen.d.ts.map +1 -1
  49. package/dist/stripe/server/internal/html.gen.js +1 -1
  50. package/dist/stripe/server/internal/html.gen.js.map +1 -1
  51. package/dist/tempo/client/Methods.d.ts +1 -1
  52. package/dist/tempo/internal/types.d.ts +10 -1
  53. package/dist/tempo/internal/types.d.ts.map +1 -1
  54. package/dist/tempo/legacy/client/Session.d.ts +2 -2
  55. package/dist/tempo/legacy/server/Session.d.ts +3 -3
  56. package/dist/tempo/legacy/server/Session.d.ts.map +1 -1
  57. package/dist/tempo/legacy/server/Session.js.map +1 -1
  58. package/dist/tempo/server/Charge.d.ts +3 -2
  59. package/dist/tempo/server/Charge.d.ts.map +1 -1
  60. package/dist/tempo/server/Charge.js.map +1 -1
  61. package/dist/tempo/server/Methods.d.ts +2 -23
  62. package/dist/tempo/server/Methods.d.ts.map +1 -1
  63. package/dist/tempo/server/Methods.js +2 -2
  64. package/dist/tempo/server/Methods.js.map +1 -1
  65. package/dist/tempo/server/Subscription.d.ts +3 -2
  66. package/dist/tempo/server/Subscription.d.ts.map +1 -1
  67. package/dist/tempo/server/Subscription.js.map +1 -1
  68. package/dist/tempo/server/index.d.ts +1 -1
  69. package/dist/tempo/server/index.d.ts.map +1 -1
  70. package/dist/tempo/server/index.js.map +1 -1
  71. package/dist/tempo/server/internal/html.gen.d.ts +1 -1
  72. package/dist/tempo/server/internal/html.gen.d.ts.map +1 -1
  73. package/dist/tempo/server/internal/html.gen.js +1 -1
  74. package/dist/tempo/server/internal/html.gen.js.map +1 -1
  75. package/dist/tempo/session/Snapshot.d.ts +9 -0
  76. package/dist/tempo/session/Snapshot.d.ts.map +1 -1
  77. package/dist/tempo/session/Snapshot.js +6 -0
  78. package/dist/tempo/session/Snapshot.js.map +1 -1
  79. package/dist/tempo/session/client/ChannelOps.d.ts.map +1 -1
  80. package/dist/tempo/session/client/ChannelOps.js +11 -2
  81. package/dist/tempo/session/client/ChannelOps.js.map +1 -1
  82. package/dist/tempo/session/client/CredentialState.d.ts +21 -1
  83. package/dist/tempo/session/client/CredentialState.d.ts.map +1 -1
  84. package/dist/tempo/session/client/CredentialState.js +66 -1
  85. package/dist/tempo/session/client/CredentialState.js.map +1 -1
  86. package/dist/tempo/session/client/Session.d.ts +1 -1
  87. package/dist/tempo/session/client/SessionManager.d.ts +2 -2
  88. package/dist/tempo/session/client/SessionManager.d.ts.map +1 -1
  89. package/dist/tempo/session/client/SessionManager.js +128 -30
  90. package/dist/tempo/session/client/SessionManager.js.map +1 -1
  91. package/dist/tempo/session/client/Transports.d.ts +11 -2
  92. package/dist/tempo/session/client/Transports.d.ts.map +1 -1
  93. package/dist/tempo/session/client/Transports.js +33 -9
  94. package/dist/tempo/session/client/Transports.js.map +1 -1
  95. package/dist/tempo/session/client/internal/SessionManager.d.ts +19 -0
  96. package/dist/tempo/session/client/internal/SessionManager.d.ts.map +1 -0
  97. package/dist/tempo/session/client/internal/SessionManager.js +13 -0
  98. package/dist/tempo/session/client/internal/SessionManager.js.map +1 -0
  99. package/dist/tempo/session/precompile/Chain.js +13 -4
  100. package/dist/tempo/session/precompile/Chain.js.map +1 -1
  101. package/dist/tempo/session/server/CredentialVerification.d.ts +3 -0
  102. package/dist/tempo/session/server/CredentialVerification.d.ts.map +1 -1
  103. package/dist/tempo/session/server/CredentialVerification.js +14 -0
  104. package/dist/tempo/session/server/CredentialVerification.js.map +1 -1
  105. package/dist/tempo/session/server/MeteredStream.d.ts +7 -1
  106. package/dist/tempo/session/server/MeteredStream.d.ts.map +1 -1
  107. package/dist/tempo/session/server/MeteredStream.js +5 -4
  108. package/dist/tempo/session/server/MeteredStream.js.map +1 -1
  109. package/dist/tempo/session/server/RequestState.d.ts +5 -1
  110. package/dist/tempo/session/server/RequestState.d.ts.map +1 -1
  111. package/dist/tempo/session/server/RequestState.js +10 -4
  112. package/dist/tempo/session/server/RequestState.js.map +1 -1
  113. package/dist/tempo/session/server/Session.d.ts +21 -6
  114. package/dist/tempo/session/server/Session.d.ts.map +1 -1
  115. package/dist/tempo/session/server/Session.js +4 -1
  116. package/dist/tempo/session/server/Session.js.map +1 -1
  117. package/dist/tempo/session/server/Settlement.d.ts +20 -0
  118. package/dist/tempo/session/server/Settlement.d.ts.map +1 -1
  119. package/dist/tempo/session/server/Settlement.js +20 -0
  120. package/dist/tempo/session/server/Settlement.js.map +1 -1
  121. package/dist/tempo/session/server/Ws.d.ts +2 -0
  122. package/dist/tempo/session/server/Ws.d.ts.map +1 -1
  123. package/dist/tempo/session/server/Ws.js.map +1 -1
  124. package/dist/tempo/session/server/index.d.ts +1 -1
  125. package/dist/tempo/session/server/index.d.ts.map +1 -1
  126. package/dist/tempo/subscription/KeyAuthorization.d.ts +21 -21
  127. package/dist/validation/core.d.ts.map +1 -1
  128. package/dist/validation/core.js +6 -2
  129. package/dist/validation/core.js.map +1 -1
  130. package/dist/viem/Client.d.ts.map +1 -1
  131. package/dist/viem/Client.js +24 -17
  132. package/dist/viem/Client.js.map +1 -1
  133. package/package.json +6 -1
  134. package/src/cli/account.ts +45 -10
  135. package/src/cli/cli.test.ts +165 -70
  136. package/src/cli/cli.ts +67 -2
  137. package/src/cli/mcp.test.ts +11 -0
  138. package/src/cli/sessions/Manager.test.ts +249 -0
  139. package/src/cli/sessions/Manager.ts +93 -0
  140. package/src/cli/sessions/commands.ts +444 -0
  141. package/src/cli/sessions/request.test.ts +51 -0
  142. package/src/cli/sessions/request.ts +353 -0
  143. package/src/cli/sessions/store.test.ts +581 -0
  144. package/src/cli/sessions/store.ts +940 -0
  145. package/src/cli/utils.test.ts +23 -0
  146. package/src/cli/utils.ts +10 -0
  147. package/src/cli/validate/index.ts +12 -14
  148. package/src/cli/validate/messages.ts +7 -0
  149. package/src/cli/validate.test.ts +38 -5
  150. package/src/client/node.test.ts +115 -0
  151. package/src/client/node.ts +247 -0
  152. package/src/internal/types.test-d.ts +21 -0
  153. package/src/internal/types.ts +33 -0
  154. package/src/server/Mppx.test-d.ts +42 -0
  155. package/src/stripe/Methods.test.ts +10 -0
  156. package/src/stripe/server/Charge.test-d.ts +66 -0
  157. package/src/stripe/server/Charge.ts +8 -5
  158. package/src/stripe/server/internal/html.gen.ts +1 -1
  159. package/src/tempo/internal/types.ts +13 -2
  160. package/src/tempo/legacy/server/Defaults.test-d.ts +9 -0
  161. package/src/tempo/legacy/server/Session.ts +6 -5
  162. package/src/tempo/server/Charge.ts +6 -4
  163. package/src/tempo/server/Methods.ts +5 -4
  164. package/src/tempo/server/Subscription.ts +6 -4
  165. package/src/tempo/server/index.ts +5 -1
  166. package/src/tempo/server/internal/html.gen.ts +1 -1
  167. package/src/tempo/session/README.md +201 -0
  168. package/src/tempo/session/Snapshot.ts +21 -0
  169. package/src/tempo/session/client/ChannelOps.test.ts +40 -0
  170. package/src/tempo/session/client/ChannelOps.ts +12 -2
  171. package/src/tempo/session/client/CredentialState.test.ts +2 -2
  172. package/src/tempo/session/client/CredentialState.ts +103 -1
  173. package/src/tempo/session/client/Session.test.ts +3 -3
  174. package/src/tempo/session/client/SessionManager.test.ts +137 -4
  175. package/src/tempo/session/client/SessionManager.ts +139 -33
  176. package/src/tempo/session/client/Transports.test.ts +150 -8
  177. package/src/tempo/session/client/Transports.ts +48 -10
  178. package/src/tempo/session/client/internal/SessionManager.ts +36 -0
  179. package/src/tempo/session/precompile/Chain.test.ts +26 -0
  180. package/src/tempo/session/precompile/Chain.ts +17 -4
  181. package/src/tempo/session/server/CredentialVerification.ts +18 -1
  182. package/src/tempo/session/server/MeteredStream.ts +12 -5
  183. package/src/tempo/session/server/RequestState.test.ts +39 -3
  184. package/src/tempo/session/server/RequestState.ts +13 -6
  185. package/src/tempo/session/server/Session.test.ts +461 -0
  186. package/src/tempo/session/server/Session.ts +31 -8
  187. package/src/tempo/session/server/Settlement.ts +45 -0
  188. package/src/tempo/session/server/Ws.test.ts +113 -0
  189. package/src/tempo/session/server/Ws.ts +2 -0
  190. package/src/tempo/session/server/index.ts +2 -0
  191. package/src/validation/core.ts +7 -1
  192. package/src/viem/Client.test.ts +44 -1
  193. package/src/viem/Client.ts +31 -17
@@ -408,6 +408,119 @@ describe('isows', () => {
408
408
  expect(channel?.units).toBe(0)
409
409
  })
410
410
 
411
+ test('aborts a blocked application generator before sending close-ready', async () => {
412
+ const socket = new MockSocket()
413
+ const store = memoryChannelStore()
414
+ await seedChannel(store, 1n)
415
+ let generatorAborted = false
416
+
417
+ await Ws.serve({
418
+ socket,
419
+ store,
420
+ url: 'ws://example.test/stream',
421
+ route: async () => ({
422
+ status: 200,
423
+ withReceipt(response = new Response(null, { status: 204 })) {
424
+ response.headers.set(
425
+ 'Payment-Receipt',
426
+ serializeSessionReceipt(
427
+ createSessionReceipt({
428
+ challengeId: challenge.id,
429
+ channelId,
430
+ acceptedCumulative: 1n,
431
+ spent: 0n,
432
+ units: 0,
433
+ }),
434
+ ),
435
+ )
436
+ return response
437
+ },
438
+ }),
439
+ generate: async function* (stream) {
440
+ await new Promise<void>((resolve) => {
441
+ stream.signal.addEventListener('abort', () => resolve(), { once: true })
442
+ })
443
+ generatorAborted = true
444
+ yield* []
445
+ },
446
+ })
447
+
448
+ socket.receive(
449
+ Ws.formatAuthorizationMessage(
450
+ makeCredential({
451
+ action: 'open',
452
+ channelId,
453
+ cumulativeAmount: '1',
454
+ signature: `0x${'77'.repeat(65)}`,
455
+ transaction: '0x01',
456
+ type: 'transaction',
457
+ }),
458
+ ),
459
+ )
460
+ await sleep(10)
461
+ socket.receive(Ws.formatCloseRequestMessage())
462
+ await sleep(10)
463
+
464
+ expect(generatorAborted).toBe(true)
465
+ expect(
466
+ socket.sent
467
+ .map((message) => Ws.parseMessage(message))
468
+ .some((message) => message?.mpp === 'payment-close-ready'),
469
+ ).toBe(true)
470
+ })
471
+
472
+ test('meters an explicit per-message amount independently of the challenge tick cost', async () => {
473
+ const socket = new MockSocket()
474
+ const store = memoryChannelStore()
475
+ await seedChannel(store, 25n)
476
+
477
+ await Ws.serve({
478
+ socket,
479
+ store,
480
+ url: 'ws://example.test/stream',
481
+ route: async () => ({
482
+ status: 200,
483
+ withReceipt(response = new Response(null, { status: 204 })) {
484
+ response.headers.set(
485
+ 'Payment-Receipt',
486
+ serializeSessionReceipt(
487
+ createSessionReceipt({
488
+ challengeId: challenge.id,
489
+ channelId,
490
+ acceptedCumulative: 25n,
491
+ spent: 0n,
492
+ units: 0,
493
+ }),
494
+ ),
495
+ )
496
+ return response
497
+ },
498
+ }),
499
+ generate: async function* (stream) {
500
+ await stream.charge(7n)
501
+ yield 'priced-response'
502
+ },
503
+ })
504
+
505
+ socket.receive(
506
+ Ws.formatAuthorizationMessage(
507
+ makeCredential({
508
+ action: 'open',
509
+ channelId,
510
+ cumulativeAmount: '25',
511
+ signature: `0x${'77'.repeat(65)}`,
512
+ transaction: '0x01',
513
+ type: 'transaction',
514
+ }),
515
+ ),
516
+ )
517
+
518
+ await sleep(10)
519
+
520
+ expect(await store.getChannel(channelId)).toMatchObject({ spent: 7n, units: 1 })
521
+ expect(socket.sent.some((message) => message.includes('priced-response'))).toBe(true)
522
+ })
523
+
411
524
  test('does not meter or emit application messages after close is requested on-chain', async () => {
412
525
  const socket = new MockSocket()
413
526
  const store = memoryChannelStore()
@@ -322,6 +322,8 @@ export declare namespace serve {
322
322
  * multiple offers — otherwise a client can select the cheapest offer
323
323
  * and still receive the same stream. */
324
324
  amount?: string | undefined
325
+ /** Application stream. A manual stream can call `charge(amount)` with a
326
+ * per-message raw-unit amount; omitting it uses the challenge tick cost. */
325
327
  generate: AsyncIterable<string> | ((stream: SessionController) => AsyncIterable<string>)
326
328
  pollIntervalMs?: number | undefined
327
329
  /** Payment route handler. Receives synthetic `POST` requests with only
@@ -3,8 +3,10 @@ export { charge, session, settle, settleBatch } from './Session.js'
3
3
  export * as Sse from './Sse.js'
4
4
  /** Server-side automatic settlement schedule. */
5
5
  export type {
6
+ OnSessionSettlement,
6
7
  ResolveSessionChannelId,
7
8
  ResolveSessionChannelIdParameters,
8
9
  SessionChannelIdRequest,
10
+ SessionSettlementContext,
9
11
  SettlementSchedule,
10
12
  } from './Session.js'
@@ -14,6 +14,7 @@ import {
14
14
  parseEndpointArg,
15
15
  resolveBodyForEndpoint,
16
16
  } from '../cli/validate/helpers.js'
17
+ import { missingDiscoverySuggestion } from '../cli/validate/messages.js'
17
18
  import { validatePaymentFlow } from '../cli/validate/payment.js'
18
19
  import { validate as validateDiscoveryDoc } from '../discovery/Validate.js'
19
20
 
@@ -237,7 +238,7 @@ export async function validate(options: ValidateOptions): Promise<ValidateResult
237
238
 
238
239
  if (!discovery) throw new Error('Discovery phase did not complete')
239
240
 
240
- const suggestions = computeSuggestions(endpointResults, { sawTestnet, sawMainnet })
241
+ const suggestions = computeSuggestions(endpointResults, discovery, { sawTestnet, sawMainnet })
241
242
 
242
243
  return {
243
244
  url: baseUrl,
@@ -250,11 +251,16 @@ export async function validate(options: ValidateOptions): Promise<ValidateResult
250
251
 
251
252
  function computeSuggestions(
252
253
  endpoints: EndpointValidationResult[],
254
+ discovery: DiscoveryResult,
253
255
  flags: { sawTestnet: boolean; sawMainnet: boolean },
254
256
  ): string[] {
255
257
  const steps: string[] = []
256
258
  const allResults = endpoints.flatMap((ep) => [...ep.challenge, ...ep.payment])
257
259
 
260
+ if (!discovery.found) {
261
+ steps.push(missingDiscoverySuggestion)
262
+ }
263
+
258
264
  const sawCryptoMainnet = flags.sawMainnet
259
265
  const sawCryptoTestnet = flags.sawTestnet
260
266
  const sawStripeLive = allResults.some(
@@ -3,12 +3,16 @@ import { privateKeyToAccount } from 'viem/accounts'
3
3
  import { signTransaction } from 'viem/actions'
4
4
  import { Account as TempoAccount, Transaction } from 'viem/tempo'
5
5
  import { tempoLocalnet } from 'viem/tempo/chains'
6
- import { describe, expect, test } from 'vp/test'
6
+ import { afterEach, describe, expect, test, vi } from 'vp/test'
7
7
 
8
8
  import * as Client from './Client.js'
9
9
 
10
10
  const rpcUrl = { 42: 'https://rpc.example.com', 99: 'https://rpc2.example.com' } as const
11
11
 
12
+ afterEach(() => {
13
+ vi.unstubAllGlobals()
14
+ })
15
+
12
16
  describe('getResolver', () => {
13
17
  test('behavior: creates client from rpcUrl for given chainId', async () => {
14
18
  const getClient = Client.getResolver({
@@ -61,6 +65,45 @@ describe('getResolver', () => {
61
65
  `[Error: No \`rpcUrl\` configured for \`chainId\` (99).]`,
62
66
  )
63
67
  })
68
+
69
+ test('behavior: wraps custom client transports with a hosted fee payer', async () => {
70
+ const defaultRequests: string[] = []
71
+ const client = createClient({
72
+ chain: tempoLocalnet,
73
+ transport: custom({
74
+ async request({ method }) {
75
+ defaultRequests.push(method)
76
+ return { source: 'default' }
77
+ },
78
+ }),
79
+ })
80
+ const fetchMock = vi.fn(async (_input: RequestInfo | URL, init?: RequestInit) => {
81
+ const request = JSON.parse(String(init?.body)) as { id: number; jsonrpc: string }
82
+ return Response.json({
83
+ id: request.id,
84
+ jsonrpc: request.jsonrpc,
85
+ result: { source: 'relay' },
86
+ })
87
+ })
88
+ vi.stubGlobal('fetch', fetchMock)
89
+
90
+ const getClient = Client.getResolver({
91
+ chain: tempoLocalnet,
92
+ feePayerUrl: 'https://sponsor.example',
93
+ getClient: () => client,
94
+ rpcUrl: { [tempoLocalnet.id]: 'https://rpc.example.com' },
95
+ })
96
+ const resolved = await getClient({ chainId: tempoLocalnet.id })
97
+ const result = await resolved.request({
98
+ method: 'eth_fillTransaction',
99
+ params: [{ feePayer: true }],
100
+ } as never)
101
+
102
+ expect(result).toEqual({ source: 'relay' })
103
+ expect(fetchMock).toHaveBeenCalledOnce()
104
+ expect(String(fetchMock.mock.calls[0]?.[0])).toBe('https://sponsor.example/')
105
+ expect(defaultRequests).toEqual([])
106
+ })
64
107
  })
65
108
 
66
109
  // ---------------------------------------------------------------------------
@@ -1,4 +1,4 @@
1
- import { type Chain, type Client, createClient, http } from 'viem'
1
+ import { type Chain, type Client, createClient, createTransport, custom, http } from 'viem'
2
2
  import { withFeePayer } from 'viem/tempo'
3
3
 
4
4
  import type { MaybePromise } from '../internal/types.js'
@@ -23,31 +23,45 @@ export function getResolver(
23
23
  if (!chain?.serializers && !feePayerUrl) return getClient
24
24
  return async (params) => {
25
25
  const client = await getClient(params)
26
+ let resolvedClient = client
26
27
 
27
28
  // Wrap the client's transport with `withFeePayer` when a fee payer URL is provided.
28
29
  if (feePayerUrl && client.transport.key !== 'feePayer') {
29
- const url = (client.transport as { url?: string }).url
30
- if (url) {
31
- const wrapped = createClient({
32
- chain: client.chain,
33
- transport: withFeePayer(http(url), http(feePayerUrl)),
34
- })
35
- Object.assign(client, { transport: wrapped.transport, request: wrapped.request })
36
- }
30
+ const request = client.request.bind(client)
31
+ // The supplied client already owns retries. Keep the relay middleware retry-free so
32
+ // failures are not retried once per nested transport layer.
33
+ const feePayerTransport = withFeePayer(
34
+ custom({ request: (args) => request(args as never) }, { retryCount: 0 }),
35
+ http(feePayerUrl, { retryCount: client.transport.retryCount }),
36
+ )({
37
+ account: client.account,
38
+ chain: client.chain,
39
+ pollingInterval: client.pollingInterval,
40
+ retryCount: 0,
41
+ })
42
+ const wrapped = createTransport(
43
+ { ...feePayerTransport.config, retryCount: 0 },
44
+ feePayerTransport.value,
45
+ )
46
+ resolvedClient = Object.assign({}, client, {
47
+ request: wrapped.request,
48
+ transport: { ...wrapped.config, ...wrapped.value },
49
+ })
37
50
  }
38
51
 
39
- if (!chain?.serializers || client.chain?.serializers?.transaction) return client
40
- return Object.assign({}, client, {
52
+ if (!chain?.serializers || resolvedClient.chain?.serializers?.transaction)
53
+ return resolvedClient
54
+ return Object.assign({}, resolvedClient, {
41
55
  chain: {
42
56
  ...chain,
43
- ...client.chain,
44
- formatters: client.chain?.formatters ?? chain.formatters,
57
+ ...resolvedClient.chain,
58
+ formatters: resolvedClient.chain?.formatters ?? chain.formatters,
45
59
  prepareTransactionRequest:
46
- client.chain?.prepareTransactionRequest ?? chain.prepareTransactionRequest,
47
- serializers: client.chain?.serializers?.transaction
48
- ? client.chain.serializers
60
+ resolvedClient.chain?.prepareTransactionRequest ?? chain.prepareTransactionRequest,
61
+ serializers: resolvedClient.chain?.serializers?.transaction
62
+ ? resolvedClient.chain.serializers
49
63
  : chain.serializers,
50
- } as typeof client.chain,
64
+ } as typeof resolvedClient.chain,
51
65
  })
52
66
  }
53
67
  }