@aztec/ethereum 3.0.0-canary.a9708bd → 3.0.0-devnet.20251212

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 (195) hide show
  1. package/dest/account.d.ts +1 -1
  2. package/dest/chain.d.ts +1 -1
  3. package/dest/client.d.ts +2 -2
  4. package/dest/client.d.ts.map +1 -1
  5. package/dest/config.d.ts +16 -8
  6. package/dest/config.d.ts.map +1 -1
  7. package/dest/config.js +160 -62
  8. package/dest/constants.d.ts +1 -1
  9. package/dest/contracts/empire_base.d.ts +7 -6
  10. package/dest/contracts/empire_base.d.ts.map +1 -1
  11. package/dest/contracts/empire_base.js +1 -1
  12. package/dest/contracts/empire_slashing_proposer.d.ts +7 -6
  13. package/dest/contracts/empire_slashing_proposer.d.ts.map +1 -1
  14. package/dest/contracts/empire_slashing_proposer.js +9 -3
  15. package/dest/contracts/errors.d.ts +1 -1
  16. package/dest/contracts/errors.d.ts.map +1 -1
  17. package/dest/contracts/fee_asset_handler.d.ts +4 -4
  18. package/dest/contracts/fee_asset_handler.d.ts.map +1 -1
  19. package/dest/contracts/fee_juice.d.ts +1 -1
  20. package/dest/contracts/fee_juice.d.ts.map +1 -1
  21. package/dest/contracts/governance.d.ts +16 -16
  22. package/dest/contracts/governance.d.ts.map +1 -1
  23. package/dest/contracts/governance.js +7 -3
  24. package/dest/contracts/governance_proposer.d.ts +6 -6
  25. package/dest/contracts/governance_proposer.d.ts.map +1 -1
  26. package/dest/contracts/governance_proposer.js +9 -4
  27. package/dest/contracts/gse.d.ts +1 -1
  28. package/dest/contracts/gse.d.ts.map +1 -1
  29. package/dest/contracts/inbox.d.ts +1 -1
  30. package/dest/contracts/inbox.d.ts.map +1 -1
  31. package/dest/contracts/index.d.ts +1 -1
  32. package/dest/contracts/multicall.d.ts +5 -7
  33. package/dest/contracts/multicall.d.ts.map +1 -1
  34. package/dest/contracts/multicall.js +6 -4
  35. package/dest/contracts/registry.d.ts +1 -1
  36. package/dest/contracts/registry.d.ts.map +1 -1
  37. package/dest/contracts/rollup.d.ts +83 -72
  38. package/dest/contracts/rollup.d.ts.map +1 -1
  39. package/dest/contracts/rollup.js +144 -139
  40. package/dest/contracts/slasher_contract.d.ts +11 -1
  41. package/dest/contracts/slasher_contract.d.ts.map +1 -1
  42. package/dest/contracts/slasher_contract.js +18 -0
  43. package/dest/contracts/tally_slashing_proposer.d.ts +30 -9
  44. package/dest/contracts/tally_slashing_proposer.d.ts.map +1 -1
  45. package/dest/contracts/tally_slashing_proposer.js +58 -8
  46. package/dest/contracts/utils.d.ts +1 -1
  47. package/dest/deploy_l1_contracts.d.ts +477 -15
  48. package/dest/deploy_l1_contracts.d.ts.map +1 -1
  49. package/dest/deploy_l1_contracts.js +610 -386
  50. package/dest/eth-signer/eth-signer.d.ts +1 -1
  51. package/dest/eth-signer/index.d.ts +1 -1
  52. package/dest/forwarder_proxy.d.ts +32 -0
  53. package/dest/forwarder_proxy.d.ts.map +1 -0
  54. package/dest/forwarder_proxy.js +93 -0
  55. package/dest/l1_artifacts.d.ts +14258 -6015
  56. package/dest/l1_artifacts.d.ts.map +1 -1
  57. package/dest/l1_artifacts.js +10 -5
  58. package/dest/l1_contract_addresses.d.ts +8 -4
  59. package/dest/l1_contract_addresses.d.ts.map +1 -1
  60. package/dest/l1_contract_addresses.js +16 -26
  61. package/dest/l1_reader.d.ts +4 -2
  62. package/dest/l1_reader.d.ts.map +1 -1
  63. package/dest/l1_reader.js +14 -8
  64. package/dest/l1_tx_utils/config.d.ts +59 -0
  65. package/dest/l1_tx_utils/config.d.ts.map +1 -0
  66. package/dest/l1_tx_utils/config.js +96 -0
  67. package/dest/l1_tx_utils/constants.d.ts +6 -0
  68. package/dest/l1_tx_utils/constants.d.ts.map +1 -0
  69. package/dest/l1_tx_utils/constants.js +14 -0
  70. package/dest/l1_tx_utils/factory.d.ts +24 -0
  71. package/dest/l1_tx_utils/factory.d.ts.map +1 -0
  72. package/dest/l1_tx_utils/factory.js +12 -0
  73. package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts +41 -0
  74. package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts.map +1 -0
  75. package/dest/l1_tx_utils/forwarder_l1_tx_utils.js +48 -0
  76. package/dest/l1_tx_utils/index-blobs.d.ts +3 -0
  77. package/dest/l1_tx_utils/index-blobs.d.ts.map +1 -0
  78. package/dest/l1_tx_utils/index-blobs.js +2 -0
  79. package/dest/l1_tx_utils/index.d.ts +10 -0
  80. package/dest/l1_tx_utils/index.d.ts.map +1 -0
  81. package/dest/l1_tx_utils/index.js +10 -0
  82. package/dest/l1_tx_utils/interfaces.d.ts +76 -0
  83. package/dest/l1_tx_utils/interfaces.d.ts.map +1 -0
  84. package/dest/l1_tx_utils/interfaces.js +4 -0
  85. package/dest/l1_tx_utils/l1_tx_utils.d.ts +94 -0
  86. package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -0
  87. package/dest/l1_tx_utils/l1_tx_utils.js +623 -0
  88. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts +26 -0
  89. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts.map +1 -0
  90. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.js +26 -0
  91. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +94 -0
  92. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -0
  93. package/dest/l1_tx_utils/readonly_l1_tx_utils.js +431 -0
  94. package/dest/l1_tx_utils/signer.d.ts +4 -0
  95. package/dest/l1_tx_utils/signer.d.ts.map +1 -0
  96. package/dest/l1_tx_utils/signer.js +16 -0
  97. package/dest/l1_tx_utils/types.d.ts +67 -0
  98. package/dest/l1_tx_utils/types.d.ts.map +1 -0
  99. package/dest/l1_tx_utils/types.js +26 -0
  100. package/dest/l1_tx_utils/utils.d.ts +4 -0
  101. package/dest/l1_tx_utils/utils.d.ts.map +1 -0
  102. package/dest/l1_tx_utils/utils.js +14 -0
  103. package/dest/l1_types.d.ts +1 -1
  104. package/dest/publisher_manager.d.ts +8 -3
  105. package/dest/publisher_manager.d.ts.map +1 -1
  106. package/dest/publisher_manager.js +36 -8
  107. package/dest/queries.d.ts +1 -1
  108. package/dest/queries.d.ts.map +1 -1
  109. package/dest/queries.js +13 -12
  110. package/dest/test/chain_monitor.d.ts +33 -19
  111. package/dest/test/chain_monitor.d.ts.map +1 -1
  112. package/dest/test/chain_monitor.js +100 -33
  113. package/dest/test/delayed_tx_utils.d.ts +3 -3
  114. package/dest/test/delayed_tx_utils.d.ts.map +1 -1
  115. package/dest/test/delayed_tx_utils.js +2 -2
  116. package/dest/test/eth_cheat_codes.d.ts +36 -14
  117. package/dest/test/eth_cheat_codes.d.ts.map +1 -1
  118. package/dest/test/eth_cheat_codes.js +124 -31
  119. package/dest/test/eth_cheat_codes_with_state.d.ts +1 -1
  120. package/dest/test/eth_cheat_codes_with_state.d.ts.map +1 -1
  121. package/dest/test/index.d.ts +1 -1
  122. package/dest/test/rollup_cheat_codes.d.ts +23 -20
  123. package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
  124. package/dest/test/rollup_cheat_codes.js +79 -42
  125. package/dest/test/start_anvil.d.ts +2 -1
  126. package/dest/test/start_anvil.d.ts.map +1 -1
  127. package/dest/test/start_anvil.js +2 -1
  128. package/dest/test/tx_delayer.d.ts +1 -1
  129. package/dest/test/tx_delayer.d.ts.map +1 -1
  130. package/dest/test/tx_delayer.js +3 -2
  131. package/dest/test/upgrade_utils.d.ts +1 -1
  132. package/dest/test/upgrade_utils.d.ts.map +1 -1
  133. package/dest/test/upgrade_utils.js +3 -2
  134. package/dest/types.d.ts +57 -2
  135. package/dest/types.d.ts.map +1 -1
  136. package/dest/utils.d.ts +2 -2
  137. package/dest/utils.d.ts.map +1 -1
  138. package/dest/utils.js +10 -161
  139. package/dest/zkPassportVerifierAddress.d.ts +1 -1
  140. package/dest/zkPassportVerifierAddress.js +1 -1
  141. package/package.json +27 -13
  142. package/src/client.ts +1 -1
  143. package/src/config.ts +177 -65
  144. package/src/contracts/empire_base.ts +7 -6
  145. package/src/contracts/empire_slashing_proposer.ts +18 -8
  146. package/src/contracts/fee_asset_handler.ts +1 -1
  147. package/src/contracts/governance.ts +3 -3
  148. package/src/contracts/governance_proposer.ts +14 -9
  149. package/src/contracts/multicall.ts +12 -10
  150. package/src/contracts/rollup.ts +170 -171
  151. package/src/contracts/slasher_contract.ts +22 -0
  152. package/src/contracts/tally_slashing_proposer.ts +63 -12
  153. package/src/deploy_l1_contracts.ts +610 -337
  154. package/src/forwarder_proxy.ts +108 -0
  155. package/src/l1_artifacts.ts +14 -6
  156. package/src/l1_contract_addresses.ts +17 -26
  157. package/src/l1_reader.ts +17 -9
  158. package/src/l1_tx_utils/README.md +177 -0
  159. package/src/l1_tx_utils/config.ts +161 -0
  160. package/src/l1_tx_utils/constants.ts +18 -0
  161. package/src/l1_tx_utils/factory.ts +64 -0
  162. package/src/l1_tx_utils/forwarder_l1_tx_utils.ts +119 -0
  163. package/src/l1_tx_utils/index-blobs.ts +2 -0
  164. package/src/l1_tx_utils/index.ts +12 -0
  165. package/src/l1_tx_utils/interfaces.ts +86 -0
  166. package/src/l1_tx_utils/l1_tx_utils.ts +738 -0
  167. package/src/l1_tx_utils/l1_tx_utils_with_blobs.ts +77 -0
  168. package/src/l1_tx_utils/readonly_l1_tx_utils.ts +557 -0
  169. package/src/l1_tx_utils/signer.ts +28 -0
  170. package/src/l1_tx_utils/types.ts +85 -0
  171. package/src/l1_tx_utils/utils.ts +16 -0
  172. package/src/publisher_manager.ts +51 -9
  173. package/src/queries.ts +16 -8
  174. package/src/test/chain_monitor.ts +118 -36
  175. package/src/test/delayed_tx_utils.ts +2 -2
  176. package/src/test/eth_cheat_codes.ts +149 -30
  177. package/src/test/rollup_cheat_codes.ts +94 -52
  178. package/src/test/start_anvil.ts +2 -0
  179. package/src/test/tx_delayer.ts +4 -2
  180. package/src/test/upgrade_utils.ts +3 -2
  181. package/src/types.ts +62 -0
  182. package/src/utils.ts +12 -184
  183. package/src/zkPassportVerifierAddress.ts +1 -1
  184. package/dest/index.d.ts +0 -18
  185. package/dest/index.d.ts.map +0 -1
  186. package/dest/index.js +0 -17
  187. package/dest/l1_tx_utils.d.ts +0 -250
  188. package/dest/l1_tx_utils.d.ts.map +0 -1
  189. package/dest/l1_tx_utils.js +0 -826
  190. package/dest/l1_tx_utils_with_blobs.d.ts +0 -19
  191. package/dest/l1_tx_utils_with_blobs.d.ts.map +0 -1
  192. package/dest/l1_tx_utils_with_blobs.js +0 -85
  193. package/src/index.ts +0 -17
  194. package/src/l1_tx_utils.ts +0 -1105
  195. package/src/l1_tx_utils_with_blobs.ts +0 -144
@@ -0,0 +1,623 @@
1
+ import { maxBigint } from '@aztec/foundation/bigint';
2
+ import { merge, pick } from '@aztec/foundation/collection';
3
+ import { InterruptError, TimeoutError } from '@aztec/foundation/error';
4
+ import { createLogger } from '@aztec/foundation/log';
5
+ import { retryUntil } from '@aztec/foundation/retry';
6
+ import { sleep } from '@aztec/foundation/sleep';
7
+ import { DateProvider } from '@aztec/foundation/timer';
8
+ import { RollupAbi } from '@aztec/l1-artifacts/RollupAbi';
9
+ import pickBy from 'lodash.pickby';
10
+ import { createNonceManager, formatGwei, serializeTransaction } from 'viem';
11
+ import { jsonRpc } from 'viem/nonce';
12
+ import { formatViemError } from '../utils.js';
13
+ import { l1TxUtilsConfigMappings } from './config.js';
14
+ import { LARGE_GAS_LIMIT } from './constants.js';
15
+ import { ReadOnlyL1TxUtils } from './readonly_l1_tx_utils.js';
16
+ import { DroppedTransactionError, TerminalTxUtilsState, TxUtilsState, UnknownMinedTxError } from './types.js';
17
+ const MAX_L1_TX_STATES = 32;
18
+ export class L1TxUtils extends ReadOnlyL1TxUtils {
19
+ client;
20
+ address;
21
+ signer;
22
+ store;
23
+ metrics;
24
+ nonceManager;
25
+ txs;
26
+ constructor(client, address, signer, logger = createLogger('ethereum:publisher'), dateProvider = new DateProvider(), config, debugMaxGasLimit = false, store, metrics){
27
+ super(client, logger, dateProvider, config, debugMaxGasLimit), this.client = client, this.address = address, this.signer = signer, this.store = store, this.metrics = metrics, this.txs = [];
28
+ this.nonceManager = createNonceManager({
29
+ source: jsonRpc()
30
+ });
31
+ }
32
+ get state() {
33
+ return this.txs.at(-1)?.status ?? TxUtilsState.IDLE;
34
+ }
35
+ get lastMinedAtBlockNumber() {
36
+ const minedBlockNumbers = this.txs.map((tx)=>tx.receipt?.blockNumber).filter((bn)=>bn !== undefined);
37
+ return minedBlockNumbers.length === 0 ? undefined : maxBigint(...minedBlockNumbers);
38
+ }
39
+ async updateState(l1TxState, newState, l1Timestamp) {
40
+ const oldState = l1TxState.status;
41
+ l1TxState.status = newState;
42
+ const sender = this.getSenderAddress().toString();
43
+ this.logger.debug(`Tx state changed from ${TxUtilsState[oldState]} to ${TxUtilsState[newState]} for nonce ${l1TxState.nonce} account ${sender}`);
44
+ // Record metrics
45
+ if (newState === TxUtilsState.MINED && l1Timestamp !== undefined) {
46
+ this.metrics?.recordMinedTx(l1TxState, new Date(l1Timestamp));
47
+ } else if (newState === TxUtilsState.NOT_MINED) {
48
+ this.metrics?.recordDroppedTx(l1TxState);
49
+ }
50
+ // Update state in the store
51
+ await this.store?.saveState(sender, l1TxState).catch((err)=>this.logger.error('Failed to persist L1 tx state', err));
52
+ }
53
+ updateConfig(newConfig) {
54
+ this.config = merge(this.config, newConfig);
55
+ this.logger.info('Updated L1TxUtils config', pickBy(newConfig, (_, key)=>key in l1TxUtilsConfigMappings));
56
+ }
57
+ getSenderAddress() {
58
+ return this.address;
59
+ }
60
+ getSenderBalance() {
61
+ return this.client.getBalance({
62
+ address: this.getSenderAddress().toString()
63
+ });
64
+ }
65
+ /**
66
+ * Rehydrates transaction states from the store and resumes monitoring for pending transactions.
67
+ * This should be called on startup to restore state and resume monitoring of any in-flight transactions.
68
+ */ async loadStateAndResumeMonitoring() {
69
+ if (!this.store) {
70
+ return;
71
+ }
72
+ const account = this.getSenderAddress().toString();
73
+ const loadedStates = await this.store.loadStates(account);
74
+ if (loadedStates.length === 0) {
75
+ this.logger.debug(`No states to rehydrate for account ${account}`);
76
+ return;
77
+ }
78
+ // Clean up excess states if we have more than MAX_L1_TX_STATES
79
+ if (loadedStates.length > MAX_L1_TX_STATES) {
80
+ this.logger.warn(`Found ${loadedStates.length} tx states for account ${account}, pruning to most recent ${MAX_L1_TX_STATES}`);
81
+ // Keep only the most recent MAX_L1_TX_STATES
82
+ const statesToKeep = loadedStates.slice(-MAX_L1_TX_STATES);
83
+ const statesToDelete = loadedStates.slice(0, -MAX_L1_TX_STATES);
84
+ // Batch delete old states in a transaction for efficiency
85
+ const idsToDelete = statesToDelete.map((s)=>s.id);
86
+ await this.store.deleteState(account, ...idsToDelete);
87
+ this.txs = statesToKeep;
88
+ this.logger.info(`Cleaned up ${statesToDelete.length} old tx states, kept ${statesToKeep.length} for account ${account}`);
89
+ } else {
90
+ // Convert loaded states (which have id) to the txs format
91
+ this.txs = loadedStates;
92
+ this.logger.info(`Rehydrated ${loadedStates.length} tx states for account ${account}`);
93
+ }
94
+ // Find all pending states and resume monitoring
95
+ const pendingStates = this.txs.filter((state)=>!TerminalTxUtilsState.includes(state.status));
96
+ if (pendingStates.length === 0) {
97
+ return;
98
+ }
99
+ this.logger.info(`Resuming monitoring for ${pendingStates.length} pending transactions for account ${account}`, {
100
+ txs: pendingStates.map((s)=>({
101
+ id: s.id,
102
+ nonce: s.nonce,
103
+ status: TxUtilsState[s.status]
104
+ }))
105
+ });
106
+ for (const state of pendingStates){
107
+ void this.monitorTransaction(state).catch((err)=>{
108
+ this.logger.error(`Error monitoring rehydrated tx with nonce ${state.nonce} for account ${account}`, formatViemError(err), {
109
+ nonce: state.nonce,
110
+ account
111
+ });
112
+ });
113
+ }
114
+ }
115
+ async signTransaction(txRequest) {
116
+ const signature = await this.signer(txRequest, this.getSenderAddress());
117
+ return serializeTransaction(txRequest, signature);
118
+ }
119
+ async prepareSignedTransaction(txData) {
120
+ const txRequest = await this.client.prepareTransactionRequest(txData);
121
+ return await this.signTransaction(txRequest);
122
+ }
123
+ /**
124
+ * Sends a transaction with gas estimation and pricing
125
+ * @param request - The transaction request (to, data, value)
126
+ * @param gasConfig - Optional gas configuration
127
+ * @returns The transaction hash and parameters used
128
+ */ async sendTransaction(request, gasConfigOverrides, blobInputs, stateChange = TxUtilsState.SENT) {
129
+ if (this.interrupted) {
130
+ throw new InterruptError(`Transaction sending is interrupted`);
131
+ }
132
+ try {
133
+ const gasConfig = merge(this.config, gasConfigOverrides);
134
+ const account = this.getSenderAddress().toString();
135
+ let gasLimit;
136
+ if (this.debugMaxGasLimit) {
137
+ gasLimit = LARGE_GAS_LIMIT;
138
+ } else if (gasConfig.gasLimit) {
139
+ gasLimit = gasConfig.gasLimit;
140
+ } else {
141
+ gasLimit = await this.estimateGas(account, request, gasConfig);
142
+ }
143
+ this.logger.trace(`Computed gas limit ${gasLimit}`, {
144
+ gasLimit,
145
+ ...request
146
+ });
147
+ const gasPrice = await this.getGasPrice(gasConfig, !!blobInputs);
148
+ if (this.interrupted) {
149
+ throw new InterruptError(`Transaction sending is interrupted`);
150
+ }
151
+ const nonce = await this.nonceManager.consume({
152
+ client: this.client,
153
+ address: account,
154
+ chainId: this.client.chain.id
155
+ });
156
+ const baseState = {
157
+ request,
158
+ gasLimit,
159
+ blobInputs,
160
+ gasPrice,
161
+ nonce
162
+ };
163
+ const txData = this.makeTxData(baseState, {
164
+ isCancelTx: false
165
+ });
166
+ const now = new Date(await this.getL1Timestamp());
167
+ if (gasConfig.txTimeoutAt && now > gasConfig.txTimeoutAt) {
168
+ throw new TimeoutError(`Transaction timed out before sending (now ${now.toISOString()} > timeoutAt ${gasConfig.txTimeoutAt.toISOString()})`);
169
+ }
170
+ // Send the new tx
171
+ const signedRequest = await this.prepareSignedTransaction(txData);
172
+ const txHash = await this.client.sendRawTransaction({
173
+ serializedTransaction: signedRequest
174
+ });
175
+ // Create the new state for monitoring
176
+ const l1TxState = {
177
+ ...baseState,
178
+ id: await this.store?.consumeNextStateId(account) ?? Math.max(...this.txs.map((tx)=>tx.id), 0),
179
+ txHashes: [
180
+ txHash
181
+ ],
182
+ cancelTxHashes: [],
183
+ status: TxUtilsState.IDLE,
184
+ txConfigOverrides: gasConfigOverrides ?? {},
185
+ sentAtL1Ts: now,
186
+ lastSentAtL1Ts: now
187
+ };
188
+ // And persist it
189
+ await this.updateState(l1TxState, stateChange);
190
+ await this.store?.saveBlobs(account, l1TxState.id, blobInputs);
191
+ this.txs.push(l1TxState);
192
+ // Clean up stale states
193
+ if (this.txs.length > MAX_L1_TX_STATES) {
194
+ const removed = this.txs.shift();
195
+ if (removed && this.store) {
196
+ await this.store.deleteState(account, removed.id);
197
+ }
198
+ }
199
+ this.logger.info(`Sent L1 transaction ${txHash}`, {
200
+ to: request.to,
201
+ value: request.value,
202
+ nonce,
203
+ account,
204
+ sentAt: now,
205
+ gasLimit,
206
+ maxFeePerGas: formatGwei(gasPrice.maxFeePerGas),
207
+ maxPriorityFeePerGas: formatGwei(gasPrice.maxPriorityFeePerGas),
208
+ ...gasPrice.maxFeePerBlobGas && {
209
+ maxFeePerBlobGas: formatGwei(gasPrice.maxFeePerBlobGas)
210
+ },
211
+ isBlobTx: !!blobInputs,
212
+ txConfig: gasConfigOverrides
213
+ });
214
+ return {
215
+ txHash,
216
+ state: l1TxState
217
+ };
218
+ } catch (err) {
219
+ const viemError = formatViemError(err, request.abi);
220
+ this.logger.error(`Failed to send L1 transaction`, viemError, {
221
+ request: pick(request, 'to', 'value')
222
+ });
223
+ throw viemError;
224
+ }
225
+ }
226
+ async tryGetTxReceipt(txHashes, nonce, isCancelTx) {
227
+ for (const hash of txHashes){
228
+ try {
229
+ const receipt = await this.client.getTransactionReceipt({
230
+ hash
231
+ });
232
+ if (receipt) {
233
+ const account = this.getSenderAddress().toString();
234
+ const what = isCancelTx ? 'Cancellation L1 transaction' : 'L1 transaction';
235
+ if (receipt.status === 'reverted') {
236
+ this.logger.warn(`${what} ${hash} with nonce ${nonce} reverted`, {
237
+ receipt,
238
+ nonce,
239
+ account
240
+ });
241
+ } else {
242
+ this.logger.info(`${what} ${hash} with nonce ${nonce} mined`, {
243
+ receipt,
244
+ nonce,
245
+ account
246
+ });
247
+ }
248
+ return receipt;
249
+ }
250
+ } catch (err) {
251
+ if (err instanceof Error && err.name === 'TransactionReceiptNotFoundError') {
252
+ continue;
253
+ } else {
254
+ this.logger.error(`Error getting receipt for tx ${hash}`, err);
255
+ continue;
256
+ }
257
+ }
258
+ }
259
+ }
260
+ /**
261
+ * Returns whether a given tx should be considered as timed out and no longer monitored.
262
+ * Relies on the txTimeout setting for user txs, and on the txCancellationTimeout for cancel txs.
263
+ * @remarks We check against the latestBlockTimestamp as opposed to the current time to avoid a race condition where
264
+ * the tx is mined in a block with the same timestamp as txTimeoutAt, but our execution node has not yet processed it,
265
+ * or the loop here has not yet checked the tx before that timeout.
266
+ */ isTxTimedOut(state, l1Timestamp) {
267
+ const account = this.getSenderAddress().toString();
268
+ const { nonce } = state;
269
+ const txConfig = merge(this.config, state.txConfigOverrides);
270
+ const { txTimeoutAt, txTimeoutMs, maxSpeedUpAttempts } = txConfig;
271
+ const isCancelTx = state.cancelTxHashes.length > 0;
272
+ this.logger.trace(`Tx timeout check for ${account} with nonce ${nonce}`, {
273
+ nonce,
274
+ account,
275
+ l1Timestamp,
276
+ lastAttemptSent: state.lastSentAtL1Ts.getTime(),
277
+ initialTxTime: state.sentAtL1Ts.getTime(),
278
+ now: this.dateProvider.now(),
279
+ txTimeoutAt,
280
+ txTimeoutMs,
281
+ interrupted: this.interrupted
282
+ });
283
+ if (this.interrupted) {
284
+ this.logger.warn(`Tx monitoring interrupted during nonce ${nonce} for ${account} check`, {
285
+ nonce,
286
+ account
287
+ });
288
+ return true;
289
+ }
290
+ if (isCancelTx) {
291
+ // Note that we check against the lastSentAt time for cancellations, since we time them out
292
+ // after the last attempt to submit them, not the initial time.
293
+ const attempts = state.cancelTxHashes.length;
294
+ return attempts > maxSpeedUpAttempts && state.lastSentAtL1Ts.getTime() + txConfig.txCancellationFinalTimeoutMs <= l1Timestamp;
295
+ }
296
+ return txTimeoutAt !== undefined && l1Timestamp >= txTimeoutAt.getTime() || txTimeoutMs !== undefined && txTimeoutMs > 0 && l1Timestamp - state.sentAtL1Ts.getTime() >= txTimeoutMs;
297
+ }
298
+ /**
299
+ * Monitors a transaction until completion, handling speed-ups if needed
300
+ */ async monitorTransaction(state) {
301
+ const { nonce, gasLimit, blobInputs, txConfigOverrides: gasConfigOverrides } = state;
302
+ const gasConfig = merge(this.config, gasConfigOverrides);
303
+ const { maxSpeedUpAttempts, stallTimeMs } = gasConfig;
304
+ const isCancelTx = state.cancelTxHashes.length > 0;
305
+ const txHashes = isCancelTx ? state.cancelTxHashes : state.txHashes;
306
+ const isBlobTx = !!blobInputs;
307
+ const account = this.getSenderAddress().toString();
308
+ const initialTxHash = txHashes[0];
309
+ let currentTxHash = txHashes.at(-1);
310
+ let l1Timestamp;
311
+ while(true){
312
+ l1Timestamp = await this.getL1Timestamp();
313
+ try {
314
+ const timePassed = l1Timestamp - state.lastSentAtL1Ts.getTime();
315
+ const [currentNonce, pendingNonce] = await Promise.all([
316
+ this.client.getTransactionCount({
317
+ address: account,
318
+ blockTag: 'latest'
319
+ }),
320
+ this.client.getTransactionCount({
321
+ address: account,
322
+ blockTag: 'pending'
323
+ })
324
+ ]);
325
+ // If the current nonce on our account is greater than our transaction's nonce then a tx with the same nonce has been mined.
326
+ if (currentNonce > nonce) {
327
+ // We try getting the receipt twice, since sometimes anvil fails to return it if the tx has just been mined
328
+ const receipt = await this.tryGetTxReceipt(state.cancelTxHashes, nonce, true) ?? await this.tryGetTxReceipt(state.txHashes, nonce, false) ?? await sleep(500) ?? await this.tryGetTxReceipt(state.cancelTxHashes, nonce, true) ?? await this.tryGetTxReceipt(state.txHashes, nonce, false);
329
+ if (receipt) {
330
+ state.receipt = receipt;
331
+ await this.updateState(state, TxUtilsState.MINED, l1Timestamp);
332
+ return receipt;
333
+ }
334
+ // If we get here then we have checked all of our tx versions and not found anything.
335
+ // We should consider the nonce as MINED
336
+ await this.updateState(state, TxUtilsState.MINED, l1Timestamp);
337
+ throw new UnknownMinedTxError(nonce, account);
338
+ }
339
+ // If this is a cancel tx and its nonce is no longer on the mempool, we consider it dropped and stop monitoring
340
+ // If it is a regular tx, we let the loop speed it up after the stall time
341
+ if (isCancelTx && pendingNonce <= nonce && timePassed >= gasConfig.txUnseenConsideredDroppedMs) {
342
+ this.logger.warn(`Cancellation tx with nonce ${nonce} for account ${account} has been dropped from the visible mempool`, {
343
+ nonce,
344
+ account,
345
+ pendingNonce,
346
+ timePassed
347
+ });
348
+ await this.updateState(state, TxUtilsState.NOT_MINED);
349
+ this.nonceManager.reset({
350
+ address: account,
351
+ chainId: this.client.chain.id
352
+ });
353
+ throw new DroppedTransactionError(nonce, account);
354
+ }
355
+ // Break if the tx has timed out (ie expired)
356
+ if (this.isTxTimedOut(state, l1Timestamp)) {
357
+ break;
358
+ }
359
+ // Speed up the transaction if it appears to be stuck (exceeded stall time and still have retry attempts)
360
+ const attempts = txHashes.length;
361
+ if (timePassed >= stallTimeMs && attempts <= maxSpeedUpAttempts) {
362
+ const newGasPrice = await this.getGasPrice(gasConfig, isBlobTx, attempts, state.gasPrice);
363
+ state.gasPrice = newGasPrice;
364
+ this.logger.debug(`Tx ${currentTxHash} with nonce ${nonce} from ${account} appears stuck. ` + `Attempting speed-up ${attempts}/${maxSpeedUpAttempts} ` + `with new priority fee ${formatGwei(newGasPrice.maxPriorityFeePerGas)} gwei.`, {
365
+ account,
366
+ nonce,
367
+ maxFeePerGas: formatGwei(newGasPrice.maxFeePerGas),
368
+ maxPriorityFeePerGas: formatGwei(newGasPrice.maxPriorityFeePerGas),
369
+ ...newGasPrice.maxFeePerBlobGas && {
370
+ maxFeePerBlobGas: formatGwei(newGasPrice.maxFeePerBlobGas)
371
+ }
372
+ });
373
+ const txData = this.makeTxData(state, {
374
+ isCancelTx
375
+ });
376
+ const signedRequest = await this.prepareSignedTransaction(txData);
377
+ const newHash = await this.client.sendRawTransaction({
378
+ serializedTransaction: signedRequest
379
+ });
380
+ this.logger.verbose(`Sent L1 speed-up tx ${newHash} replacing ${currentTxHash} for nonce ${nonce} from ${account}`, {
381
+ nonce,
382
+ account,
383
+ gasLimit,
384
+ maxFeePerGas: formatGwei(newGasPrice.maxFeePerGas),
385
+ maxPriorityFeePerGas: formatGwei(newGasPrice.maxPriorityFeePerGas),
386
+ txConfig: state.txConfigOverrides,
387
+ ...newGasPrice.maxFeePerBlobGas && {
388
+ maxFeePerBlobGas: formatGwei(newGasPrice.maxFeePerBlobGas)
389
+ }
390
+ });
391
+ currentTxHash = newHash;
392
+ txHashes.push(currentTxHash);
393
+ state.lastSentAtL1Ts = new Date(l1Timestamp);
394
+ await this.updateState(state, isCancelTx ? TxUtilsState.CANCELLED : TxUtilsState.SPEED_UP);
395
+ await sleep(gasConfig.checkIntervalMs);
396
+ continue;
397
+ }
398
+ this.logger.debug(`Tx ${currentTxHash} from ${account} with nonce ${nonce} still pending after ${timePassed}ms`, {
399
+ account,
400
+ nonce,
401
+ pendingNonce,
402
+ attempts,
403
+ timePassed,
404
+ isBlobTx,
405
+ isCancelTx,
406
+ ...pick(state.gasPrice, 'maxFeePerGas', 'maxPriorityFeePerGas', 'maxFeePerBlobGas'),
407
+ ...pick(gasConfig, 'txUnseenConsideredDroppedMs', 'txCancellationFinalTimeoutMs', 'maxSpeedUpAttempts', 'stallTimeMs', 'txTimeoutAt', 'txTimeoutMs')
408
+ });
409
+ await sleep(gasConfig.checkIntervalMs);
410
+ } catch (err) {
411
+ if (err instanceof DroppedTransactionError || err instanceof UnknownMinedTxError) {
412
+ throw err;
413
+ }
414
+ const viemError = formatViemError(err);
415
+ this.logger.error(`Error while monitoring L1 tx ${currentTxHash}`, viemError, {
416
+ nonce,
417
+ account
418
+ });
419
+ await sleep(gasConfig.checkIntervalMs);
420
+ }
421
+ }
422
+ // Oh no, the transaction has timed out!
423
+ if (isCancelTx || !gasConfig.cancelTxOnTimeout) {
424
+ // If this was already a cancellation tx, or we are configured to not cancel txs, we just mark it as NOT_MINED
425
+ // and reset the nonce manager, so the next tx that comes along can reuse the nonce if/when this tx gets dropped.
426
+ // This is the nastiest scenario for us, since the new tx could acquire the next nonce, but then this tx is dropped,
427
+ // and the new tx would never get mined. Eventually, the new tx would also drop.
428
+ await this.updateState(state, TxUtilsState.NOT_MINED);
429
+ this.nonceManager.reset({
430
+ address: account,
431
+ chainId: this.client.chain.id
432
+ });
433
+ } else {
434
+ // Otherwise we fire the cancellation without awaiting to avoid blocking the caller,
435
+ // and monitor it in the background so we can speed it up as needed.
436
+ void this.attemptTxCancellation(state).catch(async (err)=>{
437
+ await this.updateState(state, TxUtilsState.NOT_MINED);
438
+ this.logger.error(`Failed to send cancellation for timed out tx ${initialTxHash} with nonce ${nonce}`, err, {
439
+ account,
440
+ nonce,
441
+ initialTxHash
442
+ });
443
+ });
444
+ }
445
+ const what = isCancelTx ? 'Cancellation L1' : 'L1';
446
+ this.logger.warn(`${what} transaction ${initialTxHash} with nonce ${nonce} from ${account} timed out`, {
447
+ initialTxHash,
448
+ currentTxHash,
449
+ nonce,
450
+ account,
451
+ txTimeoutAt: gasConfig.txTimeoutAt?.getTime(),
452
+ txTimeoutMs: gasConfig.txTimeoutMs,
453
+ txInitialTime: state.sentAtL1Ts.getTime(),
454
+ l1Timestamp,
455
+ now: this.dateProvider.now(),
456
+ attempts: txHashes.length - 1,
457
+ isInterrupted: this.interrupted
458
+ });
459
+ throw new TimeoutError(`L1 transaction ${initialTxHash} timed out`);
460
+ }
461
+ /**
462
+ * Creates tx data to be signed by viem signTransaction method, using the state as input.
463
+ * If isCancelTx is true, creates a 0-value tx to self with 21k gas and no data instead,
464
+ * and an empty blob input if the original tx also had blobs.
465
+ */ makeTxData(state, opts) {
466
+ const { request, gasLimit, blobInputs, gasPrice, nonce } = state;
467
+ const isBlobTx = blobInputs !== undefined;
468
+ const baseTxOpts = {
469
+ nonce,
470
+ ...pick(gasPrice, 'maxFeePerGas', 'maxPriorityFeePerGas')
471
+ };
472
+ if (opts.isCancelTx) {
473
+ const baseTxData = {
474
+ to: this.getSenderAddress().toString(),
475
+ value: 0n,
476
+ data: '0x',
477
+ gas: 21_000n,
478
+ ...baseTxOpts
479
+ };
480
+ return isBlobTx ? {
481
+ ...baseTxData,
482
+ ...this.makeEmptyBlobInputs(gasPrice.maxFeePerBlobGas)
483
+ } : baseTxData;
484
+ }
485
+ const baseTxData = {
486
+ ...request,
487
+ ...baseTxOpts,
488
+ gas: gasLimit
489
+ };
490
+ return blobInputs ? {
491
+ ...baseTxData,
492
+ ...blobInputs,
493
+ maxFeePerBlobGas: gasPrice.maxFeePerBlobGas
494
+ } : baseTxData;
495
+ }
496
+ /** Returns when all monitor loops have stopped. */ async waitMonitoringStopped(timeoutSeconds = 10) {
497
+ const account = this.getSenderAddress().toString();
498
+ await retryUntil(()=>this.txs.every((tx)=>TerminalTxUtilsState.includes(tx.status)), `monitoring stopped for ${account}`, timeoutSeconds, 0.1).catch(()=>this.logger.warn(`Timeout waiting for monitoring loops to stop for ${account}`));
499
+ }
500
+ /**
501
+ * Sends a transaction and monitors it until completion
502
+ * @param request - The transaction request (to, data, value)
503
+ * @param gasConfig - Optional gas configuration
504
+ * @returns The receipt of the successful transaction
505
+ */ async sendAndMonitorTransaction(request, gasConfig, blobInputs) {
506
+ const { state } = await this.sendTransaction(request, gasConfig, blobInputs);
507
+ const receipt = await this.monitorTransaction(state);
508
+ return {
509
+ receipt,
510
+ state
511
+ };
512
+ }
513
+ async simulate(request, _blockOverrides = {}, stateOverrides = [], abi = RollupAbi, _gasConfig) {
514
+ const blockOverrides = {
515
+ ..._blockOverrides
516
+ };
517
+ const gasConfig = merge(this.config, _gasConfig);
518
+ const gasPrice = await this.getGasPrice(gasConfig, false);
519
+ const call = {
520
+ to: request.to,
521
+ data: request.data,
522
+ from: request.from ?? this.getSenderAddress().toString(),
523
+ maxFeePerGas: gasPrice.maxFeePerGas,
524
+ maxPriorityFeePerGas: gasPrice.maxPriorityFeePerGas,
525
+ gas: request.gas ?? LARGE_GAS_LIMIT
526
+ };
527
+ if (!request.gas && !gasConfig.ignoreBlockGasLimit) {
528
+ // LARGE_GAS_LIMIT is set as call.gas, increase block gasLimit
529
+ blockOverrides.gasLimit = LARGE_GAS_LIMIT * 2n;
530
+ }
531
+ return this._simulate(call, blockOverrides, stateOverrides, gasConfig, abi);
532
+ }
533
+ /**
534
+ * Attempts to cancel a transaction by sending a 0-value tx to self with same nonce but higher gas prices
535
+ * Only sends the cancellation if the original tx is still pending, not if it was dropped
536
+ * @returns The hash of the cancellation transaction
537
+ */ async attemptTxCancellation(state) {
538
+ const isBlobTx = state.blobInputs !== undefined;
539
+ const { nonce, gasPrice: previousGasPrice } = state;
540
+ const account = this.getSenderAddress().toString();
541
+ // Do not send cancellation if interrupted
542
+ if (this.interrupted) {
543
+ this.logger.warn(`Not sending cancellation for L1 tx from account ${account} with nonce ${nonce} as interrupted`, {
544
+ nonce,
545
+ account
546
+ });
547
+ await this.updateState(state, TxUtilsState.NOT_MINED);
548
+ this.nonceManager.reset({
549
+ address: account,
550
+ chainId: this.client.chain.id
551
+ });
552
+ return;
553
+ }
554
+ // Check if the original tx is still pending
555
+ const currentNonce = await this.client.getTransactionCount({
556
+ address: account,
557
+ blockTag: 'pending'
558
+ });
559
+ if (currentNonce < nonce) {
560
+ this.logger.verbose(`Not sending cancellation for L1 tx from account ${account} with nonce ${nonce} as it is dropped`, {
561
+ nonce,
562
+ account,
563
+ currentNonce
564
+ });
565
+ await this.updateState(state, TxUtilsState.NOT_MINED);
566
+ this.nonceManager.reset({
567
+ address: account,
568
+ chainId: this.client.chain.id
569
+ });
570
+ return;
571
+ }
572
+ // Get gas price with higher priority fee for cancellation
573
+ const cancelGasPrice = await this.getGasPrice({
574
+ ...this.config,
575
+ // Use high bump for cancellation to ensure it replaces the original tx
576
+ priorityFeeRetryBumpPercentage: 150
577
+ }, isBlobTx, state.txHashes.length, previousGasPrice);
578
+ const { maxFeePerGas, maxPriorityFeePerGas, maxFeePerBlobGas } = cancelGasPrice;
579
+ this.logger.verbose(`Attempting to cancel L1 ${isBlobTx ? 'blob' : 'vanilla'} transaction from account ${account} with nonce ${nonce} after time out`, {
580
+ maxFeePerGas: formatGwei(maxFeePerGas),
581
+ maxPriorityFeePerGas: formatGwei(maxPriorityFeePerGas),
582
+ ...maxFeePerBlobGas && {
583
+ maxFeePerBlobGas: formatGwei(maxFeePerBlobGas)
584
+ }
585
+ });
586
+ // Send 0-value tx to self with higher gas price
587
+ state.gasPrice = cancelGasPrice;
588
+ state.lastSentAtL1Ts = new Date(await this.getL1Timestamp());
589
+ const txData = this.makeTxData(state, {
590
+ isCancelTx: true
591
+ });
592
+ const signedRequest = await this.prepareSignedTransaction(txData);
593
+ const cancelTxHash = await this.client.sendRawTransaction({
594
+ serializedTransaction: signedRequest
595
+ });
596
+ state.cancelTxHashes.push(cancelTxHash);
597
+ await this.updateState(state, TxUtilsState.CANCELLED);
598
+ this.logger.warn(`Sent cancellation tx ${cancelTxHash} for timed out tx from ${account} with nonce ${nonce}`, {
599
+ nonce,
600
+ cancelGasPrice,
601
+ isBlobTx,
602
+ txHashes: state.txHashes
603
+ });
604
+ // Do not await the cancel tx to be mined
605
+ void this.monitorTransaction(state).catch((err)=>{
606
+ this.logger.error(`Failed to mine cancellation tx ${cancelTxHash} for nonce ${nonce} account ${account}`, err, {
607
+ nonce,
608
+ account,
609
+ cancelTxHash
610
+ });
611
+ });
612
+ }
613
+ /** Returns L1 timestamps in milliseconds */ async getL1Timestamp() {
614
+ const { timestamp } = await this.client.getBlock({
615
+ blockTag: 'latest',
616
+ includeTransactions: false
617
+ });
618
+ return Number(timestamp) * 1000;
619
+ }
620
+ /** Makes empty blob inputs for the cancellation tx. To be overridden in L1TxUtilsWithBlobs. */ makeEmptyBlobInputs(_maxFeePerBlobGas) {
621
+ throw new Error('Cannot make empty blob inputs for cancellation');
622
+ }
623
+ }
@@ -0,0 +1,26 @@
1
+ import type { Logger } from '@aztec/foundation/log';
2
+ import { DateProvider } from '@aztec/foundation/timer';
3
+ import type { EthSigner } from '../eth-signer/eth-signer.js';
4
+ import type { ExtendedViemWalletClient, ViemClient } from '../types.js';
5
+ import type { L1TxUtilsConfig } from './config.js';
6
+ import type { IL1TxMetrics, IL1TxStore } from './interfaces.js';
7
+ import { L1TxUtils } from './l1_tx_utils.js';
8
+ import type { L1BlobInputs } from './types.js';
9
+ /** Extends L1TxUtils with the capability to cancel blobs. This needs to be a separate class so we don't require a dependency on blob-lib unnecessarily. */
10
+ export declare class L1TxUtilsWithBlobs extends L1TxUtils {
11
+ /** Makes empty blob inputs for the cancellation tx. */
12
+ protected makeEmptyBlobInputs(maxFeePerBlobGas: bigint): Required<L1BlobInputs>;
13
+ }
14
+ export declare function createL1TxUtilsWithBlobsFromViemWallet(client: ExtendedViemWalletClient, deps?: {
15
+ logger?: Logger;
16
+ dateProvider?: DateProvider;
17
+ store?: IL1TxStore;
18
+ metrics?: IL1TxMetrics;
19
+ }, config?: Partial<L1TxUtilsConfig>, debugMaxGasLimit?: boolean): L1TxUtilsWithBlobs;
20
+ export declare function createL1TxUtilsWithBlobsFromEthSigner(client: ViemClient, signer: EthSigner, deps?: {
21
+ logger?: Logger;
22
+ dateProvider?: DateProvider;
23
+ store?: IL1TxStore;
24
+ metrics?: IL1TxMetrics;
25
+ }, config?: Partial<L1TxUtilsConfig>, debugMaxGasLimit?: boolean): L1TxUtilsWithBlobs;
26
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibDFfdHhfdXRpbHNfd2l0aF9ibG9icy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2wxX3R4X3V0aWxzL2wxX3R4X3V0aWxzX3dpdGhfYmxvYnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDcEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBSXZELE9BQU8sS0FBSyxFQUFFLFNBQVMsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQzdELE9BQU8sS0FBSyxFQUFFLHdCQUF3QixFQUFFLFVBQVUsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN4RSxPQUFPLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDbkQsT0FBTyxLQUFLLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUU3QyxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQW1CLE1BQU0sWUFBWSxDQUFDO0FBRWhFLDJKQUEySjtBQUMzSixxQkFBYSxrQkFBbUIsU0FBUSxTQUFTO0lBQy9DLHVEQUF1RDtJQUN2RCxVQUFtQixtQkFBbUIsQ0FBQyxnQkFBZ0IsRUFBRSxNQUFNLEdBQUcsUUFBUSxDQUFDLFlBQVksQ0FBQyxDQUl2RjtDQUNGO0FBRUQsd0JBQWdCLHNDQUFzQyxDQUNwRCxNQUFNLEVBQUUsd0JBQXdCLEVBQ2hDLElBQUksR0FBRTtJQUNKLE1BQU0sQ0FBQyxFQUFFLE1BQU0sQ0FBQztJQUNoQixZQUFZLENBQUMsRUFBRSxZQUFZLENBQUM7SUFDNUIsS0FBSyxDQUFDLEVBQUUsVUFBVSxDQUFDO0lBQ25CLE9BQU8sQ0FBQyxFQUFFLFlBQVksQ0FBQztDQUNuQixFQUNOLE1BQU0sR0FBRSxPQUFPLENBQUMsZUFBZSxDQUFNLEVBQ3JDLGdCQUFnQixHQUFFLE9BQWUsc0JBYWxDO0FBRUQsd0JBQWdCLHFDQUFxQyxDQUNuRCxNQUFNLEVBQUUsVUFBVSxFQUNsQixNQUFNLEVBQUUsU0FBUyxFQUNqQixJQUFJLEdBQUU7SUFDSixNQUFNLENBQUMsRUFBRSxNQUFNLENBQUM7SUFDaEIsWUFBWSxDQUFDLEVBQUUsWUFBWSxDQUFDO0lBQzVCLEtBQUssQ0FBQyxFQUFFLFVBQVUsQ0FBQztJQUNuQixPQUFPLENBQUMsRUFBRSxZQUFZLENBQUM7Q0FDbkIsRUFDTixNQUFNLEdBQUUsT0FBTyxDQUFDLGVBQWUsQ0FBTSxFQUNyQyxnQkFBZ0IsR0FBRSxPQUFlLHNCQWlCbEMifQ==
@@ -0,0 +1 @@
1
+ {"version":3,"file":"l1_tx_utils_with_blobs.d.ts","sourceRoot":"","sources":["../../src/l1_tx_utils/l1_tx_utils_with_blobs.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAIvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,wBAAwB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,YAAY,CAAC;AAEhE,2JAA2J;AAC3J,qBAAa,kBAAmB,SAAQ,SAAS;IAC/C,uDAAuD;IACvD,UAAmB,mBAAmB,CAAC,gBAAgB,EAAE,MAAM,GAAG,QAAQ,CAAC,YAAY,CAAC,CAIvF;CACF;AAED,wBAAgB,sCAAsC,CACpD,MAAM,EAAE,wBAAwB,EAChC,IAAI,GAAE;IACJ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,OAAO,CAAC,EAAE,YAAY,CAAC;CACnB,EACN,MAAM,GAAE,OAAO,CAAC,eAAe,CAAM,EACrC,gBAAgB,GAAE,OAAe,sBAalC;AAED,wBAAgB,qCAAqC,CACnD,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,SAAS,EACjB,IAAI,GAAE;IACJ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,OAAO,CAAC,EAAE,YAAY,CAAC;CACnB,EACN,MAAM,GAAE,OAAO,CAAC,eAAe,CAAM,EACrC,gBAAgB,GAAE,OAAe,sBAiBlC"}