@aztec/bot 0.85.0 → 0.86.0

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/amm_bot.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { SentTx, type Wallet } from '@aztec/aztec.js';
1
+ import { SentTx, TxReceipt, type Wallet } from '@aztec/aztec.js';
2
2
  import type { AMMContract } from '@aztec/noir-contracts.js/AMM';
3
3
  import type { TokenContract } from '@aztec/noir-contracts.js/Token';
4
4
  import type { AztecNode, AztecNodeAdmin, PXE } from '@aztec/stdlib/interfaces/client';
@@ -19,6 +19,7 @@ export declare class AmmBot extends BaseBot {
19
19
  nodeAdmin?: AztecNodeAdmin;
20
20
  }): Promise<AmmBot>;
21
21
  protected createAndSendTx(logCtx: object): Promise<SentTx>;
22
+ protected onTxMined(receipt: TxReceipt, logCtx: object): Promise<void>;
22
23
  getAmmBalances(): Promise<Balances>;
23
24
  getBalances(): Promise<{
24
25
  senderPublic: Balances;
@@ -1 +1 @@
1
- {"version":3,"file":"amm_bot.d.ts","sourceRoot":"","sources":["../src/amm_bot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,MAAM,EAAE,KAAK,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,iCAAiC,CAAC;AAEtF,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAK7C,KAAK,QAAQ,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,qBAAa,MAAO,SAAQ,OAAO;aAIf,GAAG,EAAE,WAAW;aAChB,MAAM,EAAE,aAAa;aACrB,MAAM,EAAE,aAAa;IALvC,SAAS,aACP,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,EACE,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,aAAa,EACrC,MAAM,EAAE,SAAS;WAKN,MAAM,CACjB,MAAM,EAAE,SAAS,EACjB,YAAY,EAAE;QAAE,GAAG,CAAC,EAAE,GAAG,CAAC;QAAC,IAAI,CAAC,EAAE,SAAS,CAAC;QAAC,SAAS,CAAC,EAAE,cAAc,CAAA;KAAE,GACxE,OAAO,CAAC,MAAM,CAAC;cAKF,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAmCzD,cAAc,IAAI,OAAO,CAAC,QAAQ,CAAC;IAI7B,WAAW,IAAI,OAAO,CAAC;QAAE,YAAY,EAAE,QAAQ,CAAC;QAAC,aAAa,EAAE,QAAQ,CAAC;QAAC,GAAG,EAAE,QAAQ,CAAA;KAAE,CAAC;YAQzF,mBAAmB;YAMnB,oBAAoB;CAMnC"}
1
+ {"version":3,"file":"amm_bot.d.ts","sourceRoot":"","sources":["../src/amm_bot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,MAAM,EAAE,SAAS,EAAE,KAAK,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEnF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,iCAAiC,CAAC;AAEtF,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAM7C,KAAK,QAAQ,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,qBAAa,MAAO,SAAQ,OAAO;aAIf,GAAG,EAAE,WAAW;aAChB,MAAM,EAAE,aAAa;aACrB,MAAM,EAAE,aAAa;IALvC,SAAS,aACP,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,EACE,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,aAAa,EACrC,MAAM,EAAE,SAAS;WAKN,MAAM,CACjB,MAAM,EAAE,SAAS,EACjB,YAAY,EAAE;QAAE,GAAG,CAAC,EAAE,GAAG,CAAC;QAAC,IAAI,CAAC,EAAE,SAAS,CAAC;QAAC,SAAS,CAAC,EAAE,cAAc,CAAA;KAAE,GACxE,OAAO,CAAC,MAAM,CAAC;cAKF,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;cA+CvC,SAAS,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK9E,cAAc,IAAI,OAAO,CAAC,QAAQ,CAAC;IAI7B,WAAW,IAAI,OAAO,CAAC;QAAE,YAAY,EAAE,QAAQ,CAAC;QAAC,aAAa,EAAE,QAAQ,CAAC;QAAC,GAAG,EAAE,QAAQ,CAAA;KAAE,CAAC;YAQzF,mBAAmB;YAMnB,oBAAoB;CAMnC"}
package/dest/amm_bot.js CHANGED
@@ -1,7 +1,9 @@
1
1
  import { Fr } from '@aztec/aztec.js';
2
+ import { jsonStringify } from '@aztec/foundation/json-rpc';
2
3
  import { BaseBot } from './base_bot.js';
3
4
  import { BotFactory } from './factory.js';
4
- const TRANSFER_AMOUNT = 1_000;
5
+ const TRANSFER_BASE_AMOUNT = 1_000;
6
+ const TRANSFER_VARIANCE = 200;
5
7
  export class AmmBot extends BaseBot {
6
8
  amm;
7
9
  token0;
@@ -16,21 +18,43 @@ export class AmmBot extends BaseBot {
16
18
  async createAndSendTx(logCtx) {
17
19
  const { feePaymentMethod } = this.config;
18
20
  const { wallet, amm, token0, token1 } = this;
19
- this.log.verbose(`Preparing tx with ${feePaymentMethod} fee to swap tokens`, logCtx);
20
- const ammBalances = await this.getAmmBalances();
21
- const amountIn = TRANSFER_AMOUNT;
21
+ const balances = this.getBalances();
22
+ this.log.info(`Preparing tx with ${feePaymentMethod} fee to swap tokens. Balances: ${jsonStringify(balances)}`, {
23
+ ...logCtx,
24
+ balances
25
+ });
26
+ // 1000 ± 200
27
+ const amountIn = Math.floor(TRANSFER_BASE_AMOUNT + (Math.random() - 0.5) * TRANSFER_VARIANCE);
22
28
  const nonce = Fr.random();
29
+ const [tokenIn, tokenOut] = Math.random() < 0.5 ? [
30
+ token0,
31
+ token1
32
+ ] : [
33
+ token1,
34
+ token0
35
+ ];
23
36
  const swapAuthwit = await wallet.createAuthWit({
24
37
  caller: amm.address,
25
- action: token0.methods.transfer_to_public(wallet.getAddress(), amm.address, amountIn, nonce)
38
+ action: tokenIn.methods.transfer_to_public(wallet.getAddress(), amm.address, amountIn, nonce)
26
39
  });
27
- const amountOutMin = await amm.methods.get_amount_out_for_exact_in(ammBalances.token0, ammBalances.token1, amountIn).simulate();
28
- const swapExactTokensInteraction = amm.methods.swap_exact_tokens_for_tokens(token0.address, token1.address, amountIn, amountOutMin, nonce);
40
+ const amountOutMin = await amm.methods.get_amount_out_for_exact_in(await tokenIn.methods.balance_of_public(amm.address).simulate(), await tokenOut.methods.balance_of_public(amm.address).simulate(), amountIn).simulate();
41
+ const swapExactTokensInteraction = amm.methods.swap_exact_tokens_for_tokens(tokenIn.address, tokenOut.address, amountIn, amountOutMin, nonce);
29
42
  const opts = this.getSendMethodOpts(swapAuthwit);
30
43
  this.log.verbose(`Proving transaction`, logCtx);
31
44
  const tx = await swapExactTokensInteraction.prove(opts);
45
+ this.log.info(`Tx. Balances: ${jsonStringify(balances)}`, {
46
+ ...logCtx,
47
+ balances
48
+ });
32
49
  return tx.send();
33
50
  }
51
+ async onTxMined(receipt, logCtx) {
52
+ const balances = await this.getBalances();
53
+ this.log.info(`Balances after swap in tx ${receipt.txHash}: ${jsonStringify(balances)}`, {
54
+ ...logCtx,
55
+ balances
56
+ });
57
+ }
34
58
  getAmmBalances() {
35
59
  return this.getPublicBalanceFor(this.amm.address);
36
60
  }
@@ -11,6 +11,7 @@ export declare abstract class BaseBot {
11
11
  protected constructor(pxe: PXE, wallet: Wallet, config: BotConfig);
12
12
  run(): Promise<TxReceipt | TxHash>;
13
13
  protected abstract createAndSendTx(logCtx: object): Promise<SentTx>;
14
+ protected onTxMined(_receipt: TxReceipt, _logCtx: object): Promise<void>;
14
15
  protected getSendMethodOpts(...authWitnesses: AuthWitness[]): SendMethodOptions;
15
16
  }
16
17
  //# sourceMappingURL=base_bot.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"base_bot.d.ts","sourceRoot":"","sources":["../src/base_bot.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EAEX,KAAK,iBAAiB,EACtB,MAAM,EACN,MAAM,EACN,SAAS,EACT,KAAK,MAAM,EAGZ,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iCAAiC,CAAC;AAE3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,8BAAsB,OAAO;aAMW,GAAG,EAAE,GAAG;aAAkB,MAAM,EAAE,MAAM;IAAS,MAAM,EAAE,SAAS;IALxG,SAAS,CAAC,GAAG,mCAAuB;IAEpC,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAK;IAC/B,SAAS,CAAC,SAAS,EAAE,MAAM,CAAK;IAEhC,SAAS,aAA6B,GAAG,EAAE,GAAG,EAAkB,MAAM,EAAE,MAAM,EAAS,MAAM,EAAE,SAAS;IAE3F,GAAG,IAAI,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC;IAiC/C,SAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAEnE,SAAS,CAAC,iBAAiB,CAAC,GAAG,aAAa,EAAE,WAAW,EAAE,GAAG,iBAAiB;CAkBhF"}
1
+ {"version":3,"file":"base_bot.d.ts","sourceRoot":"","sources":["../src/base_bot.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EAEX,KAAK,iBAAiB,EACtB,MAAM,EACN,MAAM,EACN,SAAS,EACT,KAAK,MAAM,EAGZ,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iCAAiC,CAAC;AAE3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,8BAAsB,OAAO;aAMW,GAAG,EAAE,GAAG;aAAkB,MAAM,EAAE,MAAM;IAAS,MAAM,EAAE,SAAS;IALxG,SAAS,CAAC,GAAG,mCAAuB;IAEpC,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAK;IAC/B,SAAS,CAAC,SAAS,EAAE,MAAM,CAAK;IAEhC,SAAS,aAA6B,GAAG,EAAE,GAAG,EAAkB,MAAM,EAAE,MAAM,EAAS,MAAM,EAAE,SAAS;IAE3F,GAAG,IAAI,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC;IAoC/C,SAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAEnE,SAAS,CAAC,SAAS,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKxE,SAAS,CAAC,iBAAiB,CAAC,GAAG,aAAa,EAAE,WAAW,EAAE,GAAG,iBAAiB;CAkBhF"}
package/dest/base_bot.js CHANGED
@@ -39,8 +39,13 @@ export class BaseBot {
39
39
  }
40
40
  this.successes++;
41
41
  this.log.info(`Tx #${this.attempts} ${receipt.txHash} successfully mined in block ${receipt.blockNumber} (stats: ${this.successes}/${this.attempts} success)`, logCtx);
42
+ await this.onTxMined(receipt, logCtx);
42
43
  return receipt;
43
44
  }
45
+ onTxMined(_receipt, _logCtx) {
46
+ // no-op
47
+ return Promise.resolve();
48
+ }
44
49
  getSendMethodOpts(...authWitnesses) {
45
50
  const sender = this.wallet.getAddress();
46
51
  const { l2GasLimit, daGasLimit, skipPublicSimulation } = this.config;
@@ -1 +1 @@
1
- {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,YAAY,EAQZ,KAAK,GAAG,EAIT,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAIjF,OAAO,EAAE,KAAK,SAAS,EAAwC,MAAM,aAAa,CAAC;AAMnF,qBAAa,UAAU;IAOnB,OAAO,CAAC,QAAQ,CAAC,MAAM;IANzB,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,IAAI,CAAC,CAAY;IACzB,OAAO,CAAC,SAAS,CAAC,CAAiB;IACnC,OAAO,CAAC,GAAG,CAAuB;gBAGf,MAAM,EAAE,SAAS,EAClC,YAAY,EAAE;QAAE,GAAG,CAAC,EAAE,GAAG,CAAC;QAAC,SAAS,CAAC,EAAE,cAAc,CAAC;QAAC,IAAI,CAAC,EAAE,SAAS,CAAA;KAAE;IA4B3E;;;OAGG;IACU,KAAK;;;;;;IAQL,QAAQ;;;;;;;IAarB;;;OAGG;YACW,YAAY;YAQZ,0BAA0B;YA8B1B,gBAAgB;IAc9B;;OAEG;YACW,iBAAiB;IAK/B;;;;OAIG;YACW,UAAU;IA8BxB;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;YAYZ,gBAAgB;YAoBhB,OAAO;YAyCP,wBAAwB;IAoBtC;;;OAGG;YACW,UAAU;YAuCV,gBAAgB;YAgChB,cAAc;YAMd,WAAW;CAU1B"}
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,YAAY,EAQZ,KAAK,GAAG,EAIT,MAAM,iBAAiB,CAAC;AAIzB,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAIjF,OAAO,EAAE,KAAK,SAAS,EAAwC,MAAM,aAAa,CAAC;AAMnF,qBAAa,UAAU;IAOnB,OAAO,CAAC,QAAQ,CAAC,MAAM;IANzB,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,IAAI,CAAC,CAAY;IACzB,OAAO,CAAC,SAAS,CAAC,CAAiB;IACnC,OAAO,CAAC,GAAG,CAAuB;gBAGf,MAAM,EAAE,SAAS,EAClC,YAAY,EAAE;QAAE,GAAG,CAAC,EAAE,GAAG,CAAC;QAAC,SAAS,CAAC,EAAE,cAAc,CAAC;QAAC,IAAI,CAAC,EAAE,SAAS,CAAA;KAAE;IA4B3E;;;OAGG;IACU,KAAK;;;;;;IAQL,QAAQ;;;;;;;IAarB;;;OAGG;YACW,YAAY;YAQZ,0BAA0B;YAgC1B,gBAAgB;IAc9B;;OAEG;YACW,iBAAiB;IAK/B;;;;OAIG;YACW,UAAU;IA8BxB;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;YAYZ,gBAAgB;YAoBhB,OAAO;YA2DP,wBAAwB;IAoBtC;;;OAGG;YACW,UAAU;YAuCV,gBAAgB;YAgChB,cAAc;YAMd,WAAW;CAU1B"}
package/dest/factory.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import { getSchnorrAccount } from '@aztec/accounts/schnorr';
2
2
  import { getDeployedTestAccountsWallets, getInitialTestAccounts } from '@aztec/accounts/testing';
3
3
  import { BatchCall, FeeJuicePaymentMethodWithClaim, L1FeeJuicePortalManager, createLogger, createPXEClient, retryUntil } from '@aztec/aztec.js';
4
- import { createEthereumChain, createL1Clients } from '@aztec/ethereum';
4
+ import { createEthereumChain, createExtendedL1Client } from '@aztec/ethereum';
5
5
  import { Fr } from '@aztec/foundation/fields';
6
+ import { Timer } from '@aztec/foundation/timer';
6
7
  import { AMMContract } from '@aztec/noir-contracts.js/AMM';
7
8
  import { EasyPrivateTokenContract } from '@aztec/noir-contracts.js/EasyPrivateToken';
8
9
  import { TokenContract } from '@aztec/noir-contracts.js/Token';
@@ -65,7 +66,7 @@ export class BotFactory {
65
66
  const token1 = await this.setupTokenContract(wallet, this.config.tokenSalt, 'BotToken1', 'BOT1');
66
67
  const liquidityToken = await this.setupTokenContract(wallet, this.config.tokenSalt, 'BotLPToken', 'BOTLP');
67
68
  const amm = await this.setupAmmContract(wallet, this.config.tokenSalt, token0, token1, liquidityToken);
68
- await this.fundAmm(wallet, amm, token0, token1);
69
+ await this.fundAmm(wallet, amm, token0, token1, liquidityToken);
69
70
  this.log.info(`AMM initialized and funded`);
70
71
  return {
71
72
  wallet,
@@ -92,7 +93,9 @@ export class BotFactory {
92
93
  const isInit = (await this.pxe.getContractMetadata(account.getAddress())).isContractInitialized;
93
94
  if (isInit) {
94
95
  this.log.info(`Account at ${account.getAddress().toString()} already initialized`);
96
+ const timer = new Timer();
95
97
  const wallet = await account.register();
98
+ this.log.info(`Account at ${account.getAddress()} registered. duration=${timer.ms()}`);
96
99
  return wallet;
97
100
  } else {
98
101
  const address = account.getAddress();
@@ -202,13 +205,20 @@ export class BotFactory {
202
205
  this.log.info(`Liquidity token initialized`);
203
206
  return amm;
204
207
  }
205
- async fundAmm(wallet, amm, token0, token1) {
208
+ async fundAmm(wallet, amm, token0, token1, lpToken) {
209
+ const getPrivateBalances = ()=>Promise.all([
210
+ token0.methods.balance_of_private(wallet.getAddress()),
211
+ token1.methods.balance_of_private(wallet.getAddress()),
212
+ lpToken.methods.balance_of_private(wallet.getAddress())
213
+ ]);
206
214
  const nonce = Fr.random();
207
215
  // keep some tokens for swapping
208
216
  const amount0Max = MINT_BALANCE / 2;
209
217
  const amount0Min = MINT_BALANCE / 4;
210
218
  const amount1Max = MINT_BALANCE / 2;
211
219
  const amount1Min = MINT_BALANCE / 4;
220
+ const [t0Bal, t1Bal, lpBal] = await getPrivateBalances();
221
+ this.log.info(`Minting ${MINT_BALANCE} tokens of each BotToken0 and BotToken1. Current private balances of ${wallet.getAddress()}: token0=${t0Bal}, token1=${t1Bal}, lp=${lpBal}`);
212
222
  const token0Authwit = await wallet.createAuthWit({
213
223
  caller: amm.address,
214
224
  action: token0.methods.transfer_to_public(wallet.getAddress(), amm.address, amount0Max, nonce)
@@ -217,7 +227,6 @@ export class BotFactory {
217
227
  caller: amm.address,
218
228
  action: token1.methods.transfer_to_public(wallet.getAddress(), amm.address, amount1Max, nonce)
219
229
  });
220
- this.log.info(`Minting tokens`);
221
230
  const mintTx = new BatchCall(wallet, [
222
231
  token0.methods.mint_to_private(wallet.getAddress(), wallet.getAddress(), MINT_BALANCE),
223
232
  token1.methods.mint_to_private(wallet.getAddress(), wallet.getAddress(), MINT_BALANCE)
@@ -226,7 +235,6 @@ export class BotFactory {
226
235
  await mintTx.wait({
227
236
  timeout: this.config.txMinedWaitSeconds
228
237
  });
229
- this.log.info(`Funding AMM`);
230
238
  const addLiquidityTx = amm.methods.add_liquidity(amount0Max, amount1Max, amount0Min, amount1Min, nonce).send({
231
239
  authWitnesses: [
232
240
  token0Authwit,
@@ -237,6 +245,9 @@ export class BotFactory {
237
245
  await addLiquidityTx.wait({
238
246
  timeout: this.config.txMinedWaitSeconds
239
247
  });
248
+ this.log.info(`Liquidity added`);
249
+ const [newT0Bal, newT1Bal, newLPBal] = await getPrivateBalances();
250
+ this.log.info(`Updated private balances of ${wallet.getAddress()} after minting and funding AMM: token0=${newT0Bal}, token1=${newT1Bal}, lp=${newLPBal}`);
240
251
  }
241
252
  async registerOrDeployContract(name, deploy, deployOpts) {
242
253
  const address = (await deploy.getInstance(deployOpts)).address;
@@ -302,8 +313,8 @@ export class BotFactory {
302
313
  }
303
314
  const { l1ChainId } = await this.pxe.getNodeInfo();
304
315
  const chain = createEthereumChain(l1RpcUrls, l1ChainId);
305
- const { publicClient, walletClient } = createL1Clients(chain.rpcUrls, mnemonicOrPrivateKey, chain.chainInfo);
306
- const portal = await L1FeeJuicePortalManager.new(this.pxe, publicClient, walletClient, this.log);
316
+ const extendedClient = createExtendedL1Client(chain.rpcUrls, mnemonicOrPrivateKey, chain.chainInfo);
317
+ const portal = await L1FeeJuicePortalManager.new(this.pxe, extendedClient, this.log);
307
318
  const mintAmount = await portal.getTokenManager().getMintAmount();
308
319
  const claim = await portal.bridgeTokensPublic(recipient, mintAmount, true);
309
320
  const isSynced = async ()=>await this.pxe.isL1ToL2MessageSynced(Fr.fromHexString(claim.messageHash));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/bot",
3
- "version": "0.85.0",
3
+ "version": "0.86.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -13,8 +13,6 @@
13
13
  "build": "yarn clean && tsc -b",
14
14
  "build:dev": "tsc -b --watch",
15
15
  "clean": "rm -rf ./dest .tsbuildinfo",
16
- "formatting": "run -T prettier --check ./src && run -T eslint ./src",
17
- "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src",
18
16
  "bb": "node --no-warnings ./dest/bb/index.js",
19
17
  "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}"
20
18
  },
@@ -52,16 +50,16 @@
52
50
  ]
53
51
  },
54
52
  "dependencies": {
55
- "@aztec/accounts": "0.85.0",
56
- "@aztec/aztec.js": "0.85.0",
57
- "@aztec/entrypoints": "0.85.0",
58
- "@aztec/ethereum": "0.85.0",
59
- "@aztec/foundation": "0.85.0",
60
- "@aztec/noir-contracts.js": "0.85.0",
61
- "@aztec/noir-protocol-circuits-types": "0.85.0",
62
- "@aztec/protocol-contracts": "0.85.0",
63
- "@aztec/stdlib": "0.85.0",
64
- "@aztec/telemetry-client": "0.85.0",
53
+ "@aztec/accounts": "0.86.0",
54
+ "@aztec/aztec.js": "0.86.0",
55
+ "@aztec/entrypoints": "0.86.0",
56
+ "@aztec/ethereum": "0.86.0",
57
+ "@aztec/foundation": "0.86.0",
58
+ "@aztec/noir-contracts.js": "0.86.0",
59
+ "@aztec/noir-protocol-circuits-types": "0.86.0",
60
+ "@aztec/protocol-contracts": "0.86.0",
61
+ "@aztec/stdlib": "0.86.0",
62
+ "@aztec/telemetry-client": "0.86.0",
65
63
  "source-map-support": "^0.5.21",
66
64
  "tslib": "^2.4.0",
67
65
  "zod": "^3.23.8"
package/src/amm_bot.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { AztecAddress, Fr, SentTx, type Wallet } from '@aztec/aztec.js';
1
+ import { AztecAddress, Fr, SentTx, TxReceipt, type Wallet } from '@aztec/aztec.js';
2
+ import { jsonStringify } from '@aztec/foundation/json-rpc';
2
3
  import type { AMMContract } from '@aztec/noir-contracts.js/AMM';
3
4
  import type { TokenContract } from '@aztec/noir-contracts.js/Token';
4
5
  import type { AztecNode, AztecNodeAdmin, PXE } from '@aztec/stdlib/interfaces/client';
@@ -7,7 +8,8 @@ import { BaseBot } from './base_bot.js';
7
8
  import type { BotConfig } from './config.js';
8
9
  import { BotFactory } from './factory.js';
9
10
 
10
- const TRANSFER_AMOUNT = 1_000;
11
+ const TRANSFER_BASE_AMOUNT = 1_000;
12
+ const TRANSFER_VARIANCE = 200;
11
13
 
12
14
  type Balances = { token0: bigint; token1: bigint };
13
15
 
@@ -35,24 +37,34 @@ export class AmmBot extends BaseBot {
35
37
  const { feePaymentMethod } = this.config;
36
38
  const { wallet, amm, token0, token1 } = this;
37
39
 
38
- this.log.verbose(`Preparing tx with ${feePaymentMethod} fee to swap tokens`, logCtx);
40
+ const balances = this.getBalances();
41
+ this.log.info(`Preparing tx with ${feePaymentMethod} fee to swap tokens. Balances: ${jsonStringify(balances)}`, {
42
+ ...logCtx,
43
+ balances,
44
+ });
39
45
 
40
- const ammBalances = await this.getAmmBalances();
41
- const amountIn = TRANSFER_AMOUNT;
46
+ // 1000 ± 200
47
+ const amountIn = Math.floor(TRANSFER_BASE_AMOUNT + (Math.random() - 0.5) * TRANSFER_VARIANCE);
42
48
  const nonce = Fr.random();
43
49
 
50
+ const [tokenIn, tokenOut] = Math.random() < 0.5 ? [token0, token1] : [token1, token0];
51
+
44
52
  const swapAuthwit = await wallet.createAuthWit({
45
53
  caller: amm.address,
46
- action: token0.methods.transfer_to_public(wallet.getAddress(), amm.address, amountIn, nonce),
54
+ action: tokenIn.methods.transfer_to_public(wallet.getAddress(), amm.address, amountIn, nonce),
47
55
  });
48
56
 
49
57
  const amountOutMin = await amm.methods
50
- .get_amount_out_for_exact_in(ammBalances.token0, ammBalances.token1, amountIn)
58
+ .get_amount_out_for_exact_in(
59
+ await tokenIn.methods.balance_of_public(amm.address).simulate(),
60
+ await tokenOut.methods.balance_of_public(amm.address).simulate(),
61
+ amountIn,
62
+ )
51
63
  .simulate();
52
64
 
53
65
  const swapExactTokensInteraction = amm.methods.swap_exact_tokens_for_tokens(
54
- token0.address,
55
- token1.address,
66
+ tokenIn.address,
67
+ tokenOut.address,
56
68
  amountIn,
57
69
  amountOutMin,
58
70
  nonce,
@@ -63,9 +75,16 @@ export class AmmBot extends BaseBot {
63
75
  this.log.verbose(`Proving transaction`, logCtx);
64
76
  const tx = await swapExactTokensInteraction.prove(opts);
65
77
 
78
+ this.log.info(`Tx. Balances: ${jsonStringify(balances)}`, { ...logCtx, balances });
79
+
66
80
  return tx.send();
67
81
  }
68
82
 
83
+ protected override async onTxMined(receipt: TxReceipt, logCtx: object): Promise<void> {
84
+ const balances = await this.getBalances();
85
+ this.log.info(`Balances after swap in tx ${receipt.txHash}: ${jsonStringify(balances)}`, { ...logCtx, balances });
86
+ }
87
+
69
88
  public getAmmBalances(): Promise<Balances> {
70
89
  return this.getPublicBalanceFor(this.amm.address);
71
90
  }
package/src/base_bot.ts CHANGED
@@ -52,11 +52,19 @@ export abstract class BaseBot {
52
52
  `Tx #${this.attempts} ${receipt.txHash} successfully mined in block ${receipt.blockNumber} (stats: ${this.successes}/${this.attempts} success)`,
53
53
  logCtx,
54
54
  );
55
+
56
+ await this.onTxMined(receipt, logCtx);
57
+
55
58
  return receipt;
56
59
  }
57
60
 
58
61
  protected abstract createAndSendTx(logCtx: object): Promise<SentTx>;
59
62
 
63
+ protected onTxMined(_receipt: TxReceipt, _logCtx: object): Promise<void> {
64
+ // no-op
65
+ return Promise.resolve();
66
+ }
67
+
60
68
  protected getSendMethodOpts(...authWitnesses: AuthWitness[]): SendMethodOptions {
61
69
  const sender = this.wallet.getAddress();
62
70
  const { l2GasLimit, daGasLimit, skipPublicSimulation } = this.config;
package/src/factory.ts CHANGED
@@ -15,8 +15,9 @@ import {
15
15
  createPXEClient,
16
16
  retryUntil,
17
17
  } from '@aztec/aztec.js';
18
- import { createEthereumChain, createL1Clients } from '@aztec/ethereum';
18
+ import { createEthereumChain, createExtendedL1Client } from '@aztec/ethereum';
19
19
  import { Fr } from '@aztec/foundation/fields';
20
+ import { Timer } from '@aztec/foundation/timer';
20
21
  import { AMMContract } from '@aztec/noir-contracts.js/AMM';
21
22
  import { EasyPrivateTokenContract } from '@aztec/noir-contracts.js/EasyPrivateToken';
22
23
  import { TokenContract } from '@aztec/noir-contracts.js/Token';
@@ -85,7 +86,7 @@ export class BotFactory {
85
86
  const liquidityToken = await this.setupTokenContract(wallet, this.config.tokenSalt, 'BotLPToken', 'BOTLP');
86
87
  const amm = await this.setupAmmContract(wallet, this.config.tokenSalt, token0, token1, liquidityToken);
87
88
 
88
- await this.fundAmm(wallet, amm, token0, token1);
89
+ await this.fundAmm(wallet, amm, token0, token1, liquidityToken);
89
90
  this.log.info(`AMM initialized and funded`);
90
91
 
91
92
  return { wallet, amm, token0, token1, pxe: this.pxe };
@@ -110,7 +111,9 @@ export class BotFactory {
110
111
  const isInit = (await this.pxe.getContractMetadata(account.getAddress())).isContractInitialized;
111
112
  if (isInit) {
112
113
  this.log.info(`Account at ${account.getAddress().toString()} already initialized`);
114
+ const timer = new Timer();
113
115
  const wallet = await account.register();
116
+ this.log.info(`Account at ${account.getAddress()} registered. duration=${timer.ms()}`);
114
117
  return wallet;
115
118
  } else {
116
119
  const address = account.getAddress();
@@ -232,7 +235,15 @@ export class BotFactory {
232
235
  amm: AMMContract,
233
236
  token0: TokenContract,
234
237
  token1: TokenContract,
238
+ lpToken: TokenContract,
235
239
  ): Promise<void> {
240
+ const getPrivateBalances = () =>
241
+ Promise.all([
242
+ token0.methods.balance_of_private(wallet.getAddress()),
243
+ token1.methods.balance_of_private(wallet.getAddress()),
244
+ lpToken.methods.balance_of_private(wallet.getAddress()),
245
+ ]);
246
+
236
247
  const nonce = Fr.random();
237
248
 
238
249
  // keep some tokens for swapping
@@ -241,6 +252,12 @@ export class BotFactory {
241
252
  const amount1Max = MINT_BALANCE / 2;
242
253
  const amount1Min = MINT_BALANCE / 4;
243
254
 
255
+ const [t0Bal, t1Bal, lpBal] = await getPrivateBalances();
256
+
257
+ this.log.info(
258
+ `Minting ${MINT_BALANCE} tokens of each BotToken0 and BotToken1. Current private balances of ${wallet.getAddress()}: token0=${t0Bal}, token1=${t1Bal}, lp=${lpBal}`,
259
+ );
260
+
244
261
  const token0Authwit = await wallet.createAuthWit({
245
262
  caller: amm.address,
246
263
  action: token0.methods.transfer_to_public(wallet.getAddress(), amm.address, amount0Max, nonce),
@@ -250,7 +267,6 @@ export class BotFactory {
250
267
  action: token1.methods.transfer_to_public(wallet.getAddress(), amm.address, amount1Max, nonce),
251
268
  });
252
269
 
253
- this.log.info(`Minting tokens`);
254
270
  const mintTx = new BatchCall(wallet, [
255
271
  token0.methods.mint_to_private(wallet.getAddress(), wallet.getAddress(), MINT_BALANCE),
256
272
  token1.methods.mint_to_private(wallet.getAddress(), wallet.getAddress(), MINT_BALANCE),
@@ -259,13 +275,18 @@ export class BotFactory {
259
275
  this.log.info(`Sent mint tx: ${await mintTx.getTxHash()}`);
260
276
  await mintTx.wait({ timeout: this.config.txMinedWaitSeconds });
261
277
 
262
- this.log.info(`Funding AMM`);
263
278
  const addLiquidityTx = amm.methods.add_liquidity(amount0Max, amount1Max, amount0Min, amount1Min, nonce).send({
264
279
  authWitnesses: [token0Authwit, token1Authwit],
265
280
  });
266
281
 
267
282
  this.log.info(`Sent tx to add liquidity to the AMM: ${await addLiquidityTx.getTxHash()}`);
268
283
  await addLiquidityTx.wait({ timeout: this.config.txMinedWaitSeconds });
284
+ this.log.info(`Liquidity added`);
285
+
286
+ const [newT0Bal, newT1Bal, newLPBal] = await getPrivateBalances();
287
+ this.log.info(
288
+ `Updated private balances of ${wallet.getAddress()} after minting and funding AMM: token0=${newT0Bal}, token1=${newT1Bal}, lp=${newLPBal}`,
289
+ );
269
290
  }
270
291
 
271
292
  private async registerOrDeployContract<T extends ContractBase>(
@@ -345,9 +366,9 @@ export class BotFactory {
345
366
 
346
367
  const { l1ChainId } = await this.pxe.getNodeInfo();
347
368
  const chain = createEthereumChain(l1RpcUrls, l1ChainId);
348
- const { publicClient, walletClient } = createL1Clients(chain.rpcUrls, mnemonicOrPrivateKey, chain.chainInfo);
369
+ const extendedClient = createExtendedL1Client(chain.rpcUrls, mnemonicOrPrivateKey, chain.chainInfo);
349
370
 
350
- const portal = await L1FeeJuicePortalManager.new(this.pxe, publicClient, walletClient, this.log);
371
+ const portal = await L1FeeJuicePortalManager.new(this.pxe, extendedClient, this.log);
351
372
  const mintAmount = await portal.getTokenManager().getMintAmount();
352
373
  const claim = await portal.bridgeTokensPublic(recipient, mintAmount, true /* mint */);
353
374