@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,2 +1,692 @@
1
- export {};
1
+ import * as A from "effect/Array";
2
+ import * as Effect from "effect/Effect";
3
+ import { pipe } from "effect/Function";
4
+ import * as Number from "effect/Number";
5
+ import * as O from "effect/Option";
6
+ import * as R from "effect/Record";
7
+ import * as Ref from "effect/Ref";
8
+ import * as ViemChains from "viem/chains";
9
+ import * as Abi from "../Abi.js";
10
+ import * as ZAssetRegistry from "../constants/z-asset-registry.js";
11
+ import * as Domain from "../Domain.js";
12
+ import * as Error from "../Error.js";
13
+ import * as Client from "../WalletClient.js";
14
+ import * as internalEvmPublicClient from "./evmPublicClient.js";
15
+ const UniversalChainIdMap = {
16
+ [/*#__PURE__*/Domain.UniversalChainId.make("base.8453")]: ViemChains.base
17
+ };
18
+ /** @internal */
19
+ export const resolveUniversalChainId = ucid => pipe(UniversalChainIdMap, R.get(ucid), O.match({
20
+ onNone: () => Effect.fail(new Error.SystemError({
21
+ method: "resolveUniversalChainId",
22
+ module: "EvmWalletClient",
23
+ reason: "InvalidData"
24
+ })),
25
+ onSome: Effect.succeed
26
+ }));
27
+ /** @internal */
28
+ export const TypeId = /*#__PURE__*/Symbol.for("@unionlabs/payments/EvmWalletClient");
29
+ /** @internal */
30
+ export const makeViem = wallet => Effect.gen(function* () {
31
+ const Viem = yield* Effect.tryPromise({
32
+ try: () => import("viem").then(x => x),
33
+ catch: cause => new Error.SystemError({
34
+ reason: "DynamicImport",
35
+ method: "makeViem",
36
+ module: "EvmWalletClient",
37
+ cause,
38
+ description: "could not import viem"
39
+ })
40
+ });
41
+ const ViemActions = yield* Effect.tryPromise({
42
+ try: () => import("viem/actions").then(x => x),
43
+ catch: cause => new Error.SystemError({
44
+ reason: "DynamicImport",
45
+ method: "makeViemActions",
46
+ module: "EvmWalletClient",
47
+ cause,
48
+ description: "could not import viem/actions"
49
+ })
50
+ });
51
+ const publicClient = yield* pipe(Effect.try({
52
+ try: () => Viem.createPublicClient({
53
+ chain: wallet.chain,
54
+ transport: Viem.custom(wallet)
55
+ }),
56
+ catch: cause => new Error.SystemError({
57
+ reason: "DynamicImport",
58
+ method: "make",
59
+ module: "EvmWalletClient",
60
+ cause,
61
+ description: "could derive public client from wallet client"
62
+ })
63
+ }), Effect.flatMap(internalEvmPublicClient.makeViem));
64
+ // Use "latest" to avoid stale pending txs in mempool
65
+ const transactionCount = yield* pipe(Effect.tryPromise({
66
+ try: () => ViemActions.getTransactionCount(wallet, {
67
+ address: wallet.account?.address,
68
+ blockTag: "latest"
69
+ }),
70
+ catch: cause => new Error.SystemError({
71
+ reason: "InvalidData",
72
+ method: "encodeFunctionData",
73
+ module: "EvmWalletClient",
74
+ cause
75
+ })
76
+ }), Effect.flatMap(Ref.make));
77
+ const encodeFunctionData = Effect.fn("encodeFunctionData")(parameters => Effect.try({
78
+ try: () => Viem.encodeFunctionData(parameters),
79
+ catch: cause => new Error.SystemError({
80
+ reason: "InvalidData",
81
+ method: "encodeFunctionData",
82
+ module: "EvmWalletClient",
83
+ cause
84
+ })
85
+ }));
86
+ const validateFunctionData = Effect.fn("validateFunctionData")(parameters => pipe(Effect.try({
87
+ try: () => Viem.encodeFunctionData(parameters),
88
+ catch: cause => new Error.SystemError({
89
+ reason: "InvalidData",
90
+ method: "validateFunctionData",
91
+ module: "EvmWalletClient",
92
+ cause
93
+ })
94
+ }), Effect.andThen(() => ({
95
+ ...parameters,
96
+ args: parameters.args ?? [],
97
+ functionName: parameters.functionName
98
+ }))));
99
+ const writeContract = Effect.fn("writeContract")(params => pipe(Effect.tryPromise({
100
+ try: () => wallet.writeContract(params),
101
+ catch: cause => new Error.SystemError({
102
+ method: "writeContract",
103
+ module: "EvmWalletClient",
104
+ reason: "InvalidData",
105
+ cause
106
+ })
107
+ }), Effect.map(hash => Domain.SubmissionResult.SubmissionEvm({
108
+ hash: Domain.TxHash(hash)
109
+ }))));
110
+ const prepareTransactionRequest = Effect.fn("prepareTransactionRequest")(params => pipe(Ref.get(transactionCount), Effect.flatMap(nonce => Effect.tryPromise({
111
+ try: () => wallet.prepareTransactionRequest({
112
+ ...params,
113
+ nonce
114
+ }),
115
+ catch: cause => new Error.SystemError({
116
+ method: "prepareTransactionRequest",
117
+ module: "EvmWalletClient",
118
+ reason: "InvalidData",
119
+ cause
120
+ })
121
+ })), Effect.tap(() => Ref.update(transactionCount, Number.increment))));
122
+ const prepareBatchTransactionRequest = Effect.fn("prepareBatchTransactionRequest")(requests => Effect.gen(function* () {
123
+ // Refresh nonce from chain before batch to ensure we're in sync
124
+ const chainNonce = yield* Effect.tryPromise({
125
+ try: () => ViemActions.getTransactionCount(wallet, {
126
+ address: wallet.account?.address,
127
+ blockTag: "latest"
128
+ }),
129
+ catch: cause => new Error.SystemError({
130
+ reason: "InvalidData",
131
+ method: "prepareBatchTransactionRequest",
132
+ module: "EvmWalletClient",
133
+ cause
134
+ })
135
+ });
136
+ yield* Ref.set(transactionCount, chainNonce);
137
+ yield* Effect.log("[prepareBatchTransactionRequest] Synced nonce", {
138
+ chainNonce
139
+ });
140
+ const calls = yield* pipe(requests, Effect.forEach(request => pipe(encodeFunctionData({
141
+ abi: request.abi,
142
+ args: request.args,
143
+ functionName: request.functionName
144
+ }), Effect.map(data => ({
145
+ to: request.contractAddress,
146
+ data,
147
+ value: undefined
148
+ })))));
149
+ yield* Effect.log({
150
+ calls
151
+ });
152
+ const simulationResult = yield* publicClient.simulateCalls({
153
+ calls: calls.map(call => ({
154
+ to: call.to,
155
+ data: call.data,
156
+ value: call.value
157
+ })),
158
+ account: wallet.account?.address
159
+ });
160
+ yield* Effect.log("[prepareBatchTransactionRequest] Simulation results", {
161
+ results: simulationResult.results
162
+ });
163
+ // Extract gas estimates with 20% buffer for safety
164
+ const gasEstimates = simulationResult.results?.map(r => r?.gasUsed ? BigInt(r.gasUsed) * 120n / 100n : undefined) ?? [];
165
+ yield* Effect.log("[prepareBatchTransactionRequest] Gas estimates", {
166
+ gasEstimates
167
+ });
168
+ // Prepare each transaction with gas
169
+ const prepared = [];
170
+ for (let i = 0; i < calls.length; i++) {
171
+ const call = calls[i];
172
+ const gas = gasEstimates[i];
173
+ const nonce = yield* Ref.get(transactionCount);
174
+ const request = yield* Effect.tryPromise({
175
+ try: () => wallet.prepareTransactionRequest({
176
+ to: call.to,
177
+ data: call.data,
178
+ ...(call.value !== undefined && {
179
+ value: call.value
180
+ }),
181
+ ...(gas !== undefined && {
182
+ gas
183
+ }),
184
+ nonce,
185
+ chain: wallet.chain
186
+ }),
187
+ catch: cause => new Error.SystemError({
188
+ method: "prepareBatchTransactionRequest",
189
+ module: "EvmWalletClient",
190
+ reason: "InvalidData",
191
+ cause
192
+ })
193
+ });
194
+ yield* Ref.update(transactionCount, Number.increment);
195
+ prepared.push(request);
196
+ }
197
+ return prepared;
198
+ }));
199
+ const signTransaction = Effect.fn("signTransaction")(params => Effect.tryPromise({
200
+ try: () => wallet.signTransaction(params),
201
+ catch: cause => new Error.SystemError({
202
+ method: "signTransaction",
203
+ module: "EvmWalletClient",
204
+ reason: "InvalidData",
205
+ cause
206
+ })
207
+ }));
208
+ const sendRawTransaction = Effect.fn("sendRawTransaction")(params => Effect.tryPromise({
209
+ try: () => wallet.sendRawTransaction(params),
210
+ catch: cause => new Error.SystemError({
211
+ method: "sendRawTransaction",
212
+ module: "EvmWalletClient",
213
+ reason: "InvalidData",
214
+ cause
215
+ })
216
+ }));
217
+ const sign = Effect.fn("sign")(function* (request) {
218
+ // const chain = yield* resolveUniversalChainId(request.universalChainId);
219
+ const requests = yield* pipe(request, A.ensure, Effect.forEach(n => pipe(n, Effect.liftPredicate(Domain.PreparedRequest.$is("PreparedEvm"), x => new Error.SystemError({
220
+ method: "sign",
221
+ module: "EvmWalletClient",
222
+ reason: "InvalidData"
223
+ })))));
224
+ return yield* pipe(requests, prepareBatchTransactionRequest, Effect.flatMap(Effect.forEach(value => signTransaction({
225
+ ...value,
226
+ account: wallet.account,
227
+ chain: wallet.chain
228
+ }))),
229
+ // Effect.tap((success) => Effect.log({ success })),
230
+ Effect.map(A.map(value => Domain.SignedRequest.SignedEvm({
231
+ value
232
+ }))));
233
+ });
234
+ const submit = Effect.fn("submit")(request => pipe(request, Effect.liftPredicate(Domain.SignedRequest.$is("SignedEvm"), cause => new Error.SystemError({
235
+ method: "submit",
236
+ module: "EvmWalletClient",
237
+ reason: "InvalidData",
238
+ cause
239
+ })), Effect.map(x => x.value), Effect.flatMap(serializedTransaction => sendRawTransaction({
240
+ serializedTransaction
241
+ })), Effect.map(hash => Domain.SubmissionResult.SubmissionEvm({
242
+ hash: Domain.TxHash(hash)
243
+ }))));
244
+ const signAndSubmit = Effect.fn("signAndSubmit")(function* (request) {
245
+ const _request = yield* Effect.liftPredicate(request, Domain.PreparedRequest.$is("PreparedEvm"), cause => new Error.SystemError({
246
+ method: "signAndSubmit",
247
+ module: "EvmWalletClient",
248
+ reason: "InvalidData",
249
+ cause
250
+ }));
251
+ const data = yield* encodeFunctionData({
252
+ abi: _request.abi,
253
+ args: _request.args,
254
+ functionName: _request.functionName
255
+ });
256
+ const prepared = yield* prepareTransactionRequest({
257
+ to: _request.contractAddress,
258
+ data,
259
+ chain: wallet.chain
260
+ });
261
+ return yield* pipe(Effect.tryPromise({
262
+ try: () => ViemActions.sendTransaction(wallet, {
263
+ to: prepared.to,
264
+ data: prepared.data,
265
+ value: prepared.value,
266
+ gas: prepared.gas,
267
+ nonce: prepared.nonce,
268
+ account: wallet.account,
269
+ chain: wallet.chain
270
+ }),
271
+ catch: cause => new Error.SystemError({
272
+ method: "signAndSubmit",
273
+ module: "EvmWalletClient",
274
+ reason: "InvalidData",
275
+ cause
276
+ })
277
+ }), Effect.map(hash => Domain.SubmissionResult.SubmissionEvm({
278
+ hash: Domain.TxHash(hash)
279
+ })));
280
+ });
281
+ // TODO: check if required
282
+ const approveZAssetToSpendErc20 = Effect.fn("approveZAssetToSpendErc20")(function* (args) {
283
+ return yield* pipe(
284
+ // XXX: fix hardcoded chainid
285
+ ZAssetRegistry.getZAsset(8453n, args.srcErc20Address), Effect.mapError(cause => new Error.SystemError({
286
+ method: "approveZAssetToSpendErc20",
287
+ module: "EvmWalletClient",
288
+ reason: "InvalidData",
289
+ cause
290
+ })), Effect.flatMap(zAsset => validateFunctionData({
291
+ abi: Abi.ERC20_ABI,
292
+ functionName: "approve",
293
+ args: [zAsset, args.amount]
294
+ })), Effect.map(request => Domain.PreparedRequest.PreparedEvm({
295
+ abi: request.abi,
296
+ args: request.args ?? [],
297
+ contractAddress: args.srcErc20Address,
298
+ functionName: request.functionName || "",
299
+ universalChainId: args.universalChainId,
300
+ kind: "Erc20.Approve"
301
+ })));
302
+ });
303
+ // TODO: check if required
304
+ const updateLoopbackClient = Effect.fn("updateLoopbackClient")(function* ({
305
+ clientId,
306
+ height,
307
+ ibcHandlerAddress,
308
+ universalChainId
309
+ }) {
310
+ // const publicClient = Viem.createPublicClient({
311
+ // transport: Viem.http(wallet.transport.rpcUrl),
312
+ // });
313
+ const publicClient = wallet.extend(Viem.publicActions);
314
+ const blockNumber = height;
315
+ const block = yield* Effect.tryPromise({
316
+ try: () => publicClient.getBlock({
317
+ blockNumber
318
+ }),
319
+ catch: cause => new Error.SystemError({
320
+ module: "EvmWalletClient",
321
+ method: "updateLoopbackClient",
322
+ reason: "InvalidData",
323
+ description: "Cannot getBlockNumber",
324
+ cause
325
+ })
326
+ });
327
+ // if (!block.number) {
328
+ // throw new Error("Block number is null");
329
+ // }
330
+ // Helper to convert bigint/number to minimal RLP hex encoding
331
+ const toRlpHex = value => {
332
+ if (value === undefined || value === null || value === 0n || value === 0) {
333
+ return "0x";
334
+ }
335
+ let hex = typeof value === "bigint" ? value.toString(16) : value.toString(16);
336
+ if (hex.length % 2 !== 0) {
337
+ hex = "0" + hex;
338
+ }
339
+ return `0x${hex}`;
340
+ };
341
+ // Build header fields in order (pre-merge + post-merge fields)
342
+ const headerFields = [block.parentHash, block.sha3Uncles, block.miner, block.stateRoot, block.transactionsRoot, block.receiptsRoot, block.logsBloom ?? "0x" + "00".repeat(256), toRlpHex(block.difficulty), toRlpHex(block.number), toRlpHex(block.gasLimit), toRlpHex(block.gasUsed), toRlpHex(block.timestamp), block.extraData, block.mixHash ?? "0x0000000000000000000000000000000000000000000000000000000000000000", block.nonce ?? "0x0000000000000000"];
343
+ // Post-merge fields
344
+ if (block.baseFeePerGas !== undefined && block.baseFeePerGas !== null) {
345
+ headerFields.push(toRlpHex(block.baseFeePerGas));
346
+ }
347
+ if (block.withdrawalsRoot) {
348
+ headerFields.push(block.withdrawalsRoot);
349
+ }
350
+ if (block.blobGasUsed !== undefined && block.blobGasUsed !== null) {
351
+ headerFields.push(toRlpHex(block.blobGasUsed));
352
+ }
353
+ if (block.excessBlobGas !== undefined && block.excessBlobGas !== null) {
354
+ headerFields.push(toRlpHex(block.excessBlobGas));
355
+ }
356
+ if (block.parentBeaconBlockRoot) {
357
+ headerFields.push(block.parentBeaconBlockRoot);
358
+ }
359
+ const blockAny = block;
360
+ if (blockAny.requestsHash) {
361
+ headerFields.push(blockAny.requestsHash);
362
+ }
363
+ const rlpEncoded = Viem.toRlp(headerFields);
364
+ // Verify the encoding produces the correct block hash
365
+ const computedHash = Viem.keccak256(rlpEncoded);
366
+ if (computedHash !== block.hash) {
367
+ return yield* new Error.SystemError({
368
+ module: "EvmWalletClient",
369
+ method: "updateLooopbackClient",
370
+ reason: "InvalidData",
371
+ description: `RLP encoding mismatch: computed hash ${computedHash} does not match block hash ${block.hash}`
372
+ });
373
+ }
374
+ // Encode the Header struct: (uint64 height, bytes encodedHeader)
375
+ const clientMessage = Viem.encodeAbiParameters([{
376
+ type: "uint64",
377
+ name: "height"
378
+ }, {
379
+ type: "bytes",
380
+ name: "encodedHeader"
381
+ }], [block.number, rlpEncoded]);
382
+ const LIGHTCLIENT_ABI = [{
383
+ inputs: [{
384
+ name: "caller",
385
+ type: "address"
386
+ }, {
387
+ name: "clientId",
388
+ type: "uint32"
389
+ }, {
390
+ name: "clientMessage",
391
+ type: "bytes"
392
+ }, {
393
+ name: "relayer",
394
+ type: "address"
395
+ }],
396
+ name: "updateClient",
397
+ outputs: [],
398
+ stateMutability: "nonpayable",
399
+ type: "function"
400
+ }];
401
+ // Wait for the next block so the fetched block's hash is verifiable on-chain
402
+ let currentBlock = yield* Effect.tryPromise({
403
+ try: () => publicClient.getBlockNumber(),
404
+ catch: cause => new Error.SystemError({
405
+ module: "EvmWalletClient",
406
+ method: "updateLoopbackClient",
407
+ reason: "InvalidData",
408
+ description: "Cannot getBlockNumber",
409
+ cause
410
+ })
411
+ });
412
+ while (currentBlock <= blockNumber) {
413
+ yield* Effect.sleep("1 second");
414
+ currentBlock = yield* Effect.tryPromise({
415
+ try: () => publicClient.getBlockNumber(),
416
+ catch: cause => new Error.SystemError({
417
+ module: "EvmWalletClient",
418
+ method: "updateLoopbackClient",
419
+ reason: "InvalidData",
420
+ description: "Cannot getBlockNumber",
421
+ cause
422
+ })
423
+ });
424
+ }
425
+ const loopbackClient = yield* pipe(Effect.tryPromise({
426
+ try: () => publicClient.readContract({
427
+ address: ibcHandlerAddress,
428
+ abi: Abi.IBC_STORE_ABI,
429
+ functionName: "getClient",
430
+ args: [clientId]
431
+ }),
432
+ catch: cause => new Error.SystemError({
433
+ module: "EvmWalletClient",
434
+ method: "updateLoopbackClient",
435
+ reason: "InvalidData",
436
+ description: "cannot get client given ibc handler address",
437
+ cause
438
+ })
439
+ }), Effect.map(Domain.Erc20Address));
440
+ return yield* pipe(validateFunctionData({
441
+ abi: LIGHTCLIENT_ABI,
442
+ functionName: "updateClient",
443
+ args: [wallet.account.address, clientId, clientMessage, wallet.account.address]
444
+ }), Effect.map(data => Domain.PreparedRequest.PreparedEvm({
445
+ ...data,
446
+ contractAddress: loopbackClient,
447
+ universalChainId,
448
+ kind: "LoopbackClient.Update"
449
+ })));
450
+ });
451
+ const depositUnderlyingZAsset = Effect.fn("depositUnderlyingZAsset")(function* (args) {
452
+ const zAssetAddr = yield* ZAssetRegistry.getZAsset(8453n, args.srcErc20Address).pipe(Effect.mapError(cause => new Error.SystemError({
453
+ method: "depositUnderlyingZAsset",
454
+ module: "EvmWalletClient",
455
+ reason: "InvalidData",
456
+ cause
457
+ })));
458
+ return yield* pipe(validateFunctionData({
459
+ abi: Abi.ZASSET_ABI,
460
+ functionName: "deposit",
461
+ args: [args.amount]
462
+ }),
463
+ // Effect.map((data) =>
464
+ // prepareTransactionRequest({
465
+ // to: zAssetAddr,
466
+ // data,
467
+ // chain: wallet.chain,
468
+ // }),
469
+ // ),
470
+ Effect.map(data => Domain.PreparedRequest.PreparedEvm({
471
+ ...data,
472
+ contractAddress: Domain.Erc20Address(zAssetAddr),
473
+ universalChainId: args.universalChainId,
474
+ kind: "Erc20.Wrap"
475
+ })));
476
+ });
477
+ const transferZAsset = Effect.fn("transferZAsset")(function* (args) {
478
+ const zAssetAddr = yield* ZAssetRegistry.getZAsset(8453n, args.srcErc20Address).pipe(Effect.mapError(cause => new Error.SystemError({
479
+ method: "transferZAsset",
480
+ module: "EvmWalletClient",
481
+ reason: "InvalidData",
482
+ cause
483
+ })));
484
+ return yield* pipe(validateFunctionData({
485
+ abi: Abi.ZASSET_ABI,
486
+ functionName: "transfer",
487
+ args: [args.depositAddress, args.amount]
488
+ }),
489
+ // Effect.flatMap((data) =>
490
+ // prepareTransactionRequest({
491
+ // to: zAssetAddr,
492
+ // data,
493
+ // chain: wallet.chain,
494
+ // }),
495
+ // ),
496
+ Effect.map(data => Domain.PreparedRequest.PreparedEvm({
497
+ ...data,
498
+ contractAddress: Domain.Erc20Address(zAssetAddr),
499
+ universalChainId: args.universalChainId,
500
+ kind: "ZAsset.Transfer"
501
+ })));
502
+ });
503
+ const prepareDeposit = Effect.fn("prepareDeposit")(function* (args) {
504
+ const zAssetAddress = ZAssetRegistry.Z_ASSET_REGISTRY[`${args.sourceChainId}`][args.srcErc20Address];
505
+ if (!zAssetAddress) {
506
+ return yield* new Error.SystemError({
507
+ method: "deposit",
508
+ module: "PaymentClient",
509
+ reason: "InvalidData",
510
+ description: `No zAsset found for ${args.srcErc20Address} on chain ${args.sourceChainId}`
511
+ });
512
+ }
513
+ const [approval, deposit, transfer] = yield* Effect.all([pipe(validateFunctionData({
514
+ abi: Abi.ERC20_ABI,
515
+ functionName: "approve",
516
+ args: [zAssetAddress, args.amount]
517
+ }), Effect.map(data => Domain.PreparedRequest.PreparedEvm({
518
+ ...data,
519
+ contractAddress: args.srcErc20Address,
520
+ universalChainId: args.universalChainId,
521
+ kind: "Erc20.Approve"
522
+ }))), pipe(validateFunctionData({
523
+ abi: Abi.ZASSET_ABI,
524
+ functionName: "deposit",
525
+ args: [args.amount]
526
+ }), Effect.map(data => Domain.PreparedRequest.PreparedEvm({
527
+ ...data,
528
+ contractAddress: Domain.Erc20Address(zAssetAddress),
529
+ universalChainId: args.universalChainId,
530
+ kind: "Erc20.Wrap"
531
+ }))), pipe(validateFunctionData({
532
+ abi: Abi.ZASSET_ABI,
533
+ functionName: "transfer",
534
+ args: [args.depositAddress, args.amount]
535
+ }), Effect.map(data => Domain.PreparedRequest.PreparedEvm({
536
+ ...data,
537
+ contractAddress: Domain.Erc20Address(zAssetAddress),
538
+ universalChainId: args.universalChainId,
539
+ kind: "ZAsset.Transfer"
540
+ })))], {
541
+ concurrency: "unbounded"
542
+ });
543
+ yield* Effect.log("[deposit]", {
544
+ approval,
545
+ deposit,
546
+ transfer
547
+ });
548
+ return [approval, deposit, transfer];
549
+ });
550
+ const prepareRedemption = Effect.fn("prepareRedemption")(function* (args) {
551
+ const zAssetAddr = yield* ZAssetRegistry.getZAsset(8453n, args.dstErc20Address).pipe(Effect.mapError(cause => new Error.SystemError({
552
+ method: "transferZAsset",
553
+ module: "EvmWalletClient",
554
+ reason: "InvalidData",
555
+ cause
556
+ })));
557
+ return yield* pipe(validateFunctionData({
558
+ abi: Abi.ZASSET_ABI,
559
+ functionName: "redeem",
560
+ args: [args.proof, args.commitments, args.commitmentPok, args.lightClients, args.nullifier, args.value, args.beneficiary, args.attestedMessage, args.signature, args.unwrap ?? true]
561
+ }),
562
+ // Effect.flatMap((data) =>
563
+ // prepareTransactionRequest({
564
+ // to: zAssetAddr,
565
+ // data,
566
+ // chain: wallet.chain,
567
+ // }),
568
+ // ),
569
+ Effect.map(data => Domain.PreparedRequest.PreparedEvm({
570
+ ...data,
571
+ contractAddress: Domain.Erc20Address(zAssetAddr),
572
+ universalChainId: args.universalChainId,
573
+ kind: "ZAsset.Transfer"
574
+ })));
575
+ });
576
+ return Object.assign(yield* Client.make({
577
+ sign: sign,
578
+ submit,
579
+ approveZAssetToSpendErc20,
580
+ updateLoopbackClient,
581
+ depositUnderlyingZAsset,
582
+ transferZAsset,
583
+ prepareDeposit,
584
+ prepareRedemption,
585
+ signAndSubmit
586
+ }), {
587
+ [TypeId]: TypeId,
588
+ signTransaction,
589
+ sendRawTransaction,
590
+ writeContract,
591
+ prepareBatchTransactionRequest
592
+ });
593
+ });
594
+ /** @internal */
595
+ export const makeBrowser = /*#__PURE__*/Effect.fn(function* (options) {
596
+ const Mipd = yield* Effect.tryPromise({
597
+ try: () => import("mipd").then(x => x),
598
+ catch: cause => new Error.SystemError({
599
+ reason: "DynamicImport",
600
+ method: "makeBrowser",
601
+ module: "EvmWalletClient",
602
+ cause,
603
+ description: "could not import mipd"
604
+ })
605
+ });
606
+ const store = Mipd.createStore();
607
+ yield* Effect.log({
608
+ store
609
+ });
610
+ const providers = store.getProviders();
611
+ yield* Effect.log({
612
+ providers
613
+ });
614
+ const selected = yield* pipe(A.findFirst(providers, options.providerPredicate), Effect.mapError(cause => new Error.SystemError({
615
+ reason: "DynamicImport",
616
+ method: "makeBrowser",
617
+ module: "EvmWalletClient",
618
+ cause,
619
+ description: "could not find provider"
620
+ })));
621
+ yield* Effect.log({
622
+ selected
623
+ });
624
+ const account = yield* pipe(Effect.tryPromise({
625
+ try: () => selected.provider.request({
626
+ method: "eth_requestAccounts"
627
+ }),
628
+ catch: cause => new Error.SystemError({
629
+ reason: "DynamicImport",
630
+ method: "makeBrowser",
631
+ module: "EvmWalletClient",
632
+ cause,
633
+ description: "could not request accounts"
634
+ })
635
+ }), Effect.flatMap(A.findFirst(options.accountPredicate)), Effect.catchTag("NoSuchElementException", cause => new Error.SystemError({
636
+ reason: "DynamicImport",
637
+ method: "makeBrowser",
638
+ module: "EvmWalletClient",
639
+ cause,
640
+ description: "could not match account by predicate"
641
+ })));
642
+ const Viem = yield* Effect.tryPromise({
643
+ try: () => import("viem").then(x => x),
644
+ catch: cause => new Error.SystemError({
645
+ reason: "DynamicImport",
646
+ method: "makeViem",
647
+ module: "EvmWalletClient",
648
+ cause,
649
+ description: "could not import viem"
650
+ })
651
+ });
652
+ const ViemChains = yield* Effect.tryPromise({
653
+ try: () => import("viem/chains").then(x => x),
654
+ catch: cause => new Error.SystemError({
655
+ reason: "DynamicImport",
656
+ method: "makeViem",
657
+ module: "EvmWalletClient",
658
+ cause,
659
+ description: "could not import viem/chains"
660
+ })
661
+ });
662
+ const wallet = yield* Effect.try({
663
+ try: () => Viem.createWalletClient({
664
+ account: account,
665
+ chain: ViemChains.base,
666
+ transport: Viem.custom(selected.provider)
667
+ }),
668
+ catch: cause => new Error.SystemError({
669
+ reason: "DynamicImport",
670
+ method: "makeViem",
671
+ module: "EvmWalletClient",
672
+ cause,
673
+ description: "could not import viem/chains"
674
+ })
675
+ });
676
+ return yield* makeViem(wallet);
677
+ });
678
+ // import type * as ThirdwebAdaptersViem from "thirdweb/adapters/viem"
679
+ // export const makeThirdweb = Effect.fn(function* (...options: Parameters<typeof ThirdwebAdaptersViem['viemAdapter']['wallet']['toViem']>) {
680
+ // const { viemAdapter } = yield* Effect.tryPromise({
681
+ // try: () => import("thirdweb/adapters/viem"),
682
+ // catch: (cause) => new Error.SystemError({
683
+ // method: "makeThirdweb",
684
+ // module: "EvmWalletClient",
685
+ // reason: "DynamicImport",
686
+ // cause,
687
+ // })
688
+ // })
689
+ // const wallet = viemAdapter.wallet.toViem(...options)
690
+ // return layerFromViem(wallet as Viem.WalletClient)
691
+ // })
2
692
  //# sourceMappingURL=evmWalletClient.js.map