@aztec/ethereum 0.0.1-commit.24de95ac → 0.0.1-commit.2606882

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 (236) hide show
  1. package/dest/account.d.ts +1 -1
  2. package/dest/chain.d.ts +1 -1
  3. package/dest/client.d.ts +25 -3
  4. package/dest/client.d.ts.map +1 -1
  5. package/dest/client.js +60 -4
  6. package/dest/config.d.ts +29 -73
  7. package/dest/config.d.ts.map +1 -1
  8. package/dest/config.js +70 -387
  9. package/dest/constants.d.ts +1 -1
  10. package/dest/contracts/chain_state_override.d.ts +78 -0
  11. package/dest/contracts/chain_state_override.d.ts.map +1 -0
  12. package/dest/contracts/chain_state_override.js +137 -0
  13. package/dest/contracts/empire_base.d.ts +7 -5
  14. package/dest/contracts/empire_base.d.ts.map +1 -1
  15. package/dest/contracts/empire_base.js +1 -1
  16. package/dest/contracts/errors.d.ts +1 -1
  17. package/dest/contracts/errors.d.ts.map +1 -1
  18. package/dest/contracts/fee_asset_handler.d.ts +6 -5
  19. package/dest/contracts/fee_asset_handler.d.ts.map +1 -1
  20. package/dest/contracts/fee_asset_handler.js +11 -9
  21. package/dest/contracts/fee_asset_price_oracle.d.ts +105 -0
  22. package/dest/contracts/fee_asset_price_oracle.d.ts.map +1 -0
  23. package/dest/contracts/fee_asset_price_oracle.js +656 -0
  24. package/dest/contracts/fee_juice.d.ts +1 -1
  25. package/dest/contracts/fee_juice.d.ts.map +1 -1
  26. package/dest/contracts/governance.d.ts +113 -36
  27. package/dest/contracts/governance.d.ts.map +1 -1
  28. package/dest/contracts/governance.js +207 -16
  29. package/dest/contracts/governance_proposer.d.ts +38 -4
  30. package/dest/contracts/governance_proposer.d.ts.map +1 -1
  31. package/dest/contracts/governance_proposer.js +455 -12
  32. package/dest/contracts/gse.d.ts +1 -1
  33. package/dest/contracts/gse.d.ts.map +1 -1
  34. package/dest/contracts/inbox.d.ts +24 -3
  35. package/dest/contracts/inbox.d.ts.map +1 -1
  36. package/dest/contracts/inbox.js +42 -2
  37. package/dest/contracts/index.d.ts +6 -3
  38. package/dest/contracts/index.d.ts.map +1 -1
  39. package/dest/contracts/index.js +5 -2
  40. package/dest/contracts/log.d.ts +13 -0
  41. package/dest/contracts/log.d.ts.map +1 -0
  42. package/dest/contracts/log.js +1 -0
  43. package/dest/contracts/multicall.d.ts +127 -12
  44. package/dest/contracts/multicall.d.ts.map +1 -1
  45. package/dest/contracts/multicall.js +201 -93
  46. package/dest/contracts/outbox.d.ts +64 -0
  47. package/dest/contracts/outbox.d.ts.map +1 -0
  48. package/dest/contracts/outbox.js +113 -0
  49. package/dest/contracts/registry.d.ts +3 -1
  50. package/dest/contracts/registry.d.ts.map +1 -1
  51. package/dest/contracts/registry.js +30 -1
  52. package/dest/contracts/rollup.d.ts +5432 -131
  53. package/dest/contracts/rollup.d.ts.map +1 -1
  54. package/dest/contracts/rollup.js +1114 -231
  55. package/dest/contracts/slasher_contract.d.ts +1 -1
  56. package/dest/contracts/slasher_contract.d.ts.map +1 -1
  57. package/dest/contracts/{tally_slashing_proposer.d.ts → slashing_proposer.d.ts} +11 -10
  58. package/dest/contracts/slashing_proposer.d.ts.map +1 -0
  59. package/dest/contracts/{tally_slashing_proposer.js → slashing_proposer.js} +21 -16
  60. package/dest/contracts/utils.d.ts +1 -1
  61. package/dest/deploy_aztec_l1_contracts.d.ts +256 -0
  62. package/dest/deploy_aztec_l1_contracts.d.ts.map +1 -0
  63. package/dest/deploy_aztec_l1_contracts.js +411 -0
  64. package/dest/deploy_l1_contract.d.ts +68 -0
  65. package/dest/deploy_l1_contract.d.ts.map +1 -0
  66. package/dest/deploy_l1_contract.js +312 -0
  67. package/dest/eth-signer/eth-signer.d.ts +1 -1
  68. package/dest/eth-signer/index.d.ts +1 -1
  69. package/dest/forwarder_proxy.d.ts +32 -0
  70. package/dest/forwarder_proxy.d.ts.map +1 -0
  71. package/dest/forwarder_proxy.js +93 -0
  72. package/dest/generated/l1-contracts-defaults.d.ts +30 -0
  73. package/dest/generated/l1-contracts-defaults.d.ts.map +1 -0
  74. package/dest/generated/l1-contracts-defaults.js +30 -0
  75. package/dest/l1_artifacts.d.ts +19816 -16730
  76. package/dest/l1_artifacts.d.ts.map +1 -1
  77. package/dest/l1_artifacts.js +9 -24
  78. package/dest/l1_contract_addresses.d.ts +61 -65
  79. package/dest/l1_contract_addresses.d.ts.map +1 -1
  80. package/dest/l1_contract_addresses.js +99 -80
  81. package/dest/l1_reader.d.ts +7 -5
  82. package/dest/l1_reader.d.ts.map +1 -1
  83. package/dest/l1_reader.js +15 -7
  84. package/dest/l1_tx_utils/config.d.ts +11 -5
  85. package/dest/l1_tx_utils/config.d.ts.map +1 -1
  86. package/dest/l1_tx_utils/config.js +43 -7
  87. package/dest/l1_tx_utils/constants.d.ts +8 -2
  88. package/dest/l1_tx_utils/constants.d.ts.map +1 -1
  89. package/dest/l1_tx_utils/constants.js +27 -2
  90. package/dest/l1_tx_utils/factory.d.ts +18 -10
  91. package/dest/l1_tx_utils/factory.d.ts.map +1 -1
  92. package/dest/l1_tx_utils/factory.js +17 -7
  93. package/dest/l1_tx_utils/fee-strategies/index.d.ts +10 -0
  94. package/dest/l1_tx_utils/fee-strategies/index.d.ts.map +1 -0
  95. package/dest/l1_tx_utils/fee-strategies/index.js +12 -0
  96. package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts +8 -0
  97. package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts.map +1 -0
  98. package/dest/l1_tx_utils/fee-strategies/p75_competitive.js +129 -0
  99. package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.d.ts +23 -0
  100. package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.d.ts.map +1 -0
  101. package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.js +191 -0
  102. package/dest/l1_tx_utils/fee-strategies/types.d.ts +51 -0
  103. package/dest/l1_tx_utils/fee-strategies/types.d.ts.map +1 -0
  104. package/dest/l1_tx_utils/fee-strategies/types.js +3 -0
  105. package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts +41 -0
  106. package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts.map +1 -0
  107. package/dest/l1_tx_utils/forwarder_l1_tx_utils.js +42 -0
  108. package/dest/l1_tx_utils/index-blobs.d.ts +3 -0
  109. package/dest/l1_tx_utils/index-blobs.d.ts.map +1 -0
  110. package/dest/l1_tx_utils/index-blobs.js +2 -0
  111. package/dest/l1_tx_utils/index.d.ts +4 -1
  112. package/dest/l1_tx_utils/index.d.ts.map +1 -1
  113. package/dest/l1_tx_utils/index.js +3 -0
  114. package/dest/l1_tx_utils/interfaces.d.ts +2 -2
  115. package/dest/l1_tx_utils/interfaces.d.ts.map +1 -1
  116. package/dest/l1_tx_utils/l1_fee_analyzer.d.ts +233 -0
  117. package/dest/l1_tx_utils/l1_fee_analyzer.d.ts.map +1 -0
  118. package/dest/l1_tx_utils/l1_fee_analyzer.js +506 -0
  119. package/dest/l1_tx_utils/l1_tx_utils.d.ts +26 -8
  120. package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -1
  121. package/dest/l1_tx_utils/l1_tx_utils.js +118 -70
  122. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +19 -30
  123. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -1
  124. package/dest/l1_tx_utils/readonly_l1_tx_utils.js +65 -168
  125. package/dest/l1_tx_utils/signer.d.ts +1 -1
  126. package/dest/l1_tx_utils/tx_delayer.d.ts +58 -0
  127. package/dest/l1_tx_utils/tx_delayer.d.ts.map +1 -0
  128. package/dest/{test → l1_tx_utils}/tx_delayer.js +70 -39
  129. package/dest/l1_tx_utils/types.d.ts +1 -1
  130. package/dest/l1_tx_utils/types.d.ts.map +1 -1
  131. package/dest/l1_tx_utils/utils.d.ts +1 -1
  132. package/dest/l1_types.d.ts +1 -1
  133. package/dest/publisher_manager.d.ts +21 -6
  134. package/dest/publisher_manager.d.ts.map +1 -1
  135. package/dest/publisher_manager.js +81 -7
  136. package/dest/queries.d.ts +14 -3
  137. package/dest/queries.d.ts.map +1 -1
  138. package/dest/queries.js +78 -9
  139. package/dest/test/chain_monitor.d.ts +48 -25
  140. package/dest/test/chain_monitor.d.ts.map +1 -1
  141. package/dest/test/chain_monitor.js +71 -38
  142. package/dest/test/eth_cheat_codes.d.ts +22 -6
  143. package/dest/test/eth_cheat_codes.d.ts.map +1 -1
  144. package/dest/test/eth_cheat_codes.js +28 -7
  145. package/dest/test/eth_cheat_codes_with_state.d.ts +1 -1
  146. package/dest/test/eth_cheat_codes_with_state.d.ts.map +1 -1
  147. package/dest/test/index.d.ts +1 -3
  148. package/dest/test/index.d.ts.map +1 -1
  149. package/dest/test/index.js +0 -2
  150. package/dest/test/rollup_cheat_codes.d.ts +46 -14
  151. package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
  152. package/dest/test/rollup_cheat_codes.js +118 -42
  153. package/dest/test/start_anvil.d.ts +25 -2
  154. package/dest/test/start_anvil.d.ts.map +1 -1
  155. package/dest/test/start_anvil.js +143 -28
  156. package/dest/test/upgrade_utils.d.ts +1 -1
  157. package/dest/test/upgrade_utils.js +2 -2
  158. package/dest/types.d.ts +57 -2
  159. package/dest/types.d.ts.map +1 -1
  160. package/dest/utils.d.ts +24 -4
  161. package/dest/utils.d.ts.map +1 -1
  162. package/dest/utils.js +112 -16
  163. package/dest/zkPassportVerifierAddress.d.ts +1 -1
  164. package/package.json +35 -17
  165. package/src/client.ts +66 -2
  166. package/src/config.ts +91 -469
  167. package/src/contracts/README.md +157 -0
  168. package/src/contracts/chain_state_override.ts +200 -0
  169. package/src/contracts/empire_base.ts +6 -5
  170. package/src/contracts/fee_asset_handler.ts +10 -7
  171. package/src/contracts/fee_asset_price_oracle.ts +285 -0
  172. package/src/contracts/governance.ts +279 -13
  173. package/src/contracts/governance_proposer.ts +74 -7
  174. package/src/contracts/inbox.ts +64 -4
  175. package/src/contracts/index.ts +5 -2
  176. package/src/contracts/log.ts +13 -0
  177. package/src/contracts/multicall.ts +243 -102
  178. package/src/contracts/outbox.ts +132 -0
  179. package/src/contracts/registry.ts +31 -1
  180. package/src/contracts/rollup.ts +819 -192
  181. package/src/contracts/{tally_slashing_proposer.ts → slashing_proposer.ts} +26 -21
  182. package/src/deploy_aztec_l1_contracts.ts +646 -0
  183. package/src/deploy_l1_contract.ts +362 -0
  184. package/src/forwarder_proxy.ts +108 -0
  185. package/src/generated/l1-contracts-defaults.ts +32 -0
  186. package/src/l1_artifacts.ts +12 -35
  187. package/src/l1_contract_addresses.ts +120 -92
  188. package/src/l1_reader.ts +25 -10
  189. package/src/l1_tx_utils/config.ts +52 -11
  190. package/src/l1_tx_utils/constants.ts +13 -2
  191. package/src/l1_tx_utils/factory.ts +31 -31
  192. package/src/l1_tx_utils/fee-strategies/index.ts +22 -0
  193. package/src/l1_tx_utils/fee-strategies/p75_competitive.ts +163 -0
  194. package/src/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.ts +245 -0
  195. package/src/l1_tx_utils/fee-strategies/types.ts +56 -0
  196. package/src/l1_tx_utils/forwarder_l1_tx_utils.ts +108 -0
  197. package/src/l1_tx_utils/index-blobs.ts +2 -0
  198. package/src/l1_tx_utils/index.ts +3 -0
  199. package/src/l1_tx_utils/interfaces.ts +1 -1
  200. package/src/l1_tx_utils/l1_fee_analyzer.ts +803 -0
  201. package/src/l1_tx_utils/l1_tx_utils.ts +123 -52
  202. package/src/l1_tx_utils/readonly_l1_tx_utils.ts +79 -214
  203. package/src/{test → l1_tx_utils}/tx_delayer.ts +97 -58
  204. package/src/publisher_manager.ts +107 -10
  205. package/src/queries.ts +87 -10
  206. package/src/test/chain_monitor.ts +115 -51
  207. package/src/test/eth_cheat_codes.ts +25 -7
  208. package/src/test/index.ts +0 -2
  209. package/src/test/rollup_cheat_codes.ts +123 -45
  210. package/src/test/start_anvil.ts +179 -27
  211. package/src/test/upgrade_utils.ts +2 -2
  212. package/src/types.ts +62 -0
  213. package/src/utils.ts +128 -19
  214. package/dest/contracts/empire_slashing_proposer.d.ts +0 -65
  215. package/dest/contracts/empire_slashing_proposer.d.ts.map +0 -1
  216. package/dest/contracts/empire_slashing_proposer.js +0 -194
  217. package/dest/contracts/tally_slashing_proposer.d.ts.map +0 -1
  218. package/dest/deploy_l1_contracts.d.ts +0 -226
  219. package/dest/deploy_l1_contracts.d.ts.map +0 -1
  220. package/dest/deploy_l1_contracts.js +0 -1473
  221. package/dest/index.d.ts +0 -18
  222. package/dest/index.d.ts.map +0 -1
  223. package/dest/index.js +0 -17
  224. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts +0 -26
  225. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts.map +0 -1
  226. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.js +0 -26
  227. package/dest/test/delayed_tx_utils.d.ts +0 -13
  228. package/dest/test/delayed_tx_utils.d.ts.map +0 -1
  229. package/dest/test/delayed_tx_utils.js +0 -28
  230. package/dest/test/tx_delayer.d.ts +0 -36
  231. package/dest/test/tx_delayer.d.ts.map +0 -1
  232. package/src/contracts/empire_slashing_proposer.ts +0 -259
  233. package/src/deploy_l1_contracts.ts +0 -1849
  234. package/src/index.ts +0 -17
  235. package/src/l1_tx_utils/l1_tx_utils_with_blobs.ts +0 -77
  236. package/src/test/delayed_tx_utils.ts +0 -52
@@ -1,13 +1,16 @@
1
- import { getKeys, median, merge, pick, times } from '@aztec/foundation/collection';
1
+ import { getKeys, merge, pick, times } from '@aztec/foundation/collection';
2
2
  import { createLogger } from '@aztec/foundation/log';
3
3
  import { makeBackoff, retry } from '@aztec/foundation/retry';
4
+ import { getErrorCause } from '@aztec/foundation/types';
4
5
  import { RollupAbi } from '@aztec/l1-artifacts/RollupAbi';
5
6
  import pickBy from 'lodash.pickby';
6
7
  import { MethodNotFoundRpcError, MethodNotSupportedRpcError, decodeErrorResult, formatGwei, getContractError, hexToBytes } from 'viem';
7
8
  import { defaultL1TxUtilsConfig, l1TxUtilsConfigMappings } from './config.js';
8
- import { BLOCK_TIME_MS, LARGE_GAS_LIMIT, MIN_BLOB_REPLACEMENT_BUMP_PERCENTAGE, MIN_REPLACEMENT_BUMP_PERCENTAGE, WEI_CONST } from './constants.js';
9
+ import { BLOCK_TIME_MS, MAX_L1_TX_LIMIT, MIN_BLOB_REPLACEMENT_BUMP_PERCENTAGE, MIN_REPLACEMENT_BUMP_PERCENTAGE, WEI_CONST } from './constants.js';
10
+ import { P75AllTxsPriorityFeeStrategy } from './fee-strategies/index.js';
9
11
  import { getCalldataGasUsage, tryGetCustomErrorNameContractFunction } from './utils.js';
10
- const HISTORICAL_BLOCK_COUNT = 5;
12
+ // Change this to the current strategy we want to use
13
+ const CurrentStrategy = P75AllTxsPriorityFeeStrategy;
11
14
  export class ReadOnlyL1TxUtils {
12
15
  client;
13
16
  logger;
@@ -35,150 +38,51 @@ export class ReadOnlyL1TxUtils {
35
38
  getBlockNumber() {
36
39
  return this.client.getBlockNumber();
37
40
  }
38
- /**
39
- * Analyzes pending transactions and recent fee history to determine a competitive priority fee.
40
- * Falls back to network estimate if data is unavailable or fails.
41
- * @param networkEstimateResult - Result from estimateMaxPriorityFeePerGas RPC call
42
- * @param pendingBlockResult - Result from getBlock with pending tag RPC call
43
- * @param feeHistoryResult - Result from getFeeHistory RPC call
44
- * @returns A competitive priority fee based on pending txs and recent block history
45
- */ getCompetitivePriorityFee(networkEstimateResult, pendingBlockResult, feeHistoryResult) {
46
- const networkEstimate = networkEstimateResult.status === 'fulfilled' && typeof networkEstimateResult.value === 'bigint' ? networkEstimateResult.value : 0n;
47
- let competitiveFee = networkEstimate;
48
- if (pendingBlockResult.status === 'fulfilled' && pendingBlockResult.value !== null && pendingBlockResult.value.transactions && pendingBlockResult.value.transactions.length > 0) {
49
- const pendingBlock = pendingBlockResult.value;
50
- // Extract priority fees from pending transactions
51
- const pendingFees = pendingBlock.transactions.map((tx)=>{
52
- // Transaction can be just a hash string, so we need to check if it's an object
53
- if (typeof tx === 'string') {
54
- return 0n;
55
- }
56
- const fee = tx.maxPriorityFeePerGas || 0n;
57
- // Debug: Log suspicious fees
58
- if (fee > 100n * WEI_CONST) {
59
- this.logger?.warn('Suspicious high priority fee in pending tx', {
60
- txHash: tx.hash,
61
- maxPriorityFeePerGas: formatGwei(fee),
62
- maxFeePerGas: formatGwei(tx.maxFeePerGas || 0n),
63
- maxFeePerBlobGas: tx.maxFeePerBlobGas ? formatGwei(tx.maxFeePerBlobGas) : 'N/A'
64
- });
65
- }
66
- return fee;
67
- }).filter((fee)=>fee > 0n);
68
- if (pendingFees.length > 0) {
69
- // Use 75th percentile of pending fees to be competitive
70
- const sortedPendingFees = [
71
- ...pendingFees
72
- ].sort((a, b)=>a < b ? -1 : a > b ? 1 : 0);
73
- const percentile75Index = Math.floor((sortedPendingFees.length - 1) * 0.75);
74
- const pendingCompetitiveFee = sortedPendingFees[percentile75Index];
75
- if (pendingCompetitiveFee > competitiveFee) {
76
- competitiveFee = pendingCompetitiveFee;
77
- }
78
- this.logger?.debug('Analyzed pending transactions for competitive pricing', {
79
- pendingTxCount: pendingFees.length,
80
- pendingP75: formatGwei(pendingCompetitiveFee)
81
- });
82
- }
83
- }
84
- if (feeHistoryResult.status === 'fulfilled' && feeHistoryResult.value !== null && feeHistoryResult.value.reward && feeHistoryResult.value.reward.length > 0) {
85
- const feeHistory = feeHistoryResult.value;
86
- // Extract 75th percentile fees from each block
87
- const percentile75Fees = feeHistory.reward.map((rewards)=>rewards[0] || 0n).filter((fee)=>fee > 0n);
88
- if (percentile75Fees.length > 0) {
89
- // Calculate median of the 75th percentile fees across blocks
90
- const medianHistoricalFee = median(percentile75Fees) ?? 0n;
91
- // Debug: Log suspicious fees from history
92
- if (medianHistoricalFee > 100n * WEI_CONST) {
93
- this.logger?.warn('Suspicious high fee in history', {
94
- historicalMedian: formatGwei(medianHistoricalFee),
95
- allP75Fees: percentile75Fees.map((f)=>formatGwei(f))
96
- });
97
- }
98
- if (medianHistoricalFee > competitiveFee) {
99
- competitiveFee = medianHistoricalFee;
100
- }
101
- this.logger?.debug('Analyzed fee history for competitive pricing', {
102
- historicalMedian: formatGwei(medianHistoricalFee)
103
- });
104
- }
105
- }
106
- // Sanity check: cap competitive fee at 100x network estimate to avoid using unrealistic fees
107
- // (e.g., Anvil returns inflated historical fees that don't reflect actual network conditions)
108
- const maxReasonableFee = networkEstimate * 100n;
109
- if (competitiveFee > maxReasonableFee) {
110
- this.logger?.warn('Competitive fee exceeds sanity cap, using capped value', {
111
- competitiveFee: formatGwei(competitiveFee),
112
- networkEstimate: formatGwei(networkEstimate),
113
- cappedTo: formatGwei(maxReasonableFee)
114
- });
115
- competitiveFee = maxReasonableFee;
116
- }
117
- // Log final decision
118
- if (competitiveFee > networkEstimate) {
119
- this.logger?.debug('Using competitive fee from market analysis', {
120
- networkEstimate: formatGwei(networkEstimate),
121
- competitive: formatGwei(competitiveFee)
122
- });
123
- }
124
- return competitiveFee;
41
+ getCode(address) {
42
+ return this.client.getCode({
43
+ address: address.toString()
44
+ });
125
45
  }
126
46
  /**
127
47
  * Gets the current gas price with bounds checking
128
48
  */ async getGasPrice(gasConfigOverrides, isBlobTx = false, attempt = 0, previousGasPrice) {
129
49
  const gasConfig = merge(this.config, gasConfigOverrides);
130
- // Make all RPC calls in parallel upfront with retry logic
131
- const latestBlockPromise = this.tryTwice(()=>this.client.getBlock({
132
- blockTag: 'latest'
133
- }), 'Getting latest block');
134
- const networkEstimatePromise = gasConfig.fixedPriorityFeePerGas ? null : this.tryTwice(()=>this.client.estimateMaxPriorityFeePerGas(), 'Estimating max priority fee per gas');
135
- const pendingBlockPromise = gasConfig.fixedPriorityFeePerGas ? null : this.tryTwice(()=>this.client.getBlock({
136
- blockTag: 'pending',
137
- includeTransactions: true
138
- }), 'Getting pending block');
139
- const feeHistoryPromise = gasConfig.fixedPriorityFeePerGas ? null : this.tryTwice(()=>this.client.getFeeHistory({
140
- blockCount: HISTORICAL_BLOCK_COUNT,
141
- rewardPercentiles: [
142
- 75
143
- ]
144
- }), 'Getting fee history');
145
- const blobBaseFeePromise = isBlobTx ? this.tryTwice(()=>this.client.getBlobBaseFee(), 'Getting blob base fee') : null;
146
- const [latestBlockResult, networkEstimateResult, pendingBlockResult, feeHistoryResult, blobBaseFeeResult] = await Promise.allSettled([
147
- latestBlockPromise,
148
- networkEstimatePromise ?? Promise.resolve(0n),
149
- pendingBlockPromise ?? Promise.resolve(null),
150
- feeHistoryPromise ?? Promise.resolve(null),
151
- blobBaseFeePromise ?? Promise.resolve(0n)
152
- ]);
153
- // Extract results
154
- const baseFee = latestBlockResult.status === 'fulfilled' && typeof latestBlockResult.value === 'object' && latestBlockResult.value.baseFeePerGas ? latestBlockResult.value.baseFeePerGas : 0n;
155
- // Get blob base fee if available
156
- let blobBaseFee = 0n;
157
- if (isBlobTx && blobBaseFeeResult.status === 'fulfilled' && typeof blobBaseFeeResult.value === 'bigint') {
158
- blobBaseFee = blobBaseFeeResult.value;
159
- } else if (isBlobTx) {
50
+ // Execute strategy - it handles all RPC calls internally and returns everything we need
51
+ const strategyResult = await retry(()=>CurrentStrategy.execute(this.client, {
52
+ gasConfig,
53
+ isBlobTx,
54
+ logger: this.logger
55
+ }), 'Executing priority fee strategy', makeBackoff(times(2, ()=>0)), this.logger, true);
56
+ const { latestBlock, blobBaseFee, priorityFee: strategyPriorityFee } = strategyResult;
57
+ // Extract base fee from latest block
58
+ const baseFee = latestBlock.baseFeePerGas ?? 0n;
59
+ // Handle blob base fee
60
+ if (isBlobTx && blobBaseFee === undefined) {
160
61
  this.logger?.warn('Failed to get L1 blob base fee', attempt);
161
62
  }
162
- let priorityFee;
163
- if (gasConfig.fixedPriorityFeePerGas) {
164
- this.logger?.debug('Using fixed priority fee per L1 gas', {
165
- fixedPriorityFeePerGas: gasConfig.fixedPriorityFeePerGas
166
- });
167
- // try to maintain precision up to 1000000 wei
168
- priorityFee = BigInt(gasConfig.fixedPriorityFeePerGas * 1_000_000) * (WEI_CONST / 1_000_000n);
169
- } else {
170
- // Get competitive priority fee (includes network estimate + analysis)
171
- priorityFee = this.getCompetitivePriorityFee(networkEstimateResult, pendingBlockResult, feeHistoryResult);
63
+ let priorityFee = strategyPriorityFee;
64
+ // Apply minimum priority fee floor if configured
65
+ if (gasConfig.minimumPriorityFeePerGas) {
66
+ const minimumPriorityFee = BigInt(Math.trunc(gasConfig.minimumPriorityFeePerGas * Number(WEI_CONST)));
67
+ if (priorityFee < minimumPriorityFee) {
68
+ this.logger?.debug('Applying minimum priority fee floor', {
69
+ calculatedPriorityFee: formatGwei(priorityFee),
70
+ minimumPriorityFeePerGas: gasConfig.minimumPriorityFeePerGas,
71
+ appliedFee: formatGwei(minimumPriorityFee)
72
+ });
73
+ priorityFee = minimumPriorityFee;
74
+ }
172
75
  }
173
76
  let maxFeePerGas = baseFee;
174
- let maxFeePerBlobGas = blobBaseFee;
77
+ let maxFeePerBlobGas = blobBaseFee ?? 0n;
175
78
  // Bump base fee so it's valid for next blocks if it stalls
176
79
  const numBlocks = Math.ceil(gasConfig.stallTimeMs / BLOCK_TIME_MS);
177
80
  for(let i = 0; i < numBlocks; i++){
178
81
  // each block can go up 12.5% from previous baseFee
179
- maxFeePerGas = maxFeePerGas * (1_000n + 125n) / 1_000n;
82
+ // ceil, (a+b-1)/b, to avoid truncation at small values (e.g. 1 wei blob base fee)
83
+ maxFeePerGas = (maxFeePerGas * (1_000n + 125n) + 999n) / 1_000n;
180
84
  // same for blob gas fee
181
- maxFeePerBlobGas = maxFeePerBlobGas * (1_000n + 125n) / 1_000n;
85
+ maxFeePerBlobGas = (maxFeePerBlobGas * (1_000n + 125n) + 999n) / 1_000n;
182
86
  }
183
87
  if (attempt > 0) {
184
88
  const configBump = gasConfig.priorityFeeRetryBumpPercentage ?? defaultL1TxUtilsConfig.priorityFeeRetryBumpPercentage;
@@ -189,17 +93,14 @@ export class ReadOnlyL1TxUtils {
189
93
  // multiply by 100 & divide by 100 to maintain some precision
190
94
  const minPriorityFee = previousGasPrice.maxPriorityFeePerGas * (100_00n + BigInt(bumpPercentage * 1_00)) / 100_00n;
191
95
  const minMaxFee = previousGasPrice.maxFeePerGas * (100_00n + BigInt(bumpPercentage * 1_00)) / 100_00n;
192
- let competitivePriorityFee = priorityFee;
193
- if (!gasConfig.fixedPriorityFeePerGas) {
194
- // Apply bump percentage to competitive fee
195
- competitivePriorityFee = priorityFee * (100_00n + BigInt(configBump * 1_00)) / 100_00n;
196
- this.logger?.debug(`Speed-up attempt ${attempt}: using competitive fee strategy`, {
197
- networkEstimate: formatGwei(priorityFee),
198
- competitiveFee: formatGwei(competitivePriorityFee),
199
- minRequired: formatGwei(minPriorityFee),
200
- bumpPercentage: configBump
201
- });
202
- }
96
+ // Apply bump percentage to competitive fee
97
+ const competitivePriorityFee = priorityFee * (100_00n + BigInt(configBump * 1_00)) / 100_00n;
98
+ this.logger?.debug(`Speed-up attempt ${attempt}: using competitive fee strategy`, {
99
+ networkEstimate: formatGwei(priorityFee),
100
+ competitiveFee: formatGwei(competitivePriorityFee),
101
+ minRequired: formatGwei(minPriorityFee),
102
+ bumpPercentage: configBump
103
+ });
203
104
  // Use maximum between competitive fee and minimum required bump
204
105
  const finalPriorityFee = competitivePriorityFee > minPriorityFee ? competitivePriorityFee : minPriorityFee;
205
106
  const feeSource = finalPriorityFee === competitivePriorityFee ? 'competitive' : 'minimum-bump';
@@ -207,25 +108,21 @@ export class ReadOnlyL1TxUtils {
207
108
  // Add the final priority fee to maxFeePerGas
208
109
  maxFeePerGas += finalPriorityFee;
209
110
  maxFeePerGas = maxFeePerGas > minMaxFee ? maxFeePerGas : minMaxFee;
210
- if (!gasConfig.fixedPriorityFeePerGas) {
211
- this.logger?.debug(`Speed-up fee decision: using ${feeSource} fee`, {
212
- finalPriorityFee: formatGwei(finalPriorityFee)
213
- });
214
- }
111
+ this.logger?.debug(`Speed-up fee decision: using ${feeSource} fee`, {
112
+ finalPriorityFee: formatGwei(finalPriorityFee)
113
+ });
215
114
  } else {
216
115
  // First attempt: apply configured bump percentage to competitive fee
217
116
  // multiply by 100 & divide by 100 to maintain some precision
218
- if (!gasConfig.fixedPriorityFeePerGas) {
219
- priorityFee = priorityFee * (100_00n + BigInt((gasConfig.priorityFeeBumpPercentage || 0) * 1_00)) / 100_00n;
220
- this.logger?.debug('Initial transaction: using competitive fee from market analysis', {
221
- networkEstimate: formatGwei(priorityFee)
222
- });
223
- }
117
+ priorityFee = priorityFee * (100_00n + BigInt((gasConfig.priorityFeeBumpPercentage || 0) * 1_00)) / 100_00n;
118
+ this.logger?.debug('Initial transaction: using competitive fee from market analysis', {
119
+ networkEstimate: formatGwei(priorityFee)
120
+ });
224
121
  maxFeePerGas += priorityFee;
225
122
  }
226
123
  // maxGwei and maxBlobGwei are hard limits
227
- const effectiveMaxGwei = gasConfig.maxGwei * WEI_CONST;
228
- const effectiveMaxBlobGwei = gasConfig.maxBlobGwei * WEI_CONST;
124
+ const effectiveMaxGwei = BigInt(Math.trunc(gasConfig.maxGwei * Number(WEI_CONST)));
125
+ const effectiveMaxBlobGwei = BigInt(Math.trunc(gasConfig.maxBlobGwei * Number(WEI_CONST)));
229
126
  // Ensure we don't exceed maxGwei
230
127
  if (effectiveMaxGwei > 0n) {
231
128
  maxFeePerGas = maxFeePerGas > effectiveMaxGwei ? effectiveMaxGwei : maxFeePerGas;
@@ -248,7 +145,7 @@ export class ReadOnlyL1TxUtils {
248
145
  baseFee: formatGwei(baseFee),
249
146
  maxFeePerGas: formatGwei(maxFeePerGas),
250
147
  maxPriorityFeePerGas: formatGwei(maxPriorityFeePerGas),
251
- blobBaseFee: formatGwei(blobBaseFee),
148
+ blobBaseFee: formatGwei(blobBaseFee ?? 0n),
252
149
  maxFeePerBlobGas: formatGwei(maxFeePerBlobGas)
253
150
  });
254
151
  return {
@@ -268,21 +165,26 @@ export class ReadOnlyL1TxUtils {
268
165
  };
269
166
  let initialEstimate = 0n;
270
167
  if (_blobInputs) {
271
- // @note requests with blobs also require maxFeePerBlobGas to be set
168
+ // @note requests with blobs also require maxFeePerBlobGas to be set.
169
+ // Use 2x buffer for maxFeePerBlobGas to avoid stale fees and to pass EIP-4844 validation (even if it is a gas estimation call).
170
+ // 1. maxFeePerBlobGas >= blobBaseFee
171
+ // 2. account balance >= gas * maxFeePerGas + maxFeePerBlobGas * blobCount + value
272
172
  const gasPrice = await this.getGasPrice(gasConfig, true, 0);
273
173
  initialEstimate = await this.client.estimateGas({
274
174
  account,
275
175
  ...request,
276
176
  ..._blobInputs,
277
- maxFeePerBlobGas: gasPrice.maxFeePerBlobGas,
278
- gas: LARGE_GAS_LIMIT
177
+ maxFeePerBlobGas: gasPrice.maxFeePerBlobGas * 2n,
178
+ gas: MAX_L1_TX_LIMIT,
179
+ blockTag: 'latest'
279
180
  });
280
181
  this.logger?.trace(`Estimated gas for blob tx: ${initialEstimate}`);
281
182
  } else {
282
183
  initialEstimate = await this.client.estimateGas({
283
184
  account,
284
185
  ...request,
285
- gas: LARGE_GAS_LIMIT
186
+ gas: MAX_L1_TX_LIMIT,
187
+ blockTag: 'latest'
286
188
  });
287
189
  this.logger?.trace(`Estimated gas for non-blob tx: ${initialEstimate}`);
288
190
  }
@@ -396,7 +298,7 @@ export class ReadOnlyL1TxUtils {
396
298
  result: result[0].calls[0].data
397
299
  };
398
300
  } catch (err) {
399
- if (err instanceof MethodNotFoundRpcError || err instanceof MethodNotSupportedRpcError) {
301
+ if (getErrorCause(err, MethodNotFoundRpcError) || getErrorCause(err, MethodNotSupportedRpcError)) {
400
302
  if (gasConfig.fallbackGasEstimate) {
401
303
  this.logger?.warn(`Node does not support eth_simulateV1 API. Using fallback gas estimate: ${gasConfig.fallbackGasEstimate}`);
402
304
  return {
@@ -423,9 +325,4 @@ export class ReadOnlyL1TxUtils {
423
325
  });
424
326
  return bumpedGasLimit;
425
327
  }
426
- /**
427
- * Helper function to retry RPC calls twice
428
- */ tryTwice(fn, description) {
429
- return retry(fn, description, makeBackoff(times(2, ()=>0)), this.logger, true);
430
- }
431
328
  }
@@ -1,4 +1,4 @@
1
1
  import { type WalletClient } from 'viem';
2
2
  import type { SigningCallback } from './types.js';
3
3
  export declare function createViemSigner(client: WalletClient): SigningCallback;
4
- //# sourceMappingURL=signer.d.ts.map
4
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbmVyLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbDFfdHhfdXRpbHMvc2lnbmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUdBLE9BQU8sRUFBZ0MsS0FBSyxZQUFZLEVBQW9CLE1BQU0sTUFBTSxDQUFDO0FBRXpGLE9BQU8sS0FBSyxFQUFFLGVBQWUsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUVsRCx3QkFBZ0IsZ0JBQWdCLENBQUMsTUFBTSxFQUFFLFlBQVksbUJBb0JwRCJ9
@@ -0,0 +1,58 @@
1
+ import { type Logger, type LoggerBindings } from '@aztec/foundation/log';
2
+ import type { DateProvider } from '@aztec/foundation/timer';
3
+ import { type Client, type Hex } from 'viem';
4
+ import type { ViemClient } from '../types.js';
5
+ export declare function waitUntilBlock<T extends Client>(client: T, blockNumber: number | bigint, logger?: Logger, timeout?: number): Promise<boolean>;
6
+ export declare function waitUntilL1Timestamp<T extends Client>(client: T, timestamp: number | bigint, logger?: Logger, timeout?: number): Promise<boolean>;
7
+ /** Manages tx delaying for testing, intercepting sendRawTransaction calls to delay or cancel them. */
8
+ export declare class Delayer {
9
+ dateProvider: DateProvider;
10
+ private logger;
11
+ maxInclusionTimeIntoSlot: number | undefined;
12
+ ethereumSlotDuration: bigint;
13
+ nextWait: {
14
+ l1Timestamp: bigint;
15
+ timeoutSeconds?: number;
16
+ } | {
17
+ l1BlockNumber: bigint;
18
+ timeoutSeconds?: number;
19
+ } | {
20
+ indefinitely: true;
21
+ } | undefined;
22
+ sentTxHashes: Hex[];
23
+ cancelledTxs: Hex[];
24
+ constructor(dateProvider: DateProvider, opts: {
25
+ ethereumSlotDuration: bigint | number;
26
+ }, bindings: LoggerBindings);
27
+ /** Returns the logger instance used by this delayer. */
28
+ getLogger(): Logger;
29
+ /** Returns the hashes of all effectively sent txs. */
30
+ getSentTxHashes(): `0x${string}`[];
31
+ /** Returns the raw hex for all cancelled txs. */
32
+ getCancelledTxs(): Hex[];
33
+ /** Delays the next tx to be sent so it lands on the given L1 block number. */
34
+ pauseNextTxUntilBlock(l1BlockNumber: number | bigint, timeoutSeconds?: number): void;
35
+ /** Delays the next tx to be sent so it lands on the given timestamp. */
36
+ pauseNextTxUntilTimestamp(l1Timestamp: number | bigint, timeoutSeconds?: number): void;
37
+ /** Delays the next tx to be sent indefinitely. */
38
+ cancelNextTx(): void;
39
+ /**
40
+ * Sets max inclusion time into slot. If more than this many seconds have passed
41
+ * since the last L1 block was mined, then any tx will not be mined in the current
42
+ * L1 slot but will be deferred for the next one.
43
+ */
44
+ setMaxInclusionTimeIntoSlot(seconds: number | undefined): void;
45
+ }
46
+ /**
47
+ * Creates a new Delayer instance. Exposed so callers can create a single shared delayer
48
+ * and pass it to multiple `wrapClientWithDelayer` calls.
49
+ */
50
+ export declare function createDelayer(dateProvider: DateProvider, opts: {
51
+ ethereumSlotDuration: bigint | number;
52
+ }, bindings: LoggerBindings): Delayer;
53
+ /**
54
+ * Wraps a viem client with tx delaying logic. Returns the wrapped client.
55
+ * The delayer intercepts sendRawTransaction calls and delays them based on the delayer's state.
56
+ */
57
+ export declare function wrapClientWithDelayer<T extends ViemClient>(client: T, delayer: Delayer): T;
58
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHhfZGVsYXllci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2wxX3R4X3V0aWxzL3R4X2RlbGF5ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLEtBQUssTUFBTSxFQUFFLEtBQUssY0FBYyxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBRXZGLE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRzVELE9BQU8sRUFDTCxLQUFLLE1BQU0sRUFDWCxLQUFLLEdBQUcsRUFVVCxNQUFNLE1BQU0sQ0FBQztBQUVkLE9BQU8sS0FBSyxFQUE0QixVQUFVLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFJeEUsd0JBQWdCLGNBQWMsQ0FBQyxDQUFDLFNBQVMsTUFBTSxFQUM3QyxNQUFNLEVBQUUsQ0FBQyxFQUNULFdBQVcsRUFBRSxNQUFNLEdBQUcsTUFBTSxFQUM1QixNQUFNLENBQUMsRUFBRSxNQUFNLEVBQ2YsT0FBTyxDQUFDLEVBQUUsTUFBTSxvQkFpQmpCO0FBRUQsd0JBQWdCLG9CQUFvQixDQUFDLENBQUMsU0FBUyxNQUFNLEVBQ25ELE1BQU0sRUFBRSxDQUFDLEVBQ1QsU0FBUyxFQUFFLE1BQU0sR0FBRyxNQUFNLEVBQzFCLE1BQU0sQ0FBQyxFQUFFLE1BQU0sRUFDZixPQUFPLENBQUMsRUFBRSxNQUFNLG9CQXdCakI7QUFFRCxzR0FBc0c7QUFDdEcscUJBQWEsT0FBTztJQWNULFlBQVksRUFBRSxZQUFZO0lBYm5DLE9BQU8sQ0FBQyxNQUFNLENBQVM7SUFFaEIsd0JBQXdCLEVBQUUsTUFBTSxHQUFHLFNBQVMsQ0FBYTtJQUN6RCxvQkFBb0IsRUFBRSxNQUFNLENBQUM7SUFDN0IsUUFBUSxFQUNYO1FBQUUsV0FBVyxFQUFFLE1BQU0sQ0FBQztRQUFDLGNBQWMsQ0FBQyxFQUFFLE1BQU0sQ0FBQTtLQUFFLEdBQ2hEO1FBQUUsYUFBYSxFQUFFLE1BQU0sQ0FBQztRQUFDLGNBQWMsQ0FBQyxFQUFFLE1BQU0sQ0FBQTtLQUFFLEdBQ2xEO1FBQUUsWUFBWSxFQUFFLElBQUksQ0FBQTtLQUFFLEdBQ3RCLFNBQVMsQ0FBYTtJQUNuQixZQUFZLEVBQUUsR0FBRyxFQUFFLENBQU07SUFDekIsWUFBWSxFQUFFLEdBQUcsRUFBRSxDQUFNO0lBRWhDLFlBQ1MsWUFBWSxFQUFFLFlBQVksRUFDakMsSUFBSSxFQUFFO1FBQUUsb0JBQW9CLEVBQUUsTUFBTSxHQUFHLE1BQU0sQ0FBQTtLQUFFLEVBQy9DLFFBQVEsRUFBRSxjQUFjLEVBSXpCO0lBRUQsd0RBQXdEO0lBQ3hELFNBQVMsSUFBSSxNQUFNLENBRWxCO0lBRUQsc0RBQXNEO0lBQ3RELGVBQWUsb0JBRWQ7SUFFRCxpREFBaUQ7SUFDakQsZUFBZSxJQUFJLEdBQUcsRUFBRSxDQUV2QjtJQUVELDhFQUE4RTtJQUM5RSxxQkFBcUIsQ0FBQyxhQUFhLEVBQUUsTUFBTSxHQUFHLE1BQU0sRUFBRSxjQUFjLENBQUMsRUFBRSxNQUFNLFFBRTVFO0lBRUQsd0VBQXdFO0lBQ3hFLHlCQUF5QixDQUFDLFdBQVcsRUFBRSxNQUFNLEdBQUcsTUFBTSxFQUFFLGNBQWMsQ0FBQyxFQUFFLE1BQU0sUUFFOUU7SUFFRCxrREFBa0Q7SUFDbEQsWUFBWSxTQUVYO0lBRUQ7Ozs7T0FJRztJQUNILDJCQUEyQixDQUFDLE9BQU8sRUFBRSxNQUFNLEdBQUcsU0FBUyxRQUV0RDtDQUNGO0FBRUQ7OztHQUdHO0FBQ0gsd0JBQWdCLGFBQWEsQ0FDM0IsWUFBWSxFQUFFLFlBQVksRUFDMUIsSUFBSSxFQUFFO0lBQUUsb0JBQW9CLEVBQUUsTUFBTSxHQUFHLE1BQU0sQ0FBQTtDQUFFLEVBQy9DLFFBQVEsRUFBRSxjQUFjLEdBQ3ZCLE9BQU8sQ0FFVDtBQWFEOzs7R0FHRztBQUNILHdCQUFnQixxQkFBcUIsQ0FBQyxDQUFDLFNBQVMsVUFBVSxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLE9BQU8sR0FBRyxDQUFDLENBdUgxRiJ9
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tx_delayer.d.ts","sourceRoot":"","sources":["../../src/l1_tx_utils/tx_delayer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,cAAc,EAAgB,MAAM,uBAAuB,CAAC;AAEvF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAG5D,OAAO,EACL,KAAK,MAAM,EACX,KAAK,GAAG,EAUT,MAAM,MAAM,CAAC;AAEd,OAAO,KAAK,EAA4B,UAAU,EAAE,MAAM,aAAa,CAAC;AAIxE,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,EAC7C,MAAM,EAAE,CAAC,EACT,WAAW,EAAE,MAAM,GAAG,MAAM,EAC5B,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,oBAiBjB;AAED,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,EACnD,MAAM,EAAE,CAAC,EACT,SAAS,EAAE,MAAM,GAAG,MAAM,EAC1B,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,oBAwBjB;AAED,sGAAsG;AACtG,qBAAa,OAAO;IAcT,YAAY,EAAE,YAAY;IAbnC,OAAO,CAAC,MAAM,CAAS;IAEhB,wBAAwB,EAAE,MAAM,GAAG,SAAS,CAAa;IACzD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,QAAQ,EACX;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,GAChD;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,GAClD;QAAE,YAAY,EAAE,IAAI,CAAA;KAAE,GACtB,SAAS,CAAa;IACnB,YAAY,EAAE,GAAG,EAAE,CAAM;IACzB,YAAY,EAAE,GAAG,EAAE,CAAM;IAEhC,YACS,YAAY,EAAE,YAAY,EACjC,IAAI,EAAE;QAAE,oBAAoB,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,EAC/C,QAAQ,EAAE,cAAc,EAIzB;IAED,wDAAwD;IACxD,SAAS,IAAI,MAAM,CAElB;IAED,sDAAsD;IACtD,eAAe,oBAEd;IAED,iDAAiD;IACjD,eAAe,IAAI,GAAG,EAAE,CAEvB;IAED,8EAA8E;IAC9E,qBAAqB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,QAE5E;IAED,wEAAwE;IACxE,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,QAE9E;IAED,kDAAkD;IAClD,YAAY,SAEX;IAED;;;;OAIG;IACH,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,QAEtD;CACF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,YAAY,EAAE,YAAY,EAC1B,IAAI,EAAE;IAAE,oBAAoB,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,EAC/C,QAAQ,EAAE,cAAc,GACvB,OAAO,CAET;AAaD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,UAAU,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,CAuH1F"}
@@ -2,8 +2,8 @@ import { omit } from '@aztec/foundation/collection';
2
2
  import { createLogger } from '@aztec/foundation/log';
3
3
  import { retryUntil } from '@aztec/foundation/retry';
4
4
  import { inspect } from 'util';
5
- import { keccak256, parseTransaction, publicActions, serializeTransaction, walletActions } from 'viem';
6
- import { isExtendedClient } from '../types.js';
5
+ import { keccak256, parseTransaction, publicActions, recoverTransactionAddress, serializeTransaction, walletActions } from 'viem';
6
+ const MAX_WAIT_TIME_SECONDS = 180;
7
7
  export function waitUntilBlock(client, blockNumber, logger, timeout) {
8
8
  const publicClient = 'getBlockNumber' in client && typeof client.getBlockNumber === 'function' ? client : client.extend(publicActions);
9
9
  return retryUntil(async ()=>{
@@ -12,7 +12,7 @@ export function waitUntilBlock(client, blockNumber, logger, timeout) {
12
12
  });
13
13
  logger?.debug(`Block number is ${currentBlockNumber} (waiting until ${blockNumber})`);
14
14
  return currentBlockNumber >= BigInt(blockNumber);
15
- }, `Wait until L1 block ${blockNumber}`, timeout ?? 120, 0.1);
15
+ }, `Wait until L1 block ${blockNumber}`, timeout ?? MAX_WAIT_TIME_SECONDS, 0.1);
16
16
  }
17
17
  export function waitUntilL1Timestamp(client, timestamp, logger, timeout) {
18
18
  const publicClient = 'getBlockNumber' in client && typeof client.getBlockNumber === 'function' ? client : client.extend(publicActions);
@@ -32,61 +32,82 @@ export function waitUntilL1Timestamp(client, timestamp, logger, timeout) {
32
32
  const currentTs = currentBlock.timestamp;
33
33
  logger?.debug(`Block timstamp is ${currentTs} (waiting until ${timestamp})`);
34
34
  return currentTs >= BigInt(timestamp);
35
- }, `Wait until L1 timestamp ${timestamp}`, timeout ?? 120, 0.1);
35
+ }, `Wait until L1 timestamp ${timestamp}`, timeout ?? MAX_WAIT_TIME_SECONDS, 0.1);
36
36
  }
37
- class DelayerImpl {
37
+ /** Manages tx delaying for testing, intercepting sendRawTransaction calls to delay or cancel them. */ export class Delayer {
38
38
  dateProvider;
39
39
  logger;
40
- constructor(dateProvider, opts){
40
+ maxInclusionTimeIntoSlot;
41
+ ethereumSlotDuration;
42
+ nextWait;
43
+ sentTxHashes;
44
+ cancelledTxs;
45
+ constructor(dateProvider, opts, bindings){
41
46
  this.dateProvider = dateProvider;
42
- this.logger = createLogger('ethereum:tx_delayer');
43
47
  this.maxInclusionTimeIntoSlot = undefined;
44
48
  this.nextWait = undefined;
45
49
  this.sentTxHashes = [];
46
50
  this.cancelledTxs = [];
47
51
  this.ethereumSlotDuration = BigInt(opts.ethereumSlotDuration);
52
+ this.logger = createLogger('ethereum:tx_delayer', bindings);
48
53
  }
49
- maxInclusionTimeIntoSlot;
50
- ethereumSlotDuration;
51
- nextWait;
52
- sentTxHashes;
53
- cancelledTxs;
54
- getSentTxHashes() {
54
+ /** Returns the logger instance used by this delayer. */ getLogger() {
55
+ return this.logger;
56
+ }
57
+ /** Returns the hashes of all effectively sent txs. */ getSentTxHashes() {
55
58
  return this.sentTxHashes;
56
59
  }
57
- getCancelledTxs() {
60
+ /** Returns the raw hex for all cancelled txs. */ getCancelledTxs() {
58
61
  return this.cancelledTxs;
59
62
  }
60
- pauseNextTxUntilBlock(l1BlockNumber) {
63
+ /** Delays the next tx to be sent so it lands on the given L1 block number. */ pauseNextTxUntilBlock(l1BlockNumber, timeoutSeconds) {
61
64
  this.nextWait = {
62
- l1BlockNumber: BigInt(l1BlockNumber)
65
+ l1BlockNumber: BigInt(l1BlockNumber),
66
+ timeoutSeconds
63
67
  };
64
68
  }
65
- pauseNextTxUntilTimestamp(l1Timestamp) {
69
+ /** Delays the next tx to be sent so it lands on the given timestamp. */ pauseNextTxUntilTimestamp(l1Timestamp, timeoutSeconds) {
66
70
  this.nextWait = {
67
- l1Timestamp: BigInt(l1Timestamp)
71
+ l1Timestamp: BigInt(l1Timestamp),
72
+ timeoutSeconds
68
73
  };
69
74
  }
70
- cancelNextTx() {
75
+ /** Delays the next tx to be sent indefinitely. */ cancelNextTx() {
71
76
  this.nextWait = {
72
77
  indefinitely: true
73
78
  };
74
79
  }
75
- setMaxInclusionTimeIntoSlot(seconds) {
80
+ /**
81
+ * Sets max inclusion time into slot. If more than this many seconds have passed
82
+ * since the last L1 block was mined, then any tx will not be mined in the current
83
+ * L1 slot but will be deferred for the next one.
84
+ */ setMaxInclusionTimeIntoSlot(seconds) {
76
85
  this.maxInclusionTimeIntoSlot = seconds;
77
86
  }
78
87
  }
79
88
  /**
80
- * Returns a new client (without modifying the one passed in) with an injected tx delayer.
81
- * The delayer can be used to hold off the next tx to be sent until a given block number.
82
- * TODO(#10824): This doesn't play along well with blob txs for some reason.
83
- */ export function withDelayer(client, dateProvider, opts) {
84
- if (!isExtendedClient(client)) {
85
- throw new Error('withDelayer has to be instantiated with a wallet viem client.');
89
+ * Creates a new Delayer instance. Exposed so callers can create a single shared delayer
90
+ * and pass it to multiple `wrapClientWithDelayer` calls.
91
+ */ export function createDelayer(dateProvider, opts, bindings) {
92
+ return new Delayer(dateProvider, opts, bindings);
93
+ }
94
+ /** Tries to recover the sender address from a serialized signed transaction. */ async function tryRecoverSender(serializedTransaction) {
95
+ try {
96
+ return await recoverTransactionAddress({
97
+ serializedTransaction: serializedTransaction
98
+ });
99
+ } catch {
100
+ return undefined;
86
101
  }
87
- const logger = createLogger('ethereum:tx_delayer');
88
- const delayer = new DelayerImpl(dateProvider, opts);
89
- const extended = client// Tweak sendRawTransaction so it uses the delay defined in the delayer.
102
+ }
103
+ /**
104
+ * Wraps a viem client with tx delaying logic. Returns the wrapped client.
105
+ * The delayer intercepts sendRawTransaction calls and delays them based on the delayer's state.
106
+ */ export function wrapClientWithDelayer(client, delayer) {
107
+ const logger = delayer.getLogger();
108
+ // Cast to ExtendedViemWalletClient for the extend chain since it has sendRawTransaction.
109
+ // The sendRawTransaction override is applied to all clients regardless of type.
110
+ const withRawTx = client// Tweak sendRawTransaction so it uses the delay defined in the delayer.
90
111
  // Note that this will only work with local accounts (ie accounts for which we have the private key).
91
112
  // Transactions signed by the node will not be delayed since they use sendTransaction directly,
92
113
  // but we do not use them in our codebase at all.
@@ -96,6 +117,7 @@ class DelayerImpl {
96
117
  let txHash;
97
118
  const { serializedTransaction } = args[0];
98
119
  const publicClient = client;
120
+ const sender = await tryRecoverSender(serializedTransaction);
99
121
  if (delayer.nextWait !== undefined) {
100
122
  // Check if we have been instructed to delay the next tx.
101
123
  const waitUntil = delayer.nextWait;
@@ -104,13 +126,16 @@ class DelayerImpl {
104
126
  txHash = computeTxHash(serializedTransaction);
105
127
  // Cancel tx outright if instructed
106
128
  if ('indefinitely' in waitUntil && waitUntil.indefinitely) {
107
- logger.info(`Cancelling tx ${txHash}`);
129
+ logger.info(`Cancelling tx ${txHash}`, {
130
+ sender
131
+ });
108
132
  delayer.cancelledTxs.push(serializedTransaction);
109
133
  return Promise.resolve(txHash);
110
134
  }
111
135
  // Or wait until the desired block number or timestamp
112
- wait = 'l1BlockNumber' in waitUntil ? waitUntilBlock(publicClient, waitUntil.l1BlockNumber - 1n, logger) : 'l1Timestamp' in waitUntil ? waitUntilL1Timestamp(publicClient, waitUntil.l1Timestamp - delayer.ethereumSlotDuration, logger) : undefined;
136
+ wait = 'l1BlockNumber' in waitUntil ? waitUntilBlock(publicClient, waitUntil.l1BlockNumber - 1n, logger, waitUntil.timeoutSeconds) : 'l1Timestamp' in waitUntil ? waitUntilL1Timestamp(publicClient, waitUntil.l1Timestamp - delayer.ethereumSlotDuration, logger, waitUntil.timeoutSeconds) : undefined;
113
137
  logger.info(`Delaying tx ${txHash} until ${inspect(waitUntil)}`, {
138
+ sender,
114
139
  argsLen: args.length,
115
140
  ...omit(parseTransaction(serializedTransaction), 'data', 'sidecars')
116
141
  });
@@ -123,6 +148,7 @@ class DelayerImpl {
123
148
  const now = delayer.dateProvider.now();
124
149
  txHash = computeTxHash(serializedTransaction);
125
150
  const logData = {
151
+ sender,
126
152
  ...omit(parseTransaction(serializedTransaction), 'data', 'sidecars'),
127
153
  lastBlockTimestamp,
128
154
  now,
@@ -149,29 +175,34 @@ class DelayerImpl {
149
175
  computedTxHash: txHash
150
176
  });
151
177
  }
152
- logger.info(`Sent previously delayed tx ${clientTxHash}`);
178
+ logger.info(`Sent previously delayed tx ${clientTxHash}`, {
179
+ sender
180
+ });
153
181
  delayer.sentTxHashes.push(clientTxHash);
154
182
  }).catch((err)=>logger.error(`Error sending tx after delay`, err));
155
183
  return Promise.resolve(txHash);
156
184
  } else {
157
185
  const txHash = await client.sendRawTransaction(...args);
158
- logger.verbose(`Sent tx immediately ${txHash}`);
186
+ logger.debug(`Sent tx immediately ${txHash}`, {
187
+ sender
188
+ });
159
189
  delayer.sentTxHashes.push(txHash);
160
190
  return txHash;
161
191
  }
162
192
  }
163
- }))// Re-extend with sendTransaction so it uses the modified sendRawTransaction.
193
+ }));
194
+ // Only re-bind wallet actions (sendTransaction, writeContract, deployContract) for wallet clients.
195
+ // This is needed for tests that use wallet actions directly rather than sendRawTransaction.
196
+ const isWalletClient = 'account' in client && client.account !== undefined;
197
+ const extended = isWalletClient ? withRawTx// Re-extend with sendTransaction so it uses the modified sendRawTransaction.
164
198
  .extend((client)=>({
165
199
  sendTransaction: walletActions(client).sendTransaction
166
200
  }))// And with the actions that depend on the modified sendTransaction
167
201
  .extend((client)=>({
168
202
  writeContract: walletActions(client).writeContract,
169
203
  deployContract: walletActions(client).deployContract
170
- }));
171
- return {
172
- client: extended,
173
- delayer
174
- };
204
+ })) : withRawTx;
205
+ return extended;
175
206
  }
176
207
  /**
177
208
  * Compute the tx hash given the serialized tx. Note that if this is a blob tx, we need to
@@ -64,4 +64,4 @@ export declare class UnknownMinedTxError extends Error {
64
64
  export declare class DroppedTransactionError extends Error {
65
65
  constructor(nonce: number, account: string);
66
66
  }
67
- //# sourceMappingURL=types.d.ts.map
67
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9sMV90eF91dGlscy90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUM3RCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDM0QsT0FBTyxLQUFLLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUVoRixPQUFPLEtBQUssRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxrQkFBa0IsRUFBRSx1QkFBdUIsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUUzRixPQUFPLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFbkQsTUFBTSxXQUFXLFdBQVc7SUFDMUIsRUFBRSxFQUFFLE9BQU8sR0FBRyxJQUFJLENBQUM7SUFDbkIsSUFBSSxDQUFDLEVBQUUsR0FBRyxDQUFDO0lBQ1gsS0FBSyxDQUFDLEVBQUUsTUFBTSxDQUFDO0lBQ2YsR0FBRyxDQUFDLEVBQUUsR0FBRyxDQUFDO0NBQ1g7QUFFRCxNQUFNLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUMsR0FBRztJQUFFLFFBQVEsQ0FBQyxFQUFFLE1BQU0sQ0FBQztJQUFDLFdBQVcsQ0FBQyxFQUFFLElBQUksQ0FBQTtDQUFFLENBQUM7QUFFOUYsTUFBTSxXQUFXLFlBQVk7SUFDM0IsS0FBSyxFQUFFLFVBQVUsRUFBRSxDQUFDO0lBQ3BCLEdBQUcsRUFBRSxlQUFlLENBQUM7SUFDckIsZ0JBQWdCLENBQUMsRUFBRSxNQUFNLENBQUM7Q0FDM0I7QUFFRCxNQUFNLFdBQVcsUUFBUTtJQUN2QixZQUFZLEVBQUUsTUFBTSxDQUFDO0lBQ3JCLG9CQUFvQixFQUFFLE1BQU0sQ0FBQztJQUM3QixnQkFBZ0IsQ0FBQyxFQUFFLE1BQU0sQ0FBQztDQUMzQjtBQUVELE1BQU0sTUFBTSxnQkFBZ0IsR0FBRztJQUM3Qiw2QkFBNkI7SUFDN0IsTUFBTSxFQUFFLE1BQU0sQ0FBQztJQUNmLCtCQUErQjtJQUMvQixlQUFlLEVBQUUsTUFBTSxDQUFDO0lBQ3hCLHVDQUF1QztJQUN2QyxZQUFZLEVBQUUsTUFBTSxDQUFDO0lBQ3JCLDRGQUE0RjtJQUM1RixXQUFXLEVBQUUsTUFBTSxDQUFDO0NBQ3JCLENBQUM7QUFFRixvQkFBWSxZQUFZO0lBQ3RCLElBQUksSUFBQTtJQUNKLElBQUksSUFBQTtJQUNKLFFBQVEsSUFBQTtJQUNSLFNBQVMsSUFBQTtJQUNULFNBQVMsSUFBQTtJQUNULEtBQUssSUFBQTtDQUNOO0FBRUQsZUFBTyxNQUFNLG9CQUFvQixnQkFBa0UsQ0FBQztBQUVwRyxNQUFNLE1BQU0sU0FBUyxHQUFHO0lBQ3RCLEVBQUUsRUFBRSxNQUFNLENBQUM7SUFDWCxRQUFRLEVBQUUsR0FBRyxFQUFFLENBQUM7SUFDaEIsY0FBYyxFQUFFLEdBQUcsRUFBRSxDQUFDO0lBQ3RCLFFBQVEsRUFBRSxNQUFNLENBQUM7SUFDakIsUUFBUSxFQUFFLFFBQVEsQ0FBQztJQUNuQixpQkFBaUIsRUFBRSxVQUFVLENBQUM7SUFDOUIsT0FBTyxFQUFFLFdBQVcsQ0FBQztJQUNyQixNQUFNLEVBQUUsWUFBWSxDQUFDO0lBQ3JCLEtBQUssRUFBRSxNQUFNLENBQUM7SUFDZCxVQUFVLEVBQUUsSUFBSSxDQUFDO0lBQ2pCLGNBQWMsRUFBRSxJQUFJLENBQUM7SUFDckIsT0FBTyxDQUFDLEVBQUUsa0JBQWtCLENBQUM7SUFDN0IsVUFBVSxFQUFFLFlBQVksR0FBRyxTQUFTLENBQUM7Q0FDdEMsQ0FBQztBQUVGLE1BQU0sTUFBTSxlQUFlLEdBQUcsQ0FDNUIsV0FBVyxFQUFFLHVCQUF1QixFQUNwQyxjQUFjLEVBQUUsVUFBVSxLQUN2QixPQUFPLENBQUMsd0JBQXdCLENBQUMsQ0FBQztBQUV2QyxxQkFBYSxtQkFBb0IsU0FBUSxLQUFLO0lBQzVDLFlBQVksS0FBSyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUd6QztDQUNGO0FBRUQscUJBQWEsdUJBQXdCLFNBQVEsS0FBSztJQUNoRCxZQUFZLEtBQUssRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFHekM7Q0FDRiJ9
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/l1_tx_utils/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAEhF,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,MAAM,CAAC;AAE3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,GAAG,IAAI,CAAC;IACnB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,GAAG,CAAC;CACX;AAED,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,eAAe,CAAC,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAE9F,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,GAAG,EAAE,eAAe,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,QAAQ;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,uCAAuC;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,4FAA4F;IAC5F,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,oBAAY,YAAY;IACtB,IAAI,IAAA;IACJ,IAAI,IAAA;IACJ,QAAQ,IAAA;IACR,SAAS,IAAA;IACT,SAAS,IAAA;IACT,KAAK,IAAA;CACN;AAED,eAAO,MAAM,oBAAoB,gBAAkE,CAAC;AAEpG,MAAM,MAAM,SAAS,GAAG;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,GAAG,EAAE,CAAC;IAChB,cAAc,EAAE,GAAG,EAAE,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,iBAAiB,EAAE,UAAU,CAAC;IAC9B,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,IAAI,CAAC;IACjB,cAAc,EAAE,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,UAAU,EAAE,YAAY,GAAG,SAAS,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,CAC5B,WAAW,EAAE,uBAAuB,EACpC,cAAc,EAAE,UAAU,KACvB,OAAO,CAAC,wBAAwB,CAAC,CAAC;AAEvC,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAI3C;AAED,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAI3C"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/l1_tx_utils/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAEhF,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,MAAM,CAAC;AAE3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,GAAG,IAAI,CAAC;IACnB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,GAAG,CAAC;CACX;AAED,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,eAAe,CAAC,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAE9F,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,GAAG,EAAE,eAAe,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,QAAQ;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,uCAAuC;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,4FAA4F;IAC5F,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,oBAAY,YAAY;IACtB,IAAI,IAAA;IACJ,IAAI,IAAA;IACJ,QAAQ,IAAA;IACR,SAAS,IAAA;IACT,SAAS,IAAA;IACT,KAAK,IAAA;CACN;AAED,eAAO,MAAM,oBAAoB,gBAAkE,CAAC;AAEpG,MAAM,MAAM,SAAS,GAAG;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,GAAG,EAAE,CAAC;IAChB,cAAc,EAAE,GAAG,EAAE,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,iBAAiB,EAAE,UAAU,CAAC;IAC9B,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,IAAI,CAAC;IACjB,cAAc,EAAE,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,UAAU,EAAE,YAAY,GAAG,SAAS,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,CAC5B,WAAW,EAAE,uBAAuB,EACpC,cAAc,EAAE,UAAU,KACvB,OAAO,CAAC,wBAAwB,CAAC,CAAC;AAEvC,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAGzC;CACF;AAED,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,YAAY,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAGzC;CACF"}
@@ -1,4 +1,4 @@
1
1
  import type { ContractFunctionExecutionError } from 'viem';
2
2
  export declare function tryGetCustomErrorNameContractFunction(err: ContractFunctionExecutionError): string;
3
3
  export declare function getCalldataGasUsage(data: Uint8Array): number;
4
- //# sourceMappingURL=utils.d.ts.map
4
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9sMV90eF91dGlscy91dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEtBQUssRUFBRSw4QkFBOEIsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUUzRCx3QkFBZ0IscUNBQXFDLENBQUMsR0FBRyxFQUFFLDhCQUE4QixVQUV4RjtBQU9ELHdCQUFnQixtQkFBbUIsQ0FBQyxJQUFJLEVBQUUsVUFBVSxVQUVuRCJ9