@aztec/ethereum 0.0.1-commit.0c875d939 → 0.0.1-commit.10bd49492

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 (96) hide show
  1. package/dest/config.d.ts +3 -1
  2. package/dest/config.d.ts.map +1 -1
  3. package/dest/config.js +10 -2
  4. package/dest/contracts/empire_base.d.ts +3 -1
  5. package/dest/contracts/empire_base.d.ts.map +1 -1
  6. package/dest/contracts/empire_slashing_proposer.d.ts +3 -1
  7. package/dest/contracts/empire_slashing_proposer.d.ts.map +1 -1
  8. package/dest/contracts/empire_slashing_proposer.js +9 -0
  9. package/dest/contracts/fee_asset_price_oracle.d.ts +2 -1
  10. package/dest/contracts/fee_asset_price_oracle.d.ts.map +1 -1
  11. package/dest/contracts/fee_asset_price_oracle.js +20 -3
  12. package/dest/contracts/governance.js +3 -3
  13. package/dest/contracts/governance_proposer.d.ts +3 -1
  14. package/dest/contracts/governance_proposer.d.ts.map +1 -1
  15. package/dest/contracts/governance_proposer.js +9 -0
  16. package/dest/contracts/registry.d.ts +3 -1
  17. package/dest/contracts/registry.d.ts.map +1 -1
  18. package/dest/contracts/registry.js +30 -1
  19. package/dest/contracts/rollup.d.ts +9 -6
  20. package/dest/contracts/rollup.d.ts.map +1 -1
  21. package/dest/contracts/rollup.js +20 -7
  22. package/dest/deploy_aztec_l1_contracts.d.ts +2 -3
  23. package/dest/deploy_aztec_l1_contracts.d.ts.map +1 -1
  24. package/dest/deploy_l1_contract.js +3 -3
  25. package/dest/generated/l1-contracts-defaults.d.ts +1 -1
  26. package/dest/generated/l1-contracts-defaults.js +1 -1
  27. package/dest/l1_artifacts.d.ts +1051 -42
  28. package/dest/l1_artifacts.d.ts.map +1 -1
  29. package/dest/l1_tx_utils/config.d.ts +7 -1
  30. package/dest/l1_tx_utils/config.d.ts.map +1 -1
  31. package/dest/l1_tx_utils/config.js +14 -1
  32. package/dest/l1_tx_utils/factory.d.ts +18 -10
  33. package/dest/l1_tx_utils/factory.d.ts.map +1 -1
  34. package/dest/l1_tx_utils/factory.js +17 -7
  35. package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts +15 -15
  36. package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts.map +1 -1
  37. package/dest/l1_tx_utils/forwarder_l1_tx_utils.js +9 -15
  38. package/dest/l1_tx_utils/index-blobs.d.ts +3 -3
  39. package/dest/l1_tx_utils/index-blobs.d.ts.map +1 -1
  40. package/dest/l1_tx_utils/index-blobs.js +2 -2
  41. package/dest/l1_tx_utils/index.d.ts +2 -1
  42. package/dest/l1_tx_utils/index.d.ts.map +1 -1
  43. package/dest/l1_tx_utils/index.js +1 -0
  44. package/dest/l1_tx_utils/l1_tx_utils.d.ts +18 -7
  45. package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -1
  46. package/dest/l1_tx_utils/l1_tx_utils.js +52 -36
  47. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +1 -1
  48. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -1
  49. package/dest/l1_tx_utils/readonly_l1_tx_utils.js +8 -4
  50. package/dest/l1_tx_utils/tx_delayer.d.ts +56 -0
  51. package/dest/l1_tx_utils/tx_delayer.d.ts.map +1 -0
  52. package/dest/{test → l1_tx_utils}/tx_delayer.js +62 -34
  53. package/dest/test/index.d.ts +1 -3
  54. package/dest/test/index.d.ts.map +1 -1
  55. package/dest/test/index.js +0 -2
  56. package/dest/test/start_anvil.d.ts +16 -3
  57. package/dest/test/start_anvil.d.ts.map +1 -1
  58. package/dest/test/start_anvil.js +129 -29
  59. package/dest/test/upgrade_utils.js +2 -2
  60. package/dest/utils.d.ts +1 -1
  61. package/dest/utils.d.ts.map +1 -1
  62. package/dest/utils.js +16 -12
  63. package/package.json +5 -7
  64. package/src/config.ts +14 -1
  65. package/src/contracts/empire_base.ts +2 -0
  66. package/src/contracts/empire_slashing_proposer.ts +6 -0
  67. package/src/contracts/fee_asset_price_oracle.ts +20 -2
  68. package/src/contracts/governance.ts +3 -3
  69. package/src/contracts/governance_proposer.ts +6 -0
  70. package/src/contracts/registry.ts +31 -1
  71. package/src/contracts/rollup.ts +42 -17
  72. package/src/deploy_aztec_l1_contracts.ts +19 -2
  73. package/src/deploy_l1_contract.ts +3 -3
  74. package/src/generated/l1-contracts-defaults.ts +1 -1
  75. package/src/l1_tx_utils/config.ts +20 -0
  76. package/src/l1_tx_utils/factory.ts +31 -31
  77. package/src/l1_tx_utils/forwarder_l1_tx_utils.ts +43 -54
  78. package/src/l1_tx_utils/index-blobs.ts +2 -2
  79. package/src/l1_tx_utils/index.ts +1 -0
  80. package/src/l1_tx_utils/l1_tx_utils.ts +54 -26
  81. package/src/l1_tx_utils/readonly_l1_tx_utils.ts +8 -4
  82. package/src/{test → l1_tx_utils}/tx_delayer.ts +78 -50
  83. package/src/test/index.ts +0 -2
  84. package/src/test/start_anvil.ts +154 -29
  85. package/src/test/upgrade_utils.ts +2 -2
  86. package/src/utils.ts +17 -14
  87. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts +0 -26
  88. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts.map +0 -1
  89. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.js +0 -26
  90. package/dest/test/delayed_tx_utils.d.ts +0 -13
  91. package/dest/test/delayed_tx_utils.d.ts.map +0 -1
  92. package/dest/test/delayed_tx_utils.js +0 -28
  93. package/dest/test/tx_delayer.d.ts +0 -36
  94. package/dest/test/tx_delayer.d.ts.map +0 -1
  95. package/src/l1_tx_utils/l1_tx_utils_with_blobs.ts +0 -77
  96. package/src/test/delayed_tx_utils.ts +0 -52
@@ -34,12 +34,25 @@ export class FeeAssetPriceOracle {
34
34
 
35
35
  @memoize
36
36
  async getUniswapOracle(): Promise<UniswapPriceOracle | undefined> {
37
- if ((await this.client.getCode({ address: STATE_VIEW_ADDRESS.toString() })) === '0x') {
37
+ const code = await this.client.getCode({ address: STATE_VIEW_ADDRESS.toString() });
38
+ if (code === undefined || code === '0x') {
38
39
  this.log.warn('Uniswap V4 StateView contract not found, skipping fee asset price oracle');
39
40
  return undefined;
40
41
  }
41
42
  this.log.info('Uniswap V4 StateView contract found, initializing fee asset price oracle');
42
- return new UniswapPriceOracle(this.client, this.log);
43
+ const oracle = new UniswapPriceOracle(this.client, this.log);
44
+
45
+ try {
46
+ if (!(await oracle.isPoolInitialized())) {
47
+ this.log.warn('Uniswap V4 pool not initialized, skipping fee asset price oracle');
48
+ return undefined;
49
+ }
50
+ } catch (err) {
51
+ this.log.warn(`Failed to check if Uniswap V4 pool is initialized: ${err}`);
52
+ return undefined;
53
+ }
54
+
55
+ return oracle;
43
56
  }
44
57
 
45
58
  /**
@@ -210,6 +223,11 @@ class UniswapPriceOracle {
210
223
  return keccak256(encoded);
211
224
  }
212
225
 
226
+ async isPoolInitialized(): Promise<boolean> {
227
+ const [sqrtPriceX96] = await this.stateView.read.getSlot0([this.poolId], undefined);
228
+ return sqrtPriceX96 !== 0n;
229
+ }
230
+
213
231
  /**
214
232
  * Gets the price as ETH per FeeAsset, scaled by 1e12.
215
233
  * This is the format expected by the rollup contract.
@@ -14,7 +14,7 @@ import {
14
14
  } from 'viem';
15
15
 
16
16
  import type { L1ContractAddresses } from '../l1_contract_addresses.js';
17
- import { createL1TxUtilsFromViemWallet } from '../l1_tx_utils/index.js';
17
+ import { createL1TxUtils } from '../l1_tx_utils/index.js';
18
18
  import { type ExtendedViemWalletClient, type ViemClient, isExtendedClient } from '../types.js';
19
19
 
20
20
  export type L1GovernanceContractAddresses = Pick<
@@ -194,7 +194,7 @@ export class GovernanceContract extends ReadOnlyGovernanceContract {
194
194
  retries: number;
195
195
  logger: Logger;
196
196
  }) {
197
- const l1TxUtils = createL1TxUtilsFromViemWallet(this.client, { logger });
197
+ const l1TxUtils = createL1TxUtils(this.client, { logger });
198
198
  const retryDelaySeconds = 12;
199
199
 
200
200
  voteAmount = voteAmount ?? (await this.getPowerForProposal(proposalId));
@@ -252,7 +252,7 @@ export class GovernanceContract extends ReadOnlyGovernanceContract {
252
252
  retries: number;
253
253
  logger: Logger;
254
254
  }) {
255
- const l1TxUtils = createL1TxUtilsFromViemWallet(this.client, { logger });
255
+ const l1TxUtils = createL1TxUtils(this.client, { logger });
256
256
  const retryDelaySeconds = 12;
257
257
  let success = false;
258
258
  for (let i = 0; i < retries; i++) {
@@ -110,6 +110,12 @@ export class GovernanceProposerContract implements IEmpireBase {
110
110
  };
111
111
  }
112
112
 
113
+ /** Checks if a payload was ever submitted to governance via submitRoundWinner. */
114
+ public async hasPayloadBeenProposed(payload: Hex, fromBlock: bigint): Promise<boolean> {
115
+ const events = await this.proposer.getEvents.PayloadSubmitted({ payload }, { fromBlock, strict: true });
116
+ return events.length > 0;
117
+ }
118
+
113
119
  public async submitRoundWinner(
114
120
  round: bigint,
115
121
  l1TxUtils: L1TxUtils,
@@ -3,7 +3,7 @@ import { createLogger } from '@aztec/foundation/log';
3
3
  import { RegistryAbi } from '@aztec/l1-artifacts/RegistryAbi';
4
4
  import { TestERC20Abi } from '@aztec/l1-artifacts/TestERC20Abi';
5
5
 
6
- import { type GetContractReturnType, type Hex, getContract } from 'viem';
6
+ import { type GetContractReturnType, type Hex, getAbiItem, getContract } from 'viem';
7
7
 
8
8
  import type { L1ContractAddresses } from '../l1_contract_addresses.js';
9
9
  import type { ViemClient } from '../types.js';
@@ -128,4 +128,34 @@ export class RegistryContract {
128
128
  public async getRewardDistributor(): Promise<EthAddress> {
129
129
  return EthAddress.fromString(await this.registry.read.getRewardDistributor());
130
130
  }
131
+
132
+ /** Returns the L1 timestamp at which the given rollup was registered via addRollup(). */
133
+ public async getCanonicalRollupRegistrationTimestamp(
134
+ rollupAddress: EthAddress,
135
+ fromBlock?: bigint,
136
+ ): Promise<bigint | undefined> {
137
+ const event = getAbiItem({ abi: RegistryAbi, name: 'CanonicalRollupUpdated' });
138
+ const start = fromBlock ?? 0n;
139
+ const latestBlock = await this.client.getBlockNumber();
140
+ const chunkSize = 1_000n;
141
+
142
+ for (let from = start; from <= latestBlock; from += chunkSize) {
143
+ const to = from + chunkSize - 1n > latestBlock ? latestBlock : from + chunkSize - 1n;
144
+ const logs = await this.client.getLogs({
145
+ address: this.address.toString(),
146
+ fromBlock: from,
147
+ toBlock: to,
148
+ strict: true,
149
+ event,
150
+ args: { instance: rollupAddress.toString() },
151
+ });
152
+
153
+ if (logs.length > 0) {
154
+ const block = await this.client.getBlock({ blockNumber: logs[0].blockNumber });
155
+ return block.timestamp;
156
+ }
157
+ }
158
+
159
+ return undefined;
160
+ }
131
161
  }
@@ -193,10 +193,10 @@ export type CheckpointProposedArgs = {
193
193
  checkpointNumber: CheckpointNumber;
194
194
  archive: Fr;
195
195
  versionedBlobHashes: Buffer[];
196
- /** Hash of attestations. Undefined for older events (backwards compatibility). */
197
- attestationsHash?: Buffer32;
198
- /** Digest of the payload. Undefined for older events (backwards compatibility). */
199
- payloadDigest?: Buffer32;
196
+ /** Hash of attestations emitted in the CheckpointProposed event. */
197
+ attestationsHash: Buffer32;
198
+ /** Digest of the payload emitted in the CheckpointProposed event. */
199
+ payloadDigest: Buffer32;
200
200
  };
201
201
 
202
202
  /** Log type for CheckpointProposed events. */
@@ -392,16 +392,25 @@ export class RollupContract {
392
392
  epochDuration: number;
393
393
  proofSubmissionEpochs: number;
394
394
  targetCommitteeSize: number;
395
+ rollupManaLimit: number;
395
396
  }> {
396
- const [l1StartBlock, l1GenesisTime, slotDuration, epochDuration, proofSubmissionEpochs, targetCommitteeSize] =
397
- await Promise.all([
398
- this.getL1StartBlock(),
399
- this.getL1GenesisTime(),
400
- this.getSlotDuration(),
401
- this.getEpochDuration(),
402
- this.getProofSubmissionEpochs(),
403
- this.getTargetCommitteeSize(),
404
- ]);
397
+ const [
398
+ l1StartBlock,
399
+ l1GenesisTime,
400
+ slotDuration,
401
+ epochDuration,
402
+ proofSubmissionEpochs,
403
+ targetCommitteeSize,
404
+ rollupManaLimit,
405
+ ] = await Promise.all([
406
+ this.getL1StartBlock(),
407
+ this.getL1GenesisTime(),
408
+ this.getSlotDuration(),
409
+ this.getEpochDuration(),
410
+ this.getProofSubmissionEpochs(),
411
+ this.getTargetCommitteeSize(),
412
+ this.getManaLimit(),
413
+ ]);
405
414
  return {
406
415
  l1StartBlock,
407
416
  l1GenesisTime,
@@ -409,6 +418,7 @@ export class RollupContract {
409
418
  epochDuration: Number(epochDuration),
410
419
  proofSubmissionEpochs: Number(proofSubmissionEpochs),
411
420
  targetCommitteeSize,
421
+ rollupManaLimit: Number(rollupManaLimit),
412
422
  };
413
423
  }
414
424
 
@@ -503,8 +513,9 @@ export class RollupContract {
503
513
  return CheckpointNumber.fromBigInt(await this.rollup.read.getPendingCheckpointNumber());
504
514
  }
505
515
 
506
- async getProvenCheckpointNumber(): Promise<CheckpointNumber> {
507
- return CheckpointNumber.fromBigInt(await this.rollup.read.getProvenCheckpointNumber());
516
+ async getProvenCheckpointNumber(options?: { blockNumber?: bigint }): Promise<CheckpointNumber> {
517
+ await checkBlockTag(options?.blockNumber, this.client);
518
+ return CheckpointNumber.fromBigInt(await this.rollup.read.getProvenCheckpointNumber(options));
508
519
  }
509
520
 
510
521
  async getSlotNumber(): Promise<SlotNumber> {
@@ -1060,8 +1071,22 @@ export class RollupContract {
1060
1071
  checkpointNumber: CheckpointNumber.fromBigInt(log.args.checkpointNumber!),
1061
1072
  archive: Fr.fromString(log.args.archive!),
1062
1073
  versionedBlobHashes: log.args.versionedBlobHashes!.map(h => Buffer.from(h.slice(2), 'hex')),
1063
- attestationsHash: log.args.attestationsHash ? Buffer32.fromString(log.args.attestationsHash) : undefined,
1064
- payloadDigest: log.args.payloadDigest ? Buffer32.fromString(log.args.payloadDigest) : undefined,
1074
+ attestationsHash: (() => {
1075
+ if (!log.args.attestationsHash) {
1076
+ throw new Error(
1077
+ `CheckpointProposed event missing attestationsHash for checkpoint ${log.args.checkpointNumber}`,
1078
+ );
1079
+ }
1080
+ return Buffer32.fromString(log.args.attestationsHash);
1081
+ })(),
1082
+ payloadDigest: (() => {
1083
+ if (!log.args.payloadDigest) {
1084
+ throw new Error(
1085
+ `CheckpointProposed event missing payloadDigest for checkpoint ${log.args.checkpointNumber}`,
1086
+ );
1087
+ }
1088
+ return Buffer32.fromString(log.args.payloadDigest);
1089
+ })(),
1065
1090
  },
1066
1091
  }));
1067
1092
  }
@@ -23,7 +23,6 @@ import type { L1ContractsConfig } from './config.js';
23
23
  import { deployMulticall3 } from './contracts/multicall.js';
24
24
  import { RollupContract } from './contracts/rollup.js';
25
25
  import type { L1ContractAddresses } from './l1_contract_addresses.js';
26
- import type { L1TxUtilsConfig } from './l1_tx_utils/config.js';
27
26
  import type { ExtendedViemWalletClient } from './types.js';
28
27
 
29
28
  const logger = createLogger('ethereum:deploy_aztec_l1_contracts');
@@ -491,7 +490,25 @@ export type VerificationRecord = {
491
490
  libraries: VerificationLibraryEntry[];
492
491
  };
493
492
 
494
- export interface DeployAztecL1ContractsArgs extends Omit<L1ContractsConfig, keyof L1TxUtilsConfig> {
493
+ export interface DeployAztecL1ContractsArgs
494
+ extends Omit<
495
+ L1ContractsConfig,
496
+ | 'gasLimitBufferPercentage'
497
+ | 'maxGwei'
498
+ | 'maxBlobGwei'
499
+ | 'priorityFeeBumpPercentage'
500
+ | 'priorityFeeRetryBumpPercentage'
501
+ | 'minimumPriorityFeePerGas'
502
+ | 'maxSpeedUpAttempts'
503
+ | 'checkIntervalMs'
504
+ | 'stallTimeMs'
505
+ | 'txTimeoutMs'
506
+ | 'cancelTxOnTimeout'
507
+ | 'txCancellationFinalTimeoutMs'
508
+ | 'txUnseenConsideredDroppedMs'
509
+ | 'enableDelayer'
510
+ | 'txDelayerMaxInclusionTimeIntoSlot'
511
+ > {
495
512
  /** The vk tree root. */
496
513
  vkTreeRoot: Fr;
497
514
  /** The hash of the protocol contracts. */
@@ -24,7 +24,7 @@ import {
24
24
  } from './deploy_aztec_l1_contracts.js';
25
25
  import { RegisterNewRollupVersionPayloadArtifact } from './l1_artifacts.js';
26
26
  import { type L1TxUtilsConfig, getL1TxUtilsConfigEnvVars } from './l1_tx_utils/config.js';
27
- import { createL1TxUtilsFromViemWallet } from './l1_tx_utils/factory.js';
27
+ import { createL1TxUtils } from './l1_tx_utils/factory.js';
28
28
  import type { L1TxUtils } from './l1_tx_utils/l1_tx_utils.js';
29
29
  import type { GasPrice, L1TxConfig, L1TxRequest } from './l1_tx_utils/types.js';
30
30
  import type { ExtendedViemWalletClient } from './types.js';
@@ -46,7 +46,7 @@ export class L1Deployer {
46
46
  private createVerificationJson: boolean = false,
47
47
  ) {
48
48
  this.salt = maybeSalt ? padHex(numberToHex(maybeSalt), { size: 32 }) : undefined;
49
- this.l1TxUtils = createL1TxUtilsFromViemWallet(
49
+ this.l1TxUtils = createL1TxUtils(
50
50
  this.client,
51
51
  { logger: this.logger, dateProvider },
52
52
  { ...this.txUtilsConfig, debugMaxGasLimit: acceleratedTestDeployments },
@@ -179,7 +179,7 @@ export async function deployL1Contract(
179
179
 
180
180
  if (!l1TxUtils) {
181
181
  const config = getL1TxUtilsConfigEnvVars();
182
- l1TxUtils = createL1TxUtilsFromViemWallet(
182
+ l1TxUtils = createL1TxUtils(
183
183
  extendedClient,
184
184
  { logger },
185
185
  { ...config, debugMaxGasLimit: acceleratedTestDeployments },
@@ -4,7 +4,7 @@
4
4
  /** Default L1 contracts configuration values from network-defaults.yml */
5
5
  export const l1ContractsDefaultEnv = {
6
6
  ETHEREUM_SLOT_DURATION: 12,
7
- AZTEC_SLOT_DURATION: 36,
7
+ AZTEC_SLOT_DURATION: 72,
8
8
  AZTEC_EPOCH_DURATION: 32,
9
9
  AZTEC_TARGET_COMMITTEE_SIZE: 48,
10
10
  AZTEC_LAG_IN_EPOCHS_FOR_VALIDATOR_SET: 2,
@@ -5,6 +5,7 @@ import {
5
5
  getConfigFromMappings,
6
6
  getDefaultConfig,
7
7
  numberConfigHelper,
8
+ optionalNumberConfigHelper,
8
9
  } from '@aztec/foundation/config';
9
10
 
10
11
  export interface L1TxUtilsConfig {
@@ -60,6 +61,12 @@ export interface L1TxUtilsConfig {
60
61
  * How long a tx nonce can be unseen in the mempool before considering it dropped
61
62
  */
62
63
  txUnseenConsideredDroppedMs?: number;
64
+ /** Enable tx delayer. When true, wraps the viem client to intercept and delay txs. Test-only. */
65
+ enableDelayer?: boolean;
66
+ /** Max seconds into an L1 slot for tx inclusion. Txs sent later are deferred to next slot. Only used when enableDelayer is true. */
67
+ txDelayerMaxInclusionTimeIntoSlot?: number;
68
+ /** How many seconds an L1 slot lasts. */
69
+ ethereumSlotDuration?: number;
63
70
  }
64
71
 
65
72
  export const l1TxUtilsConfigMappings: ConfigMappingsType<L1TxUtilsConfig> = {
@@ -142,6 +149,19 @@ export const l1TxUtilsConfigMappings: ConfigMappingsType<L1TxUtilsConfig> = {
142
149
  env: 'L1_TX_MONITOR_TX_UNSEEN_CONSIDERED_DROPPED_MS',
143
150
  ...numberConfigHelper(6 * 12 * 1000), // 6 L1 blocks
144
151
  },
152
+ enableDelayer: {
153
+ description: 'Enable tx delayer for testing.',
154
+ ...booleanConfigHelper(false),
155
+ },
156
+ txDelayerMaxInclusionTimeIntoSlot: {
157
+ description: 'Max seconds into L1 slot for tx inclusion when delayer is enabled.',
158
+ ...optionalNumberConfigHelper(),
159
+ },
160
+ ethereumSlotDuration: {
161
+ env: 'ETHEREUM_SLOT_DURATION',
162
+ description: 'How many seconds an L1 slot lasts.',
163
+ ...numberConfigHelper(12),
164
+ },
145
165
  };
146
166
 
147
167
  // We abuse the fact that all mappings above have a non null default value and force-type this to Required
@@ -1,64 +1,64 @@
1
+ import type { BlobKzgInstance } from '@aztec/blob-lib/types';
1
2
  import { EthAddress } from '@aztec/foundation/eth-address';
2
3
  import type { Logger } from '@aztec/foundation/log';
3
4
  import { DateProvider } from '@aztec/foundation/timer';
4
5
 
5
- import type { TransactionSerializable } from 'viem';
6
-
7
6
  import type { EthSigner } from '../eth-signer/eth-signer.js';
8
7
  import type { ExtendedViemWalletClient, ViemClient } from '../types.js';
9
8
  import type { L1TxUtilsConfig } from './config.js';
10
9
  import type { IL1TxMetrics, IL1TxStore } from './interfaces.js';
11
10
  import { L1TxUtils } from './l1_tx_utils.js';
12
11
  import { createViemSigner } from './signer.js';
12
+ import { Delayer } from './tx_delayer.js';
13
13
  import type { SigningCallback } from './types.js';
14
14
 
15
- export function createL1TxUtilsFromViemWallet(
16
- client: ExtendedViemWalletClient,
17
- deps?: {
18
- logger?: Logger;
19
- dateProvider?: DateProvider;
20
- store?: IL1TxStore;
21
- metrics?: IL1TxMetrics;
22
- },
23
- config?: Partial<L1TxUtilsConfig> & { debugMaxGasLimit?: boolean },
24
- ): L1TxUtils {
25
- return new L1TxUtils(
15
+ /** Source of signing capability: either a wallet client or a separate client + signer. */
16
+ export type L1SignerSource = ExtendedViemWalletClient | { client: ViemClient; signer: EthSigner };
17
+
18
+ export function resolveSignerSource(source: L1SignerSource): {
19
+ client: ViemClient;
20
+ address: EthAddress;
21
+ signingCallback: SigningCallback;
22
+ } {
23
+ if ('account' in source && source.account) {
24
+ return {
25
+ client: source as ExtendedViemWalletClient,
26
+ address: EthAddress.fromString((source as ExtendedViemWalletClient).account.address),
27
+ signingCallback: createViemSigner(source as ExtendedViemWalletClient),
28
+ };
29
+ }
30
+ const { client, signer } = source as { client: ViemClient; signer: EthSigner };
31
+ return {
26
32
  client,
27
- EthAddress.fromString(client.account.address),
28
- createViemSigner(client),
29
- deps?.logger,
30
- deps?.dateProvider,
31
- config,
32
- config?.debugMaxGasLimit ?? false,
33
- deps?.store,
34
- deps?.metrics,
35
- );
33
+ address: signer.address,
34
+ signingCallback: async (tx, _addr) => (await signer.signTransaction(tx)).toViemTransactionSignature(),
35
+ };
36
36
  }
37
37
 
38
- export function createL1TxUtilsFromEthSigner(
39
- client: ViemClient,
40
- signer: EthSigner,
38
+ export function createL1TxUtils(
39
+ source: L1SignerSource,
41
40
  deps?: {
42
41
  logger?: Logger;
43
42
  dateProvider?: DateProvider;
44
43
  store?: IL1TxStore;
45
44
  metrics?: IL1TxMetrics;
45
+ kzg?: BlobKzgInstance;
46
+ delayer?: Delayer;
46
47
  },
47
48
  config?: Partial<L1TxUtilsConfig> & { debugMaxGasLimit?: boolean },
48
49
  ): L1TxUtils {
49
- const callback: SigningCallback = async (transaction: TransactionSerializable, _signingAddress) => {
50
- return (await signer.signTransaction(transaction)).toViemTransactionSignature();
51
- };
52
-
50
+ const { client, address, signingCallback } = resolveSignerSource(source);
53
51
  return new L1TxUtils(
54
52
  client,
55
- signer.address,
56
- callback,
53
+ address,
54
+ signingCallback,
57
55
  deps?.logger,
58
56
  deps?.dateProvider,
59
57
  config,
60
58
  config?.debugMaxGasLimit ?? false,
61
59
  deps?.store,
62
60
  deps?.metrics,
61
+ deps?.kzg,
62
+ deps?.delayer,
63
63
  );
64
64
  }
@@ -1,25 +1,27 @@
1
+ import type { BlobKzgInstance } from '@aztec/blob-lib/types';
1
2
  import { EthAddress } from '@aztec/foundation/eth-address';
2
3
  import type { Logger } from '@aztec/foundation/log';
3
4
  import type { DateProvider } from '@aztec/foundation/timer';
4
5
 
5
6
  import { type Hex, encodeFunctionData } from 'viem';
6
7
 
7
- import type { EthSigner } from '../eth-signer/eth-signer.js';
8
8
  import { FORWARDER_ABI } from '../forwarder_proxy.js';
9
- import type { ExtendedViemWalletClient, ViemClient } from '../types.js';
9
+ import type { ViemClient } from '../types.js';
10
10
  import type { L1TxUtilsConfig } from './config.js';
11
+ import type { L1SignerSource } from './factory.js';
12
+ import { resolveSignerSource } from './factory.js';
11
13
  import type { IL1TxMetrics, IL1TxStore } from './interfaces.js';
12
- import { L1TxUtilsWithBlobs } from './l1_tx_utils_with_blobs.js';
13
- import { createViemSigner } from './signer.js';
14
+ import { L1TxUtils } from './l1_tx_utils.js';
15
+ import { Delayer } from './tx_delayer.js';
14
16
  import type { L1BlobInputs, L1TxConfig, L1TxRequest, SigningCallback } from './types.js';
15
17
 
16
18
  /**
17
- * Extends L1TxUtilsWithBlobs to wrap all transactions through a forwarder contract.
19
+ * Extends L1TxUtils to wrap all transactions through a forwarder contract.
18
20
  * This is mainly used for testing the archiver's ability to decode transactions that go through proxies.
19
21
  */
20
- export class ForwarderL1TxUtils extends L1TxUtilsWithBlobs {
22
+ export class ForwarderL1TxUtils extends L1TxUtils {
21
23
  constructor(
22
- client: ViemClient | ExtendedViemWalletClient,
24
+ client: ViemClient,
23
25
  senderAddress: EthAddress,
24
26
  signingCallback: SigningCallback,
25
27
  logger: Logger | undefined,
@@ -28,9 +30,23 @@ export class ForwarderL1TxUtils extends L1TxUtilsWithBlobs {
28
30
  debugMaxGasLimit: boolean,
29
31
  store: IL1TxStore | undefined,
30
32
  metrics: IL1TxMetrics | undefined,
33
+ kzg: BlobKzgInstance | undefined,
34
+ delayer: Delayer | undefined,
31
35
  private readonly forwarderAddress: EthAddress,
32
36
  ) {
33
- super(client, senderAddress, signingCallback, logger, dateProvider, config, debugMaxGasLimit, store, metrics);
37
+ super(
38
+ client,
39
+ senderAddress,
40
+ signingCallback,
41
+ logger,
42
+ dateProvider,
43
+ config,
44
+ debugMaxGasLimit,
45
+ store,
46
+ metrics,
47
+ kzg,
48
+ delayer,
49
+ );
34
50
  }
35
51
 
36
52
  /**
@@ -61,59 +77,32 @@ export class ForwarderL1TxUtils extends L1TxUtilsWithBlobs {
61
77
  }
62
78
  }
63
79
 
64
- export function createForwarderL1TxUtilsFromViemWallet(
65
- client: ExtendedViemWalletClient,
80
+ export function createForwarderL1TxUtils(
81
+ source: L1SignerSource,
66
82
  forwarderAddress: EthAddress,
67
- deps: {
83
+ deps?: {
68
84
  logger?: Logger;
69
85
  dateProvider?: DateProvider;
70
86
  store?: IL1TxStore;
71
87
  metrics?: IL1TxMetrics;
72
- } = {},
73
- config: Partial<L1TxUtilsConfig> = {},
74
- debugMaxGasLimit: boolean = false,
75
- ) {
88
+ kzg?: BlobKzgInstance;
89
+ delayer?: Delayer;
90
+ },
91
+ config?: Partial<L1TxUtilsConfig> & { debugMaxGasLimit?: boolean },
92
+ ): ForwarderL1TxUtils {
93
+ const { client, address, signingCallback } = resolveSignerSource(source);
76
94
  return new ForwarderL1TxUtils(
77
95
  client,
78
- EthAddress.fromString(client.account.address),
79
- createViemSigner(client),
80
- deps.logger,
81
- deps.dateProvider,
82
- config,
83
- debugMaxGasLimit,
84
- deps.store,
85
- deps.metrics,
86
- forwarderAddress,
87
- );
88
- }
89
-
90
- export function createForwarderL1TxUtilsFromEthSigner(
91
- client: ViemClient,
92
- signer: EthSigner,
93
- forwarderAddress: EthAddress,
94
- deps: {
95
- logger?: Logger;
96
- dateProvider?: DateProvider;
97
- store?: IL1TxStore;
98
- metrics?: IL1TxMetrics;
99
- } = {},
100
- config: Partial<L1TxUtilsConfig> = {},
101
- debugMaxGasLimit: boolean = false,
102
- ) {
103
- const callback: SigningCallback = async (transaction, _signingAddress) => {
104
- return (await signer.signTransaction(transaction)).toViemTransactionSignature();
105
- };
106
-
107
- return new ForwarderL1TxUtils(
108
- client,
109
- signer.address,
110
- callback,
111
- deps.logger,
112
- deps.dateProvider,
113
- config,
114
- debugMaxGasLimit,
115
- deps.store,
116
- deps.metrics,
96
+ address,
97
+ signingCallback,
98
+ deps?.logger,
99
+ deps?.dateProvider,
100
+ config ?? {},
101
+ config?.debugMaxGasLimit ?? false,
102
+ deps?.store,
103
+ deps?.metrics,
104
+ deps?.kzg,
105
+ deps?.delayer,
117
106
  forwarderAddress,
118
107
  );
119
108
  }
@@ -1,2 +1,2 @@
1
- export * from './forwarder_l1_tx_utils.js';
2
- export * from './l1_tx_utils_with_blobs.js';
1
+ export { createForwarderL1TxUtils, ForwarderL1TxUtils } from './forwarder_l1_tx_utils.js';
2
+ export { createL1TxUtils, type L1SignerSource, resolveSignerSource } from './factory.js';
@@ -8,6 +8,7 @@ export * from './l1_tx_utils.js';
8
8
  export * from './readonly_l1_tx_utils.js';
9
9
  export * from './signer.js';
10
10
  export * from './types.js';
11
+ export * from './tx_delayer.js';
11
12
  export * from './utils.js';
12
13
 
13
14
  // Note: We intentionally do not export l1_tx_utils_with_blobs.js