@unionlabs/payments 0.2.1 → 0.3.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.
Files changed (126) hide show
  1. package/dist/cjs/Attestor.js +9 -2
  2. package/dist/cjs/Attestor.js.map +1 -1
  3. package/dist/cjs/Domain.js +8 -2
  4. package/dist/cjs/Domain.js.map +1 -1
  5. package/dist/cjs/Error.js +1 -1
  6. package/dist/cjs/Error.js.map +1 -1
  7. package/dist/cjs/EvmPublicClient.js +5 -277
  8. package/dist/cjs/EvmPublicClient.js.map +1 -1
  9. package/dist/cjs/EvmWalletClient.js +7 -642
  10. package/dist/cjs/EvmWalletClient.js.map +1 -1
  11. package/dist/cjs/Payment.js +84 -79
  12. package/dist/cjs/Payment.js.map +1 -1
  13. package/dist/cjs/Prover.js +2 -2
  14. package/dist/cjs/Prover.js.map +1 -1
  15. package/dist/cjs/PublicClient.js +2 -2
  16. package/dist/cjs/PublicClient.js.map +1 -1
  17. package/dist/cjs/WalletClient.js +2 -2
  18. package/dist/cjs/WalletClient.js.map +1 -1
  19. package/dist/cjs/constants/ibc-core-registry.js +6 -6
  20. package/dist/cjs/constants/ibc-core-registry.js.map +1 -1
  21. package/dist/cjs/internal/evmPublicClient.js +261 -0
  22. package/dist/cjs/internal/evmPublicClient.js.map +1 -0
  23. package/dist/cjs/internal/evmWalletClient.js +695 -0
  24. package/dist/cjs/internal/evmWalletClient.js.map +1 -1
  25. package/dist/cjs/internal/publicClient.js +0 -2
  26. package/dist/cjs/internal/publicClient.js.map +1 -1
  27. package/dist/cjs/promises/Payment.js +4 -3
  28. package/dist/cjs/promises/Payment.js.map +1 -1
  29. package/dist/cjs/promises/PublicClient.js +1 -2
  30. package/dist/cjs/promises/PublicClient.js.map +1 -1
  31. package/dist/cjs/promises/WalletClient.js +0 -1
  32. package/dist/cjs/promises/WalletClient.js.map +1 -1
  33. package/dist/cjs/rpc.js +3 -5
  34. package/dist/cjs/rpc.js.map +1 -1
  35. package/dist/dts/Attestor.d.ts +21 -6
  36. package/dist/dts/Attestor.d.ts.map +1 -1
  37. package/dist/dts/Domain.d.ts +92 -59
  38. package/dist/dts/Domain.d.ts.map +1 -1
  39. package/dist/dts/Error.d.ts +2 -2
  40. package/dist/dts/Error.d.ts.map +1 -1
  41. package/dist/dts/EvmPublicClient.d.ts +7 -19
  42. package/dist/dts/EvmPublicClient.d.ts.map +1 -1
  43. package/dist/dts/EvmWalletClient.d.ts +7 -23
  44. package/dist/dts/EvmWalletClient.d.ts.map +1 -1
  45. package/dist/dts/Payment.d.ts +71 -69
  46. package/dist/dts/Payment.d.ts.map +1 -1
  47. package/dist/dts/Prover.d.ts +6 -0
  48. package/dist/dts/Prover.d.ts.map +1 -1
  49. package/dist/dts/PublicClient.d.ts +7 -11
  50. package/dist/dts/PublicClient.d.ts.map +1 -1
  51. package/dist/dts/WalletClient.d.ts +10 -4
  52. package/dist/dts/WalletClient.d.ts.map +1 -1
  53. package/dist/dts/constants/ibc-core-registry.d.ts +5 -6
  54. package/dist/dts/constants/ibc-core-registry.d.ts.map +1 -1
  55. package/dist/dts/internal/evm.d.ts +3 -3
  56. package/dist/dts/internal/evm.d.ts.map +1 -1
  57. package/dist/dts/internal/evmPublicClient.d.ts +6 -0
  58. package/dist/dts/internal/evmPublicClient.d.ts.map +1 -0
  59. package/dist/dts/promises/Attestor.d.ts +5 -5
  60. package/dist/dts/promises/EvmPublicClient.d.ts +73 -74
  61. package/dist/dts/promises/EvmPublicClient.d.ts.map +1 -1
  62. package/dist/dts/promises/EvmWalletClient.d.ts +4 -5
  63. package/dist/dts/promises/EvmWalletClient.d.ts.map +1 -1
  64. package/dist/dts/promises/Payment.d.ts +39 -17
  65. package/dist/dts/promises/Payment.d.ts.map +1 -1
  66. package/dist/dts/promises/PublicClient.d.ts +3 -4
  67. package/dist/dts/promises/PublicClient.d.ts.map +1 -1
  68. package/dist/dts/promises/WalletClient.d.ts +77 -34
  69. package/dist/dts/promises/WalletClient.d.ts.map +1 -1
  70. package/dist/dts/rpc.d.ts +31 -0
  71. package/dist/dts/rpc.d.ts.map +1 -1
  72. package/dist/esm/Attestor.js +8 -1
  73. package/dist/esm/Attestor.js.map +1 -1
  74. package/dist/esm/Domain.js +7 -1
  75. package/dist/esm/Domain.js.map +1 -1
  76. package/dist/esm/Error.js +1 -1
  77. package/dist/esm/Error.js.map +1 -1
  78. package/dist/esm/EvmPublicClient.js +4 -275
  79. package/dist/esm/EvmPublicClient.js.map +1 -1
  80. package/dist/esm/EvmWalletClient.js +5 -638
  81. package/dist/esm/EvmWalletClient.js.map +1 -1
  82. package/dist/esm/Payment.js +82 -78
  83. package/dist/esm/Payment.js.map +1 -1
  84. package/dist/esm/Prover.js +1 -1
  85. package/dist/esm/Prover.js.map +1 -1
  86. package/dist/esm/PublicClient.js +2 -2
  87. package/dist/esm/PublicClient.js.map +1 -1
  88. package/dist/esm/Schema.js +8 -4
  89. package/dist/esm/Schema.js.map +1 -1
  90. package/dist/esm/WalletClient.js +2 -2
  91. package/dist/esm/WalletClient.js.map +1 -1
  92. package/dist/esm/constants/ibc-core-registry.js +4 -4
  93. package/dist/esm/constants/ibc-core-registry.js.map +1 -1
  94. package/dist/esm/internal/evmPublicClient.js +253 -0
  95. package/dist/esm/internal/evmPublicClient.js.map +1 -0
  96. package/dist/esm/internal/evmWalletClient.js +691 -1
  97. package/dist/esm/internal/evmWalletClient.js.map +1 -1
  98. package/dist/esm/internal/publicClient.js +0 -2
  99. package/dist/esm/internal/publicClient.js.map +1 -1
  100. package/dist/esm/promises/Payment.js +2 -2
  101. package/dist/esm/promises/Payment.js.map +1 -1
  102. package/dist/esm/promises/PublicClient.js +2 -3
  103. package/dist/esm/promises/PublicClient.js.map +1 -1
  104. package/dist/esm/promises/WalletClient.js +0 -1
  105. package/dist/esm/promises/WalletClient.js.map +1 -1
  106. package/dist/esm/rpc.js +2 -4
  107. package/dist/esm/rpc.js.map +1 -1
  108. package/package.json +7 -3
  109. package/src/Attestor.ts +12 -3
  110. package/src/Domain.ts +30 -9
  111. package/src/Error.ts +1 -0
  112. package/src/EvmPublicClient.ts +9 -488
  113. package/src/EvmWalletClient.ts +21 -973
  114. package/src/Payment.ts +216 -149
  115. package/src/Prover.ts +2 -2
  116. package/src/PublicClient.ts +7 -14
  117. package/src/WalletClient.ts +11 -5
  118. package/src/constants/ibc-core-registry.ts +9 -13
  119. package/src/internal/evmPublicClient.ts +459 -0
  120. package/src/internal/evmWalletClient.ts +1063 -0
  121. package/src/internal/publicClient.ts +0 -3
  122. package/src/promises/Payment.ts +26 -25
  123. package/src/promises/PublicClient.ts +2 -3
  124. package/src/promises/WalletClient.ts +0 -1
  125. package/src/rpc.ts +2 -4
  126. package/unionlabs-payments-0.3.0.tgz +0 -0
@@ -1,25 +1,21 @@
1
- import { type Brand, Effect, flow, Option } from "effect";
1
+ import { Effect, flow, Option } from "effect";
2
2
  import * as Domain from "../Domain.js";
3
3
  import * as Error from "../Error.js";
4
4
 
5
- export type ZAssetAddress = `0x${string}` & Brand.Brand<"ZAssetAddress">;
6
-
7
5
  export const IBC_CORE_REGISTRY: {
8
- [chainId: string]: Domain.IbcHandlerAddress;
6
+ [chainId: string]: Domain.IbcCoreAddress;
9
7
  } = {
10
- "8453": Domain.IbcHandlerAddress(
11
- "0xee4ea8d358473f0fcebf0329feed95d56e8c04d7",
12
- ),
8
+ "8453": Domain.IbcCoreAddress("0xee4ea8d358473f0fcebf0329feed95d56e8c04d7"),
13
9
  } as const;
14
10
 
15
- export function getIbcHandler(
11
+ export function getIbcCoreAddress(
16
12
  chainId: bigint,
17
- ): Option.Option<Domain.IbcHandlerAddress> {
13
+ ): Option.Option<Domain.IbcCoreAddress> {
18
14
  return Option.fromNullable(IBC_CORE_REGISTRY[`${chainId}`]);
19
15
  }
20
16
 
21
- export const getIbcHandlerOrError = flow(
22
- getIbcHandler,
17
+ export const getIbcCoreAddressOrError = flow(
18
+ getIbcCoreAddress,
23
19
  Effect.mapError(
24
20
  (cause) =>
25
21
  new Error.SystemError({
@@ -31,8 +27,8 @@ export const getIbcHandlerOrError = flow(
31
27
  ),
32
28
  );
33
29
 
34
- export const getIbcHandlerOrThrow = flow(
35
- getIbcHandler,
30
+ export const getIbcCoreAddressOrThrow = flow(
31
+ getIbcCoreAddress,
36
32
  Option.getOrThrowWith(
37
33
  () =>
38
34
  new Error.SystemError({
@@ -0,0 +1,459 @@
1
+ import * as Duration from "effect/Duration";
2
+ import * as Effect from "effect/Effect";
3
+ import { pipe } from "effect/Function";
4
+ import * as S from "effect/Schema";
5
+ import type * as Viem from "viem";
6
+ import { bytesToHex, hexToBytes } from "viem";
7
+ import * as Abi from "../Abi.js";
8
+ import * as ZAssetRegistry from "../constants/z-asset-registry.js";
9
+ import * as Domain from "../Domain.js";
10
+ import * as Error from "../Error.js";
11
+ import type * as EvmPublicClient from "../EvmPublicClient.js";
12
+ import * as Client from "../PublicClient.js";
13
+ import * as PS from "../Schema.js";
14
+
15
+ /** @internal */
16
+ export const TypeId: EvmPublicClient.TypeId = Symbol.for(
17
+ "@unionlabs/payments/EvmPublicClient",
18
+ ) as EvmPublicClient.TypeId;
19
+
20
+ export const makeViem = (
21
+ client: Viem.PublicClient,
22
+ ): Effect.Effect<EvmPublicClient.EvmPublicClient, Error.SdkError, never> =>
23
+ Effect.gen(function* () {
24
+ // const Viem = yield* Effect.tryPromise({
25
+ // try: () => import("viem").then((x) => x.default),
26
+ // catch: (cause) =>
27
+ // new Error.SystemError({
28
+ // reason: "DynamicImport",
29
+ // method: "makeViem",
30
+ // module: "EvmPublicClient",
31
+ // cause,
32
+ // description: "could not import viem",
33
+ // }),
34
+ // });
35
+
36
+ const readContract = Effect.fn("readContract")(
37
+ <
38
+ TAbi extends Viem.Abi,
39
+ A,
40
+ I,
41
+ R = never,
42
+ TFunctionName extends Viem.ContractFunctionName<
43
+ TAbi,
44
+ "pure" | "view"
45
+ > = Viem.ContractFunctionName<TAbi, "pure" | "view">,
46
+ TArgs extends Viem.ContractFunctionArgs<
47
+ TAbi,
48
+ "pure" | "view",
49
+ TFunctionName
50
+ > = Viem.ContractFunctionArgs<TAbi, "pure" | "view", TFunctionName>,
51
+ >(
52
+ params: Viem.ReadContractParameters<TAbi, TFunctionName, TArgs>,
53
+ schema: S.Schema<A, I, R>,
54
+ ): Effect.Effect<A, Error.SdkError, R> =>
55
+ pipe(
56
+ Effect.tryPromise({
57
+ try: () => client.readContract(params),
58
+ catch: (cause) =>
59
+ new Error.SystemError({
60
+ method: "readContract",
61
+ module: "EvmPublicClient",
62
+ reason: "ReadContract",
63
+ cause,
64
+ }),
65
+ }),
66
+ Effect.flatMap(S.decodeUnknown(schema)),
67
+ Effect.catchTag(
68
+ "ParseError",
69
+ (cause) =>
70
+ new Error.SystemError({
71
+ method: "readContract",
72
+ module: "EvmPublicClient",
73
+ reason: "InvalidData",
74
+ cause,
75
+ }),
76
+ ),
77
+ ),
78
+ );
79
+
80
+ const getLatestHeight = Effect.fn("getLatestHeight")(
81
+ (lightClientAddress: Domain.LightClientAddress, clientId: number) =>
82
+ readContract(
83
+ {
84
+ address: lightClientAddress,
85
+ abi: Abi.LIGHT_CLIENT_ABI,
86
+ functionName: "getLatestHeight",
87
+ args: [clientId],
88
+ },
89
+ S.BigIntFromSelf,
90
+ ),
91
+ );
92
+
93
+ const getLightClientAddress = Effect.fn("getLightClientAddress")(function* (
94
+ ibcStoreAddress: Domain.IbcCoreAddress,
95
+ clientId: number,
96
+ ) {
97
+ const res = yield* readContract(
98
+ {
99
+ address: ibcStoreAddress,
100
+ abi: Abi.IBC_STORE_ABI,
101
+ functionName: "getClient",
102
+ args: [clientId],
103
+ },
104
+ PS.Hex,
105
+ );
106
+
107
+ return Domain.LightClientAddress(res);
108
+ });
109
+
110
+ const getStateRootIndex = Effect.fn("getStateRootIndex")(
111
+ (zAssetAddress: Domain.ZAssetAddress, clientId: number) =>
112
+ readContract(
113
+ {
114
+ address: zAssetAddress,
115
+ abi: Abi.ZASSET_ABI,
116
+ functionName: "stateRootIndex",
117
+ args: [clientId],
118
+ },
119
+ S.BigIntFromSelf,
120
+ ),
121
+ );
122
+
123
+ const getConsensusState = Effect.fn("getConsensusState")(
124
+ (
125
+ lightClientAddress: Domain.LightClientAddress,
126
+ clientId: number,
127
+ height: bigint,
128
+ stateRootIndex: bigint,
129
+ ) =>
130
+ pipe(
131
+ readContract(
132
+ {
133
+ address: lightClientAddress,
134
+ abi: Abi.LIGHT_CLIENT_ABI,
135
+ functionName: "getConsensusState",
136
+ args: [clientId, height],
137
+ },
138
+ PS.Hex,
139
+ ),
140
+ // XXX: this can definitely fail
141
+ Effect.map((consensusBytes) => {
142
+ const bytes: Uint8Array = hexToBytes(consensusBytes);
143
+ const idx = Number(stateRootIndex);
144
+ const stateRoot = bytesToHex(bytes.slice(idx, idx + 32));
145
+ return { stateRoot } as const;
146
+ }),
147
+ ),
148
+ );
149
+
150
+ const getIbcHandlerAddress = Effect.fn("getIbcHandlerAddress")(function* (
151
+ zAssetAddress: Domain.ZAssetAddress,
152
+ ) {
153
+ return Domain.IbcCoreAddress(
154
+ yield* readContract(
155
+ {
156
+ address: zAssetAddress,
157
+ abi: Abi.ZASSET_ABI,
158
+ functionName: "ibcHandler",
159
+ },
160
+ PS.Hex,
161
+ ),
162
+ );
163
+ });
164
+
165
+ const readZAssetTokenBalance = Effect.fn("readZAssetTokenBalance")(
166
+ (
167
+ tokenAddress: Domain.ZAssetAddress,
168
+ accountAddress: `0x${string}`,
169
+ blockNumber?: bigint,
170
+ ) =>
171
+ readContract(
172
+ {
173
+ address: tokenAddress,
174
+ abi: [
175
+ {
176
+ inputs: [{ name: "account", type: "address" }],
177
+ name: "balanceOf",
178
+ outputs: [{ name: "", type: "uint256" }],
179
+ stateMutability: "view",
180
+ type: "function",
181
+ },
182
+ ] as const,
183
+ functionName: "balanceOf",
184
+ args: [accountAddress],
185
+ blockNumber,
186
+ },
187
+ S.BigIntFromSelf,
188
+ ),
189
+ );
190
+
191
+ const readNullifierBalance = Effect.fn("readNullifierBalance")(
192
+ (zAssetAddress: Domain.ZAssetAddress, nullifier: bigint) =>
193
+ readContract(
194
+ {
195
+ address: zAssetAddress,
196
+ abi: Abi.ZASSET_ABI,
197
+ functionName: "nullifierBalance",
198
+ args: [nullifier],
199
+ },
200
+ S.BigIntFromSelf,
201
+ ),
202
+ );
203
+
204
+ const getLatestBlockNumber = Effect.tryPromise({
205
+ try: () => client.getBlockNumber(),
206
+ catch: (cause) =>
207
+ new Error.SystemError({
208
+ method: "getLatestBlockNumber",
209
+ module: "EvmPublicClient",
210
+ reason: "InvalidData",
211
+ cause,
212
+ }),
213
+ });
214
+
215
+ const readBalanceAtHeight = Effect.fn("readBalanceAtHeight")(
216
+ (
217
+ opts: Client.PublicClient.ReadBalanceAtHeightOptions,
218
+ ): Effect.Effect<
219
+ Client.PublicClient.BalanceAtHeightInfo,
220
+ Error.SdkError
221
+ > =>
222
+ Effect.gen(function* () {
223
+ const latestHeight = yield* getLatestBlockNumber;
224
+
225
+ const srcZAssetAddress = yield* ZAssetRegistry.getZAsset(
226
+ opts.srcChainId,
227
+ opts.srcErc20Address,
228
+ ).pipe(
229
+ Effect.mapError(
230
+ (cause) =>
231
+ new Error.SystemError({
232
+ method: "readBalanceAtHeight",
233
+ module: "EvmPublicClient",
234
+ reason: "InvalidData",
235
+ cause,
236
+ }),
237
+ ),
238
+ );
239
+
240
+ const dstZAssetAddress = yield* ZAssetRegistry.getZAsset(
241
+ opts.dstChainId,
242
+ opts.dstErc20Address,
243
+ ).pipe(
244
+ Effect.mapError(
245
+ (cause) =>
246
+ new Error.SystemError({
247
+ method: "readBalanceAtHeight",
248
+ module: "EvmPublicClient",
249
+ reason: "InvalidData",
250
+ cause,
251
+ }),
252
+ ),
253
+ );
254
+
255
+ const [balanceAtTip, confirmed, redeemed] = yield* Effect.all(
256
+ [
257
+ // ZAsset balance of the deposit address ZAsset on the source chain at the tip of the chain
258
+ readZAssetTokenBalance(
259
+ srcZAssetAddress,
260
+ opts.depositAddress,
261
+ latestHeight,
262
+ ),
263
+ // ZAsset balance of the deposit address on the source chain at the (latest) light client height
264
+ readZAssetTokenBalance(
265
+ srcZAssetAddress,
266
+ opts.depositAddress,
267
+ opts.height,
268
+ ),
269
+ // amount that has already been redeemed under the specified nullifier
270
+ readNullifierBalance(dstZAssetAddress, opts.nullifier),
271
+ ],
272
+ { concurrency: "unbounded" },
273
+ );
274
+
275
+ const available = confirmed > redeemed ? confirmed - redeemed : 0n;
276
+ const pending =
277
+ balanceAtTip > confirmed ? balanceAtTip - confirmed : 0n;
278
+
279
+ return { confirmed, redeemed, available, pending, latestHeight };
280
+ }),
281
+ );
282
+
283
+ const readBalance = Effect.fn("readBalance")(
284
+ (
285
+ opts: Client.PublicClient.ReadBalanceOptions,
286
+ ): Effect.Effect<Client.PublicClient.BalanceInfo, Error.SdkError> =>
287
+ Effect.gen(function* () {
288
+ const dstZAssetAddress = yield* ZAssetRegistry.getZAsset(
289
+ opts.dstChainId,
290
+ opts.dstErc20Address,
291
+ ).pipe(
292
+ Effect.mapError(
293
+ (cause) =>
294
+ new Error.SystemError({
295
+ method: "readBalance",
296
+ module: "EvmPublicClient",
297
+ reason: "InvalidData",
298
+ cause,
299
+ }),
300
+ ),
301
+ );
302
+
303
+ yield* Effect.log({ opts, dstZAssetAddress });
304
+
305
+ const ibcHandlerAddress =
306
+ yield* getIbcHandlerAddress(dstZAssetAddress);
307
+
308
+ const lightClientAddress = yield* getLightClientAddress(
309
+ ibcHandlerAddress,
310
+ opts.clientId,
311
+ );
312
+ const lightClientHeight = yield* getLatestHeight(
313
+ lightClientAddress,
314
+ opts.clientId,
315
+ );
316
+
317
+ const balance = yield* readBalanceAtHeight({
318
+ srcErc20Address: opts.srcErc20Address,
319
+ srcChainId: opts.srcChainId,
320
+ dstErc20Address: opts.dstErc20Address,
321
+ dstChainId: opts.dstChainId,
322
+ depositAddress: opts.depositAddress,
323
+ nullifier: opts.nullifier,
324
+ height: lightClientHeight,
325
+ });
326
+
327
+ return { ...balance, lightClientHeight };
328
+ }),
329
+ );
330
+
331
+ const getCounterparty = Effect.fn("getCounterparty")(
332
+ (zAssetAddress: Domain.ZAssetAddress, clientId: number) =>
333
+ readContract(
334
+ {
335
+ address: zAssetAddress,
336
+ abi: Abi.ZASSET_ABI,
337
+ functionName: "counterparty",
338
+ args: [clientId],
339
+ },
340
+ Domain.CounterpartyInfo,
341
+ ),
342
+ );
343
+
344
+ const getProof = Effect.fn("getProof")(
345
+ (options: {
346
+ address: `0x${string}`;
347
+ storageKeys: `0x${string}`[];
348
+ blockNumber: bigint;
349
+ }) =>
350
+ Effect.tryPromise({
351
+ try: () => client.getProof(options),
352
+ catch: (cause) =>
353
+ new Error.SystemError({
354
+ method: "getProof",
355
+ module: "EvmPublicClient",
356
+ reason: "InvalidData",
357
+ cause,
358
+ }),
359
+ }),
360
+ );
361
+
362
+ const waitForTransactionReceipt = Effect.fn("waitForTransactionReceipt")(
363
+ (hash: Domain.TxHash) =>
364
+ pipe(
365
+ Effect.tryPromise({
366
+ try: () => client.waitForTransactionReceipt({ hash }),
367
+ catch: (cause) =>
368
+ new Error.SystemError({
369
+ method: "waitForTransactionReceipt",
370
+ module: "EvmPublicClient",
371
+ reason: "InvalidData",
372
+ cause,
373
+ }),
374
+ }),
375
+ Effect.flatMap((x) =>
376
+ x.status === "success"
377
+ ? Effect.succeed(x)
378
+ : Effect.fail(
379
+ new Error.SystemError({
380
+ method: "waitForTransactionReceipt",
381
+ module: "EvmPublicClient",
382
+ reason: "InvalidData",
383
+ description: "contract reverted",
384
+ }),
385
+ ),
386
+ ),
387
+ ),
388
+ );
389
+
390
+ const waitForBlock = Effect.fn("waitForBlock")(
391
+ (targetHeight: bigint): Effect.Effect<bigint, Error.SdkError> =>
392
+ pipe(
393
+ getLatestBlockNumber,
394
+ Effect.flatMap((initial) =>
395
+ Effect.iterate(initial, {
396
+ // one block extra to avoid loadbalancer issues
397
+ while: (height) => height <= targetHeight,
398
+ body: () =>
399
+ pipe(
400
+ Effect.sleep(Duration.seconds(1)),
401
+ Effect.andThen(getLatestBlockNumber),
402
+ ),
403
+ }),
404
+ ),
405
+ ),
406
+ );
407
+
408
+ const simulateCalls = Effect.fn("simulateCalls")(
409
+ (params: {
410
+ calls: Array<{
411
+ to: `0x${string}`;
412
+ data: `0x${string}`;
413
+ value?: bigint | undefined;
414
+ }>;
415
+ account?: `0x${string}` | undefined;
416
+ }) =>
417
+ Effect.tryPromise({
418
+ try: async () => {
419
+ const { simulateCalls } = await import("viem/actions");
420
+ return simulateCalls(client, {
421
+ calls: params.calls.map((call) => ({
422
+ to: call.to,
423
+ data: call.data,
424
+ value: call.value,
425
+ })),
426
+ account: params.account,
427
+ });
428
+ },
429
+ catch: (cause) =>
430
+ new Error.SystemError({
431
+ method: "simulateCalls",
432
+ module: "EvmPublicClient",
433
+ reason: "InvalidData",
434
+ cause,
435
+ }),
436
+ }),
437
+ );
438
+
439
+ return Object.assign(
440
+ yield* Client.make({
441
+ getLatestHeight,
442
+ getLatestBlockNumber,
443
+ readBalance,
444
+ readBalanceAtHeight,
445
+ getLightClientAddress,
446
+ getStateRootIndex,
447
+ getConsensusState,
448
+ getIbcHandlerAddress,
449
+ getCounterparty,
450
+ getProof,
451
+ waitForBlock,
452
+ }),
453
+ {
454
+ [TypeId]: TypeId as EvmPublicClient.TypeId,
455
+ waitForTransactionReceipt,
456
+ simulateCalls,
457
+ },
458
+ );
459
+ });