@aztec/bot 0.0.1-commit.2448fdb → 0.0.1-commit.2606882

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dest/factory.js CHANGED
@@ -7,6 +7,7 @@ import { deriveKeys } from '@aztec/aztec.js/keys';
7
7
  import { createLogger } from '@aztec/aztec.js/log';
8
8
  import { waitForL1ToL2MessageReady } from '@aztec/aztec.js/messaging';
9
9
  import { waitForTx } from '@aztec/aztec.js/node';
10
+ import { getFeeJuiceBalance } from '@aztec/aztec.js/utils';
10
11
  import { ContractInitializationStatus } from '@aztec/aztec.js/wallet';
11
12
  import { createEthereumChain } from '@aztec/ethereum/chain';
12
13
  import { createExtendedL1Client } from '@aztec/ethereum/client';
@@ -18,12 +19,15 @@ import { AMMContract } from '@aztec/noir-contracts.js/AMM';
18
19
  import { PrivateTokenContract } from '@aztec/noir-contracts.js/PrivateToken';
19
20
  import { TokenContract } from '@aztec/noir-contracts.js/Token';
20
21
  import { TestContract } from '@aztec/noir-test-contracts.js/Test';
22
+ import { GasFees, GasSettings, ManaUsageEstimate } from '@aztec/stdlib/gas';
21
23
  import { deriveSigningKey } from '@aztec/stdlib/keys';
22
24
  import { SupportedTokenContracts } from './config.js';
23
25
  import { seedL1ToL2Message } from './l1_to_l2_seeding.js';
24
26
  import { getBalances, getPrivateBalance, isStandardTokenContract } from './utils.js';
25
27
  const MINT_BALANCE = 1e12;
26
28
  const MIN_BALANCE = 1e3;
29
+ const FEE_JUICE_TOP_UP_THRESHOLD = 100n * 10n ** 18n;
30
+ const FEE_JUICE_TOP_UP_TARGET = 10_000n * 10n ** 18n;
27
31
  export class BotFactory {
28
32
  config;
29
33
  wallet;
@@ -48,7 +52,8 @@ export class BotFactory {
48
52
  */ async setup() {
49
53
  const defaultAccountAddress = await this.setupAccount();
50
54
  const recipient = (await this.wallet.createSchnorrAccount(Fr.random(), Fr.random())).address;
51
- const token = await this.setupToken(defaultAccountAddress);
55
+ const token = await this.setupTokenWithOptionalEarlyRefuel(defaultAccountAddress);
56
+ await this.ensureFeeJuiceBalance(defaultAccountAddress, token);
52
57
  await this.mintTokens(token, defaultAccountAddress);
53
58
  return {
54
59
  wallet: this.wallet,
@@ -60,7 +65,8 @@ export class BotFactory {
60
65
  }
61
66
  async setupAmm() {
62
67
  const defaultAccountAddress = await this.setupAccount();
63
- const token0 = await this.setupTokenContract(defaultAccountAddress, this.config.tokenSalt, 'BotToken0', 'BOT0');
68
+ const token0 = await this.setupTokenContractWithOptionalEarlyRefuel(defaultAccountAddress, this.config.tokenSalt, 'BotToken0', 'BOT0');
69
+ await this.ensureFeeJuiceBalance(defaultAccountAddress, token0);
64
70
  const token1 = await this.setupTokenContract(defaultAccountAddress, this.config.tokenSalt, 'BotToken1', 'BOT1');
65
71
  const liquidityToken = await this.setupTokenContract(defaultAccountAddress, this.config.tokenSalt, 'BotLPToken', 'BOTLP');
66
72
  const amm = await this.setupAmmContract(defaultAccountAddress, this.config.tokenSalt, token0, token1, liquidityToken);
@@ -126,11 +132,12 @@ export class BotFactory {
126
132
  }
127
133
  async setupTestContract(deployer) {
128
134
  const deployOpts = {
129
- from: deployer,
130
- contractAddressSalt: this.config.tokenSalt,
131
- universalDeploy: true
135
+ from: deployer
132
136
  };
133
- const deploy = TestContract.deploy(this.wallet);
137
+ const deploy = TestContract.deploy(this.wallet, {
138
+ salt: this.config.tokenSalt,
139
+ universalDeploy: true
140
+ });
134
141
  const instance = await this.registerOrDeployContract('TestContract', deploy, deployOpts);
135
142
  return TestContract.at(instance.address, this.wallet);
136
143
  }
@@ -190,32 +197,92 @@ export class BotFactory {
190
197
  return accountManager.address;
191
198
  }
192
199
  /**
200
+ * Setup token and refuel first: if the token already exists (restart scenario),
201
+ * run ensureFeeJuiceBalance before any step that might need fee juice. When deploying,
202
+ * use a bridge claim if balance is below threshold.
203
+ */ async setupTokenWithOptionalEarlyRefuel(sender) {
204
+ const token = await this.getTokenInstance(sender);
205
+ const address = token.address;
206
+ const metadata = await this.wallet.getContractMetadata(address);
207
+ if (metadata.isContractPublished) {
208
+ this.log.info(`Token at ${address.toString()} already deployed, refueling before setup`);
209
+ await this.ensureFeeJuiceBalance(sender, token);
210
+ }
211
+ return this.setupToken(sender);
212
+ }
213
+ /**
214
+ * Setup token0 for AMM with refuel-first behaviour when token already exists.
215
+ */ async setupTokenContractWithOptionalEarlyRefuel(deployer, salt, name, ticker, decimals = 18) {
216
+ const deploy = TokenContract.deploy(this.wallet, deployer, name, ticker, decimals, {
217
+ salt,
218
+ universalDeploy: true
219
+ });
220
+ const instance = await deploy.getInstance();
221
+ const metadata = await this.wallet.getContractMetadata(instance.address);
222
+ if (metadata.isContractPublished) {
223
+ this.log.info(`Token ${name} at ${instance.address.toString()} already deployed, refueling before setup`);
224
+ const token = TokenContract.at(instance.address, this.wallet);
225
+ await this.ensureFeeJuiceBalance(deployer, token);
226
+ }
227
+ return this.setupTokenContract(deployer, salt, name, ticker, decimals);
228
+ }
229
+ async getTokenInstance(sender) {
230
+ const salt = this.config.tokenSalt;
231
+ if (this.config.contract === SupportedTokenContracts.TokenContract) {
232
+ const deploy = TokenContract.deploy(this.wallet, sender, 'BotToken', 'BOT', 18, {
233
+ salt,
234
+ universalDeploy: true
235
+ });
236
+ const instance = await deploy.getInstance();
237
+ return TokenContract.at(instance.address, this.wallet);
238
+ }
239
+ if (this.config.contract === SupportedTokenContracts.PrivateTokenContract) {
240
+ const tokenSecretKey = Fr.random();
241
+ const tokenPublicKeys = (await deriveKeys(tokenSecretKey)).publicKeys;
242
+ const deploy = PrivateTokenContract.deploy(this.wallet, MINT_BALANCE, sender, {
243
+ salt,
244
+ universalDeploy: true,
245
+ publicKeys: tokenPublicKeys
246
+ });
247
+ const instance = await deploy.getInstance();
248
+ return PrivateTokenContract.at(instance.address, this.wallet);
249
+ }
250
+ throw new Error(`Unsupported token contract type: ${this.config.contract}`);
251
+ }
252
+ /**
193
253
  * Checks if the token contract is deployed and deploys it if necessary.
194
- * @param wallet - Wallet to deploy the token contract from.
195
- * @returns The TokenContract instance.
254
+ * Uses a bridge claim for deploy when balance is below threshold to avoid failing before refuel.
255
+ * @param sender - Aztec address to deploy the token contract from.
256
+ * @param existingToken - Optional token instance when called from setupTokenWithOptionalEarlyRefuel.
257
+ * @returns The TokenContract or PrivateTokenContract instance.
196
258
  */ async setupToken(sender) {
197
259
  let deploy;
198
- let tokenInstance;
260
+ const salt = this.config.tokenSalt;
199
261
  const deployOpts = {
200
- from: sender,
201
- contractAddressSalt: this.config.tokenSalt,
202
- universalDeploy: true
262
+ from: sender
203
263
  };
204
264
  let token;
205
265
  if (this.config.contract === SupportedTokenContracts.TokenContract) {
206
- deploy = TokenContract.deploy(this.wallet, sender, 'BotToken', 'BOT', 18);
207
- tokenInstance = await deploy.getInstance(deployOpts);
208
- token = TokenContract.at(tokenInstance.address, this.wallet);
266
+ deploy = TokenContract.deploy(this.wallet, sender, 'BotToken', 'BOT', 18, {
267
+ salt,
268
+ universalDeploy: true
269
+ });
270
+ const instance = await deploy.getInstance();
271
+ token = TokenContract.at(instance.address, this.wallet);
209
272
  } else if (this.config.contract === SupportedTokenContracts.PrivateTokenContract) {
210
273
  // Generate keys for the contract since PrivateToken uses SinglePrivateMutable which requires keys
211
274
  const tokenSecretKey = Fr.random();
212
275
  const tokenPublicKeys = (await deriveKeys(tokenSecretKey)).publicKeys;
213
- deploy = PrivateTokenContract.deployWithPublicKeys(tokenPublicKeys, this.wallet, MINT_BALANCE, sender);
276
+ deploy = PrivateTokenContract.deploy(this.wallet, MINT_BALANCE, sender, {
277
+ salt,
278
+ universalDeploy: true,
279
+ publicKeys: tokenPublicKeys
280
+ });
214
281
  deployOpts.skipInstancePublication = true;
215
282
  deployOpts.skipClassPublication = true;
216
283
  deployOpts.skipInitialization = false;
217
284
  // Register the contract with the secret key before deployment
218
- tokenInstance = await deploy.getInstance(deployOpts);
285
+ const tokenInstance = await deploy.getInstance();
219
286
  token = PrivateTokenContract.at(tokenInstance.address, this.wallet);
220
287
  await this.wallet.registerContract(tokenInstance, PrivateTokenContract.artifact, tokenSecretKey);
221
288
  // The contract constructor initializes private storage vars that need the contract's own nullifier key.
@@ -225,52 +292,37 @@ export class BotFactory {
225
292
  } else {
226
293
  throw new Error(`Unsupported token contract type: ${this.config.contract}`);
227
294
  }
228
- const address = tokenInstance?.address ?? (await deploy.getInstance(deployOpts)).address;
229
- const metadata = await this.wallet.getContractMetadata(address);
230
- if (metadata.isContractPublished) {
231
- this.log.info(`Token at ${address.toString()} already deployed`);
232
- await deploy.register();
233
- } else {
234
- this.log.info(`Deploying token contract at ${address.toString()}`);
235
- const { txHash } = await deploy.send({
236
- ...deployOpts,
237
- wait: NO_WAIT
238
- });
239
- this.log.info(`Sent tx for token setup with hash ${txHash.toString()}`);
240
- await this.withNoMinTxsPerBlock(async ()=>{
241
- await waitForTx(this.aztecNode, txHash, {
242
- timeout: this.config.txMinedWaitSeconds
243
- });
244
- return token;
245
- });
246
- }
295
+ await this.registerOrDeployContract('token', deploy, deployOpts);
247
296
  return token;
248
297
  }
249
298
  /**
250
299
  * Checks if the token contract is deployed and deploys it if necessary.
251
300
  * @param wallet - Wallet to deploy the token contract from.
252
301
  * @returns The TokenContract instance.
253
- */ async setupTokenContract(deployer, contractAddressSalt, name, ticker, decimals = 18) {
302
+ */ async setupTokenContract(deployer, salt, name, ticker, decimals = 18) {
254
303
  const deployOpts = {
255
- from: deployer,
256
- contractAddressSalt,
257
- universalDeploy: true
304
+ from: deployer
258
305
  };
259
- const deploy = TokenContract.deploy(this.wallet, deployer, name, ticker, decimals);
306
+ const deploy = TokenContract.deploy(this.wallet, deployer, name, ticker, decimals, {
307
+ salt,
308
+ universalDeploy: true
309
+ });
260
310
  const instance = await this.registerOrDeployContract('Token - ' + name, deploy, deployOpts);
261
311
  return TokenContract.at(instance.address, this.wallet);
262
312
  }
263
- async setupAmmContract(deployer, contractAddressSalt, token0, token1, lpToken) {
313
+ async setupAmmContract(deployer, salt, token0, token1, lpToken) {
264
314
  const deployOpts = {
265
- from: deployer,
266
- contractAddressSalt,
267
- universalDeploy: true
315
+ from: deployer
268
316
  };
269
- const deploy = AMMContract.deploy(this.wallet, token0.address, token1.address, lpToken.address);
317
+ const deploy = AMMContract.deploy(this.wallet, token0.address, token1.address, lpToken.address, {
318
+ salt,
319
+ universalDeploy: true
320
+ });
270
321
  const instance = await this.registerOrDeployContract('AMM', deploy, deployOpts);
271
322
  const amm = AMMContract.at(instance.address, this.wallet);
272
323
  this.log.info(`AMM deployed at ${amm.address}`);
273
- const { receipt: minterReceipt } = await lpToken.methods.set_minter(amm.address, true).send({
324
+ const setMinterInteraction = lpToken.methods.set_minter(amm.address, true);
325
+ const { receipt: minterReceipt } = await setMinterInteraction.send({
274
326
  from: deployer,
275
327
  wait: {
276
328
  timeout: this.config.txMinedWaitSeconds
@@ -309,17 +361,19 @@ export class BotFactory {
309
361
  caller: amm.address,
310
362
  call: await token1.methods.transfer_to_public_and_prepare_private_balance_increase(liquidityProvider, amm.address, amount1Max, authwitNonce).getFunctionCall()
311
363
  });
312
- const { receipt: mintReceipt } = await new BatchCall(this.wallet, [
364
+ const mintBatch = new BatchCall(this.wallet, [
313
365
  token0.methods.mint_to_private(liquidityProvider, MINT_BALANCE),
314
366
  token1.methods.mint_to_private(liquidityProvider, MINT_BALANCE)
315
- ]).send({
367
+ ]);
368
+ const { receipt: mintReceipt } = await mintBatch.send({
316
369
  from: liquidityProvider,
317
370
  wait: {
318
371
  timeout: this.config.txMinedWaitSeconds
319
372
  }
320
373
  });
321
374
  this.log.info(`Sent mint tx: ${mintReceipt.txHash.toString()}`);
322
- const { receipt: addLiquidityReceipt } = await amm.methods.add_liquidity(amount0Max, amount1Max, amount0Min, amount1Min, authwitNonce).send({
375
+ const addLiquidityInteraction = amm.methods.add_liquidity(amount0Max, amount1Max, amount0Min, amount1Min, authwitNonce);
376
+ const { receipt: addLiquidityReceipt } = await addLiquidityInteraction.send({
323
377
  from: liquidityProvider,
324
378
  authWitnesses: [
325
379
  token0Authwit,
@@ -335,31 +389,134 @@ export class BotFactory {
335
389
  this.log.info(`Updated private balances of ${defaultAccountAddress} after minting and funding AMM: token0=${newT0Bal}, token1=${newT1Bal}, lp=${newLPBal}`);
336
390
  }
337
391
  async registerOrDeployContract(name, deploy, deployOpts) {
338
- const instance = await deploy.getInstance(deployOpts);
392
+ const instance = await deploy.getInstance();
339
393
  const address = instance.address;
340
394
  const metadata = await this.wallet.getContractMetadata(address);
341
395
  if (metadata.isContractPublished) {
342
396
  this.log.info(`Contract ${name} at ${address.toString()} already deployed`);
343
397
  await deploy.register();
344
398
  } else {
345
- this.log.info(`Deploying contract ${name} at ${address.toString()}`);
346
- await this.withNoMinTxsPerBlock(async ()=>{
347
- const { txHash } = await deploy.send({
399
+ const sender = deployOpts.from === NO_FROM ? undefined : deployOpts.from;
400
+ const balance = sender ? await getFeeJuiceBalance(sender, this.aztecNode) : 0n;
401
+ const useClaim = sender && balance < FEE_JUICE_TOP_UP_THRESHOLD && this.config.feePaymentMethod === 'fee_juice' && !!this.config.l1RpcUrls?.length;
402
+ const mnemonicOrPrivateKey = this.config.l1PrivateKey?.getValue() ?? this.config.l1Mnemonic?.getValue();
403
+ if (useClaim && mnemonicOrPrivateKey) {
404
+ const claim = await this.getOrCreateBridgeClaim(sender);
405
+ const paymentMethod = new FeeJuicePaymentMethodWithClaim(sender, claim);
406
+ const { estimatedGas } = await deploy.simulate({
348
407
  ...deployOpts,
349
- wait: NO_WAIT
408
+ fee: {
409
+ estimateGas: true,
410
+ paymentMethod
411
+ }
350
412
  });
351
- this.log.info(`Sent contract ${name} setup tx with hash ${txHash.toString()}`);
352
- return waitForTx(this.aztecNode, txHash, {
353
- timeout: this.config.txMinedWaitSeconds
413
+ const maxFeesPerGas = (await this.getMinFees()).mul(1 + this.config.minFeePadding);
414
+ const gasSettings = GasSettings.from({
415
+ ...estimatedGas,
416
+ maxFeesPerGas,
417
+ maxPriorityFeesPerGas: GasFees.empty()
354
418
  });
355
- });
419
+ await this.withNoMinTxsPerBlock(async ()=>{
420
+ const { txHash } = await deploy.send({
421
+ ...deployOpts,
422
+ fee: {
423
+ gasSettings,
424
+ paymentMethod
425
+ },
426
+ wait: NO_WAIT
427
+ });
428
+ this.log.info(`Sent contract ${name} deploy tx ${txHash.toString()} (using bridge claim, balance was ${balance})`);
429
+ return waitForTx(this.aztecNode, txHash, {
430
+ timeout: this.config.txMinedWaitSeconds
431
+ });
432
+ });
433
+ await this.store.deleteBridgeClaim(sender);
434
+ } else {
435
+ const { estimatedGas } = await deploy.simulate({
436
+ ...deployOpts,
437
+ fee: {
438
+ estimateGas: true
439
+ }
440
+ });
441
+ this.log.info(`Deploying contract ${name} at ${address.toString()}`, {
442
+ estimatedGas
443
+ });
444
+ await this.withNoMinTxsPerBlock(async ()=>{
445
+ const { txHash } = await deploy.send({
446
+ ...deployOpts,
447
+ fee: {
448
+ gasSettings: estimatedGas
449
+ },
450
+ wait: NO_WAIT
451
+ });
452
+ this.log.info(`Sent contract ${name} setup tx with hash ${txHash.toString()}`);
453
+ return waitForTx(this.aztecNode, txHash, {
454
+ timeout: this.config.txMinedWaitSeconds
455
+ });
456
+ });
457
+ }
356
458
  }
357
459
  return instance;
358
460
  }
359
461
  /**
360
462
  * Mints private and public tokens for the sender if their balance is below the minimum.
361
463
  * @param token - Token contract.
362
- */ async mintTokens(token, minter) {
464
+ */ /**
465
+ * Ensures the account has sufficient fee juice by bridging from L1 if balance is below threshold.
466
+ * Bridges repeatedly until balance reaches the target (10k FJ).
467
+ * Used on startup/restart to top up when the account has run out after previous runs.
468
+ */ async ensureFeeJuiceBalance(account, token) {
469
+ const { feePaymentMethod, l1RpcUrls } = this.config;
470
+ if (feePaymentMethod !== 'fee_juice' || !l1RpcUrls?.length) {
471
+ return;
472
+ }
473
+ const mnemonicOrPrivateKey = this.config.l1PrivateKey?.getValue() ?? this.config.l1Mnemonic?.getValue();
474
+ if (!mnemonicOrPrivateKey) {
475
+ return;
476
+ }
477
+ let balance = await getFeeJuiceBalance(account, this.aztecNode);
478
+ if (balance >= FEE_JUICE_TOP_UP_THRESHOLD) {
479
+ this.log.info(`Fee juice balance ${balance} above threshold ${FEE_JUICE_TOP_UP_THRESHOLD}, skipping top-up`);
480
+ return;
481
+ }
482
+ this.log.info(`Fee juice balance ${balance} below threshold ${FEE_JUICE_TOP_UP_THRESHOLD}, bridging from L1 until ${FEE_JUICE_TOP_UP_TARGET}`);
483
+ const maxFeesPerGas = (await this.getMinFees()).mul(1 + this.config.minFeePadding);
484
+ const minimalInteraction = isStandardTokenContract(token) ? token.methods.transfer_in_public(account, account, 0n, 0) : token.methods.transfer(0n, account, account);
485
+ while(balance < FEE_JUICE_TOP_UP_TARGET){
486
+ const claim = await this.bridgeL1FeeJuice(account);
487
+ const paymentMethod = new FeeJuicePaymentMethodWithClaim(account, claim);
488
+ const { estimatedGas } = await minimalInteraction.simulate({
489
+ from: account,
490
+ fee: {
491
+ estimateGas: true,
492
+ paymentMethod
493
+ }
494
+ });
495
+ const gasSettings = GasSettings.from({
496
+ ...estimatedGas,
497
+ maxFeesPerGas,
498
+ maxPriorityFeesPerGas: GasFees.empty()
499
+ });
500
+ await this.withNoMinTxsPerBlock(async ()=>{
501
+ const { txHash } = await minimalInteraction.send({
502
+ from: account,
503
+ fee: {
504
+ gasSettings,
505
+ paymentMethod
506
+ },
507
+ wait: NO_WAIT
508
+ });
509
+ this.log.info(`Sent fee juice top-up tx ${txHash.toString()}`);
510
+ return waitForTx(this.aztecNode, txHash, {
511
+ timeout: this.config.txMinedWaitSeconds
512
+ });
513
+ });
514
+ balance = await getFeeJuiceBalance(account, this.aztecNode);
515
+ this.log.info(`Fee juice balance after top-up: ${balance}`);
516
+ }
517
+ this.log.info(`Fee juice top-up complete for ${account.toString()}`);
518
+ }
519
+ async mintTokens(token, minter) {
363
520
  const isStandardToken = isStandardTokenContract(token);
364
521
  let privateBalance = 0n;
365
522
  let publicBalance = 0n;
@@ -385,8 +542,9 @@ export class BotFactory {
385
542
  const additionalScopes = isStandardToken ? undefined : [
386
543
  token.address
387
544
  ];
545
+ const mintBatch = new BatchCall(token.wallet, calls);
388
546
  await this.withNoMinTxsPerBlock(async ()=>{
389
- const { txHash } = await new BatchCall(token.wallet, calls).send({
547
+ const { txHash } = await mintBatch.send({
390
548
  from: minter,
391
549
  additionalScopes,
392
550
  wait: NO_WAIT
@@ -443,6 +601,17 @@ export class BotFactory {
443
601
  this.log.info(`Created a claim for ${mintAmount} L1 fee juice to ${recipient}.`, claim);
444
602
  return claim;
445
603
  }
604
+ /** Returns worst-case min fees across predicted slots, with fallback to current min fees. */ async getMinFees() {
605
+ try {
606
+ const predicted = await this.aztecNode.getPredictedMinFees(ManaUsageEstimate.Limit);
607
+ if (predicted.length === 0) {
608
+ return this.aztecNode.getCurrentMinFees();
609
+ }
610
+ return predicted.reduce((worst, fees)=>fees.feePerL2Gas > worst.feePerL2Gas ? fees : worst);
611
+ } catch {
612
+ return this.aztecNode.getCurrentMinFees();
613
+ }
614
+ }
446
615
  async withNoMinTxsPerBlock(fn) {
447
616
  if (!this.aztecNodeAdmin || !this.config.flushSetupTransactions) {
448
617
  this.log.verbose(`No node admin client or flushing not requested (not setting minTxsPerBlock to 0)`);
@@ -4,11 +4,7 @@ import { z } from 'zod';
4
4
  import { type BotConfig } from './config.js';
5
5
  export declare const BotInfoSchema: z.ZodObject<{
6
6
  botAddress: import("@aztec/stdlib/schemas").ZodFor<AztecAddress>;
7
- }, "strip", z.ZodTypeAny, {
8
- botAddress: AztecAddress;
9
- }, {
10
- botAddress?: any;
11
- }>;
7
+ }, z.core.$strip>;
12
8
  export type BotInfo = z.infer<typeof BotInfoSchema>;
13
9
  export interface BotRunnerApi {
14
10
  start(): Promise<void>;
@@ -20,4 +16,4 @@ export interface BotRunnerApi {
20
16
  update(config: BotConfig): Promise<void>;
21
17
  }
22
18
  export declare const BotRunnerApiSchema: ApiSchemaFor<BotRunnerApi>;
23
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW50ZXJmYWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN6RCxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUUxRCxPQUFPLEVBQUUsQ0FBQyxFQUFFLE1BQU0sS0FBSyxDQUFDO0FBRXhCLE9BQU8sRUFBRSxLQUFLLFNBQVMsRUFBbUIsTUFBTSxhQUFhLENBQUM7QUFFOUQsZUFBTyxNQUFNLGFBQWE7Ozs7OztFQUV4QixDQUFDO0FBRUgsTUFBTSxNQUFNLE9BQU8sR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sYUFBYSxDQUFDLENBQUM7QUFFcEQsTUFBTSxXQUFXLFlBQVk7SUFDM0IsS0FBSyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN2QixJQUFJLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3RCLEdBQUcsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDckIsS0FBSyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN2QixTQUFTLElBQUksT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ2hDLE9BQU8sSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDNUIsTUFBTSxDQUFDLE1BQU0sRUFBRSxTQUFTLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0NBQzFDO0FBRUQsZUFBTyxNQUFNLGtCQUFrQixFQUFFLFlBQVksQ0FBQyxZQUFZLENBUXpELENBQUMifQ==
19
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW50ZXJmYWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN6RCxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUUxRCxPQUFPLEVBQUUsQ0FBQyxFQUFFLE1BQU0sS0FBSyxDQUFDO0FBRXhCLE9BQU8sRUFBRSxLQUFLLFNBQVMsRUFBbUIsTUFBTSxhQUFhLENBQUM7QUFFOUQsZUFBTyxNQUFNLGFBQWE7O2lCQUV4QixDQUFDO0FBRUgsTUFBTSxNQUFNLE9BQU8sR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sYUFBYSxDQUFDLENBQUM7QUFFcEQsTUFBTSxXQUFXLFlBQVk7SUFDM0IsS0FBSyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN2QixJQUFJLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3RCLEdBQUcsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDckIsS0FBSyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN2QixTQUFTLElBQUksT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ2hDLE9BQU8sSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDNUIsTUFBTSxDQUFDLE1BQU0sRUFBRSxTQUFTLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0NBQzFDO0FBRUQsZUFBTyxNQUFNLGtCQUFrQixFQUFFLFlBQVksQ0FBQyxZQUFZLENBUXpELENBQUMifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../src/interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,KAAK,SAAS,EAAmB,MAAM,aAAa,CAAC;AAE9D,eAAO,MAAM,aAAa;;;;;;EAExB,CAAC;AAEH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEpD,MAAM,WAAW,YAAY;IAC3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5B,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED,eAAO,MAAM,kBAAkB,EAAE,YAAY,CAAC,YAAY,CAQzD,CAAC"}
1
+ {"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../src/interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,KAAK,SAAS,EAAmB,MAAM,aAAa,CAAC;AAE9D,eAAO,MAAM,aAAa;;iBAExB,CAAC;AAEH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEpD,MAAM,WAAW,YAAY;IAC3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5B,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED,eAAO,MAAM,kBAAkB,EAAE,YAAY,CAAC,YAAY,CAQzD,CAAC"}
package/dest/interface.js CHANGED
@@ -5,11 +5,34 @@ export const BotInfoSchema = z.object({
5
5
  botAddress: AztecAddress.schema
6
6
  });
7
7
  export const BotRunnerApiSchema = {
8
- start: z.function().args().returns(z.void()),
9
- stop: z.function().args().returns(z.void()),
10
- run: z.function().args().returns(z.void()),
11
- setup: z.function().args().returns(z.void()),
12
- getInfo: z.function().args().returns(BotInfoSchema),
13
- getConfig: z.function().args().returns(BotConfigSchema),
14
- update: z.function().args(BotConfigSchema).returns(z.void())
8
+ start: z.function({
9
+ input: z.tuple([]),
10
+ output: z.void()
11
+ }),
12
+ stop: z.function({
13
+ input: z.tuple([]),
14
+ output: z.void()
15
+ }),
16
+ run: z.function({
17
+ input: z.tuple([]),
18
+ output: z.void()
19
+ }),
20
+ setup: z.function({
21
+ input: z.tuple([]),
22
+ output: z.void()
23
+ }),
24
+ getInfo: z.function({
25
+ input: z.tuple([]),
26
+ output: BotInfoSchema
27
+ }),
28
+ getConfig: z.function({
29
+ input: z.tuple([]),
30
+ output: BotConfigSchema
31
+ }),
32
+ update: z.function({
33
+ input: z.tuple([
34
+ BotConfigSchema
35
+ ]),
36
+ output: z.void()
37
+ })
15
38
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/bot",
3
- "version": "0.0.1-commit.2448fdb",
3
+ "version": "0.0.1-commit.2606882",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -54,24 +54,24 @@
54
54
  ]
55
55
  },
56
56
  "dependencies": {
57
- "@aztec/accounts": "0.0.1-commit.2448fdb",
58
- "@aztec/aztec.js": "0.0.1-commit.2448fdb",
59
- "@aztec/entrypoints": "0.0.1-commit.2448fdb",
60
- "@aztec/ethereum": "0.0.1-commit.2448fdb",
61
- "@aztec/foundation": "0.0.1-commit.2448fdb",
62
- "@aztec/kv-store": "0.0.1-commit.2448fdb",
63
- "@aztec/l1-artifacts": "0.0.1-commit.2448fdb",
64
- "@aztec/noir-contracts.js": "0.0.1-commit.2448fdb",
65
- "@aztec/noir-protocol-circuits-types": "0.0.1-commit.2448fdb",
66
- "@aztec/noir-test-contracts.js": "0.0.1-commit.2448fdb",
67
- "@aztec/protocol-contracts": "0.0.1-commit.2448fdb",
68
- "@aztec/stdlib": "0.0.1-commit.2448fdb",
69
- "@aztec/telemetry-client": "0.0.1-commit.2448fdb",
70
- "@aztec/wallets": "0.0.1-commit.2448fdb",
57
+ "@aztec/accounts": "0.0.1-commit.2606882",
58
+ "@aztec/aztec.js": "0.0.1-commit.2606882",
59
+ "@aztec/entrypoints": "0.0.1-commit.2606882",
60
+ "@aztec/ethereum": "0.0.1-commit.2606882",
61
+ "@aztec/foundation": "0.0.1-commit.2606882",
62
+ "@aztec/kv-store": "0.0.1-commit.2606882",
63
+ "@aztec/l1-artifacts": "0.0.1-commit.2606882",
64
+ "@aztec/noir-contracts.js": "0.0.1-commit.2606882",
65
+ "@aztec/noir-protocol-circuits-types": "0.0.1-commit.2606882",
66
+ "@aztec/noir-test-contracts.js": "0.0.1-commit.2606882",
67
+ "@aztec/protocol-contracts": "0.0.1-commit.2606882",
68
+ "@aztec/stdlib": "0.0.1-commit.2606882",
69
+ "@aztec/telemetry-client": "0.0.1-commit.2606882",
70
+ "@aztec/wallets": "0.0.1-commit.2606882",
71
71
  "source-map-support": "^0.5.21",
72
72
  "tslib": "^2.4.0",
73
73
  "viem": "npm:@aztec/viem@2.38.2",
74
- "zod": "^3.23.8"
74
+ "zod": "^4"
75
75
  },
76
76
  "devDependencies": {
77
77
  "@jest/globals": "^30.0.0",
package/src/amm_bot.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { AztecAddress } from '@aztec/aztec.js/addresses';
2
2
  import { NO_WAIT } from '@aztec/aztec.js/contracts';
3
3
  import { Fr } from '@aztec/aztec.js/fields';
4
- import { TxHash, TxReceipt } from '@aztec/aztec.js/tx';
4
+ import type { TxHash, TxReceipt } from '@aztec/aztec.js/tx';
5
5
  import { jsonStringify } from '@aztec/foundation/json-rpc';
6
6
  import type { AMMContract } from '@aztec/noir-contracts.js/AMM';
7
7
  import type { TokenContract } from '@aztec/noir-contracts.js/Token';
package/src/base_bot.ts CHANGED
@@ -2,7 +2,8 @@ import { AztecAddress } from '@aztec/aztec.js/addresses';
2
2
  import type { SendInteractionOptions } from '@aztec/aztec.js/contracts';
3
3
  import { createLogger } from '@aztec/aztec.js/log';
4
4
  import { waitForTx } from '@aztec/aztec.js/node';
5
- import { TxHash, TxReceipt, TxStatus } from '@aztec/aztec.js/tx';
5
+ import { TxStatus } from '@aztec/aztec.js/tx';
6
+ import type { TxHash, TxReceipt } from '@aztec/aztec.js/tx';
6
7
  import { Gas } from '@aztec/stdlib/gas';
7
8
  import type { AztecNode } from '@aztec/stdlib/interfaces/client';
8
9
  import type { EmbeddedWallet } from '@aztec/wallets/embedded';
package/src/config.ts CHANGED
@@ -11,9 +11,9 @@ import {
11
11
  secretStringConfigHelper,
12
12
  } from '@aztec/foundation/config';
13
13
  import { Fr } from '@aztec/foundation/curves/bn254';
14
- import { type DataStoreConfig, dataConfigMappings } from '@aztec/kv-store/config';
15
14
  import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
16
15
  import { protocolContractsHash } from '@aztec/protocol-contracts';
16
+ import { type DataStoreConfig, dataConfigMappings } from '@aztec/stdlib/kv-store';
17
17
  import { schemas, zodFor } from '@aztec/stdlib/schemas';
18
18
  import type { ComponentsVersions } from '@aztec/stdlib/versioning';
19
19
 
@@ -130,7 +130,6 @@ export const BotConfigSchema = zodFor<BotConfig>()(
130
130
  l1Mnemonic: undefined,
131
131
  l1PrivateKey: undefined,
132
132
  senderPrivateKey: undefined,
133
- dataDirectory: undefined,
134
133
  dataStoreMapSizeKb: 1_024 * 1_024,
135
134
  ...config,
136
135
  })),
@@ -26,7 +26,7 @@
26
26
  import { AztecAddress } from '@aztec/aztec.js/addresses';
27
27
  import { BatchCall, NO_WAIT } from '@aztec/aztec.js/contracts';
28
28
  import { isL1ToL2MessageReady } from '@aztec/aztec.js/messaging';
29
- import { TxHash, TxReceipt } from '@aztec/aztec.js/tx';
29
+ import type { TxHash, TxReceipt } from '@aztec/aztec.js/tx';
30
30
  import type { ExtendedViemWalletClient } from '@aztec/ethereum/types';
31
31
  import { Fr } from '@aztec/foundation/curves/bn254';
32
32
  import { EthAddress } from '@aztec/foundation/eth-address';
@@ -146,9 +146,10 @@ export class CrossChainBot extends BaseBot {
146
146
 
147
147
  protected override async onTxMined(receipt: TxReceipt, logCtx: object): Promise<void> {
148
148
  // Verify L2→L1 messages appeared in this tx's effects
149
- const indexed = await this.node.getTxEffect(receipt.txHash);
150
- if (indexed) {
151
- const l2ToL1Msgs = indexed.data.l2ToL1Msgs.filter(m => !m.isZero());
149
+ const minedReceipt = await this.node.getTxReceipt(receipt.txHash, { includeTxEffect: true });
150
+ const l2ToL1MsgsRaw = minedReceipt.txEffect?.l2ToL1Msgs;
151
+ if (l2ToL1MsgsRaw) {
152
+ const l2ToL1Msgs = l2ToL1MsgsRaw.filter(m => !m.isZero());
152
153
  if (l2ToL1Msgs.length >= this.config.l2ToL1MessagesPerTx) {
153
154
  this.l2ToL1Sent += l2ToL1Msgs.length;
154
155
  } else {