viem 2.55.5 → 2.55.8

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 (107) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/_cjs/errors/version.js +1 -1
  3. package/_cjs/tempo/Abis.js +1809 -1
  4. package/_cjs/tempo/Abis.js.map +1 -1
  5. package/_cjs/tempo/Decorator.js +25 -2
  6. package/_cjs/tempo/Decorator.js.map +1 -1
  7. package/_cjs/tempo/actions/earn.js +1368 -0
  8. package/_cjs/tempo/actions/earn.js.map +1 -0
  9. package/_cjs/tempo/actions/index.js +2 -1
  10. package/_cjs/tempo/actions/index.js.map +1 -1
  11. package/_cjs/tempo/actions/zone.js +47 -61
  12. package/_cjs/tempo/actions/zone.js.map +1 -1
  13. package/_cjs/tempo/chainConfig.js +3 -1
  14. package/_cjs/tempo/chainConfig.js.map +1 -1
  15. package/_cjs/tempo/errors.js +28 -4
  16. package/_cjs/tempo/errors.js.map +1 -1
  17. package/_cjs/tempo/index.js +2 -1
  18. package/_cjs/tempo/index.js.map +1 -1
  19. package/_cjs/tempo/internal/WithdrawalSenderTag.js +9 -0
  20. package/_cjs/tempo/internal/WithdrawalSenderTag.js.map +1 -0
  21. package/_cjs/tempo/zones/Abis.js +46 -0
  22. package/_cjs/tempo/zones/Abis.js.map +1 -1
  23. package/_cjs/tempo/zones/Addresses.js +17 -0
  24. package/_cjs/tempo/zones/Addresses.js.map +1 -0
  25. package/_cjs/tempo/zones/index.js +2 -2
  26. package/_cjs/tempo/zones/index.js.map +1 -1
  27. package/_cjs/tempo/zones/zone.js +30 -16
  28. package/_cjs/tempo/zones/zone.js.map +1 -1
  29. package/_cjs/utils/blob/fromBlobs.js +5 -2
  30. package/_cjs/utils/blob/fromBlobs.js.map +1 -1
  31. package/_cjs/utils/encoding/fromBytes.js +2 -2
  32. package/_cjs/utils/encoding/fromBytes.js.map +1 -1
  33. package/_esm/errors/version.js +1 -1
  34. package/_esm/tempo/Abis.js +1810 -0
  35. package/_esm/tempo/Abis.js.map +1 -1
  36. package/_esm/tempo/Decorator.js +25 -2
  37. package/_esm/tempo/Decorator.js.map +1 -1
  38. package/_esm/tempo/actions/earn.js +2100 -0
  39. package/_esm/tempo/actions/earn.js.map +1 -0
  40. package/_esm/tempo/actions/index.js +1 -0
  41. package/_esm/tempo/actions/index.js.map +1 -1
  42. package/_esm/tempo/actions/zone.js +104 -119
  43. package/_esm/tempo/actions/zone.js.map +1 -1
  44. package/_esm/tempo/chainConfig.js +4 -1
  45. package/_esm/tempo/chainConfig.js.map +1 -1
  46. package/_esm/tempo/errors.js +25 -2
  47. package/_esm/tempo/errors.js.map +1 -1
  48. package/_esm/tempo/index.js +1 -1
  49. package/_esm/tempo/index.js.map +1 -1
  50. package/_esm/tempo/internal/WithdrawalSenderTag.js +7 -0
  51. package/_esm/tempo/internal/WithdrawalSenderTag.js.map +1 -0
  52. package/_esm/tempo/zones/Abis.js +46 -0
  53. package/_esm/tempo/zones/Abis.js.map +1 -1
  54. package/_esm/tempo/zones/Addresses.js +14 -0
  55. package/_esm/tempo/zones/Addresses.js.map +1 -0
  56. package/_esm/tempo/zones/index.js +2 -1
  57. package/_esm/tempo/zones/index.js.map +1 -1
  58. package/_esm/tempo/zones/zone.js +29 -15
  59. package/_esm/tempo/zones/zone.js.map +1 -1
  60. package/_esm/utils/blob/fromBlobs.js +6 -2
  61. package/_esm/utils/blob/fromBlobs.js.map +1 -1
  62. package/_esm/utils/encoding/fromBytes.js +2 -2
  63. package/_esm/utils/encoding/fromBytes.js.map +1 -1
  64. package/_types/errors/version.d.ts +1 -1
  65. package/_types/tempo/Abis.d.ts +2880 -0
  66. package/_types/tempo/Abis.d.ts.map +1 -1
  67. package/_types/tempo/Decorator.d.ts +499 -41
  68. package/_types/tempo/Decorator.d.ts.map +1 -1
  69. package/_types/tempo/actions/earn.d.ts +7549 -0
  70. package/_types/tempo/actions/earn.d.ts.map +1 -0
  71. package/_types/tempo/actions/index.d.ts +1 -0
  72. package/_types/tempo/actions/index.d.ts.map +1 -1
  73. package/_types/tempo/actions/zone.d.ts +86 -109
  74. package/_types/tempo/actions/zone.d.ts.map +1 -1
  75. package/_types/tempo/chainConfig.d.ts.map +1 -1
  76. package/_types/tempo/errors.d.ts +33 -3
  77. package/_types/tempo/errors.d.ts.map +1 -1
  78. package/_types/tempo/index.d.ts +1 -1
  79. package/_types/tempo/index.d.ts.map +1 -1
  80. package/_types/tempo/internal/WithdrawalSenderTag.d.ts +11 -0
  81. package/_types/tempo/internal/WithdrawalSenderTag.d.ts.map +1 -0
  82. package/_types/tempo/zones/Abis.d.ts +87 -0
  83. package/_types/tempo/zones/Abis.d.ts.map +1 -1
  84. package/_types/tempo/zones/Addresses.d.ts +13 -0
  85. package/_types/tempo/zones/Addresses.d.ts.map +1 -0
  86. package/_types/tempo/zones/index.d.ts +2 -1
  87. package/_types/tempo/zones/index.d.ts.map +1 -1
  88. package/_types/tempo/zones/zone.d.ts +14 -33
  89. package/_types/tempo/zones/zone.d.ts.map +1 -1
  90. package/_types/utils/blob/fromBlobs.d.ts.map +1 -1
  91. package/errors/version.ts +1 -1
  92. package/package.json +2 -2
  93. package/tempo/Abis.ts +1822 -0
  94. package/tempo/Decorator.ts +572 -47
  95. package/tempo/actions/earn.ts +3319 -0
  96. package/tempo/actions/index.ts +1 -0
  97. package/tempo/actions/zone.ts +183 -230
  98. package/tempo/chainConfig.ts +7 -1
  99. package/tempo/errors.ts +54 -6
  100. package/tempo/index.ts +1 -0
  101. package/tempo/internal/WithdrawalSenderTag.ts +20 -0
  102. package/tempo/zones/Abis.ts +46 -0
  103. package/tempo/zones/Addresses.ts +15 -0
  104. package/tempo/zones/index.ts +1 -1
  105. package/tempo/zones/zone.ts +38 -17
  106. package/utils/blob/fromBlobs.ts +6 -2
  107. package/utils/encoding/fromBytes.ts +2 -2
@@ -3,6 +3,7 @@ export * as accessKey from './accessKey.js'
3
3
  export * as amm from './amm.js'
4
4
  export * as channel from './channel.js'
5
5
  export * as dex from './dex.js'
6
+ export * as earn from './earn.js'
6
7
  export * as faucet from './faucet.js'
7
8
  export * as fee from './fee.js'
8
9
  export * as nonce from './nonce.js'
@@ -37,8 +37,8 @@ import { stringify } from '../../utils/stringify.js'
37
37
  import * as Abis from '../Abis.js'
38
38
  import * as Addresses from '../Addresses.js'
39
39
  import {
40
- WaitForDepositStatusTimeoutError,
41
- type WaitForDepositStatusTimeoutErrorType,
40
+ WaitForTempoBlockTimeoutError,
41
+ type WaitForTempoBlockTimeoutErrorType,
42
42
  } from '../errors.js'
43
43
  import type {
44
44
  GetAccountParameter,
@@ -51,11 +51,14 @@ import {
51
51
  pickWriteParameters,
52
52
  pickWriteSyncParameters,
53
53
  } from '../internal/utils.js'
54
+ import * as WithdrawalSenderTag from '../internal/WithdrawalSenderTag.js'
54
55
  import * as Storage from '../Storage.js'
55
56
  import type { TransactionReceipt } from '../Transaction.js'
56
57
  import * as ZoneAbis from '../zones/Abis.js'
57
58
  import { getPortalAddress } from '../zones/zone.js'
58
59
 
60
+ const defaultWithdrawalGas = 10_000_000n
61
+
59
62
  export type EncryptedPayload = {
60
63
  ciphertext: Hex.Hex
61
64
  ephemeralPubkeyX: Hex.Hex
@@ -945,220 +948,6 @@ export namespace getAuthorizationTokenInfo {
945
948
  export type ErrorType = RequestErrorType | BaseErrorType
946
949
  }
947
950
 
948
- /**
949
- * Returns deposit processing status for a given Tempo block number.
950
- *
951
- * @example
952
- * ```ts
953
- * import { createClient } from 'viem'
954
- * import { http, zoneModerato } from 'viem/tempo/zones'
955
- * import { Actions } from 'viem/tempo'
956
- *
957
- * const client = createClient({
958
- * chain: zoneModerato(7),
959
- * transport: http(),
960
- * })
961
- *
962
- * const status = await Actions.zone.getDepositStatus(client, {
963
- * tempoBlockNumber: 42n,
964
- * })
965
- * ```
966
- *
967
- * @param client - Zone client.
968
- * @param parameters - Parameters including the Tempo block number.
969
- * @returns Deposit status.
970
- */
971
- export async function getDepositStatus<
972
- chain extends Chain | undefined,
973
- account extends Account | undefined,
974
- >(
975
- client: Client<Transport, chain, account>,
976
- parameters: getDepositStatus.Parameters,
977
- ): Promise<getDepositStatus.ReturnType> {
978
- const { tempoBlockNumber } = parameters
979
- const status = await client.request<{
980
- Method: 'zone_getDepositStatus'
981
- Parameters: [Hex.Hex]
982
- ReturnType: getDepositStatus.RpcReturnType
983
- }>({
984
- method: 'zone_getDepositStatus',
985
- params: [Hex.fromNumber(tempoBlockNumber)],
986
- })
987
-
988
- return {
989
- deposits: status.deposits.map((deposit) => ({
990
- amount: Hex.toBigInt(deposit.amount),
991
- depositHash: deposit.depositHash,
992
- kind: deposit.kind,
993
- memo: deposit.memo,
994
- recipient: deposit.recipient,
995
- sender: deposit.sender,
996
- status: deposit.status,
997
- token: deposit.token,
998
- })),
999
- processed: status.processed,
1000
- tempoBlockNumber: Hex.toBigInt(status.tempoBlockNumber),
1001
- zoneProcessedThrough: Hex.toBigInt(status.zoneProcessedThrough),
1002
- }
1003
- }
1004
-
1005
- export namespace getDepositStatus {
1006
- export type DepositStatus = 'failed' | 'pending' | 'processed'
1007
- export type DepositKind = 'encrypted' | 'regular'
1008
-
1009
- export type DepositRpc = {
1010
- amount: Hex.Hex
1011
- depositHash: Hex.Hex
1012
- kind: DepositKind
1013
- memo: Hex.Hex | null
1014
- recipient: Address | null
1015
- sender: Address
1016
- status: DepositStatus
1017
- token: Address
1018
- }
1019
-
1020
- export type Deposit = {
1021
- amount: bigint
1022
- depositHash: Hex.Hex
1023
- kind: DepositKind
1024
- memo: Hex.Hex | null
1025
- recipient: Address | null
1026
- sender: Address
1027
- status: DepositStatus
1028
- token: Address
1029
- }
1030
-
1031
- export type RpcReturnType = {
1032
- deposits: readonly DepositRpc[]
1033
- processed: boolean
1034
- tempoBlockNumber: Hex.Hex
1035
- zoneProcessedThrough: Hex.Hex
1036
- }
1037
-
1038
- export type Parameters = {
1039
- tempoBlockNumber: bigint
1040
- }
1041
-
1042
- export type ReturnType = {
1043
- deposits: readonly Deposit[]
1044
- processed: boolean
1045
- tempoBlockNumber: bigint
1046
- zoneProcessedThrough: bigint
1047
- }
1048
-
1049
- export type ErrorType = RequestErrorType | BaseErrorType
1050
- }
1051
-
1052
- /**
1053
- * Waits for a Tempo block's deposits to be processed by a zone.
1054
- *
1055
- * @example
1056
- * ```ts
1057
- * import { createClient } from 'viem'
1058
- * import { Actions } from 'viem/tempo'
1059
- * import { http, zoneModerato } from 'viem/tempo/zones'
1060
- *
1061
- * const client = createClient({
1062
- * chain: zoneModerato(7),
1063
- * transport: http(),
1064
- * })
1065
- *
1066
- * const status = await Actions.zone.waitForDepositStatus(client, {
1067
- * tempoBlockNumber: 42n,
1068
- * })
1069
- * ```
1070
- *
1071
- * @param client - Zone client.
1072
- * @param parameters - Tempo block number and polling options.
1073
- * @returns The processed deposit status.
1074
- */
1075
- export async function waitForDepositStatus<
1076
- chain extends Chain | undefined,
1077
- account extends Account | undefined,
1078
- >(
1079
- client: Client<Transport, chain, account>,
1080
- parameters: waitForDepositStatus.Parameters,
1081
- ): Promise<waitForDepositStatus.ReturnType> {
1082
- const {
1083
- pollingInterval = client.pollingInterval,
1084
- tempoBlockNumber,
1085
- timeout = 60_000,
1086
- } = parameters
1087
- const observerId = stringify([
1088
- 'waitForDepositStatus',
1089
- client.uid,
1090
- tempoBlockNumber,
1091
- ])
1092
- const { promise, reject, resolve } =
1093
- withResolvers<waitForDepositStatus.ReturnType>()
1094
-
1095
- let timer: ReturnType<typeof setTimeout> | undefined
1096
- let unobserve: () => void
1097
- const cleanup = () => {
1098
- clearTimeout(timer)
1099
- unobserve()
1100
- }
1101
- const resolve_ = (status: waitForDepositStatus.ReturnType) => {
1102
- cleanup()
1103
- resolve(status)
1104
- }
1105
- const reject_ = (error: unknown) => {
1106
- cleanup()
1107
- reject(error)
1108
- }
1109
-
1110
- unobserve = observe(
1111
- observerId,
1112
- { reject: reject_, resolve: resolve_ },
1113
- (emit) => {
1114
- const unpoll = poll(
1115
- async () => {
1116
- try {
1117
- const status = await getDepositStatus(client, { tempoBlockNumber })
1118
- if (!status.processed) return
1119
- unpoll()
1120
- emit.resolve(status)
1121
- } catch (error) {
1122
- unpoll()
1123
- emit.reject(error)
1124
- }
1125
- },
1126
- {
1127
- emitOnBegin: true,
1128
- interval: pollingInterval,
1129
- },
1130
- )
1131
-
1132
- return unpoll
1133
- },
1134
- )
1135
-
1136
- timer = timeout
1137
- ? setTimeout(() => {
1138
- reject_(new WaitForDepositStatusTimeoutError({ tempoBlockNumber }))
1139
- }, timeout)
1140
- : undefined
1141
-
1142
- return await promise
1143
- }
1144
-
1145
- export namespace waitForDepositStatus {
1146
- export type Parameters = getDepositStatus.Parameters & {
1147
- /** Polling frequency in milliseconds. @default `client.pollingInterval` */
1148
- pollingInterval?: number | undefined
1149
- /** Timeout in milliseconds. @default `60_000` */
1150
- timeout?: number | undefined
1151
- }
1152
-
1153
- export type ReturnType = getDepositStatus.ReturnType
1154
-
1155
- export type ErrorType =
1156
- | getDepositStatus.ErrorType
1157
- | ObserveErrorType
1158
- | PollErrorType
1159
- | WaitForDepositStatusTimeoutErrorType
1160
- }
1161
-
1162
951
  /**
1163
952
  * Returns the fee required for a withdrawal from a zone, given a callback gas
1164
953
  * limit.
@@ -1243,10 +1032,23 @@ export async function getZoneInfo<
1243
1032
  method: 'zone_getZoneInfo',
1244
1033
  params: [],
1245
1034
  })
1035
+ const tempoBlockNumber =
1036
+ info.tempoBlockNumber ??
1037
+ (
1038
+ await client.request<{
1039
+ Method: 'zone_getDepositStatus'
1040
+ Parameters: [Hex.Hex]
1041
+ ReturnType: { zoneProcessedThrough: Hex.Hex }
1042
+ }>({
1043
+ method: 'zone_getDepositStatus',
1044
+ params: ['0x0'],
1045
+ })
1046
+ ).zoneProcessedThrough
1246
1047
 
1247
1048
  return {
1248
1049
  chainId: Hex.toNumber(info.chainId),
1249
- sequencer: info.sequencer,
1050
+ sequencers: 'sequencers' in info ? info.sequencers : [info.sequencer],
1051
+ tempoBlockNumber: Hex.toBigInt(tempoBlockNumber),
1250
1052
  zoneId: Hex.toNumber(info.zoneId),
1251
1053
  zoneTokens: info.zoneTokens,
1252
1054
  }
@@ -1254,22 +1056,141 @@ export async function getZoneInfo<
1254
1056
 
1255
1057
  export namespace getZoneInfo {
1256
1058
  export type RpcReturnType = {
1059
+ /** Zone chain ID. */
1257
1060
  chainId: Hex.Hex
1258
- sequencer: Address
1061
+ /** Latest Tempo block imported by the zone. */
1062
+ tempoBlockNumber?: Hex.Hex | undefined
1063
+ /** Zone ID. */
1259
1064
  zoneId: Hex.Hex
1065
+ /** Enabled zone token addresses. */
1260
1066
  zoneTokens: readonly Address[]
1261
- }
1067
+ } & (
1068
+ | {
1069
+ /** Active sequencer addresses. */
1070
+ sequencers: readonly Address[]
1071
+ }
1072
+ | {
1073
+ /** Active sequencer address. */
1074
+ sequencer: Address
1075
+ }
1076
+ )
1262
1077
 
1263
1078
  export type ReturnType = {
1079
+ /** Zone chain ID. */
1264
1080
  chainId: number
1265
- sequencer: Address
1081
+ /** Active sequencer addresses. */
1082
+ sequencers: readonly Address[]
1083
+ /** Latest Tempo block imported by the zone. */
1084
+ tempoBlockNumber: bigint
1085
+ /** Zone ID. */
1266
1086
  zoneId: number
1087
+ /** Enabled zone token addresses. */
1267
1088
  zoneTokens: readonly Address[]
1268
1089
  }
1269
1090
 
1270
1091
  export type ErrorType = RequestErrorType | BaseErrorType
1271
1092
  }
1272
1093
 
1094
+ /**
1095
+ * Waits for a zone to import a Tempo block.
1096
+ *
1097
+ * @example
1098
+ * ```ts
1099
+ * import { createClient } from 'viem'
1100
+ * import { Actions } from 'viem/tempo'
1101
+ * import { http, zoneModerato } from 'viem/tempo/zones'
1102
+ *
1103
+ * const client = createClient({
1104
+ * chain: zoneModerato(7),
1105
+ * transport: http(),
1106
+ * })
1107
+ *
1108
+ * const info = await Actions.zone.waitForTempoBlock(client, {
1109
+ * tempoBlockNumber: 42n,
1110
+ * })
1111
+ * ```
1112
+ *
1113
+ * @param client - Zone client.
1114
+ * @param parameters - Tempo block number and polling options.
1115
+ * @returns Zone metadata after the block has been imported.
1116
+ */
1117
+ export async function waitForTempoBlock<
1118
+ chain extends Chain | undefined,
1119
+ account extends Account | undefined,
1120
+ >(
1121
+ client: Client<Transport, chain, account>,
1122
+ parameters: waitForTempoBlock.Parameters,
1123
+ ): Promise<waitForTempoBlock.ReturnType> {
1124
+ const {
1125
+ pollingInterval = client.pollingInterval,
1126
+ tempoBlockNumber,
1127
+ timeout = 60_000,
1128
+ } = parameters
1129
+ const observerId = stringify([
1130
+ 'waitForTempoBlock',
1131
+ client.uid,
1132
+ tempoBlockNumber,
1133
+ ])
1134
+ const { promise, reject, resolve } =
1135
+ withResolvers<waitForTempoBlock.ReturnType>()
1136
+
1137
+ let timer: ReturnType<typeof setTimeout> | undefined
1138
+ let unobserve: () => void
1139
+ const cleanup = () => {
1140
+ clearTimeout(timer)
1141
+ unobserve()
1142
+ }
1143
+
1144
+ unobserve = observe(observerId, { reject, resolve }, (emit) => {
1145
+ const unpoll = poll(
1146
+ async () => {
1147
+ try {
1148
+ const info = await getZoneInfo(client)
1149
+ if (info.tempoBlockNumber < tempoBlockNumber) return
1150
+ unpoll()
1151
+ emit.resolve(info)
1152
+ } catch (error) {
1153
+ unpoll()
1154
+ emit.reject(error)
1155
+ }
1156
+ },
1157
+ {
1158
+ emitOnBegin: true,
1159
+ interval: pollingInterval,
1160
+ },
1161
+ )
1162
+
1163
+ return unpoll
1164
+ })
1165
+
1166
+ timer = timeout
1167
+ ? setTimeout(() => {
1168
+ reject(new WaitForTempoBlockTimeoutError({ tempoBlockNumber }))
1169
+ }, timeout)
1170
+ : undefined
1171
+
1172
+ return await promise.finally(cleanup)
1173
+ }
1174
+
1175
+ export namespace waitForTempoBlock {
1176
+ export type Parameters = {
1177
+ /** Polling frequency in milliseconds. @default `client.pollingInterval` */
1178
+ pollingInterval?: number | undefined
1179
+ /** Tempo block number to wait for. */
1180
+ tempoBlockNumber: bigint
1181
+ /** Timeout in milliseconds. @default `60_000` */
1182
+ timeout?: number | undefined
1183
+ }
1184
+
1185
+ export type ReturnType = getZoneInfo.ReturnType
1186
+
1187
+ export type ErrorType =
1188
+ | getZoneInfo.ErrorType
1189
+ | ObserveErrorType
1190
+ | PollErrorType
1191
+ | WaitForTempoBlockTimeoutErrorType
1192
+ }
1193
+
1273
1194
  /**
1274
1195
  * Requests a withdrawal from a zone to the parent Tempo chain via the
1275
1196
  * ZoneOutbox contract.
@@ -1318,6 +1239,7 @@ export async function requestWithdrawal<
1318
1239
  return sendTransaction(client, {
1319
1240
  ...pickWriteParameters(parameters as never),
1320
1241
  calls: requestWithdrawal.calls(args),
1242
+ gas: parameters.gas ?? defaultWithdrawalGas,
1321
1243
  } as never) as never
1322
1244
  }
1323
1245
 
@@ -1469,6 +1391,7 @@ export namespace requestWithdrawal {
1469
1391
  to,
1470
1392
  token,
1471
1393
  }),
1394
+ gas: transactionRequest.gas ?? defaultWithdrawalGas,
1472
1395
  } as never)
1473
1396
  const feePerGas = request.maxFeePerGas ?? request.gasPrice
1474
1397
  if (typeof request.gas !== 'bigint' || typeof feePerGas !== 'bigint')
@@ -1559,26 +1482,47 @@ type WithdrawalCalls = ReturnType<typeof requestWithdrawal.calls>
1559
1482
  *
1560
1483
  * @example
1561
1484
  * ```ts
1562
- * import { createClient } from 'viem'
1485
+ * import { createClient, createPublicClient, http } from 'viem'
1563
1486
  * import { privateKeyToAccount } from 'viem/accounts'
1564
- * import { http, zoneModerato } from 'viem/tempo/zones'
1487
+ * import { tempoModerato } from 'viem/chains'
1565
1488
  * import { Actions } from 'viem/tempo'
1489
+ * import {
1490
+ * Abis,
1491
+ * getPortalAddress,
1492
+ * http as zoneHttp,
1493
+ * zoneModerato,
1494
+ * } from 'viem/tempo/zones'
1566
1495
  *
1567
1496
  * const client = createClient({
1568
1497
  * account: privateKeyToAccount('0x...'),
1569
1498
  * chain: zoneModerato(7),
1570
- * transport: http(),
1499
+ * transport: zoneHttp(),
1571
1500
  * })
1572
1501
  *
1573
- * const result = await Actions.zone.requestWithdrawalSync(client, {
1574
- * token: '0x20c0...0001',
1575
- * amount: 1_000_000n,
1502
+ * const { receipt, senderTag } =
1503
+ * await Actions.zone.requestWithdrawalSync(client, {
1504
+ * amount: 1_000_000n,
1505
+ * token: '0x20c0...0001',
1506
+ * })
1507
+ *
1508
+ * // `senderTag` identifies the indexed WithdrawalProcessed event emitted on
1509
+ * // the parent Tempo chain after the withdrawal is processed.
1510
+ * const tempoClient = createPublicClient({
1511
+ * chain: tempoModerato,
1512
+ * transport: http(),
1513
+ * })
1514
+ * const [withdrawal] = await tempoClient.getContractEvents({
1515
+ * address: getPortalAddress(tempoModerato.id, 7),
1516
+ * abi: Abis.zonePortal,
1517
+ * eventName: 'WithdrawalProcessed',
1518
+ * args: { senderTag },
1519
+ * fromBlock: 0n,
1576
1520
  * })
1577
1521
  * ```
1578
1522
  *
1579
1523
  * @param client - Wallet client connected to the zone chain.
1580
1524
  * @param parameters - Withdrawal parameters.
1581
- * @returns The transaction receipt.
1525
+ * @returns The transaction receipt and sender tag for the parent-chain withdrawal event.
1582
1526
  */
1583
1527
  export async function requestWithdrawalSync<
1584
1528
  chain extends Chain | undefined,
@@ -1589,10 +1533,10 @@ export async function requestWithdrawalSync<
1589
1533
  ): Promise<requestWithdrawalSync.ReturnValue> {
1590
1534
  const { account = client.account, throwOnReceiptRevert = true } = parameters
1591
1535
 
1592
- const account_ = account ? parseAccount(account) : undefined
1593
1536
  if (!account) throw new Error('`account` is required.')
1537
+ const account_ = parseAccount(account)
1594
1538
 
1595
- const to = parameters.to ?? account_?.address
1539
+ const to = parameters.to ?? account_.address
1596
1540
  if (!to) throw new Error('`to` is required.')
1597
1541
 
1598
1542
  const args = { ...parameters, to }
@@ -1600,9 +1544,14 @@ export async function requestWithdrawalSync<
1600
1544
  ...pickWriteParameters(parameters as never),
1601
1545
  ...pickWriteSyncParameters(parameters as never),
1602
1546
  calls: requestWithdrawal.calls(args),
1547
+ gas: parameters.gas ?? defaultWithdrawalGas,
1603
1548
  throwOnReceiptRevert,
1604
1549
  } as never)
1605
- return { receipt }
1550
+ const senderTag = WithdrawalSenderTag.from({
1551
+ sender: account_.address,
1552
+ transactionHash: receipt.transactionHash,
1553
+ })
1554
+ return { receipt, senderTag }
1606
1555
  }
1607
1556
 
1608
1557
  export namespace requestWithdrawalSync {
@@ -1617,6 +1566,8 @@ export namespace requestWithdrawalSync {
1617
1566
  export type ReturnValue = Compute<{
1618
1567
  /** Transaction receipt. */
1619
1568
  receipt: TransactionReceipt
1569
+ /** Sender tag identifying the indexed parent-chain `WithdrawalProcessed` event. */
1570
+ senderTag: Hex.Hex
1620
1571
  }>
1621
1572
 
1622
1573
  // TODO: exhaustive error type
@@ -1673,6 +1624,7 @@ export async function requestVerifiableWithdrawal<
1673
1624
  return sendTransaction(client, {
1674
1625
  ...pickWriteParameters(parameters as never),
1675
1626
  calls: requestVerifiableWithdrawal.calls(args),
1627
+ gas: parameters.gas ?? defaultWithdrawalGas,
1676
1628
  } as never) as never
1677
1629
  }
1678
1630
 
@@ -1787,6 +1739,7 @@ export async function requestVerifiableWithdrawalSync<
1787
1739
  ...pickWriteParameters(parameters as never),
1788
1740
  ...pickWriteSyncParameters(parameters as never),
1789
1741
  calls: requestVerifiableWithdrawal.calls(args),
1742
+ gas: parameters.gas ?? defaultWithdrawalGas,
1790
1743
  throwOnReceiptRevert,
1791
1744
  } as never)
1792
1745
  return { receipt }
@@ -58,6 +58,7 @@ export const chainConfig = {
58
58
  feeToken?: TokenId.TokenIdOrAddress | undefined
59
59
  })
60
60
  | undefined
61
+ feePayerSignature?: Transaction.TransactionSerializableTempo['feePayerSignature']
61
62
  from?: Address | undefined
62
63
  multisig?: MultisigConfig.Config | undefined
63
64
  signatures?: readonly unknown[] | undefined
@@ -66,7 +67,12 @@ export const chainConfig = {
66
67
  // FIXME: node estimates gas with secp256k1 dummy sig + null feePayerSignature.
67
68
  // Actual tx has larger keychain/webAuthn sigs + real fee payer sig, costing more intrinsic gas.
68
69
  if (phase === 'afterFillParameters') {
69
- if (request.feePayer) {
70
+ // Fee payer signature covers the gas limit, so the relay must set it before signing and Viem must not change it afterward.
71
+ if (
72
+ typeof request.gas !== 'undefined' &&
73
+ request.feePayer &&
74
+ !request.feePayerSignature
75
+ ) {
70
76
  if (request.keyAuthorization?.signature.type === 'webAuthn')
71
77
  request.gas = (request.gas ?? 0n) + 20_000n
72
78
  else if (request.account?.source === 'accessKey')
package/tempo/errors.ts CHANGED
@@ -1,15 +1,63 @@
1
+ import type { Address } from 'abitype'
2
+ import type { Hex } from 'ox'
1
3
  import { BaseError } from '../errors/base.js'
2
4
 
3
- export type WaitForDepositStatusTimeoutErrorType =
4
- WaitForDepositStatusTimeoutError & {
5
- name: 'WaitForDepositStatusTimeoutError'
5
+ export type GetVaultEngineChangedErrorType = GetVaultEngineChangedError & {
6
+ name: 'GetVaultEngineChangedError'
7
+ }
8
+
9
+ export class GetVaultEngineChangedError extends BaseError {
10
+ constructor({ vault }: { vault: Address }) {
11
+ super(`Engine of vault "${vault}" changed while reading.`, {
12
+ metaMessages: [
13
+ 'An engine migration raced the snapshot; state from two different engines cannot be mixed.',
14
+ 'Retry the read.',
15
+ ],
16
+ name: 'GetVaultEngineChangedError',
17
+ })
18
+ }
19
+ }
20
+
21
+ export type WaitForPrivateDepositTimeoutErrorType =
22
+ WaitForPrivateDepositTimeoutError & {
23
+ name: 'WaitForPrivateDepositTimeoutError'
24
+ }
25
+
26
+ /** Thrown when a Zone gateway deposit event is not found before the timeout. */
27
+ export class WaitForPrivateDepositTimeoutError extends BaseError {
28
+ constructor({ actionId, gateway }: { actionId: Hex.Hex; gateway: Address }) {
29
+ super(
30
+ `Timed out while waiting for Zone deposit "${actionId}" at gateway "${gateway}".`,
31
+ { name: 'WaitForPrivateDepositTimeoutError' },
32
+ )
33
+ }
34
+ }
35
+
36
+ export type WaitForTempoBlockTimeoutErrorType =
37
+ WaitForTempoBlockTimeoutError & {
38
+ name: 'WaitForTempoBlockTimeoutError'
6
39
  }
7
40
 
8
- export class WaitForDepositStatusTimeoutError extends BaseError {
41
+ export class WaitForTempoBlockTimeoutError extends BaseError {
9
42
  constructor({ tempoBlockNumber }: { tempoBlockNumber: bigint }) {
10
43
  super(
11
- `Timed out while waiting for deposits from Tempo block "${tempoBlockNumber}" to be processed.`,
12
- { name: 'WaitForDepositStatusTimeoutError' },
44
+ `Timed out while waiting for Tempo block "${tempoBlockNumber}" to be imported by the zone.`,
45
+ { name: 'WaitForTempoBlockTimeoutError' },
46
+ )
47
+ }
48
+ }
49
+
50
+ export type WaitForPrivateRedeemTimeoutErrorType =
51
+ WaitForPrivateRedeemTimeoutError & {
52
+ name: 'WaitForPrivateRedeemTimeoutError'
53
+ }
54
+
55
+ /** Thrown when a Zone gateway redeem event is not found before the timeout. */
56
+ export class WaitForPrivateRedeemTimeoutError extends BaseError {
57
+ constructor({ actionId, gateway }: { actionId: Hex.Hex; gateway: Address }) {
58
+ super(
59
+ `Timed out while waiting for Zone redemption "${actionId}" at gateway "${gateway}".`,
60
+ { name: 'WaitForPrivateRedeemTimeoutError' },
13
61
  )
14
62
  }
15
63
  }
package/tempo/index.ts CHANGED
@@ -13,6 +13,7 @@ export type {
13
13
  } from 'ox/tempo'
14
14
  export {
15
15
  Channel,
16
+ EarnShares,
16
17
  MultisigConfig,
17
18
  Period,
18
19
  ReceivePolicyReceipt,
@@ -0,0 +1,20 @@
1
+ import type { Address } from 'abitype'
2
+ import { AbiParameters, Hash, type Hex } from 'ox'
3
+
4
+ /** Derives a withdrawal sender tag from its sender and transaction hash. @internal */
5
+ export function from(options: from.Options): Hex.Hex {
6
+ const { sender, transactionHash } = options
7
+ return Hash.keccak256(
8
+ AbiParameters.encodePacked(
9
+ ['address', 'bytes32'],
10
+ [sender, transactionHash],
11
+ ),
12
+ )
13
+ }
14
+
15
+ export declare namespace from {
16
+ type Options = {
17
+ sender: Address
18
+ transactionHash: Hex.Hex
19
+ }
20
+ }