@aztec/ethereum 0.0.0-test.1 → 0.0.1-commit.b655e406

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 (229) hide show
  1. package/dest/account.d.ts +2 -0
  2. package/dest/account.d.ts.map +1 -0
  3. package/dest/account.js +4 -0
  4. package/dest/client.d.ts +5 -3
  5. package/dest/client.d.ts.map +1 -1
  6. package/dest/client.js +16 -2
  7. package/dest/config.d.ts +107 -16
  8. package/dest/config.d.ts.map +1 -1
  9. package/dest/config.js +456 -22
  10. package/dest/contracts/empire_base.d.ts +21 -6
  11. package/dest/contracts/empire_base.d.ts.map +1 -1
  12. package/dest/contracts/empire_base.js +75 -2
  13. package/dest/contracts/empire_slashing_proposer.d.ts +65 -0
  14. package/dest/contracts/empire_slashing_proposer.d.ts.map +1 -0
  15. package/dest/contracts/empire_slashing_proposer.js +194 -0
  16. package/dest/contracts/errors.d.ts +7 -0
  17. package/dest/contracts/errors.d.ts.map +1 -0
  18. package/dest/contracts/errors.js +12 -0
  19. package/dest/contracts/fee_asset_handler.d.ts +19 -0
  20. package/dest/contracts/fee_asset_handler.d.ts.map +1 -0
  21. package/dest/contracts/fee_asset_handler.js +57 -0
  22. package/dest/contracts/fee_juice.d.ts +5 -6
  23. package/dest/contracts/fee_juice.d.ts.map +1 -1
  24. package/dest/contracts/fee_juice.js +27 -20
  25. package/dest/contracts/governance.d.ts +36 -25
  26. package/dest/contracts/governance.d.ts.map +1 -1
  27. package/dest/contracts/governance.js +87 -84
  28. package/dest/contracts/governance_proposer.d.ts +13 -11
  29. package/dest/contracts/governance_proposer.d.ts.map +1 -1
  30. package/dest/contracts/governance_proposer.js +32 -18
  31. package/dest/contracts/gse.d.ts +32 -0
  32. package/dest/contracts/gse.d.ts.map +1 -0
  33. package/dest/contracts/gse.js +72 -0
  34. package/dest/contracts/inbox.d.ts +26 -0
  35. package/dest/contracts/inbox.d.ts.map +1 -0
  36. package/dest/contracts/inbox.js +45 -0
  37. package/dest/contracts/index.d.ts +8 -2
  38. package/dest/contracts/index.d.ts.map +1 -1
  39. package/dest/contracts/index.js +8 -2
  40. package/dest/contracts/multicall.d.ts +21 -0
  41. package/dest/contracts/multicall.d.ts.map +1 -0
  42. package/dest/contracts/multicall.js +156 -0
  43. package/dest/contracts/registry.d.ts +9 -4
  44. package/dest/contracts/registry.d.ts.map +1 -1
  45. package/dest/contracts/registry.js +44 -16
  46. package/dest/contracts/rollup.d.ts +202 -29
  47. package/dest/contracts/rollup.d.ts.map +1 -1
  48. package/dest/contracts/rollup.js +500 -55
  49. package/dest/contracts/slasher_contract.d.ts +44 -0
  50. package/dest/contracts/slasher_contract.d.ts.map +1 -0
  51. package/dest/contracts/slasher_contract.js +75 -0
  52. package/dest/contracts/tally_slashing_proposer.d.ts +138 -0
  53. package/dest/contracts/tally_slashing_proposer.d.ts.map +1 -0
  54. package/dest/contracts/tally_slashing_proposer.js +313 -0
  55. package/dest/contracts/utils.d.ts +3 -0
  56. package/dest/contracts/utils.d.ts.map +1 -0
  57. package/dest/contracts/utils.js +11 -0
  58. package/dest/deploy_l1_contracts.d.ts +128 -21112
  59. package/dest/deploy_l1_contracts.d.ts.map +1 -1
  60. package/dest/deploy_l1_contracts.js +1204 -418
  61. package/dest/eth-signer/eth-signer.d.ts +21 -0
  62. package/dest/eth-signer/eth-signer.d.ts.map +1 -0
  63. package/dest/eth-signer/eth-signer.js +5 -0
  64. package/dest/eth-signer/index.d.ts +2 -0
  65. package/dest/eth-signer/index.d.ts.map +1 -0
  66. package/dest/eth-signer/index.js +1 -0
  67. package/dest/index.d.ts +6 -2
  68. package/dest/index.d.ts.map +1 -1
  69. package/dest/index.js +6 -2
  70. package/dest/l1_artifacts.d.ts +76184 -0
  71. package/dest/l1_artifacts.d.ts.map +1 -0
  72. package/dest/l1_artifacts.js +166 -0
  73. package/dest/l1_contract_addresses.d.ts +21 -1
  74. package/dest/l1_contract_addresses.d.ts.map +1 -1
  75. package/dest/l1_contract_addresses.js +22 -18
  76. package/dest/l1_reader.d.ts +1 -1
  77. package/dest/l1_reader.d.ts.map +1 -1
  78. package/dest/l1_reader.js +8 -8
  79. package/dest/l1_tx_utils/config.d.ts +59 -0
  80. package/dest/l1_tx_utils/config.d.ts.map +1 -0
  81. package/dest/l1_tx_utils/config.js +73 -0
  82. package/dest/l1_tx_utils/constants.d.ts +6 -0
  83. package/dest/l1_tx_utils/constants.d.ts.map +1 -0
  84. package/dest/l1_tx_utils/constants.js +14 -0
  85. package/dest/l1_tx_utils/factory.d.ts +24 -0
  86. package/dest/l1_tx_utils/factory.d.ts.map +1 -0
  87. package/dest/l1_tx_utils/factory.js +12 -0
  88. package/dest/l1_tx_utils/index.d.ts +10 -0
  89. package/dest/l1_tx_utils/index.d.ts.map +1 -0
  90. package/dest/l1_tx_utils/index.js +10 -0
  91. package/dest/l1_tx_utils/interfaces.d.ts +76 -0
  92. package/dest/l1_tx_utils/interfaces.d.ts.map +1 -0
  93. package/dest/l1_tx_utils/interfaces.js +4 -0
  94. package/dest/l1_tx_utils/l1_tx_utils.d.ts +95 -0
  95. package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -0
  96. package/dest/l1_tx_utils/l1_tx_utils.js +610 -0
  97. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts +26 -0
  98. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts.map +1 -0
  99. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.js +26 -0
  100. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +94 -0
  101. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -0
  102. package/dest/l1_tx_utils/readonly_l1_tx_utils.js +431 -0
  103. package/dest/l1_tx_utils/signer.d.ts +4 -0
  104. package/dest/l1_tx_utils/signer.d.ts.map +1 -0
  105. package/dest/l1_tx_utils/signer.js +16 -0
  106. package/dest/l1_tx_utils/types.d.ts +67 -0
  107. package/dest/l1_tx_utils/types.d.ts.map +1 -0
  108. package/dest/l1_tx_utils/types.js +26 -0
  109. package/dest/l1_tx_utils/utils.d.ts +4 -0
  110. package/dest/l1_tx_utils/utils.d.ts.map +1 -0
  111. package/dest/l1_tx_utils/utils.js +14 -0
  112. package/dest/l1_types.d.ts +6 -0
  113. package/dest/l1_types.d.ts.map +1 -0
  114. package/dest/l1_types.js +1 -0
  115. package/dest/publisher_manager.d.ts +15 -0
  116. package/dest/publisher_manager.d.ts.map +1 -0
  117. package/dest/publisher_manager.js +88 -0
  118. package/dest/queries.d.ts +3 -1
  119. package/dest/queries.d.ts.map +1 -1
  120. package/dest/queries.js +51 -12
  121. package/dest/test/chain_monitor.d.ts +72 -0
  122. package/dest/test/chain_monitor.d.ts.map +1 -0
  123. package/dest/test/chain_monitor.js +216 -0
  124. package/dest/test/delayed_tx_utils.d.ts +7 -2
  125. package/dest/test/delayed_tx_utils.d.ts.map +1 -1
  126. package/dest/test/delayed_tx_utils.js +13 -6
  127. package/dest/{eth_cheat_codes.d.ts → test/eth_cheat_codes.d.ts} +87 -13
  128. package/dest/test/eth_cheat_codes.d.ts.map +1 -0
  129. package/dest/test/eth_cheat_codes.js +552 -0
  130. package/dest/test/eth_cheat_codes_with_state.d.ts +1 -1
  131. package/dest/test/eth_cheat_codes_with_state.d.ts.map +1 -1
  132. package/dest/test/eth_cheat_codes_with_state.js +1 -1
  133. package/dest/test/index.d.ts +3 -0
  134. package/dest/test/index.d.ts.map +1 -1
  135. package/dest/test/index.js +3 -0
  136. package/dest/test/rollup_cheat_codes.d.ts +86 -0
  137. package/dest/test/rollup_cheat_codes.d.ts.map +1 -0
  138. package/dest/test/rollup_cheat_codes.js +268 -0
  139. package/dest/test/start_anvil.d.ts +5 -0
  140. package/dest/test/start_anvil.d.ts.map +1 -1
  141. package/dest/test/start_anvil.js +15 -7
  142. package/dest/test/tx_delayer.d.ts +17 -6
  143. package/dest/test/tx_delayer.d.ts.map +1 -1
  144. package/dest/test/tx_delayer.js +95 -19
  145. package/dest/test/upgrade_utils.d.ts +5 -4
  146. package/dest/test/upgrade_utils.d.ts.map +1 -1
  147. package/dest/test/upgrade_utils.js +23 -16
  148. package/dest/types.d.ts +6 -7
  149. package/dest/types.d.ts.map +1 -1
  150. package/dest/types.js +3 -1
  151. package/dest/utils.d.ts +1 -0
  152. package/dest/utils.d.ts.map +1 -1
  153. package/dest/utils.js +43 -88
  154. package/dest/zkPassportVerifierAddress.d.ts +15 -0
  155. package/dest/zkPassportVerifierAddress.d.ts.map +1 -0
  156. package/dest/zkPassportVerifierAddress.js +11 -0
  157. package/package.json +24 -16
  158. package/src/account.ts +5 -0
  159. package/src/client.ts +42 -4
  160. package/src/config.ts +584 -31
  161. package/src/contracts/empire_base.ts +75 -6
  162. package/src/contracts/empire_slashing_proposer.ts +259 -0
  163. package/src/contracts/errors.ts +13 -0
  164. package/src/contracts/fee_asset_handler.ts +63 -0
  165. package/src/contracts/fee_juice.ts +29 -15
  166. package/src/contracts/governance.ts +80 -77
  167. package/src/contracts/governance_proposer.ts +60 -24
  168. package/src/contracts/gse.ts +88 -0
  169. package/src/contracts/inbox.ts +63 -0
  170. package/src/contracts/index.ts +8 -2
  171. package/src/contracts/multicall.ts +155 -0
  172. package/src/contracts/registry.ts +51 -26
  173. package/src/contracts/rollup.ts +585 -56
  174. package/src/contracts/slasher_contract.ts +89 -0
  175. package/src/contracts/tally_slashing_proposer.ts +315 -0
  176. package/src/contracts/utils.ts +14 -0
  177. package/src/deploy_l1_contracts.ts +1467 -566
  178. package/src/eth-signer/eth-signer.ts +25 -0
  179. package/src/eth-signer/index.ts +1 -0
  180. package/src/index.ts +6 -2
  181. package/src/l1_artifacts.ts +254 -0
  182. package/src/l1_contract_addresses.ts +32 -19
  183. package/src/l1_reader.ts +9 -9
  184. package/src/l1_tx_utils/README.md +177 -0
  185. package/src/l1_tx_utils/config.ts +140 -0
  186. package/src/l1_tx_utils/constants.ts +18 -0
  187. package/src/l1_tx_utils/factory.ts +64 -0
  188. package/src/l1_tx_utils/index.ts +12 -0
  189. package/src/l1_tx_utils/interfaces.ts +86 -0
  190. package/src/l1_tx_utils/l1_tx_utils.ts +718 -0
  191. package/src/l1_tx_utils/l1_tx_utils_with_blobs.ts +77 -0
  192. package/src/l1_tx_utils/readonly_l1_tx_utils.ts +559 -0
  193. package/src/l1_tx_utils/signer.ts +28 -0
  194. package/src/l1_tx_utils/types.ts +85 -0
  195. package/src/l1_tx_utils/utils.ts +16 -0
  196. package/src/l1_types.ts +6 -0
  197. package/src/publisher_manager.ts +106 -0
  198. package/src/queries.ts +70 -15
  199. package/src/test/chain_monitor.ts +243 -0
  200. package/src/test/delayed_tx_utils.ts +34 -6
  201. package/src/test/eth_cheat_codes.ts +582 -0
  202. package/src/test/eth_cheat_codes_with_state.ts +1 -1
  203. package/src/test/index.ts +3 -0
  204. package/src/test/rollup_cheat_codes.ts +310 -0
  205. package/src/test/start_anvil.ts +20 -5
  206. package/src/test/tx_delayer.ts +127 -26
  207. package/src/test/upgrade_utils.ts +30 -21
  208. package/src/types.ts +10 -8
  209. package/src/utils.ts +49 -90
  210. package/src/zkPassportVerifierAddress.ts +15 -0
  211. package/dest/contracts/forwarder.d.ts +0 -24
  212. package/dest/contracts/forwarder.d.ts.map +0 -1
  213. package/dest/contracts/forwarder.js +0 -101
  214. package/dest/contracts/slashing_proposer.d.ts +0 -21
  215. package/dest/contracts/slashing_proposer.d.ts.map +0 -1
  216. package/dest/contracts/slashing_proposer.js +0 -47
  217. package/dest/eth_cheat_codes.d.ts.map +0 -1
  218. package/dest/eth_cheat_codes.js +0 -303
  219. package/dest/l1_tx_utils.d.ts +0 -192
  220. package/dest/l1_tx_utils.d.ts.map +0 -1
  221. package/dest/l1_tx_utils.js +0 -641
  222. package/dest/l1_tx_utils_with_blobs.d.ts +0 -12
  223. package/dest/l1_tx_utils_with_blobs.d.ts.map +0 -1
  224. package/dest/l1_tx_utils_with_blobs.js +0 -64
  225. package/src/contracts/forwarder.ts +0 -132
  226. package/src/contracts/slashing_proposer.ts +0 -51
  227. package/src/eth_cheat_codes.ts +0 -314
  228. package/src/l1_tx_utils.ts +0 -847
  229. package/src/l1_tx_utils_with_blobs.ts +0 -86
@@ -0,0 +1,94 @@
1
+ import { type Logger } from '@aztec/foundation/log';
2
+ import { DateProvider } from '@aztec/foundation/timer';
3
+ import { type Abi, type Account, type BlockOverrides, type Hex, type StateOverride } from 'viem';
4
+ import type { ViemClient } from '../types.js';
5
+ import { type L1TxUtilsConfig } from './config.js';
6
+ import type { GasPrice, L1BlobInputs, L1TxRequest, TransactionStats } from './types.js';
7
+ export declare class ReadOnlyL1TxUtils {
8
+ client: ViemClient;
9
+ protected logger: Logger;
10
+ readonly dateProvider: DateProvider;
11
+ protected debugMaxGasLimit: boolean;
12
+ config: Required<L1TxUtilsConfig>;
13
+ protected interrupted: boolean;
14
+ constructor(client: ViemClient, logger: Logger | undefined, dateProvider: DateProvider, config?: Partial<L1TxUtilsConfig>, debugMaxGasLimit?: boolean);
15
+ interrupt(): void;
16
+ restart(): void;
17
+ getBlock(): Promise<{
18
+ number: bigint;
19
+ hash: `0x${string}`;
20
+ nonce: `0x${string}`;
21
+ logsBloom: `0x${string}`;
22
+ baseFeePerGas: bigint | null;
23
+ blobGasUsed: bigint;
24
+ difficulty: bigint;
25
+ excessBlobGas: bigint;
26
+ extraData: Hex;
27
+ gasLimit: bigint;
28
+ gasUsed: bigint;
29
+ miner: import("viem").Address;
30
+ mixHash: import("viem").Hash;
31
+ parentBeaconBlockRoot?: `0x${string}` | undefined;
32
+ parentHash: import("viem").Hash;
33
+ receiptsRoot: Hex;
34
+ sealFields: Hex[];
35
+ sha3Uncles: import("viem").Hash;
36
+ size: bigint;
37
+ stateRoot: import("viem").Hash;
38
+ timestamp: bigint;
39
+ totalDifficulty: bigint | null;
40
+ transactionsRoot: import("viem").Hash;
41
+ uncles: import("viem").Hash[];
42
+ withdrawals?: import("viem").Withdrawal[] | undefined | undefined;
43
+ withdrawalsRoot?: `0x${string}` | undefined;
44
+ transactions: `0x${string}`[];
45
+ }>;
46
+ getBlockNumber(): Promise<bigint>;
47
+ /**
48
+ * Analyzes pending transactions and recent fee history to determine a competitive priority fee.
49
+ * Falls back to network estimate if data is unavailable or fails.
50
+ * @param networkEstimateResult - Result from estimateMaxPriorityFeePerGas RPC call
51
+ * @param pendingBlockResult - Result from getBlock with pending tag RPC call
52
+ * @param feeHistoryResult - Result from getFeeHistory RPC call
53
+ * @returns A competitive priority fee based on pending txs and recent block history
54
+ */
55
+ protected getCompetitivePriorityFee(networkEstimateResult: PromiseSettledResult<bigint | null>, pendingBlockResult: PromiseSettledResult<Awaited<ReturnType<ViemClient['getBlock']>> | null>, feeHistoryResult: PromiseSettledResult<Awaited<ReturnType<ViemClient['getFeeHistory']>> | null>): bigint;
56
+ /**
57
+ * Gets the current gas price with bounds checking
58
+ */
59
+ getGasPrice(gasConfigOverrides?: L1TxUtilsConfig, isBlobTx?: boolean, attempt?: number, previousGasPrice?: typeof attempt extends 0 ? never : GasPrice): Promise<GasPrice>;
60
+ /**
61
+ * Estimates gas and adds buffer
62
+ */
63
+ estimateGas(account: Account | Hex, request: L1TxRequest, _gasConfig?: L1TxUtilsConfig, _blobInputs?: L1BlobInputs): Promise<bigint>;
64
+ getTransactionStats(txHash: string): Promise<TransactionStats | undefined>;
65
+ tryGetErrorFromRevertedTx(data: Hex, args: {
66
+ args: readonly any[];
67
+ functionName: string;
68
+ abi: Abi;
69
+ address: Hex;
70
+ }, blobInputs: (L1BlobInputs & {
71
+ maxFeePerBlobGas: bigint;
72
+ }) | undefined, stateOverride?: StateOverride): Promise<string | undefined>;
73
+ simulate(request: L1TxRequest & {
74
+ gas?: bigint;
75
+ from?: Hex;
76
+ }, blockOverrides?: BlockOverrides<bigint, number>, stateOverrides?: StateOverride, abi?: Abi, _gasConfig?: L1TxUtilsConfig & {
77
+ fallbackGasEstimate?: bigint;
78
+ }): Promise<{
79
+ gasUsed: bigint;
80
+ result: `0x${string}`;
81
+ }>;
82
+ protected _simulate(call: any, blockOverrides: BlockOverrides<bigint, number> | undefined, stateOverrides: StateOverride | undefined, gasConfig: L1TxUtilsConfig & {
83
+ fallbackGasEstimate?: bigint;
84
+ }, abi: Abi): Promise<{
85
+ gasUsed: bigint;
86
+ result: `0x${string}`;
87
+ }>;
88
+ bumpGasLimit(gasLimit: bigint, _gasConfig?: L1TxUtilsConfig): bigint;
89
+ /**
90
+ * Helper function to retry RPC calls twice
91
+ */
92
+ private tryTwice;
93
+ }
94
+ //# sourceMappingURL=readonly_l1_tx_utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readonly_l1_tx_utils.d.ts","sourceRoot":"","sources":["../../src/l1_tx_utils/readonly_l1_tx_utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,431 @@
1
+ import { getKeys, median, merge, pick, times } from '@aztec/foundation/collection';
2
+ import { createLogger } from '@aztec/foundation/log';
3
+ import { makeBackoff, retry } from '@aztec/foundation/retry';
4
+ import { RollupAbi } from '@aztec/l1-artifacts/RollupAbi';
5
+ import pickBy from 'lodash.pickby';
6
+ import { MethodNotFoundRpcError, MethodNotSupportedRpcError, decodeErrorResult, formatGwei, getContractError, hexToBytes } from 'viem';
7
+ 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 { getCalldataGasUsage, tryGetCustomErrorNameContractFunction } from './utils.js';
10
+ const HISTORICAL_BLOCK_COUNT = 5;
11
+ export class ReadOnlyL1TxUtils {
12
+ client;
13
+ logger;
14
+ dateProvider;
15
+ debugMaxGasLimit;
16
+ config;
17
+ interrupted;
18
+ constructor(client, logger = createLogger('ethereum:readonly-l1-utils'), dateProvider, config, debugMaxGasLimit = false){
19
+ this.client = client;
20
+ this.logger = logger;
21
+ this.dateProvider = dateProvider;
22
+ this.debugMaxGasLimit = debugMaxGasLimit;
23
+ this.interrupted = false;
24
+ this.config = merge(defaultL1TxUtilsConfig, pick(config || {}, ...getKeys(l1TxUtilsConfigMappings)));
25
+ }
26
+ interrupt() {
27
+ this.interrupted = true;
28
+ }
29
+ restart() {
30
+ this.interrupted = false;
31
+ }
32
+ getBlock() {
33
+ return this.client.getBlock();
34
+ }
35
+ getBlockNumber() {
36
+ return this.client.getBlockNumber();
37
+ }
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;
125
+ }
126
+ /**
127
+ * Gets the current gas price with bounds checking
128
+ */ async getGasPrice(gasConfigOverrides, isBlobTx = false, attempt = 0, previousGasPrice) {
129
+ 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) {
160
+ this.logger?.warn('Failed to get L1 blob base fee', attempt);
161
+ }
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);
172
+ }
173
+ let maxFeePerGas = baseFee;
174
+ let maxFeePerBlobGas = blobBaseFee;
175
+ // Bump base fee so it's valid for next blocks if it stalls
176
+ const numBlocks = Math.ceil(gasConfig.stallTimeMs / BLOCK_TIME_MS);
177
+ for(let i = 0; i < numBlocks; i++){
178
+ // each block can go up 12.5% from previous baseFee
179
+ maxFeePerGas = maxFeePerGas * (1_000n + 125n) / 1_000n;
180
+ // same for blob gas fee
181
+ maxFeePerBlobGas = maxFeePerBlobGas * (1_000n + 125n) / 1_000n;
182
+ }
183
+ if (attempt > 0) {
184
+ const configBump = gasConfig.priorityFeeRetryBumpPercentage ?? defaultL1TxUtilsConfig.priorityFeeRetryBumpPercentage;
185
+ // if this is a blob tx, we have to use the blob bump percentage
186
+ const minBumpPercentage = isBlobTx ? MIN_BLOB_REPLACEMENT_BUMP_PERCENTAGE : MIN_REPLACEMENT_BUMP_PERCENTAGE;
187
+ const bumpPercentage = configBump > minBumpPercentage ? configBump : minBumpPercentage;
188
+ // Calculate minimum required fees based on previous attempt
189
+ // multiply by 100 & divide by 100 to maintain some precision
190
+ const minPriorityFee = previousGasPrice.maxPriorityFeePerGas * (100_00n + BigInt(bumpPercentage * 1_00)) / 100_00n;
191
+ 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
+ }
203
+ // Use maximum between competitive fee and minimum required bump
204
+ const finalPriorityFee = competitivePriorityFee > minPriorityFee ? competitivePriorityFee : minPriorityFee;
205
+ const feeSource = finalPriorityFee === competitivePriorityFee ? 'competitive' : 'minimum-bump';
206
+ priorityFee = finalPriorityFee;
207
+ // Add the final priority fee to maxFeePerGas
208
+ maxFeePerGas += finalPriorityFee;
209
+ 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
+ }
215
+ } else {
216
+ // First attempt: apply configured bump percentage to competitive fee
217
+ // 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
+ }
224
+ maxFeePerGas += priorityFee;
225
+ }
226
+ // maxGwei and maxBlobGwei are hard limits
227
+ const effectiveMaxGwei = gasConfig.maxGwei * WEI_CONST;
228
+ const effectiveMaxBlobGwei = gasConfig.maxBlobGwei * WEI_CONST;
229
+ // Ensure we don't exceed maxGwei
230
+ if (effectiveMaxGwei > 0n) {
231
+ maxFeePerGas = maxFeePerGas > effectiveMaxGwei ? effectiveMaxGwei : maxFeePerGas;
232
+ }
233
+ // Ensure we don't exceed maxBlobGwei
234
+ if (maxFeePerBlobGas && effectiveMaxBlobGwei > 0n) {
235
+ maxFeePerBlobGas = maxFeePerBlobGas > effectiveMaxBlobGwei ? effectiveMaxBlobGwei : maxFeePerBlobGas;
236
+ }
237
+ // Ensure priority fee doesn't exceed max fee
238
+ const maxPriorityFeePerGas = priorityFee > maxFeePerGas ? maxFeePerGas : priorityFee;
239
+ if (attempt > 0 && previousGasPrice?.maxFeePerBlobGas) {
240
+ const bumpPercentage = gasConfig.priorityFeeRetryBumpPercentage > MIN_BLOB_REPLACEMENT_BUMP_PERCENTAGE ? gasConfig.priorityFeeRetryBumpPercentage : MIN_BLOB_REPLACEMENT_BUMP_PERCENTAGE;
241
+ // calculate min blob fee based on previous attempt
242
+ const minBlobFee = previousGasPrice.maxFeePerBlobGas * (100_00n + BigInt(bumpPercentage * 1_00)) / 100_00n;
243
+ // use max between current network values and min required values
244
+ maxFeePerBlobGas = maxFeePerBlobGas > minBlobFee ? maxFeePerBlobGas : minBlobFee;
245
+ }
246
+ this.logger?.trace(`Computed L1 gas price max fee ${formatGwei(maxFeePerGas)} and max priority fee ${formatGwei(maxPriorityFeePerGas)}`, {
247
+ attempt,
248
+ baseFee: formatGwei(baseFee),
249
+ maxFeePerGas: formatGwei(maxFeePerGas),
250
+ maxPriorityFeePerGas: formatGwei(maxPriorityFeePerGas),
251
+ blobBaseFee: formatGwei(blobBaseFee),
252
+ maxFeePerBlobGas: formatGwei(maxFeePerBlobGas)
253
+ });
254
+ return {
255
+ maxFeePerGas,
256
+ maxPriorityFeePerGas,
257
+ ...maxFeePerBlobGas && {
258
+ maxFeePerBlobGas: maxFeePerBlobGas
259
+ }
260
+ };
261
+ }
262
+ /**
263
+ * Estimates gas and adds buffer
264
+ */ async estimateGas(account, request, _gasConfig, _blobInputs) {
265
+ const gasConfig = {
266
+ ...this.config,
267
+ ..._gasConfig
268
+ };
269
+ let initialEstimate = 0n;
270
+ if (_blobInputs) {
271
+ // @note requests with blobs also require maxFeePerBlobGas to be set
272
+ const gasPrice = await this.getGasPrice(gasConfig, true, 0);
273
+ initialEstimate = await this.client.estimateGas({
274
+ account,
275
+ ...request,
276
+ ..._blobInputs,
277
+ maxFeePerBlobGas: gasPrice.maxFeePerBlobGas,
278
+ gas: LARGE_GAS_LIMIT
279
+ });
280
+ this.logger?.trace(`Estimated gas for blob tx: ${initialEstimate}`);
281
+ } else {
282
+ initialEstimate = await this.client.estimateGas({
283
+ account,
284
+ ...request,
285
+ gas: LARGE_GAS_LIMIT
286
+ });
287
+ this.logger?.trace(`Estimated gas for non-blob tx: ${initialEstimate}`);
288
+ }
289
+ // Add buffer based on either fixed amount or percentage
290
+ const withBuffer = this.bumpGasLimit(initialEstimate, gasConfig);
291
+ return withBuffer;
292
+ }
293
+ async getTransactionStats(txHash) {
294
+ const tx = await this.client.getTransaction({
295
+ hash: txHash
296
+ });
297
+ if (!tx) {
298
+ return undefined;
299
+ }
300
+ const calldata = hexToBytes(tx.input);
301
+ return {
302
+ sender: tx.from.toString(),
303
+ transactionHash: tx.hash,
304
+ calldataSize: calldata.length,
305
+ calldataGas: getCalldataGasUsage(calldata)
306
+ };
307
+ }
308
+ async tryGetErrorFromRevertedTx(data, args, blobInputs, stateOverride = []) {
309
+ try {
310
+ await this.client.simulateContract({
311
+ ...args,
312
+ account: this.client.account,
313
+ stateOverride
314
+ });
315
+ this.logger?.trace('Simulated blob tx', {
316
+ blobInputs
317
+ });
318
+ // If the above passes, we have a blob error. We cannot simulate blob txs, and failed txs no longer throw errors.
319
+ // Strangely, the only way to throw the revert reason as an error and provide blobs is prepareTransactionRequest.
320
+ // See: https://github.com/wevm/viem/issues/2075
321
+ // This throws a EstimateGasExecutionError with the custom error information:
322
+ const request = blobInputs ? {
323
+ account: this.client.account,
324
+ to: args.address,
325
+ data,
326
+ blobs: blobInputs.blobs,
327
+ kzg: blobInputs.kzg,
328
+ maxFeePerBlobGas: blobInputs.maxFeePerBlobGas
329
+ } : {
330
+ account: this.client.account,
331
+ to: args.address,
332
+ data
333
+ };
334
+ this.logger?.trace('Preparing tx', {
335
+ request
336
+ });
337
+ await this.client.prepareTransactionRequest(request);
338
+ this.logger?.trace('Prepared tx');
339
+ return undefined;
340
+ } catch (simulationErr) {
341
+ // If we don't have a ContractFunctionExecutionError, we have a blob related error => use getContractError to get the error msg.
342
+ const contractErr = simulationErr.name === 'ContractFunctionExecutionError' ? simulationErr : getContractError(simulationErr, {
343
+ args: [],
344
+ abi: args.abi,
345
+ functionName: args.functionName,
346
+ address: args.address
347
+ });
348
+ if (contractErr.name === 'ContractFunctionExecutionError') {
349
+ const execErr = contractErr;
350
+ return tryGetCustomErrorNameContractFunction(execErr);
351
+ }
352
+ this.logger?.error(`Error getting error from simulation`, simulationErr);
353
+ }
354
+ }
355
+ async simulate(request, blockOverrides = {}, stateOverrides = [], abi = RollupAbi, _gasConfig) {
356
+ const gasConfig = {
357
+ ...this.config,
358
+ ..._gasConfig
359
+ };
360
+ const call = {
361
+ to: request.to,
362
+ data: request.data,
363
+ ...request.from && {
364
+ from: request.from
365
+ }
366
+ };
367
+ return await this._simulate(call, blockOverrides, stateOverrides, gasConfig, abi);
368
+ }
369
+ async _simulate(call, blockOverrides = {}, stateOverrides = [], gasConfig, abi) {
370
+ try {
371
+ const result = await this.client.simulateBlocks({
372
+ validation: false,
373
+ blocks: [
374
+ {
375
+ blockOverrides,
376
+ stateOverrides,
377
+ calls: [
378
+ call
379
+ ]
380
+ }
381
+ ]
382
+ });
383
+ if (result[0].calls[0].status === 'failure') {
384
+ this.logger?.error('L1 transaction simulation failed', result[0].calls[0].error);
385
+ const decodedError = decodeErrorResult({
386
+ abi,
387
+ data: result[0].calls[0].data
388
+ });
389
+ throw new Error(`L1 transaction simulation failed with error ${decodedError.errorName}(${decodedError.args?.join(',')})`);
390
+ }
391
+ this.logger?.debug(`L1 transaction simulation succeeded`, {
392
+ ...result[0].calls[0]
393
+ });
394
+ return {
395
+ gasUsed: result[0].gasUsed,
396
+ result: result[0].calls[0].data
397
+ };
398
+ } catch (err) {
399
+ if (err instanceof MethodNotFoundRpcError || err instanceof MethodNotSupportedRpcError) {
400
+ if (gasConfig.fallbackGasEstimate) {
401
+ this.logger?.warn(`Node does not support eth_simulateV1 API. Using fallback gas estimate: ${gasConfig.fallbackGasEstimate}`);
402
+ return {
403
+ gasUsed: gasConfig.fallbackGasEstimate,
404
+ result: '0x'
405
+ };
406
+ }
407
+ this.logger?.error('Node does not support eth_simulateV1 API');
408
+ }
409
+ throw err;
410
+ }
411
+ }
412
+ bumpGasLimit(gasLimit, _gasConfig) {
413
+ const gasConfig = {
414
+ ...this.config,
415
+ ..._gasConfig
416
+ };
417
+ const bumpedGasLimit = gasLimit + gasLimit * BigInt((gasConfig?.gasLimitBufferPercentage || 0) * 1_00) / 100_00n;
418
+ const cleanGasConfig = pickBy(gasConfig, (_, key)=>key in l1TxUtilsConfigMappings);
419
+ this.logger?.trace(`Bumping gas limit from ${gasLimit} to ${bumpedGasLimit}`, {
420
+ gasLimit,
421
+ gasConfig: cleanGasConfig,
422
+ bumpedGasLimit
423
+ });
424
+ return bumpedGasLimit;
425
+ }
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
+ }
@@ -0,0 +1,4 @@
1
+ import { type WalletClient } from 'viem';
2
+ import type { SigningCallback } from './types.js';
3
+ export declare function createViemSigner(client: WalletClient): SigningCallback;
4
+ //# sourceMappingURL=signer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../../src/l1_tx_utils/signer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgC,KAAK,YAAY,EAAoB,MAAM,MAAM,CAAC;AAEzF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,mBAoBpD"}
@@ -0,0 +1,16 @@
1
+ import { parseTransaction } from 'viem';
2
+ export function createViemSigner(client) {
3
+ const signer = async (tx, _address)=>{
4
+ const signedTx = await client.signTransaction(tx);
5
+ const parsed = parseTransaction(signedTx);
6
+ if (!parsed.r || !parsed.s || parsed.yParity !== 0 && parsed.yParity !== 1) {
7
+ throw new Error('Failed to extract signature from viem signed transaction');
8
+ }
9
+ return {
10
+ r: parsed.r,
11
+ s: parsed.s,
12
+ yParity: parsed.yParity
13
+ };
14
+ };
15
+ return signer;
16
+ }
@@ -0,0 +1,67 @@
1
+ import type { BlobKzgInstance } from '@aztec/blob-lib/types';
2
+ import { EthAddress } from '@aztec/foundation/eth-address';
3
+ import type { ViemTransactionSignature } from '@aztec/foundation/eth-signature';
4
+ import type { Abi, Address, Hex, TransactionReceipt, TransactionSerializable } from 'viem';
5
+ import type { L1TxUtilsConfig } from './config.js';
6
+ export interface L1TxRequest {
7
+ to: Address | null;
8
+ data?: Hex;
9
+ value?: bigint;
10
+ abi?: Abi;
11
+ }
12
+ export type L1TxConfig = Partial<L1TxUtilsConfig> & {
13
+ gasLimit?: bigint;
14
+ txTimeoutAt?: Date;
15
+ };
16
+ export interface L1BlobInputs {
17
+ blobs: Uint8Array[];
18
+ kzg: BlobKzgInstance;
19
+ maxFeePerBlobGas?: bigint;
20
+ }
21
+ export interface GasPrice {
22
+ maxFeePerGas: bigint;
23
+ maxPriorityFeePerGas: bigint;
24
+ maxFeePerBlobGas?: bigint;
25
+ }
26
+ export type TransactionStats = {
27
+ /** Address of the sender. */
28
+ sender: string;
29
+ /** Hash of the transaction. */
30
+ transactionHash: string;
31
+ /** Size in bytes of the tx calldata */
32
+ calldataSize: number;
33
+ /** Gas required to pay for the calldata inclusion (depends on size and number of zeros) */
34
+ calldataGas: number;
35
+ };
36
+ export declare enum TxUtilsState {
37
+ IDLE = 0,
38
+ SENT = 1,
39
+ SPEED_UP = 2,
40
+ CANCELLED = 3,
41
+ NOT_MINED = 4,
42
+ MINED = 5
43
+ }
44
+ export declare const TerminalTxUtilsState: TxUtilsState[];
45
+ export type L1TxState = {
46
+ id: number;
47
+ txHashes: Hex[];
48
+ cancelTxHashes: Hex[];
49
+ gasLimit: bigint;
50
+ gasPrice: GasPrice;
51
+ txConfigOverrides: L1TxConfig;
52
+ request: L1TxRequest;
53
+ status: TxUtilsState;
54
+ nonce: number;
55
+ sentAtL1Ts: Date;
56
+ lastSentAtL1Ts: Date;
57
+ receipt?: TransactionReceipt;
58
+ blobInputs: L1BlobInputs | undefined;
59
+ };
60
+ export type SigningCallback = (transaction: TransactionSerializable, signingAddress: EthAddress) => Promise<ViemTransactionSignature>;
61
+ export declare class UnknownMinedTxError extends Error {
62
+ constructor(nonce: number, account: string);
63
+ }
64
+ export declare class DroppedTransactionError extends Error {
65
+ constructor(nonce: number, account: string);
66
+ }
67
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,26 @@
1
+ export var TxUtilsState = /*#__PURE__*/ function(TxUtilsState) {
2
+ TxUtilsState[TxUtilsState["IDLE"] = 0] = "IDLE";
3
+ TxUtilsState[TxUtilsState["SENT"] = 1] = "SENT";
4
+ TxUtilsState[TxUtilsState["SPEED_UP"] = 2] = "SPEED_UP";
5
+ TxUtilsState[TxUtilsState["CANCELLED"] = 3] = "CANCELLED";
6
+ TxUtilsState[TxUtilsState["NOT_MINED"] = 4] = "NOT_MINED";
7
+ TxUtilsState[TxUtilsState["MINED"] = 5] = "MINED";
8
+ return TxUtilsState;
9
+ }({});
10
+ export const TerminalTxUtilsState = [
11
+ 0,
12
+ 5,
13
+ 4
14
+ ];
15
+ export class UnknownMinedTxError extends Error {
16
+ constructor(nonce, account){
17
+ super(`Nonce ${nonce} from account ${account} is MINED but not by one of our expected transactions`);
18
+ this.name = 'UnknownMinedTxError';
19
+ }
20
+ }
21
+ export class DroppedTransactionError extends Error {
22
+ constructor(nonce, account){
23
+ super(`Transaction with nonce ${nonce} from account ${account} was dropped from the mempool`);
24
+ this.name = 'DroppedTransactionError';
25
+ }
26
+ }
@@ -0,0 +1,4 @@
1
+ import type { ContractFunctionExecutionError } from 'viem';
2
+ export declare function tryGetCustomErrorNameContractFunction(err: ContractFunctionExecutionError): string;
3
+ export declare function getCalldataGasUsage(data: Uint8Array): number;
4
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/l1_tx_utils/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,MAAM,CAAC;AAE3D,wBAAgB,qCAAqC,CAAC,GAAG,EAAE,8BAA8B,UAExF;AAOD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,UAAU,UAEnD"}