@wagmi/core 3.4.3 → 3.4.5

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.
@@ -0,0 +1,1415 @@
1
+ import {
2
+ type Account,
3
+ type Address,
4
+ encodeAbiParameters,
5
+ encodeFunctionData,
6
+ type Hex,
7
+ zeroHash,
8
+ } from 'viem'
9
+ import {
10
+ readContract as viem_readContract,
11
+ sendTransaction as viem_sendTransaction,
12
+ sendTransactionSync as viem_sendTransactionSync,
13
+ } from 'viem/actions'
14
+ import { Abis, Actions, Bytes, PublicKey, Secp256k1, TokenId } from 'viem/tempo'
15
+ import { Abis as ZoneAbis } from 'viem/tempo/zones'
16
+ import { parseAccount } from 'viem/utils'
17
+ import { getConnectorClient } from '../../actions/getConnectorClient.js'
18
+ import type { Config } from '../../createConfig.js'
19
+ import type {
20
+ ChainIdParameter,
21
+ ConnectorParameter,
22
+ } from '../../types/properties.js'
23
+ import type { PartialBy, UnionLooseOmit } from '../../types/utils.js'
24
+ import type { QueryOptions, QueryParameter } from './utils.js'
25
+ import { filterQueryOptions } from './utils.js'
26
+
27
+ /**
28
+ * Gets information about the currently stored zone authorization token.
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * import { createConfig } from '@wagmi/core'
33
+ * import { Actions, dangerous_secp256k1 } from '@wagmi/core/tempo'
34
+ * import { Account } from 'viem/tempo'
35
+ * import { http as zoneHttp, zone } from 'viem/tempo/zones'
36
+ *
37
+ * const zoneChain = zone(7)
38
+ * const account = Account.fromSecp256k1('0x...')
39
+ * const config = createConfig({
40
+ * chains: [zoneChain],
41
+ * connectors: [dangerous_secp256k1({ account })],
42
+ * transports: {
43
+ * [zoneChain.id]: zoneHttp(),
44
+ * },
45
+ * })
46
+ *
47
+ * await Actions.zone.signAuthorizationToken(config, {
48
+ * chainId: zoneChain.id,
49
+ * })
50
+ *
51
+ * const info = await Actions.zone.getAuthorizationTokenInfo(config, {
52
+ * chainId: zoneChain.id,
53
+ * })
54
+ *
55
+ * console.log(info.expiresAt)
56
+ * ```
57
+ *
58
+ * @param config - Config.
59
+ * @param parameters - Parameters.
60
+ * @returns The authorization token info.
61
+ */
62
+ export function getAuthorizationTokenInfo<config extends Config>(
63
+ config: config,
64
+ parameters: getAuthorizationTokenInfo.Parameters<config>,
65
+ ): Promise<getAuthorizationTokenInfo.ReturnValue> {
66
+ const client = config.getClient({ chainId: parameters.chainId })
67
+ return Actions.zone.getAuthorizationTokenInfo(client)
68
+ }
69
+
70
+ export namespace getAuthorizationTokenInfo {
71
+ export type Parameters<config extends Config> = ChainIdParameter<config>
72
+
73
+ export type ReturnValue = Actions.zone.getAuthorizationTokenInfo.ReturnType
74
+
75
+ export type ErrorType = Actions.zone.getAuthorizationTokenInfo.ErrorType
76
+
77
+ export function queryKey<config extends Config>(
78
+ parameters: Parameters<config>,
79
+ ) {
80
+ return [
81
+ 'getAuthorizationTokenInfo',
82
+ filterQueryOptions(parameters),
83
+ ] as const
84
+ }
85
+
86
+ export type QueryKey<config extends Config> = ReturnType<
87
+ typeof queryKey<config>
88
+ >
89
+
90
+ export function queryOptions<config extends Config, selectData = ReturnValue>(
91
+ config: Config,
92
+ parameters: queryOptions.Parameters<config, selectData>,
93
+ ): queryOptions.ReturnValue<config, selectData> {
94
+ const { query, ...rest } = parameters
95
+ return {
96
+ ...query,
97
+ enabled: Boolean(query?.enabled ?? true),
98
+ queryKey: queryKey(rest),
99
+ async queryFn(context) {
100
+ const [, parameters] = context.queryKey
101
+ return await getAuthorizationTokenInfo(config, parameters)
102
+ },
103
+ }
104
+ }
105
+
106
+ export declare namespace queryOptions {
107
+ export type Parameters<
108
+ config extends Config,
109
+ selectData = getAuthorizationTokenInfo.ReturnValue,
110
+ > = getAuthorizationTokenInfo.Parameters<config> &
111
+ QueryParameter<
112
+ getAuthorizationTokenInfo.ReturnValue,
113
+ getAuthorizationTokenInfo.ErrorType,
114
+ selectData,
115
+ getAuthorizationTokenInfo.QueryKey<config>
116
+ >
117
+
118
+ export type ReturnValue<
119
+ config extends Config,
120
+ selectData = getAuthorizationTokenInfo.ReturnValue,
121
+ > = QueryOptions<
122
+ getAuthorizationTokenInfo.ReturnValue,
123
+ getAuthorizationTokenInfo.ErrorType,
124
+ selectData,
125
+ getAuthorizationTokenInfo.QueryKey<config>
126
+ >
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Gets deposit processing status for a Tempo block number.
132
+ *
133
+ * @example
134
+ * ```ts
135
+ * import { createConfig } from '@wagmi/core'
136
+ * import { Actions, dangerous_secp256k1 } from '@wagmi/core/tempo'
137
+ * import { Account } from 'viem/tempo'
138
+ * import { http as zoneHttp, zone } from 'viem/tempo/zones'
139
+ *
140
+ * const zoneChain = zone(7)
141
+ * const account = Account.fromSecp256k1('0x...')
142
+ * const config = createConfig({
143
+ * chains: [zoneChain],
144
+ * connectors: [dangerous_secp256k1({ account })],
145
+ * transports: {
146
+ * [zoneChain.id]: zoneHttp(),
147
+ * },
148
+ * })
149
+ *
150
+ * await Actions.zone.signAuthorizationToken(config, {
151
+ * chainId: zoneChain.id,
152
+ * })
153
+ *
154
+ * const status = await Actions.zone.getDepositStatus(config, {
155
+ * chainId: zoneChain.id,
156
+ * tempoBlockNumber: 42n,
157
+ * })
158
+ *
159
+ * console.log(status.processed)
160
+ * ```
161
+ *
162
+ * @param config - Config.
163
+ * @param parameters - Parameters.
164
+ * @returns The deposit status.
165
+ */
166
+ export function getDepositStatus<config extends Config>(
167
+ config: config,
168
+ parameters: getDepositStatus.Parameters<config>,
169
+ ): Promise<getDepositStatus.ReturnValue> {
170
+ const { chainId, ...rest } = parameters
171
+ const client = config.getClient({ chainId })
172
+ return Actions.zone.getDepositStatus(client, rest)
173
+ }
174
+
175
+ export namespace getDepositStatus {
176
+ export type Parameters<config extends Config> = ChainIdParameter<config> &
177
+ Actions.zone.getDepositStatus.Parameters
178
+
179
+ export type ReturnValue = Actions.zone.getDepositStatus.ReturnType
180
+
181
+ export type ErrorType = Actions.zone.getDepositStatus.ErrorType
182
+
183
+ export function queryKey<config extends Config>(
184
+ parameters: PartialBy<Parameters<config>, 'tempoBlockNumber'>,
185
+ ) {
186
+ return ['getDepositStatus', filterQueryOptions(parameters)] as const
187
+ }
188
+
189
+ export type QueryKey<config extends Config> = ReturnType<
190
+ typeof queryKey<config>
191
+ >
192
+
193
+ export function queryOptions<config extends Config, selectData = ReturnValue>(
194
+ config: Config,
195
+ parameters: queryOptions.Parameters<config, selectData>,
196
+ ): queryOptions.ReturnValue<config, selectData> {
197
+ const { query, ...rest } = parameters
198
+ return {
199
+ ...query,
200
+ enabled: Boolean(
201
+ rest.tempoBlockNumber !== undefined && (query?.enabled ?? true),
202
+ ),
203
+ queryKey: queryKey(rest),
204
+ async queryFn(context) {
205
+ const [, { tempoBlockNumber, ...parameters }] = context.queryKey
206
+ if (tempoBlockNumber === undefined)
207
+ throw new Error('tempoBlockNumber is required.')
208
+ return await getDepositStatus(config, {
209
+ ...parameters,
210
+ tempoBlockNumber,
211
+ })
212
+ },
213
+ }
214
+ }
215
+
216
+ export declare namespace queryOptions {
217
+ export type Parameters<
218
+ config extends Config,
219
+ selectData = getDepositStatus.ReturnValue,
220
+ > = PartialBy<getDepositStatus.Parameters<config>, 'tempoBlockNumber'> &
221
+ QueryParameter<
222
+ getDepositStatus.ReturnValue,
223
+ getDepositStatus.ErrorType,
224
+ selectData,
225
+ getDepositStatus.QueryKey<config>
226
+ >
227
+
228
+ export type ReturnValue<
229
+ config extends Config,
230
+ selectData = getDepositStatus.ReturnValue,
231
+ > = QueryOptions<
232
+ getDepositStatus.ReturnValue,
233
+ getDepositStatus.ErrorType,
234
+ selectData,
235
+ getDepositStatus.QueryKey<config>
236
+ >
237
+ }
238
+ }
239
+
240
+ /**
241
+ * Gets the withdrawal fee for a given gas limit.
242
+ *
243
+ * @example
244
+ * ```ts
245
+ * import { createConfig } from '@wagmi/core'
246
+ * import { Actions } from '@wagmi/core/tempo'
247
+ * import { http as zoneHttp, zone } from 'viem/tempo/zones'
248
+ *
249
+ * const zoneChain = zone(7)
250
+ * const config = createConfig({
251
+ * chains: [zoneChain],
252
+ * transports: {
253
+ * [zoneChain.id]: zoneHttp(),
254
+ * },
255
+ * })
256
+ *
257
+ * const fee = await Actions.zone.getWithdrawalFee(config, {
258
+ * chainId: zoneChain.id,
259
+ * gas: 21_000n,
260
+ * })
261
+ *
262
+ * console.log(fee)
263
+ * ```
264
+ *
265
+ * @param config - Config.
266
+ * @param parameters - Parameters.
267
+ * @returns The withdrawal fee.
268
+ */
269
+ export function getWithdrawalFee<config extends Config>(
270
+ config: config,
271
+ parameters: getWithdrawalFee.Parameters<config>,
272
+ ): Promise<getWithdrawalFee.ReturnValue> {
273
+ const { chainId, ...rest } = parameters
274
+ const client = config.getClient({ chainId })
275
+ return Actions.zone.getWithdrawalFee(client, rest)
276
+ }
277
+
278
+ export namespace getWithdrawalFee {
279
+ export type Parameters<config extends Config> = ChainIdParameter<config> &
280
+ Actions.zone.getWithdrawalFee.Parameters
281
+
282
+ export type ReturnValue = Actions.zone.getWithdrawalFee.ReturnType
283
+
284
+ export type ErrorType = Actions.zone.getWithdrawalFee.ErrorType
285
+
286
+ export function queryKey<config extends Config>(
287
+ parameters: Parameters<config>,
288
+ ) {
289
+ return ['getWithdrawalFee', filterQueryOptions(parameters)] as const
290
+ }
291
+
292
+ export type QueryKey<config extends Config> = ReturnType<
293
+ typeof queryKey<config>
294
+ >
295
+
296
+ export function queryOptions<config extends Config, selectData = ReturnValue>(
297
+ config: Config,
298
+ parameters: queryOptions.Parameters<config, selectData>,
299
+ ): queryOptions.ReturnValue<config, selectData> {
300
+ const { query, ...rest } = parameters
301
+ return {
302
+ ...query,
303
+ enabled: Boolean(query?.enabled ?? true),
304
+ queryKey: queryKey(rest),
305
+ async queryFn(context) {
306
+ const [, parameters] = context.queryKey
307
+ return await getWithdrawalFee(config, parameters)
308
+ },
309
+ }
310
+ }
311
+
312
+ export declare namespace queryOptions {
313
+ export type Parameters<
314
+ config extends Config,
315
+ selectData = getWithdrawalFee.ReturnValue,
316
+ > = getWithdrawalFee.Parameters<config> &
317
+ QueryParameter<
318
+ getWithdrawalFee.ReturnValue,
319
+ getWithdrawalFee.ErrorType,
320
+ selectData,
321
+ getWithdrawalFee.QueryKey<config>
322
+ >
323
+
324
+ export type ReturnValue<
325
+ config extends Config,
326
+ selectData = getWithdrawalFee.ReturnValue,
327
+ > = QueryOptions<
328
+ getWithdrawalFee.ReturnValue,
329
+ getWithdrawalFee.ErrorType,
330
+ selectData,
331
+ getWithdrawalFee.QueryKey<config>
332
+ >
333
+ }
334
+ }
335
+
336
+ /**
337
+ * Gets the current zone metadata.
338
+ *
339
+ * @example
340
+ * ```ts
341
+ * import { createConfig } from '@wagmi/core'
342
+ * import { Actions } from '@wagmi/core/tempo'
343
+ * import { http as zoneHttp, zone } from 'viem/tempo/zones'
344
+ *
345
+ * const zoneChain = zone(7)
346
+ * const config = createConfig({
347
+ * chains: [zoneChain],
348
+ * transports: {
349
+ * [zoneChain.id]: zoneHttp(),
350
+ * },
351
+ * })
352
+ *
353
+ * const info = await Actions.zone.getZoneInfo(config, {
354
+ * chainId: zoneChain.id,
355
+ * })
356
+ *
357
+ * console.log(info.zoneId)
358
+ * ```
359
+ *
360
+ * @param config - Config.
361
+ * @param parameters - Parameters.
362
+ * @returns The zone metadata.
363
+ */
364
+ export function getZoneInfo<config extends Config>(
365
+ config: config,
366
+ parameters: getZoneInfo.Parameters<config>,
367
+ ): Promise<getZoneInfo.ReturnValue> {
368
+ const client = config.getClient({ chainId: parameters.chainId })
369
+ return Actions.zone.getZoneInfo(client)
370
+ }
371
+
372
+ export namespace getZoneInfo {
373
+ export type Parameters<config extends Config> = ChainIdParameter<config>
374
+
375
+ export type ReturnValue = Actions.zone.getZoneInfo.ReturnType
376
+
377
+ export type ErrorType = Actions.zone.getZoneInfo.ErrorType
378
+
379
+ export function queryKey<config extends Config>(
380
+ parameters: Parameters<config>,
381
+ ) {
382
+ return ['getZoneInfo', filterQueryOptions(parameters)] as const
383
+ }
384
+
385
+ export type QueryKey<config extends Config> = ReturnType<
386
+ typeof queryKey<config>
387
+ >
388
+
389
+ export function queryOptions<config extends Config, selectData = ReturnValue>(
390
+ config: Config,
391
+ parameters: queryOptions.Parameters<config, selectData>,
392
+ ): queryOptions.ReturnValue<config, selectData> {
393
+ const { query, ...rest } = parameters
394
+ return {
395
+ ...query,
396
+ enabled: Boolean(query?.enabled ?? true),
397
+ queryKey: queryKey(rest),
398
+ async queryFn(context) {
399
+ const [, parameters] = context.queryKey
400
+ return await getZoneInfo(config, parameters)
401
+ },
402
+ }
403
+ }
404
+
405
+ export declare namespace queryOptions {
406
+ export type Parameters<
407
+ config extends Config,
408
+ selectData = getZoneInfo.ReturnValue,
409
+ > = getZoneInfo.Parameters<config> &
410
+ QueryParameter<
411
+ getZoneInfo.ReturnValue,
412
+ getZoneInfo.ErrorType,
413
+ selectData,
414
+ getZoneInfo.QueryKey<config>
415
+ >
416
+
417
+ export type ReturnValue<
418
+ config extends Config,
419
+ selectData = getZoneInfo.ReturnValue,
420
+ > = QueryOptions<
421
+ getZoneInfo.ReturnValue,
422
+ getZoneInfo.ErrorType,
423
+ selectData,
424
+ getZoneInfo.QueryKey<config>
425
+ >
426
+ }
427
+ }
428
+
429
+ /**
430
+ * Signs and stores a zone authorization token for the configured zone transport.
431
+ *
432
+ * @example
433
+ * ```ts
434
+ * import { createConfig } from '@wagmi/core'
435
+ * import { Actions, dangerous_secp256k1 } from '@wagmi/core/tempo'
436
+ * import { Account } from 'viem/tempo'
437
+ * import { http as zoneHttp, zone } from 'viem/tempo/zones'
438
+ *
439
+ * const zoneChain = zone(7)
440
+ * const account = Account.fromSecp256k1('0x...')
441
+ * const config = createConfig({
442
+ * chains: [zoneChain],
443
+ * connectors: [dangerous_secp256k1({ account })],
444
+ * transports: {
445
+ * [zoneChain.id]: zoneHttp(),
446
+ * },
447
+ * })
448
+ *
449
+ * const result = await Actions.zone.signAuthorizationToken(config, {
450
+ * chainId: zoneChain.id,
451
+ * })
452
+ *
453
+ * console.log(result.token)
454
+ * ```
455
+ *
456
+ * @param config - Config.
457
+ * @param parameters - Parameters.
458
+ * @returns The authentication payload and serialized token.
459
+ */
460
+ export async function signAuthorizationToken<config extends Config>(
461
+ config: config,
462
+ parameters: signAuthorizationToken.Parameters<config>,
463
+ ): Promise<signAuthorizationToken.ReturnValue> {
464
+ const { account, chainId, connector, ...rest } = parameters
465
+ const client = await getZoneWalletClient(config, {
466
+ account,
467
+ chainId,
468
+ connector,
469
+ })
470
+ return Actions.zone.signAuthorizationToken(client, rest as never)
471
+ }
472
+
473
+ export declare namespace signAuthorizationToken {
474
+ export type Parameters<config extends Config> = ChainIdParameter<config> &
475
+ ConnectorParameter & {
476
+ account?: Address | Account | undefined
477
+ } & UnionLooseOmit<
478
+ Actions.zone.signAuthorizationToken.Parameters<Account>,
479
+ 'account' | 'chain'
480
+ >
481
+
482
+ export type ReturnValue = Actions.zone.signAuthorizationToken.ReturnType
483
+
484
+ export type ErrorType = Actions.zone.signAuthorizationToken.ErrorType
485
+ }
486
+
487
+ /**
488
+ * Deposits tokens into a zone on the parent Tempo chain.
489
+ *
490
+ * @example
491
+ * ```ts
492
+ * import { createConfig, http } from '@wagmi/core'
493
+ * import { tempoModerato } from '@wagmi/core/chains'
494
+ * import { Actions } from '@wagmi/core/tempo'
495
+ *
496
+ * const config = createConfig({
497
+ * chains: [tempoModerato],
498
+ * transports: {
499
+ * [tempoModerato.id]: http(),
500
+ * },
501
+ * })
502
+ *
503
+ * const hash = await Actions.zone.deposit(config, {
504
+ * amount: 1_000_000n,
505
+ * token: '0x20c0000000000000000000000000000000000001',
506
+ * zoneId: 7,
507
+ * })
508
+ * ```
509
+ *
510
+ * @param config - Config.
511
+ * @param parameters - Parameters.
512
+ * @returns Transaction hash.
513
+ */
514
+ export async function deposit<config extends Config>(
515
+ config: config,
516
+ parameters: deposit.Parameters<config>,
517
+ ): Promise<deposit.ReturnValue> {
518
+ const { account, chainId, connector, ...rest } = parameters
519
+ const client = await getConnectorClient(config, {
520
+ account,
521
+ assertChainId: false,
522
+ chainId,
523
+ connector,
524
+ })
525
+
526
+ const resolvedChainId = chainId ?? client.chain?.id
527
+ if (!resolvedChainId) throw new Error('`chainId` is required.')
528
+
529
+ const account_ = account ?? client.account
530
+ if (!account_) throw new Error('`account` is required.')
531
+
532
+ const accountAddress = parseAccount(account_).address
533
+ const {
534
+ amount,
535
+ memo = zeroHash,
536
+ recipient = accountAddress,
537
+ token,
538
+ zoneId,
539
+ ...tx
540
+ } = rest
541
+ const { address: portalAddress } = resolvePortal(
542
+ config,
543
+ resolvedChainId,
544
+ zoneId,
545
+ )
546
+ const tokenAddress = TokenId.toAddress(token)
547
+
548
+ return viem_sendTransaction(client, {
549
+ ...tx,
550
+ calls: [
551
+ {
552
+ data: encodeFunctionData({
553
+ abi: Abis.tip20,
554
+ functionName: 'approve',
555
+ args: [portalAddress, amount],
556
+ }),
557
+ to: tokenAddress,
558
+ },
559
+ {
560
+ data: encodeFunctionData({
561
+ abi: ZoneAbis.zonePortal,
562
+ functionName: 'deposit',
563
+ args: [tokenAddress, recipient, amount, memo],
564
+ }),
565
+ to: portalAddress,
566
+ },
567
+ ],
568
+ } as never) as never
569
+ }
570
+
571
+ export declare namespace deposit {
572
+ export type Parameters<config extends Config> = ChainIdParameter<config> &
573
+ ConnectorParameter &
574
+ UnionLooseOmit<
575
+ Actions.zone.deposit.Parameters<config['chains'][number], Account>,
576
+ 'chain'
577
+ >
578
+
579
+ export type ReturnValue = Actions.zone.deposit.ReturnValue
580
+
581
+ export type ErrorType = Actions.zone.deposit.ErrorType
582
+ }
583
+
584
+ /**
585
+ * Deposits tokens into a zone on the parent Tempo chain.
586
+ *
587
+ * Note: This is a synchronous action that waits for the transaction to
588
+ * be included on a block before returning a response.
589
+ *
590
+ * @example
591
+ * ```ts
592
+ * import { createConfig, http } from '@wagmi/core'
593
+ * import { tempoModerato } from '@wagmi/core/chains'
594
+ * import { Actions } from '@wagmi/core/tempo'
595
+ *
596
+ * const config = createConfig({
597
+ * chains: [tempoModerato],
598
+ * transports: {
599
+ * [tempoModerato.id]: http(),
600
+ * },
601
+ * })
602
+ *
603
+ * const result = await Actions.zone.depositSync(config, {
604
+ * amount: 1_000_000n,
605
+ * token: '0x20c0000000000000000000000000000000000001',
606
+ * zoneId: 7,
607
+ * })
608
+ *
609
+ * console.log(result.receipt.transactionHash)
610
+ * ```
611
+ *
612
+ * @param config - Config.
613
+ * @param parameters - Parameters.
614
+ * @returns The transaction receipt.
615
+ */
616
+ export async function depositSync<config extends Config>(
617
+ config: config,
618
+ parameters: depositSync.Parameters<config>,
619
+ ): Promise<depositSync.ReturnValue> {
620
+ const {
621
+ account,
622
+ chainId,
623
+ connector,
624
+ throwOnReceiptRevert = true,
625
+ ...rest
626
+ } = parameters
627
+ const client = await getConnectorClient(config, {
628
+ account,
629
+ assertChainId: false,
630
+ chainId,
631
+ connector,
632
+ })
633
+
634
+ const resolvedChainId = chainId ?? client.chain?.id
635
+ if (!resolvedChainId) throw new Error('`chainId` is required.')
636
+
637
+ const account_ = account ?? client.account
638
+ if (!account_) throw new Error('`account` is required.')
639
+
640
+ const accountAddress = parseAccount(account_).address
641
+ const {
642
+ amount,
643
+ memo = zeroHash,
644
+ recipient = accountAddress,
645
+ token,
646
+ zoneId,
647
+ ...tx
648
+ } = rest
649
+ const { address: portalAddress } = resolvePortal(
650
+ config,
651
+ resolvedChainId,
652
+ zoneId,
653
+ )
654
+ const tokenAddress = TokenId.toAddress(token)
655
+
656
+ const receipt = await viem_sendTransactionSync(client, {
657
+ ...tx,
658
+ calls: [
659
+ {
660
+ data: encodeFunctionData({
661
+ abi: Abis.tip20,
662
+ functionName: 'approve',
663
+ args: [portalAddress, amount],
664
+ }),
665
+ to: tokenAddress,
666
+ },
667
+ {
668
+ data: encodeFunctionData({
669
+ abi: ZoneAbis.zonePortal,
670
+ functionName: 'deposit',
671
+ args: [tokenAddress, recipient, amount, memo],
672
+ }),
673
+ to: portalAddress,
674
+ },
675
+ ],
676
+ throwOnReceiptRevert,
677
+ } as never)
678
+
679
+ return { receipt }
680
+ }
681
+
682
+ export declare namespace depositSync {
683
+ export type Parameters<config extends Config> = ChainIdParameter<config> &
684
+ ConnectorParameter &
685
+ UnionLooseOmit<
686
+ Actions.zone.depositSync.Parameters<config['chains'][number], Account>,
687
+ 'chain'
688
+ >
689
+
690
+ export type ReturnValue = Actions.zone.depositSync.ReturnValue
691
+
692
+ export type ErrorType = Actions.zone.depositSync.ErrorType
693
+ }
694
+
695
+ /**
696
+ * Deposits tokens into a zone on the parent Tempo chain with an encrypted
697
+ * recipient and memo.
698
+ *
699
+ * @example
700
+ * ```ts
701
+ * import { createConfig, http } from '@wagmi/core'
702
+ * import { tempoModerato } from '@wagmi/core/chains'
703
+ * import { Actions } from '@wagmi/core/tempo'
704
+ *
705
+ * const config = createConfig({
706
+ * chains: [tempoModerato],
707
+ * transports: {
708
+ * [tempoModerato.id]: http(),
709
+ * },
710
+ * })
711
+ *
712
+ * const hash = await Actions.zone.encryptedDeposit(config, {
713
+ * amount: 1_000_000n,
714
+ * token: '0x20c0000000000000000000000000000000000001',
715
+ * zoneId: 7,
716
+ * })
717
+ * ```
718
+ *
719
+ * @param config - Config.
720
+ * @param parameters - Parameters.
721
+ * @returns Transaction hash.
722
+ */
723
+ export async function encryptedDeposit<config extends Config>(
724
+ config: config,
725
+ parameters: encryptedDeposit.Parameters<config>,
726
+ ): Promise<encryptedDeposit.ReturnValue> {
727
+ const { account, chainId, connector, ...rest } = parameters
728
+ const client = await getConnectorClient(config, {
729
+ account,
730
+ assertChainId: false,
731
+ chainId,
732
+ connector,
733
+ })
734
+
735
+ const resolvedChainId = chainId ?? client.chain?.id
736
+ if (!resolvedChainId) throw new Error('`chainId` is required.')
737
+
738
+ const account_ = account ?? client.account
739
+ if (!account_) throw new Error('`account` is required.')
740
+
741
+ const accountAddress = parseAccount(account_).address
742
+ const {
743
+ amount,
744
+ memo,
745
+ recipient = accountAddress,
746
+ token,
747
+ zoneId,
748
+ ...tx
749
+ } = rest
750
+ const portal = resolvePortal(config, resolvedChainId, zoneId)
751
+ const portalAddress = portal.address
752
+ const tokenAddress = TokenId.toAddress(token)
753
+ const [publicKey, keyIndex] =
754
+ portal.sequencerEncryptionKey && portal.encryptionKeyCount !== undefined
755
+ ? [portal.sequencerEncryptionKey, portal.encryptionKeyCount]
756
+ : await Promise.all([
757
+ viem_readContract(client, {
758
+ address: portalAddress,
759
+ abi: ZoneAbis.zonePortal,
760
+ functionName: 'sequencerEncryptionKey',
761
+ }).then(([x, yParity]) => ({ x, yParity: Number(yParity) })),
762
+ viem_readContract(client, {
763
+ address: portalAddress,
764
+ abi: ZoneAbis.zonePortal,
765
+ functionName: 'encryptionKeyCount',
766
+ }),
767
+ ])
768
+ if (keyIndex === 0n)
769
+ throw new Error('No sequencer encryption key configured.')
770
+ const encrypted = await encryptDepositPayload(publicKey, recipient, memo)
771
+
772
+ return viem_sendTransaction(client, {
773
+ ...tx,
774
+ calls: [
775
+ {
776
+ data: encodeFunctionData({
777
+ abi: Abis.tip20,
778
+ functionName: 'approve',
779
+ args: [portalAddress, amount],
780
+ }),
781
+ to: tokenAddress,
782
+ },
783
+ {
784
+ data: encodeFunctionData({
785
+ abi: ZoneAbis.zonePortal,
786
+ functionName: 'depositEncrypted',
787
+ args: [tokenAddress, amount, keyIndex - 1n, encrypted],
788
+ }),
789
+ to: portalAddress,
790
+ },
791
+ ],
792
+ } as never) as never
793
+ }
794
+
795
+ export declare namespace encryptedDeposit {
796
+ export type Parameters<config extends Config> = ChainIdParameter<config> &
797
+ ConnectorParameter &
798
+ UnionLooseOmit<
799
+ Actions.zone.encryptedDeposit.Parameters<
800
+ config['chains'][number],
801
+ Account
802
+ >,
803
+ 'chain'
804
+ >
805
+
806
+ export type ReturnValue = Actions.zone.encryptedDeposit.ReturnValue
807
+
808
+ export type ErrorType = Actions.zone.encryptedDeposit.ErrorType
809
+ }
810
+
811
+ /**
812
+ * Deposits tokens into a zone on the parent Tempo chain with an encrypted
813
+ * recipient and memo.
814
+ *
815
+ * Note: This is a synchronous action that waits for the transaction to
816
+ * be included on a block before returning a response.
817
+ *
818
+ * @example
819
+ * ```ts
820
+ * import { createConfig, http } from '@wagmi/core'
821
+ * import { tempoModerato } from '@wagmi/core/chains'
822
+ * import { Actions } from '@wagmi/core/tempo'
823
+ *
824
+ * const config = createConfig({
825
+ * chains: [tempoModerato],
826
+ * transports: {
827
+ * [tempoModerato.id]: http(),
828
+ * },
829
+ * })
830
+ *
831
+ * const result = await Actions.zone.encryptedDepositSync(config, {
832
+ * amount: 1_000_000n,
833
+ * token: '0x20c0000000000000000000000000000000000001',
834
+ * zoneId: 7,
835
+ * })
836
+ *
837
+ * console.log(result.receipt.transactionHash)
838
+ * ```
839
+ *
840
+ * @param config - Config.
841
+ * @param parameters - Parameters.
842
+ * @returns The transaction receipt.
843
+ */
844
+ export async function encryptedDepositSync<config extends Config>(
845
+ config: config,
846
+ parameters: encryptedDepositSync.Parameters<config>,
847
+ ): Promise<encryptedDepositSync.ReturnValue> {
848
+ const {
849
+ account,
850
+ chainId,
851
+ connector,
852
+ throwOnReceiptRevert = true,
853
+ ...rest
854
+ } = parameters
855
+ const client = await getConnectorClient(config, {
856
+ account,
857
+ assertChainId: false,
858
+ chainId,
859
+ connector,
860
+ })
861
+
862
+ const resolvedChainId = chainId ?? client.chain?.id
863
+ if (!resolvedChainId) throw new Error('`chainId` is required.')
864
+
865
+ const account_ = account ?? client.account
866
+ if (!account_) throw new Error('`account` is required.')
867
+
868
+ const accountAddress = parseAccount(account_).address
869
+ const {
870
+ amount,
871
+ memo,
872
+ recipient = accountAddress,
873
+ token,
874
+ zoneId,
875
+ ...tx
876
+ } = rest
877
+ const portal = resolvePortal(config, resolvedChainId, zoneId)
878
+ const portalAddress = portal.address
879
+ const tokenAddress = TokenId.toAddress(token)
880
+ const [publicKey, keyIndex] =
881
+ portal.sequencerEncryptionKey && portal.encryptionKeyCount !== undefined
882
+ ? [portal.sequencerEncryptionKey, portal.encryptionKeyCount]
883
+ : await Promise.all([
884
+ viem_readContract(client, {
885
+ address: portalAddress,
886
+ abi: ZoneAbis.zonePortal,
887
+ functionName: 'sequencerEncryptionKey',
888
+ }).then(([x, yParity]) => ({ x, yParity: Number(yParity) })),
889
+ viem_readContract(client, {
890
+ address: portalAddress,
891
+ abi: ZoneAbis.zonePortal,
892
+ functionName: 'encryptionKeyCount',
893
+ }),
894
+ ])
895
+ if (keyIndex === 0n)
896
+ throw new Error('No sequencer encryption key configured.')
897
+ const encrypted = await encryptDepositPayload(publicKey, recipient, memo)
898
+
899
+ const receipt = await viem_sendTransactionSync(client, {
900
+ ...tx,
901
+ calls: [
902
+ {
903
+ data: encodeFunctionData({
904
+ abi: Abis.tip20,
905
+ functionName: 'approve',
906
+ args: [portalAddress, amount],
907
+ }),
908
+ to: tokenAddress,
909
+ },
910
+ {
911
+ data: encodeFunctionData({
912
+ abi: ZoneAbis.zonePortal,
913
+ functionName: 'depositEncrypted',
914
+ args: [tokenAddress, amount, keyIndex - 1n, encrypted],
915
+ }),
916
+ to: portalAddress,
917
+ },
918
+ ],
919
+ throwOnReceiptRevert,
920
+ } as never)
921
+
922
+ return { receipt }
923
+ }
924
+
925
+ export declare namespace encryptedDepositSync {
926
+ export type Parameters<config extends Config> = ChainIdParameter<config> &
927
+ ConnectorParameter &
928
+ UnionLooseOmit<
929
+ Actions.zone.encryptedDepositSync.Parameters<
930
+ config['chains'][number],
931
+ Account
932
+ >,
933
+ 'chain'
934
+ >
935
+
936
+ export type ReturnValue = Actions.zone.encryptedDepositSync.ReturnValue
937
+
938
+ export type ErrorType = Actions.zone.encryptedDepositSync.ErrorType
939
+ }
940
+
941
+ /**
942
+ * Requests a withdrawal from a zone to the parent Tempo chain.
943
+ *
944
+ * @example
945
+ * ```ts
946
+ * import { createConfig } from '@wagmi/core'
947
+ * import { Actions, dangerous_secp256k1 } from '@wagmi/core/tempo'
948
+ * import { Account } from 'viem/tempo'
949
+ * import { http as zoneHttp, zone } from 'viem/tempo/zones'
950
+ *
951
+ * const zoneChain = zone(7)
952
+ * const account = Account.fromSecp256k1('0x...')
953
+ * const config = createConfig({
954
+ * chains: [zoneChain],
955
+ * connectors: [dangerous_secp256k1({ account })],
956
+ * transports: {
957
+ * [zoneChain.id]: zoneHttp(),
958
+ * },
959
+ * })
960
+ *
961
+ * const hash = await Actions.zone.requestWithdrawal(config, {
962
+ * amount: 1_000_000n,
963
+ * chainId: zoneChain.id,
964
+ * token: '0x20c0000000000000000000000000000000000001',
965
+ * })
966
+ *
967
+ * console.log(hash)
968
+ * ```
969
+ *
970
+ * @param config - Config.
971
+ * @param parameters - Parameters.
972
+ * @returns Transaction hash.
973
+ */
974
+ export async function requestWithdrawal<config extends Config>(
975
+ config: config,
976
+ parameters: requestWithdrawal.Parameters<config>,
977
+ ): Promise<requestWithdrawal.ReturnValue> {
978
+ const { account, chainId, connector } = parameters
979
+ const client = await getZoneWalletClient(config, {
980
+ account,
981
+ chainId,
982
+ connector,
983
+ })
984
+ return Actions.zone.requestWithdrawal(client, parameters as never)
985
+ }
986
+
987
+ export declare namespace requestWithdrawal {
988
+ export type Parameters<config extends Config> = ChainIdParameter<config> &
989
+ ConnectorParameter &
990
+ UnionLooseOmit<
991
+ Actions.zone.requestWithdrawal.Parameters<
992
+ config['chains'][number],
993
+ Account
994
+ >,
995
+ 'chain'
996
+ >
997
+
998
+ export type ReturnValue = Actions.zone.requestWithdrawal.ReturnValue
999
+
1000
+ export type ErrorType = Actions.zone.requestWithdrawal.ErrorType
1001
+ }
1002
+
1003
+ /**
1004
+ * Requests a withdrawal from a zone to the parent Tempo chain.
1005
+ *
1006
+ * Note: This is a synchronous action that waits for the transaction to
1007
+ * be included on a block before returning a response.
1008
+ *
1009
+ * @example
1010
+ * ```ts
1011
+ * import { createConfig } from '@wagmi/core'
1012
+ * import { Actions, dangerous_secp256k1 } from '@wagmi/core/tempo'
1013
+ * import { Account } from 'viem/tempo'
1014
+ * import { http as zoneHttp, zone } from 'viem/tempo/zones'
1015
+ *
1016
+ * const zoneChain = zone(7)
1017
+ * const account = Account.fromSecp256k1('0x...')
1018
+ * const config = createConfig({
1019
+ * chains: [zoneChain],
1020
+ * connectors: [dangerous_secp256k1({ account })],
1021
+ * transports: {
1022
+ * [zoneChain.id]: zoneHttp(),
1023
+ * },
1024
+ * })
1025
+ *
1026
+ * const result = await Actions.zone.requestWithdrawalSync(config, {
1027
+ * amount: 1_000_000n,
1028
+ * chainId: zoneChain.id,
1029
+ * token: '0x20c0000000000000000000000000000000000001',
1030
+ * })
1031
+ *
1032
+ * console.log(result.receipt.transactionHash)
1033
+ * ```
1034
+ *
1035
+ * @param config - Config.
1036
+ * @param parameters - Parameters.
1037
+ * @returns The transaction receipt.
1038
+ */
1039
+ export async function requestWithdrawalSync<config extends Config>(
1040
+ config: config,
1041
+ parameters: requestWithdrawalSync.Parameters<config>,
1042
+ ): Promise<requestWithdrawalSync.ReturnValue> {
1043
+ const { account, chainId, connector } = parameters
1044
+ const client = await getZoneWalletClient(config, {
1045
+ account,
1046
+ chainId,
1047
+ connector,
1048
+ })
1049
+ return Actions.zone.requestWithdrawalSync(client, parameters as never)
1050
+ }
1051
+
1052
+ export declare namespace requestWithdrawalSync {
1053
+ export type Parameters<config extends Config> = ChainIdParameter<config> &
1054
+ ConnectorParameter &
1055
+ UnionLooseOmit<
1056
+ Actions.zone.requestWithdrawalSync.Parameters<
1057
+ config['chains'][number],
1058
+ Account
1059
+ >,
1060
+ 'chain'
1061
+ >
1062
+
1063
+ export type ReturnValue = Actions.zone.requestWithdrawalSync.ReturnValue
1064
+
1065
+ export type ErrorType = Actions.zone.requestWithdrawalSync.ErrorType
1066
+ }
1067
+
1068
+ /**
1069
+ * Requests a verifiable withdrawal from a zone to the parent Tempo chain.
1070
+ *
1071
+ * @example
1072
+ * ```ts
1073
+ * import { createConfig } from '@wagmi/core'
1074
+ * import { Actions, dangerous_secp256k1 } from '@wagmi/core/tempo'
1075
+ * import { Account } from 'viem/tempo'
1076
+ * import { http as zoneHttp, zone } from 'viem/tempo/zones'
1077
+ *
1078
+ * const zoneChain = zone(7)
1079
+ * const account = Account.fromSecp256k1('0x...')
1080
+ * const config = createConfig({
1081
+ * chains: [zoneChain],
1082
+ * connectors: [dangerous_secp256k1({ account })],
1083
+ * transports: {
1084
+ * [zoneChain.id]: zoneHttp(),
1085
+ * },
1086
+ * })
1087
+ *
1088
+ * const hash = await Actions.zone.requestVerifiableWithdrawal(config, {
1089
+ * amount: 1_000_000n,
1090
+ * chainId: zoneChain.id,
1091
+ * revealTo:
1092
+ * '0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
1093
+ * token: '0x20c0000000000000000000000000000000000001',
1094
+ * })
1095
+ *
1096
+ * console.log(hash)
1097
+ * ```
1098
+ *
1099
+ * @param config - Config.
1100
+ * @param parameters - Parameters.
1101
+ * @returns Transaction hash.
1102
+ */
1103
+ export async function requestVerifiableWithdrawal<config extends Config>(
1104
+ config: config,
1105
+ parameters: requestVerifiableWithdrawal.Parameters<config>,
1106
+ ): Promise<requestVerifiableWithdrawal.ReturnValue> {
1107
+ const { account, chainId, connector } = parameters
1108
+ const client = await getZoneWalletClient(config, {
1109
+ account,
1110
+ chainId,
1111
+ connector,
1112
+ })
1113
+ return Actions.zone.requestVerifiableWithdrawal(client, parameters as never)
1114
+ }
1115
+
1116
+ export declare namespace requestVerifiableWithdrawal {
1117
+ export type Parameters<config extends Config> = ChainIdParameter<config> &
1118
+ ConnectorParameter &
1119
+ UnionLooseOmit<
1120
+ Actions.zone.requestVerifiableWithdrawal.Parameters<
1121
+ config['chains'][number],
1122
+ Account
1123
+ >,
1124
+ 'chain'
1125
+ >
1126
+
1127
+ export type ReturnValue = Actions.zone.requestVerifiableWithdrawal.ReturnValue
1128
+
1129
+ export type ErrorType = Actions.zone.requestVerifiableWithdrawal.ErrorType
1130
+ }
1131
+
1132
+ /**
1133
+ * Requests a verifiable withdrawal from a zone to the parent Tempo chain.
1134
+ *
1135
+ * Note: This is a synchronous action that waits for the transaction to
1136
+ * be included on a block before returning a response.
1137
+ *
1138
+ * @example
1139
+ * ```ts
1140
+ * import { createConfig } from '@wagmi/core'
1141
+ * import { Actions, dangerous_secp256k1 } from '@wagmi/core/tempo'
1142
+ * import { Account } from 'viem/tempo'
1143
+ * import { http as zoneHttp, zone } from 'viem/tempo/zones'
1144
+ *
1145
+ * const zoneChain = zone(7)
1146
+ * const account = Account.fromSecp256k1('0x...')
1147
+ * const config = createConfig({
1148
+ * chains: [zoneChain],
1149
+ * connectors: [dangerous_secp256k1({ account })],
1150
+ * transports: {
1151
+ * [zoneChain.id]: zoneHttp(),
1152
+ * },
1153
+ * })
1154
+ *
1155
+ * const result = await Actions.zone.requestVerifiableWithdrawalSync(config, {
1156
+ * amount: 1_000_000n,
1157
+ * chainId: zoneChain.id,
1158
+ * revealTo:
1159
+ * '0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
1160
+ * token: '0x20c0000000000000000000000000000000000001',
1161
+ * })
1162
+ *
1163
+ * console.log(result.receipt.transactionHash)
1164
+ * ```
1165
+ *
1166
+ * @param config - Config.
1167
+ * @param parameters - Parameters.
1168
+ * @returns The transaction receipt.
1169
+ */
1170
+ export async function requestVerifiableWithdrawalSync<config extends Config>(
1171
+ config: config,
1172
+ parameters: requestVerifiableWithdrawalSync.Parameters<config>,
1173
+ ): Promise<requestVerifiableWithdrawalSync.ReturnValue> {
1174
+ const { account, chainId, connector } = parameters
1175
+ const client = await getZoneWalletClient(config, {
1176
+ account,
1177
+ chainId,
1178
+ connector,
1179
+ })
1180
+ return Actions.zone.requestVerifiableWithdrawalSync(
1181
+ client,
1182
+ parameters as never,
1183
+ )
1184
+ }
1185
+
1186
+ export declare namespace requestVerifiableWithdrawalSync {
1187
+ export type Parameters<config extends Config> = ChainIdParameter<config> &
1188
+ ConnectorParameter &
1189
+ UnionLooseOmit<
1190
+ Actions.zone.requestVerifiableWithdrawalSync.Parameters<
1191
+ config['chains'][number],
1192
+ Account
1193
+ >,
1194
+ 'chain'
1195
+ >
1196
+
1197
+ export type ReturnValue =
1198
+ Actions.zone.requestVerifiableWithdrawalSync.ReturnValue
1199
+
1200
+ export type ErrorType = Actions.zone.requestVerifiableWithdrawalSync.ErrorType
1201
+ }
1202
+
1203
+ const portalAddresses = {
1204
+ 42431: {
1205
+ 6: '0x7069DeC4E64Fd07334A0933eDe836C17259c9B23',
1206
+ 7: '0x3F5296303400B56271b476F5A0B9cBF74350D6Ac',
1207
+ },
1208
+ } as const satisfies Record<number, Record<number, Address>>
1209
+
1210
+ async function getZoneWalletClient<config extends Config>(
1211
+ config: config,
1212
+ parameters: {
1213
+ account?: Address | Account | null | undefined
1214
+ chainId?: number | undefined
1215
+ connector?: ConnectorParameter['connector']
1216
+ },
1217
+ ) {
1218
+ const client = await getConnectorClient(config, {
1219
+ ...parameters,
1220
+ assertChainId: false,
1221
+ })
1222
+ const resolvedChainId = parameters.chainId ?? client.chain?.id
1223
+ const account =
1224
+ resolveSignableAccount(parameters.account) ??
1225
+ (await getSignableConnectorAccount(config, {
1226
+ account: parameters.account ?? client.account,
1227
+ chainId: resolvedChainId,
1228
+ connector: parameters.connector,
1229
+ }))
1230
+ if (!account || resolvedChainId === undefined) return client
1231
+
1232
+ // Local accounts can sign against the zone transport directly without
1233
+ // depending on the connector provider's currently selected chain.
1234
+ return Object.assign(config.getClient({ chainId: resolvedChainId }), {
1235
+ account,
1236
+ }) as typeof client
1237
+ }
1238
+
1239
+ async function getSignableConnectorAccount<config extends Config>(
1240
+ config: config,
1241
+ parameters: {
1242
+ account?: Address | Account | null | undefined
1243
+ chainId?: number | undefined
1244
+ connector?: ConnectorParameter['connector']
1245
+ },
1246
+ ) {
1247
+ const connector =
1248
+ parameters.connector ??
1249
+ config.state.connections.get(config.state.current!)?.connector
1250
+ const provider = (await connector?.getProvider?.({
1251
+ chainId: parameters.chainId,
1252
+ })) as
1253
+ | {
1254
+ getAccount?:
1255
+ | ((parameters?: {
1256
+ address?: Address | undefined
1257
+ signable?: boolean | undefined
1258
+ }) => Account | undefined)
1259
+ | undefined
1260
+ }
1261
+ | undefined
1262
+ if (typeof provider?.getAccount !== 'function') return
1263
+
1264
+ try {
1265
+ return provider.getAccount({
1266
+ address: parameters.account
1267
+ ? parseAccount(parameters.account).address
1268
+ : undefined,
1269
+ signable: true,
1270
+ })
1271
+ } catch {
1272
+ return
1273
+ }
1274
+ }
1275
+
1276
+ function resolveSignableAccount(
1277
+ account?: Address | Account | null | undefined,
1278
+ ) {
1279
+ if (typeof account !== 'object' || account === null) return
1280
+ return 'sign' in account ? account : undefined
1281
+ }
1282
+
1283
+ function resolvePortal<config extends Config>(
1284
+ config: config,
1285
+ chainId: number,
1286
+ zoneId: number,
1287
+ ): {
1288
+ address: Address
1289
+ encryptionKeyCount?: bigint | undefined
1290
+ sequencerEncryptionKey?: { x: Hex; yParity: number } | undefined
1291
+ } {
1292
+ const chain = config.chains.find((chain) => chain.id === chainId)
1293
+ const zonePortal = chain?.contracts?.zonePortal as
1294
+ | Address
1295
+ | {
1296
+ [key: number]:
1297
+ | Address
1298
+ | {
1299
+ address?: Address | undefined
1300
+ encryptionKeyCount?: bigint | undefined
1301
+ sequencerEncryptionKey?: { x: Hex; yParity: number } | undefined
1302
+ }
1303
+ | undefined
1304
+ address?: Address | undefined
1305
+ encryptionKeyCount?: bigint | undefined
1306
+ sequencerEncryptionKey?: { x: Hex; yParity: number } | undefined
1307
+ }
1308
+ | undefined
1309
+
1310
+ // Allow custom chains to supply portal addresses until viem exposes a
1311
+ // generic resolver for non-hardcoded Tempo networks.
1312
+ if (typeof zonePortal === 'string') return { address: zonePortal }
1313
+ if (zonePortal && typeof zonePortal === 'object') {
1314
+ const portal =
1315
+ 'address' in zonePortal && typeof zonePortal.address === 'string'
1316
+ ? zonePortal
1317
+ : zonePortal[zoneId]
1318
+
1319
+ if (typeof portal === 'string') return { address: portal as Address }
1320
+ if (
1321
+ portal &&
1322
+ typeof portal === 'object' &&
1323
+ typeof portal.address === 'string'
1324
+ ) {
1325
+ return {
1326
+ address: portal.address,
1327
+ encryptionKeyCount: portal.encryptionKeyCount,
1328
+ sequencerEncryptionKey: portal.sequencerEncryptionKey,
1329
+ }
1330
+ }
1331
+ }
1332
+
1333
+ const address = (portalAddresses as Record<number, Record<number, Address>>)[
1334
+ chainId
1335
+ ]?.[zoneId]
1336
+ if (address) return { address }
1337
+
1338
+ throw new Error(
1339
+ `No portal address configured for zone ${zoneId} on chain ${chainId}.`,
1340
+ )
1341
+ }
1342
+
1343
+ async function encryptDepositPayload(
1344
+ publicKey: { x: Hex; yParity: number },
1345
+ recipient: Address,
1346
+ memo: Hex = zeroHash,
1347
+ ): Promise<{
1348
+ ciphertext: Hex
1349
+ ephemeralPubkeyX: Hex
1350
+ ephemeralPubkeyYParity: number
1351
+ nonce: Hex
1352
+ tag: Hex
1353
+ }> {
1354
+ const sequencerPublicKey = PublicKey.from({
1355
+ prefix: publicKey.yParity,
1356
+ x: BigInt(publicKey.x),
1357
+ })
1358
+
1359
+ const { privateKey: ephemeralPrivateKey, publicKey: ephemeralPublicKey } =
1360
+ Secp256k1.createKeyPair()
1361
+
1362
+ const sharedSecret = Secp256k1.getSharedSecret({
1363
+ privateKey: ephemeralPrivateKey,
1364
+ publicKey: sequencerPublicKey,
1365
+ as: 'Bytes',
1366
+ })
1367
+
1368
+ const hkdfKey = await globalThis.crypto.subtle.importKey(
1369
+ 'raw',
1370
+ sharedSecret.buffer as ArrayBuffer,
1371
+ 'HKDF',
1372
+ false,
1373
+ ['deriveKey'],
1374
+ )
1375
+ const aesKey = await globalThis.crypto.subtle.deriveKey(
1376
+ {
1377
+ name: 'HKDF',
1378
+ hash: 'SHA-256',
1379
+ salt: new Uint8Array(12),
1380
+ info: new TextEncoder().encode('ecies-aes-key'),
1381
+ },
1382
+ hkdfKey,
1383
+ { name: 'AES-GCM', length: 256 },
1384
+ false,
1385
+ ['encrypt'],
1386
+ )
1387
+
1388
+ const nonce = Bytes.random(12)
1389
+ const plaintext = encodeAbiParameters(
1390
+ [{ type: 'address' }, { type: 'bytes32' }],
1391
+ [recipient, memo],
1392
+ )
1393
+ const ciphertextWithTag = new Uint8Array(
1394
+ await globalThis.crypto.subtle.encrypt(
1395
+ { name: 'AES-GCM', iv: nonce as BufferSource, tagLength: 128 },
1396
+ aesKey,
1397
+ Bytes.from(plaintext) as BufferSource,
1398
+ ),
1399
+ )
1400
+ const ciphertext = ciphertextWithTag.slice(0, -16)
1401
+ const tag = ciphertextWithTag.slice(-16)
1402
+ const compressedEphemeral = PublicKey.compress(ephemeralPublicKey)
1403
+
1404
+ return {
1405
+ ciphertext: bytesToHex(ciphertext),
1406
+ ephemeralPubkeyX: `0x${compressedEphemeral.x.toString(16).padStart(64, '0')}`,
1407
+ ephemeralPubkeyYParity: compressedEphemeral.prefix,
1408
+ nonce: bytesToHex(nonce),
1409
+ tag: bytesToHex(tag),
1410
+ }
1411
+ }
1412
+
1413
+ function bytesToHex(bytes: Uint8Array): Hex {
1414
+ return `0x${Array.from(bytes, (value) => value.toString(16).padStart(2, '0')).join('')}` as Hex
1415
+ }