@aztec/bot 0.0.1-commit.fcb71a6 → 0.0.1-commit.fffb133c

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/config.ts CHANGED
@@ -54,8 +54,8 @@ export type BotConfig = {
54
54
  publicTransfersPerTx: number;
55
55
  /** How to handle fee payments. */
56
56
  feePaymentMethod: 'fee_juice';
57
- /** 'How much is the bot willing to overpay vs. the current base fee' */
58
- baseFeePadding: number;
57
+ /** 'How much is the bot willing to overpay vs. the current min fee' */
58
+ minFeePadding: number;
59
59
  /** True to not automatically setup or start the bot on initialization. */
60
60
  noStart: boolean;
61
61
  /** How long to wait for a tx to be mined before reporting an error. */
@@ -96,7 +96,7 @@ export const BotConfigSchema = zodFor<BotConfig>()(
96
96
  privateTransfersPerTx: z.number().int().nonnegative(),
97
97
  publicTransfersPerTx: z.number().int().nonnegative(),
98
98
  feePaymentMethod: z.literal('fee_juice'),
99
- baseFeePadding: z.number().int().nonnegative(),
99
+ minFeePadding: z.number().int().nonnegative(),
100
100
  noStart: z.boolean(),
101
101
  txMinedWaitSeconds: z.number(),
102
102
  followChain: z.enum(BotFollowChain),
@@ -193,8 +193,8 @@ export const botConfigMappings: ConfigMappingsType<BotConfig> = {
193
193
  parseEnv: val => (val as 'fee_juice') || undefined,
194
194
  defaultValue: 'fee_juice',
195
195
  },
196
- baseFeePadding: {
197
- env: 'BOT_BASE_FEE_PADDING',
196
+ minFeePadding: {
197
+ env: 'BOT_MIN_FEE_PADDING',
198
198
  description: 'How much is the bot willing to overpay vs. the current base fee',
199
199
  ...numberConfigHelper(3),
200
200
  },
package/src/factory.ts CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  ContractFunctionInteraction,
8
8
  type DeployMethod,
9
9
  type DeployOptions,
10
+ NO_WAIT,
10
11
  } from '@aztec/aztec.js/contracts';
11
12
  import { L1FeeJuicePortalManager } from '@aztec/aztec.js/ethereum';
12
13
  import type { L2AmountClaim } from '@aztec/aztec.js/ethereum';
@@ -14,6 +15,7 @@ import { FeeJuicePaymentMethodWithClaim } from '@aztec/aztec.js/fee';
14
15
  import { deriveKeys } from '@aztec/aztec.js/keys';
15
16
  import { createLogger } from '@aztec/aztec.js/log';
16
17
  import { waitForL1ToL2MessageReady } from '@aztec/aztec.js/messaging';
18
+ import { waitForTx } from '@aztec/aztec.js/node';
17
19
  import { createEthereumChain } from '@aztec/ethereum/chain';
18
20
  import { createExtendedL1Client } from '@aztec/ethereum/client';
19
21
  import { Fr } from '@aztec/foundation/curves/bn254';
@@ -56,8 +58,8 @@ export class BotFactory {
56
58
  node: AztecNode;
57
59
  recipient: AztecAddress;
58
60
  }> {
59
- const recipient = (await this.wallet.createAccount()).address;
60
61
  const defaultAccountAddress = await this.setupAccount();
62
+ const recipient = (await this.wallet.createAccount()).address;
61
63
  const token = await this.setupToken(defaultAccountAddress);
62
64
  await this.mintTokens(token, defaultAccountAddress);
63
65
  return { wallet: this.wallet, defaultAccountAddress, token, node: this.aztecNode, recipient };
@@ -118,8 +120,8 @@ export class BotFactory {
118
120
  contract: new SchnorrAccountContract(signingKey!),
119
121
  };
120
122
  const accountManager = await this.wallet.createAccount(accountData);
121
- const isInit = (await this.wallet.getContractMetadata(accountManager.address)).isContractInitialized;
122
- if (isInit) {
123
+ const metadata = await this.wallet.getContractMetadata(accountManager.address);
124
+ if (metadata.isContractInitialized) {
123
125
  this.log.info(`Account at ${accountManager.address.toString()} already initialized`);
124
126
  const timer = new Timer();
125
127
  const address = accountManager.address;
@@ -134,12 +136,18 @@ export class BotFactory {
134
136
 
135
137
  const paymentMethod = new FeeJuicePaymentMethodWithClaim(accountManager.address, claim);
136
138
  const deployMethod = await accountManager.getDeployMethod();
137
- const maxFeesPerGas = (await this.aztecNode.getCurrentBaseFees()).mul(1 + this.config.baseFeePadding);
139
+ const maxFeesPerGas = (await this.aztecNode.getCurrentMinFees()).mul(1 + this.config.minFeePadding);
138
140
  const gasSettings = GasSettings.default({ maxFeesPerGas });
139
- const sentTx = deployMethod.send({ from: AztecAddress.ZERO, fee: { gasSettings, paymentMethod } });
140
- const txHash = await sentTx.getTxHash();
141
- this.log.info(`Sent tx for account deployment with hash ${txHash.toString()}`);
142
- await this.withNoMinTxsPerBlock(() => sentTx.wait({ timeout: this.config.txMinedWaitSeconds }));
141
+
142
+ await this.withNoMinTxsPerBlock(async () => {
143
+ const txHash = await deployMethod.send({
144
+ from: AztecAddress.ZERO,
145
+ fee: { gasSettings, paymentMethod },
146
+ wait: NO_WAIT,
147
+ });
148
+ this.log.info(`Sent tx for account deployment with hash ${txHash.toString()}`);
149
+ return waitForTx(this.aztecNode, txHash, { timeout: this.config.txMinedWaitSeconds });
150
+ });
143
151
  this.log.info(`Account deployed at ${address}`);
144
152
 
145
153
  // Clean up the consumed bridge claim
@@ -173,8 +181,11 @@ export class BotFactory {
173
181
  contractAddressSalt: this.config.tokenSalt,
174
182
  universalDeploy: true,
175
183
  };
184
+ let token: TokenContract | PrivateTokenContract;
176
185
  if (this.config.contract === SupportedTokenContracts.TokenContract) {
177
186
  deploy = TokenContract.deploy(this.wallet, sender, 'BotToken', 'BOT', 18);
187
+ tokenInstance = await deploy.getInstance(deployOpts);
188
+ token = TokenContract.at(tokenInstance.address, this.wallet);
178
189
  } else if (this.config.contract === SupportedTokenContracts.PrivateTokenContract) {
179
190
  // Generate keys for the contract since PrivateToken uses SinglePrivateMutable which requires keys
180
191
  const tokenSecretKey = Fr.random();
@@ -186,22 +197,27 @@ export class BotFactory {
186
197
 
187
198
  // Register the contract with the secret key before deployment
188
199
  tokenInstance = await deploy.getInstance(deployOpts);
200
+ token = PrivateTokenContract.at(tokenInstance.address, this.wallet);
189
201
  await this.wallet.registerContract(tokenInstance, PrivateTokenContract.artifact, tokenSecretKey);
190
202
  } else {
191
203
  throw new Error(`Unsupported token contract type: ${this.config.contract}`);
192
204
  }
193
205
 
194
206
  const address = tokenInstance?.address ?? (await deploy.getInstance(deployOpts)).address;
195
- if ((await this.wallet.getContractMetadata(address)).isContractPublished) {
207
+ const metadata = await this.wallet.getContractMetadata(address);
208
+ if (metadata.isContractPublished) {
196
209
  this.log.info(`Token at ${address.toString()} already deployed`);
197
- return deploy.register();
210
+ await deploy.register();
198
211
  } else {
199
212
  this.log.info(`Deploying token contract at ${address.toString()}`);
200
- const sentTx = deploy.send(deployOpts);
201
- const txHash = await sentTx.getTxHash();
213
+ const txHash = await deploy.send({ ...deployOpts, wait: NO_WAIT });
202
214
  this.log.info(`Sent tx for token setup with hash ${txHash.toString()}`);
203
- return this.withNoMinTxsPerBlock(() => sentTx.deployed({ timeout: this.config.txMinedWaitSeconds }));
215
+ await this.withNoMinTxsPerBlock(async () => {
216
+ await waitForTx(this.aztecNode, txHash, { timeout: this.config.txMinedWaitSeconds });
217
+ return token;
218
+ });
204
219
  }
220
+ return token;
205
221
  }
206
222
 
207
223
  /**
@@ -209,7 +225,7 @@ export class BotFactory {
209
225
  * @param wallet - Wallet to deploy the token contract from.
210
226
  * @returns The TokenContract instance.
211
227
  */
212
- private setupTokenContract(
228
+ private async setupTokenContract(
213
229
  deployer: AztecAddress,
214
230
  contractAddressSalt: Fr,
215
231
  name: string,
@@ -218,7 +234,8 @@ export class BotFactory {
218
234
  ): Promise<TokenContract> {
219
235
  const deployOpts: DeployOptions = { from: deployer, contractAddressSalt, universalDeploy: true };
220
236
  const deploy = TokenContract.deploy(this.wallet, deployer, name, ticker, decimals);
221
- return this.registerOrDeployContract('Token - ' + name, deploy, deployOpts);
237
+ const instance = await this.registerOrDeployContract('Token - ' + name, deploy, deployOpts);
238
+ return TokenContract.at(instance.address, this.wallet);
222
239
  }
223
240
 
224
241
  private async setupAmmContract(
@@ -230,12 +247,14 @@ export class BotFactory {
230
247
  ): Promise<AMMContract> {
231
248
  const deployOpts: DeployOptions = { from: deployer, contractAddressSalt, universalDeploy: true };
232
249
  const deploy = AMMContract.deploy(this.wallet, token0.address, token1.address, lpToken.address);
233
- const amm = await this.registerOrDeployContract('AMM', deploy, deployOpts);
250
+ const instance = await this.registerOrDeployContract('AMM', deploy, deployOpts);
251
+ const amm = AMMContract.at(instance.address, this.wallet);
234
252
 
235
253
  this.log.info(`AMM deployed at ${amm.address}`);
236
- const minterTx = lpToken.methods.set_minter(amm.address, true).send({ from: deployer });
237
- this.log.info(`Set LP token minter to AMM txHash=${(await minterTx.getTxHash()).toString()}`);
238
- await minterTx.wait({ timeout: this.config.txMinedWaitSeconds });
254
+ const minterReceipt = await lpToken.methods
255
+ .set_minter(amm.address, true)
256
+ .send({ from: deployer, wait: { timeout: this.config.txMinedWaitSeconds } });
257
+ this.log.info(`Set LP token minter to AMM txHash=${minterReceipt.txHash.toString()}`);
239
258
  this.log.info(`Liquidity token initialized`);
240
259
 
241
260
  return amm;
@@ -294,23 +313,22 @@ export class BotFactory {
294
313
  .getFunctionCall(),
295
314
  });
296
315
 
297
- const mintTx = new BatchCall(this.wallet, [
316
+ const mintReceipt = await new BatchCall(this.wallet, [
298
317
  token0.methods.mint_to_private(liquidityProvider, MINT_BALANCE),
299
318
  token1.methods.mint_to_private(liquidityProvider, MINT_BALANCE),
300
- ]).send({ from: liquidityProvider });
319
+ ]).send({ from: liquidityProvider, wait: { timeout: this.config.txMinedWaitSeconds } });
301
320
 
302
- this.log.info(`Sent mint tx: ${(await mintTx.getTxHash()).toString()}`);
303
- await mintTx.wait({ timeout: this.config.txMinedWaitSeconds });
321
+ this.log.info(`Sent mint tx: ${mintReceipt.txHash.toString()}`);
304
322
 
305
- const addLiquidityTx = amm.methods
323
+ const addLiquidityReceipt = await amm.methods
306
324
  .add_liquidity(amount0Max, amount1Max, amount0Min, amount1Min, authwitNonce)
307
325
  .send({
308
326
  from: liquidityProvider,
309
327
  authWitnesses: [token0Authwit, token1Authwit],
328
+ wait: { timeout: this.config.txMinedWaitSeconds },
310
329
  });
311
330
 
312
- this.log.info(`Sent tx to add liquidity to the AMM: ${(await addLiquidityTx.getTxHash()).toString()}`);
313
- await addLiquidityTx.wait({ timeout: this.config.txMinedWaitSeconds });
331
+ this.log.info(`Sent tx to add liquidity to the AMM: ${addLiquidityReceipt.txHash.toString()}`);
314
332
  this.log.info(`Liquidity added`);
315
333
 
316
334
  const [newT0Bal, newT1Bal, newLPBal] = await getPrivateBalances();
@@ -323,18 +341,22 @@ export class BotFactory {
323
341
  name: string,
324
342
  deploy: DeployMethod<T>,
325
343
  deployOpts: DeployOptions,
326
- ): Promise<T> {
327
- const address = (await deploy.getInstance(deployOpts)).address;
328
- if ((await this.wallet.getContractMetadata(address)).isContractPublished) {
344
+ ): Promise<ContractInstanceWithAddress> {
345
+ const instance = await deploy.getInstance(deployOpts);
346
+ const address = instance.address;
347
+ const metadata = await this.wallet.getContractMetadata(address);
348
+ if (metadata.isContractPublished) {
329
349
  this.log.info(`Contract ${name} at ${address.toString()} already deployed`);
330
- return deploy.register();
350
+ await deploy.register();
331
351
  } else {
332
352
  this.log.info(`Deploying contract ${name} at ${address.toString()}`);
333
- const sentTx = deploy.send(deployOpts);
334
- const txHash = await sentTx.getTxHash();
335
- this.log.info(`Sent contract ${name} setup tx with hash ${txHash.toString()}`);
336
- return this.withNoMinTxsPerBlock(() => sentTx.deployed({ timeout: this.config.txMinedWaitSeconds }));
353
+ await this.withNoMinTxsPerBlock(async () => {
354
+ const txHash = await deploy.send({ ...deployOpts, wait: NO_WAIT });
355
+ this.log.info(`Sent contract ${name} setup tx with hash ${txHash.toString()}`);
356
+ return waitForTx(this.aztecNode, txHash, { timeout: this.config.txMinedWaitSeconds });
357
+ });
337
358
  }
359
+ return instance;
338
360
  }
339
361
 
340
362
  /**
@@ -370,10 +392,12 @@ export class BotFactory {
370
392
  this.log.info(`Skipping minting as ${minter.toString()} has enough tokens`);
371
393
  return;
372
394
  }
373
- const sentTx = new BatchCall(token.wallet, calls).send({ from: minter });
374
- const txHash = await sentTx.getTxHash();
375
- this.log.info(`Sent token mint tx with hash ${txHash.toString()}`);
376
- await this.withNoMinTxsPerBlock(() => sentTx.wait({ timeout: this.config.txMinedWaitSeconds }));
395
+
396
+ await this.withNoMinTxsPerBlock(async () => {
397
+ const txHash = await new BatchCall(token.wallet, calls).send({ from: minter, wait: NO_WAIT });
398
+ this.log.info(`Sent token mint tx with hash ${txHash.toString()}`);
399
+ return waitForTx(this.aztecNode, txHash, { timeout: this.config.txMinedWaitSeconds });
400
+ });
377
401
  }
378
402
 
379
403
  /**