@aztec/bot 0.0.1-commit.343b43af6 → 0.0.1-commit.350e0a4d

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/src/amm_bot.ts CHANGED
@@ -1,10 +1,11 @@
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';
8
+ import type { BlockTag } from '@aztec/stdlib/block';
8
9
  import type { AztecNode, AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
9
10
  import type { EmbeddedWallet } from '@aztec/wallets/embedded';
10
11
 
@@ -37,6 +38,7 @@ export class AmmBot extends BaseBot {
37
38
  aztecNode: AztecNode,
38
39
  aztecNodeAdmin: AztecNodeAdmin | undefined,
39
40
  store: BotStore,
41
+ syncChainTip?: BlockTag,
40
42
  ): Promise<AmmBot> {
41
43
  const { defaultAccountAddress, token0, token1, amm } = await new BotFactory(
42
44
  config,
@@ -44,6 +46,7 @@ export class AmmBot extends BaseBot {
44
46
  store,
45
47
  aztecNode,
46
48
  aztecNodeAdmin,
49
+ syncChainTip,
47
50
  ).setupAmm();
48
51
  return new AmmBot(aztecNode, wallet, defaultAccountAddress, amm, token0, token1, config);
49
52
  }
@@ -87,7 +90,7 @@ export class AmmBot extends BaseBot {
87
90
  authWitnesses: [swapAuthwit],
88
91
  });
89
92
 
90
- const opts = await this.getSendMethodOpts(swapExactTokensInteraction);
93
+ const opts = this.getSendMethodOpts();
91
94
 
92
95
  this.log.verbose(`Sending transaction`, logCtx);
93
96
  this.log.info(`Tx. Balances: ${jsonStringify(balances)}`, { ...logCtx, balances });
package/src/base_bot.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { AztecAddress } from '@aztec/aztec.js/addresses';
2
- import { BatchCall, ContractFunctionInteraction, type SendInteractionOptions } from '@aztec/aztec.js/contracts';
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';
@@ -56,27 +57,19 @@ export abstract class BaseBot {
56
57
  return Promise.resolve();
57
58
  }
58
59
 
59
- protected async getSendMethodOpts(
60
- interaction: ContractFunctionInteraction | BatchCall,
61
- ): Promise<SendInteractionOptions> {
60
+ protected getSendMethodOpts(): SendInteractionOptions {
62
61
  const { l2GasLimit, daGasLimit, minFeePadding } = this.config;
63
62
 
64
63
  this.wallet.setMinFeePadding(minFeePadding);
65
64
 
66
- let gasSettings;
67
- if (l2GasLimit !== undefined && l2GasLimit > 0 && daGasLimit !== undefined && daGasLimit > 0) {
68
- gasSettings = { gasLimits: Gas.from({ l2Gas: l2GasLimit, daGas: daGasLimit }) };
69
- this.log.verbose(`Using gas limits ${l2GasLimit} L2 gas ${daGasLimit} DA gas`);
70
- } else {
71
- this.log.verbose(`Estimating gas for transaction`);
72
- ({ estimatedGas: gasSettings } = await interaction.simulate({
73
- fee: { estimateGas: true },
74
- from: this.defaultAccountAddress,
75
- }));
76
- }
65
+ const gasSettings =
66
+ l2GasLimit !== undefined && l2GasLimit > 0 && daGasLimit !== undefined && daGasLimit > 0
67
+ ? { gasLimits: Gas.from({ l2Gas: l2GasLimit, daGas: daGasLimit }) }
68
+ : undefined;
69
+
77
70
  return {
78
71
  from: this.defaultAccountAddress,
79
- fee: { gasSettings },
72
+ ...(gasSettings ? { fee: { gasSettings } } : {}),
80
73
  };
81
74
  }
82
75
  }
package/src/bot.ts CHANGED
@@ -4,6 +4,7 @@ import { TxHash } from '@aztec/aztec.js/tx';
4
4
  import { times } from '@aztec/foundation/collection';
5
5
  import type { PrivateTokenContract } from '@aztec/noir-contracts.js/PrivateToken';
6
6
  import type { TokenContract } from '@aztec/noir-contracts.js/Token';
7
+ import type { BlockTag } from '@aztec/stdlib/block';
7
8
  import type { AztecNode, AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
8
9
  import type { EmbeddedWallet } from '@aztec/wallets/embedded';
9
10
 
@@ -33,6 +34,7 @@ export class Bot extends BaseBot {
33
34
  aztecNode: AztecNode,
34
35
  aztecNodeAdmin: AztecNodeAdmin | undefined,
35
36
  store: BotStore,
37
+ syncChainTip?: BlockTag,
36
38
  ): Promise<Bot> {
37
39
  const { defaultAccountAddress, token, recipient } = await new BotFactory(
38
40
  config,
@@ -40,6 +42,7 @@ export class Bot extends BaseBot {
40
42
  store,
41
43
  aztecNode,
42
44
  aztecNodeAdmin,
45
+ syncChainTip,
43
46
  ).setup();
44
47
  return new Bot(aztecNode, wallet, defaultAccountAddress, token, recipient, config);
45
48
  }
@@ -70,10 +73,7 @@ export class Bot extends BaseBot {
70
73
  );
71
74
 
72
75
  const batch = new BatchCall(wallet, calls);
73
- const opts = await this.getSendMethodOpts(batch);
74
-
75
- this.log.verbose(`Simulating transaction with ${calls.length}`, logCtx);
76
- await batch.simulate({ from: this.defaultAccountAddress });
76
+ const opts = this.getSendMethodOpts();
77
77
 
78
78
  this.log.verbose(`Sending transaction`, logCtx);
79
79
  const { txHash } = await batch.send({ ...opts, wait: NO_WAIT });
package/src/config.ts CHANGED
@@ -2,6 +2,7 @@ import {
2
2
  type ConfigMappingsType,
3
3
  SecretValue,
4
4
  booleanConfigHelper,
5
+ floatConfigHelper,
5
6
  getConfigFromMappings,
6
7
  getDefaultConfig,
7
8
  numberConfigHelper,
@@ -69,9 +70,9 @@ export type BotConfig = {
69
70
  maxPendingTxs: number;
70
71
  /** Whether to flush after sending each 'setup' transaction */
71
72
  flushSetupTransactions: boolean;
72
- /** L2 gas limit for the tx (empty to have the bot trigger an estimate gas). */
73
+ /** L2 gas limit for the tx (empty to let the bot's wallet estimate). */
73
74
  l2GasLimit: number | undefined;
74
- /** DA gas limit for the tx (empty to have the bot trigger an estimate gas). */
75
+ /** DA gas limit for the tx (empty to let the bot's wallet estimate). */
75
76
  daGasLimit: number | undefined;
76
77
  /** Token contract to use */
77
78
  contract: SupportedTokenContracts;
@@ -103,7 +104,7 @@ export const BotConfigSchema = zodFor<BotConfig>()(
103
104
  privateTransfersPerTx: z.number().int().nonnegative(),
104
105
  publicTransfersPerTx: z.number().int().nonnegative(),
105
106
  feePaymentMethod: z.literal('fee_juice'),
106
- minFeePadding: z.number().int().nonnegative(),
107
+ minFeePadding: z.number().nonnegative(),
107
108
  noStart: z.boolean(),
108
109
  txMinedWaitSeconds: z.number(),
109
110
  followChain: z.enum(BotFollowChain),
@@ -204,7 +205,7 @@ export const botConfigMappings: ConfigMappingsType<BotConfig> = {
204
205
  minFeePadding: {
205
206
  env: 'BOT_MIN_FEE_PADDING',
206
207
  description: 'How much is the bot willing to overpay vs. the current base fee',
207
- ...numberConfigHelper(3),
208
+ ...floatConfigHelper(3),
208
209
  },
209
210
  noStart: {
210
211
  env: 'BOT_NO_START',
@@ -243,12 +244,12 @@ export const botConfigMappings: ConfigMappingsType<BotConfig> = {
243
244
  },
244
245
  l2GasLimit: {
245
246
  env: 'BOT_L2_GAS_LIMIT',
246
- description: 'L2 gas limit for the tx (empty to have the bot trigger an estimate gas).',
247
+ description: "L2 gas limit for the tx (empty to let the bot's wallet estimate).",
247
248
  ...optionalNumberConfigHelper(),
248
249
  },
249
250
  daGasLimit: {
250
251
  env: 'BOT_DA_GAS_LIMIT',
251
- description: 'DA gas limit for the tx (empty to have the bot trigger an estimate gas).',
252
+ description: "DA gas limit for the tx (empty to let the bot's wallet estimate).",
252
253
  ...optionalNumberConfigHelper(),
253
254
  },
254
255
  contract: {
@@ -26,11 +26,12 @@
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';
33
33
  import type { TestContract } from '@aztec/noir-test-contracts.js/Test';
34
+ import type { BlockTag } from '@aztec/stdlib/block';
34
35
  import type { AztecNode, AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
35
36
  import type { EmbeddedWallet } from '@aztec/wallets/embedded';
36
37
 
@@ -60,6 +61,7 @@ export class CrossChainBot extends BaseBot {
60
61
  private readonly rollupVersion: bigint,
61
62
  private readonly store: BotStore,
62
63
  config: BotConfig,
64
+ private readonly syncChainTip?: BlockTag,
63
65
  ) {
64
66
  super(node, wallet, defaultAccountAddress, config);
65
67
  }
@@ -70,11 +72,12 @@ export class CrossChainBot extends BaseBot {
70
72
  aztecNode: AztecNode,
71
73
  aztecNodeAdmin: AztecNodeAdmin | undefined,
72
74
  store: BotStore,
75
+ syncChainTip?: BlockTag,
73
76
  ): Promise<CrossChainBot> {
74
77
  if (config.followChain === 'NONE') {
75
78
  throw new Error(`CrossChainBot requires followChain to be set (got NONE)`);
76
79
  }
77
- const factory = new BotFactory(config, wallet, store, aztecNode, aztecNodeAdmin);
80
+ const factory = new BotFactory(config, wallet, store, aztecNode, aztecNodeAdmin, syncChainTip);
78
81
  const { defaultAccountAddress, contract, l1Client, rollupVersion } = await factory.setupCrossChain();
79
82
  const l1Recipient = EthAddress.fromString(l1Client.account!.address);
80
83
  const { l1ContractAddresses } = await aztecNode.getNodeInfo();
@@ -90,6 +93,7 @@ export class CrossChainBot extends BaseBot {
90
93
  rollupVersion,
91
94
  store,
92
95
  config,
96
+ syncChainTip,
93
97
  );
94
98
  }
95
99
 
@@ -137,7 +141,7 @@ export class CrossChainBot extends BaseBot {
137
141
  }
138
142
 
139
143
  const batch = new BatchCall(this.wallet, calls);
140
- const opts = await this.getSendMethodOpts(batch);
144
+ const opts = this.getSendMethodOpts();
141
145
 
142
146
  this.log.verbose(`Sending cross-chain batch with ${calls.length} calls`, logCtx);
143
147
  const { txHash } = await batch.send({ ...opts, wait: NO_WAIT });
@@ -146,9 +150,10 @@ export class CrossChainBot extends BaseBot {
146
150
 
147
151
  protected override async onTxMined(receipt: TxReceipt, logCtx: object): Promise<void> {
148
152
  // 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());
153
+ const minedReceipt = await this.node.getTxReceipt(receipt.txHash, { includeTxEffect: true });
154
+ const l2ToL1MsgsRaw = minedReceipt.txEffect?.l2ToL1Msgs;
155
+ if (l2ToL1MsgsRaw) {
156
+ const l2ToL1Msgs = l2ToL1MsgsRaw.filter(m => !m.isZero());
152
157
  if (l2ToL1Msgs.length >= this.config.l2ToL1MessagesPerTx) {
153
158
  this.l2ToL1Sent += l2ToL1Msgs.length;
154
159
  } else {
@@ -175,7 +180,7 @@ export class CrossChainBot extends BaseBot {
175
180
  ): Promise<PendingL1ToL2Message | undefined> {
176
181
  const now = Date.now();
177
182
  for (const msg of pendingMessages) {
178
- const ready = await isL1ToL2MessageReady(this.node, Fr.fromHexString(msg.msgHash));
183
+ const ready = await isL1ToL2MessageReady(this.node, Fr.fromHexString(msg.msgHash), this.syncChainTip);
179
184
  if (ready) {
180
185
  return msg;
181
186
  }