@aztec/bot 0.0.0-test.1 → 0.0.1-fake-ceab37513c

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.
@@ -0,0 +1,33 @@
1
+ import { AztecAddress, SentTx, TxReceipt, type Wallet } from '@aztec/aztec.js';
2
+ import type { AMMContract } from '@aztec/noir-contracts.js/AMM';
3
+ import type { TokenContract } from '@aztec/noir-contracts.js/Token';
4
+ import type { AztecNode, AztecNodeAdmin, PXE } from '@aztec/stdlib/interfaces/client';
5
+ import { BaseBot } from './base_bot.js';
6
+ import type { BotConfig } from './config.js';
7
+ type Balances = {
8
+ token0: bigint;
9
+ token1: bigint;
10
+ };
11
+ export declare class AmmBot extends BaseBot {
12
+ readonly amm: AMMContract;
13
+ readonly token0: TokenContract;
14
+ readonly token1: TokenContract;
15
+ protected constructor(pxe: PXE, wallet: Wallet, defaultAccountAddress: AztecAddress, amm: AMMContract, token0: TokenContract, token1: TokenContract, config: BotConfig);
16
+ static create(config: BotConfig, dependencies: {
17
+ pxe?: PXE;
18
+ node?: AztecNode;
19
+ nodeAdmin?: AztecNodeAdmin;
20
+ }): Promise<AmmBot>;
21
+ protected createAndSendTx(logCtx: object): Promise<SentTx>;
22
+ protected onTxMined(receipt: TxReceipt, logCtx: object): Promise<void>;
23
+ getAmmBalances(): Promise<Balances>;
24
+ getBalances(): Promise<{
25
+ senderPublic: Balances;
26
+ senderPrivate: Balances;
27
+ amm: Balances;
28
+ }>;
29
+ private getPublicBalanceFor;
30
+ private getPrivateBalanceFor;
31
+ }
32
+ export {};
33
+ //# sourceMappingURL=amm_bot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"amm_bot.d.ts","sourceRoot":"","sources":["../src/amm_bot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAM,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;aAKf,GAAG,EAAE,WAAW;aAChB,MAAM,EAAE,aAAa;aACrB,MAAM,EAAE,aAAa;IANvC,SAAS,aACP,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,EACd,qBAAqB,EAAE,YAAY,EACnB,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;cAQF,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"}
@@ -0,0 +1,94 @@
1
+ import { Fr } from '@aztec/aztec.js';
2
+ import { jsonStringify } from '@aztec/foundation/json-rpc';
3
+ import { BaseBot } from './base_bot.js';
4
+ import { BotFactory } from './factory.js';
5
+ const TRANSFER_BASE_AMOUNT = 1_000;
6
+ const TRANSFER_VARIANCE = 200;
7
+ export class AmmBot extends BaseBot {
8
+ amm;
9
+ token0;
10
+ token1;
11
+ constructor(pxe, wallet, defaultAccountAddress, amm, token0, token1, config){
12
+ super(pxe, wallet, defaultAccountAddress, config), this.amm = amm, this.token0 = token0, this.token1 = token1;
13
+ }
14
+ static async create(config, dependencies) {
15
+ const { pxe, wallet, defaultAccountAddress, token0, token1, amm } = await new BotFactory(config, dependencies).setupAmm();
16
+ return new AmmBot(pxe, wallet, defaultAccountAddress, amm, token0, token1, config);
17
+ }
18
+ async createAndSendTx(logCtx) {
19
+ const { feePaymentMethod } = this.config;
20
+ const { wallet, amm, token0, token1 } = this;
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);
28
+ const authwitNonce = Fr.random();
29
+ const [tokenIn, tokenOut] = Math.random() < 0.5 ? [
30
+ token0,
31
+ token1
32
+ ] : [
33
+ token1,
34
+ token0
35
+ ];
36
+ const swapAuthwit = await wallet.createAuthWit({
37
+ caller: amm.address,
38
+ action: tokenIn.methods.transfer_to_public(this.defaultAccountAddress, amm.address, amountIn, authwitNonce)
39
+ });
40
+ const amountOutMin = await amm.methods.get_amount_out_for_exact_in(await tokenIn.methods.balance_of_public(amm.address).simulate({
41
+ from: this.defaultAccountAddress
42
+ }), await tokenOut.methods.balance_of_public(amm.address).simulate({
43
+ from: this.defaultAccountAddress
44
+ }), amountIn).simulate({
45
+ from: this.defaultAccountAddress
46
+ });
47
+ const swapExactTokensInteraction = amm.methods.swap_exact_tokens_for_tokens(tokenIn.address, tokenOut.address, amountIn, amountOutMin, authwitNonce);
48
+ const opts = this.getSendMethodOpts(swapAuthwit);
49
+ this.log.verbose(`Proving transaction`, logCtx);
50
+ const tx = await swapExactTokensInteraction.prove(opts);
51
+ this.log.info(`Tx. Balances: ${jsonStringify(balances)}`, {
52
+ ...logCtx,
53
+ balances
54
+ });
55
+ return tx.send();
56
+ }
57
+ async onTxMined(receipt, logCtx) {
58
+ const balances = await this.getBalances();
59
+ this.log.info(`Balances after swap in tx ${receipt.txHash}: ${jsonStringify(balances)}`, {
60
+ ...logCtx,
61
+ balances
62
+ });
63
+ }
64
+ getAmmBalances() {
65
+ return this.getPublicBalanceFor(this.amm.address);
66
+ }
67
+ async getBalances() {
68
+ return {
69
+ senderPublic: await this.getPublicBalanceFor(this.defaultAccountAddress),
70
+ senderPrivate: await this.getPrivateBalanceFor(this.defaultAccountAddress),
71
+ amm: await this.getPublicBalanceFor(this.amm.address)
72
+ };
73
+ }
74
+ async getPublicBalanceFor(address) {
75
+ return {
76
+ token0: await this.token0.methods.balance_of_public(address).simulate({
77
+ from: address
78
+ }),
79
+ token1: await this.token1.methods.balance_of_public(address).simulate({
80
+ from: address
81
+ })
82
+ };
83
+ }
84
+ async getPrivateBalanceFor(address) {
85
+ return {
86
+ token0: await this.token0.methods.balance_of_private(address).simulate({
87
+ from: address
88
+ }),
89
+ token1: await this.token1.methods.balance_of_private(address).simulate({
90
+ from: address
91
+ })
92
+ };
93
+ }
94
+ }
@@ -0,0 +1,18 @@
1
+ import { AuthWitness, AztecAddress, type SendMethodOptions, SentTx, TxHash, TxReceipt, type Wallet } from '@aztec/aztec.js';
2
+ import type { PXE } from '@aztec/stdlib/interfaces/client';
3
+ import type { BotConfig } from './config.js';
4
+ export declare abstract class BaseBot {
5
+ readonly pxe: PXE;
6
+ readonly wallet: Wallet;
7
+ readonly defaultAccountAddress: AztecAddress;
8
+ config: BotConfig;
9
+ protected log: import("@aztec/aztec.js").Logger;
10
+ protected attempts: number;
11
+ protected successes: number;
12
+ protected constructor(pxe: PXE, wallet: Wallet, defaultAccountAddress: AztecAddress, config: BotConfig);
13
+ run(): Promise<TxReceipt | TxHash>;
14
+ protected abstract createAndSendTx(logCtx: object): Promise<SentTx>;
15
+ protected onTxMined(_receipt: TxReceipt, _logCtx: object): Promise<void>;
16
+ protected getSendMethodOpts(...authWitnesses: AuthWitness[]): SendMethodOptions;
17
+ }
18
+ //# sourceMappingURL=base_bot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base_bot.d.ts","sourceRoot":"","sources":["../src/base_bot.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,YAAY,EAEZ,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;aAOT,GAAG,EAAE,GAAG;aACR,MAAM,EAAE,MAAM;aACd,qBAAqB,EAAE,YAAY;IAC5C,MAAM,EAAE,SAAS;IAT1B,SAAS,CAAC,GAAG,mCAAuB;IAEpC,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAK;IAC/B,SAAS,CAAC,SAAS,EAAE,MAAM,CAAK;IAEhC,SAAS,aACS,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,EACd,qBAAqB,EAAE,YAAY,EAC5C,MAAM,EAAE,SAAS;IAGb,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;CAoBhF"}
@@ -0,0 +1,80 @@
1
+ import { FeeJuicePaymentMethod, createLogger, waitForProven } from '@aztec/aztec.js';
2
+ import { Gas } from '@aztec/stdlib/gas';
3
+ export class BaseBot {
4
+ pxe;
5
+ wallet;
6
+ defaultAccountAddress;
7
+ config;
8
+ log;
9
+ attempts;
10
+ successes;
11
+ constructor(pxe, wallet, defaultAccountAddress, config){
12
+ this.pxe = pxe;
13
+ this.wallet = wallet;
14
+ this.defaultAccountAddress = defaultAccountAddress;
15
+ this.config = config;
16
+ this.log = createLogger('bot');
17
+ this.attempts = 0;
18
+ this.successes = 0;
19
+ }
20
+ async run() {
21
+ this.attempts++;
22
+ const logCtx = {
23
+ runId: Date.now() * 1000 + Math.floor(Math.random() * 1000)
24
+ };
25
+ const { followChain, txMinedWaitSeconds } = this.config;
26
+ this.log.verbose(`Creating tx`, logCtx);
27
+ const tx = await this.createAndSendTx(logCtx);
28
+ const txHash = await tx.getTxHash();
29
+ if (followChain === 'NONE') {
30
+ this.log.info(`Transaction ${txHash.toString()} sent, not waiting for it to be mined`);
31
+ return txHash;
32
+ }
33
+ this.log.verbose(`Awaiting tx ${txHash.toString()} to be on the ${followChain} chain (timeout ${txMinedWaitSeconds}s)`, logCtx);
34
+ const receipt = await tx.wait({
35
+ timeout: txMinedWaitSeconds
36
+ });
37
+ if (followChain === 'PROVEN') {
38
+ await waitForProven(this.pxe, receipt, {
39
+ provenTimeout: txMinedWaitSeconds
40
+ });
41
+ }
42
+ this.successes++;
43
+ this.log.info(`Tx #${this.attempts} ${receipt.txHash} successfully mined in block ${receipt.blockNumber} (stats: ${this.successes}/${this.attempts} success)`, logCtx);
44
+ await this.onTxMined(receipt, logCtx);
45
+ return receipt;
46
+ }
47
+ onTxMined(_receipt, _logCtx) {
48
+ // no-op
49
+ return Promise.resolve();
50
+ }
51
+ getSendMethodOpts(...authWitnesses) {
52
+ const { l2GasLimit, daGasLimit } = this.config;
53
+ const paymentMethod = new FeeJuicePaymentMethod(this.defaultAccountAddress);
54
+ let gasSettings, estimateGas;
55
+ if (l2GasLimit !== undefined && l2GasLimit > 0 && daGasLimit !== undefined && daGasLimit > 0) {
56
+ gasSettings = {
57
+ gasLimits: Gas.from({
58
+ l2Gas: l2GasLimit,
59
+ daGas: daGasLimit
60
+ })
61
+ };
62
+ estimateGas = false;
63
+ this.log.verbose(`Using gas limits ${l2GasLimit} L2 gas ${daGasLimit} DA gas`);
64
+ } else {
65
+ estimateGas = true;
66
+ this.log.verbose(`Estimating gas for transaction`);
67
+ }
68
+ const baseFeePadding = 2; // Send 3x the current base fee
69
+ return {
70
+ from: this.defaultAccountAddress,
71
+ fee: {
72
+ estimateGas,
73
+ paymentMethod,
74
+ gasSettings,
75
+ baseFeePadding
76
+ },
77
+ authWitnesses
78
+ };
79
+ }
80
+ }
package/dest/bot.d.ts CHANGED
@@ -1,23 +1,20 @@
1
- import { type AztecAddress, type Wallet } from '@aztec/aztec.js';
2
- import type { EasyPrivateTokenContract } from '@aztec/noir-contracts.js/EasyPrivateToken';
1
+ import { type AztecAddress, SentTx, type Wallet } from '@aztec/aztec.js';
2
+ import type { PrivateTokenContract } from '@aztec/noir-contracts.js/PrivateToken';
3
3
  import type { TokenContract } from '@aztec/noir-contracts.js/Token';
4
- import type { AztecNode, PXE } from '@aztec/stdlib/interfaces/client';
4
+ import type { AztecNode, AztecNodeAdmin, PXE } from '@aztec/stdlib/interfaces/client';
5
+ import { BaseBot } from './base_bot.js';
5
6
  import type { BotConfig } from './config.js';
6
- export declare class Bot {
7
- readonly wallet: Wallet;
8
- readonly token: TokenContract | EasyPrivateTokenContract;
7
+ export declare class Bot extends BaseBot {
8
+ readonly token: TokenContract | PrivateTokenContract;
9
9
  readonly recipient: AztecAddress;
10
- config: BotConfig;
11
- private log;
12
- private attempts;
13
- private successes;
14
- protected constructor(wallet: Wallet, token: TokenContract | EasyPrivateTokenContract, recipient: AztecAddress, config: BotConfig);
15
- static create(config: BotConfig, dependencies?: {
10
+ protected constructor(pxe: PXE, wallet: Wallet, defaultAccountAddress: AztecAddress, token: TokenContract | PrivateTokenContract, recipient: AztecAddress, config: BotConfig);
11
+ static create(config: BotConfig, dependencies: {
16
12
  pxe?: PXE;
17
13
  node?: AztecNode;
14
+ nodeAdmin?: AztecNodeAdmin;
18
15
  }): Promise<Bot>;
19
16
  updateConfig(config: Partial<BotConfig>): void;
20
- run(): Promise<void>;
17
+ protected createAndSendTx(logCtx: object): Promise<SentTx>;
21
18
  getBalances(): Promise<{
22
19
  sender: {
23
20
  privateBalance: bigint;
@@ -28,6 +25,5 @@ export declare class Bot {
28
25
  publicBalance: bigint;
29
26
  };
30
27
  }>;
31
- private getSendMethodOpts;
32
28
  }
33
29
  //# sourceMappingURL=bot.d.ts.map
package/dest/bot.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EAIjB,KAAK,MAAM,EAEZ,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;AAC1F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAGpE,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,iCAAiC,CAAC;AAEtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAM7C,qBAAa,GAAG;aAOI,MAAM,EAAE,MAAM;aACd,KAAK,EAAE,aAAa,GAAG,wBAAwB;aAC/C,SAAS,EAAE,YAAY;IAChC,MAAM,EAAE,SAAS;IAT1B,OAAO,CAAC,GAAG,CAAuB;IAElC,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,SAAS,CAAa;IAE9B,SAAS,aACS,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,aAAa,GAAG,wBAAwB,EAC/C,SAAS,EAAE,YAAY,EAChC,MAAM,EAAE,SAAS;WAGb,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,GAAE;QAAE,GAAG,CAAC,EAAE,GAAG,CAAC;QAAC,IAAI,CAAC,EAAE,SAAS,CAAA;KAAO,GAAG,OAAO,CAAC,GAAG,CAAC;IAKjG,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC;IAKjC,GAAG;IAoEH,WAAW;;;;;;;;;;IAoBxB,OAAO,CAAC,iBAAiB;CAkB1B"}
1
+ {"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAa,MAAM,EAAE,KAAK,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEpF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAClF,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,qBAAa,GAAI,SAAQ,OAAO;aAKZ,KAAK,EAAE,aAAa,GAAG,oBAAoB;aAC3C,SAAS,EAAE,YAAY;IALzC,SAAS,aACP,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,EACd,qBAAqB,EAAE,YAAY,EACnB,KAAK,EAAE,aAAa,GAAG,oBAAoB,EAC3C,SAAS,EAAE,YAAY,EACvC,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,GAAG,CAAC;IAKR,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC;cAK9B,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA+BnD,WAAW;;;;;;;;;;CAmBzB"}
package/dest/bot.js CHANGED
@@ -1,29 +1,18 @@
1
- import { BatchCall, FeeJuicePaymentMethod, createLogger } from '@aztec/aztec.js';
2
- import { timesParallel } from '@aztec/foundation/collection';
3
- import { Gas } from '@aztec/stdlib/gas';
1
+ import { BatchCall } from '@aztec/aztec.js';
2
+ import { times } from '@aztec/foundation/collection';
3
+ import { BaseBot } from './base_bot.js';
4
4
  import { BotFactory } from './factory.js';
5
5
  import { getBalances, getPrivateBalance, isStandardTokenContract } from './utils.js';
6
6
  const TRANSFER_AMOUNT = 1;
7
- export class Bot {
8
- wallet;
7
+ export class Bot extends BaseBot {
9
8
  token;
10
9
  recipient;
11
- config;
12
- log;
13
- attempts;
14
- successes;
15
- constructor(wallet, token, recipient, config){
16
- this.wallet = wallet;
17
- this.token = token;
18
- this.recipient = recipient;
19
- this.config = config;
20
- this.log = createLogger('bot');
21
- this.attempts = 0;
22
- this.successes = 0;
10
+ constructor(pxe, wallet, defaultAccountAddress, token, recipient, config){
11
+ super(pxe, wallet, defaultAccountAddress, config), this.token = token, this.recipient = recipient;
23
12
  }
24
- static async create(config, dependencies = {}) {
25
- const { wallet, token, recipient } = await new BotFactory(config, dependencies).setup();
26
- return new Bot(wallet, token, recipient, config);
13
+ static async create(config, dependencies) {
14
+ const { pxe, wallet, defaultAccountAddress, token, recipient } = await new BotFactory(config, dependencies).setup();
15
+ return new Bot(pxe, wallet, defaultAccountAddress, token, recipient, config);
27
16
  }
28
17
  updateConfig(config) {
29
18
  this.log.info(`Updating bot config ${Object.keys(config).join(', ')}`);
@@ -32,54 +21,34 @@ export class Bot {
32
21
  ...config
33
22
  };
34
23
  }
35
- async run() {
36
- this.attempts++;
37
- const logCtx = {
38
- runId: Date.now() * 1000 + Math.floor(Math.random() * 1000)
39
- };
40
- const { privateTransfersPerTx, publicTransfersPerTx, feePaymentMethod, followChain, txMinedWaitSeconds } = this.config;
24
+ async createAndSendTx(logCtx) {
25
+ const { privateTransfersPerTx, publicTransfersPerTx, feePaymentMethod } = this.config;
41
26
  const { token, recipient, wallet } = this;
42
- const sender = wallet.getAddress();
43
27
  this.log.verbose(`Preparing tx with ${feePaymentMethod} fee with ${privateTransfersPerTx} private and ${publicTransfersPerTx} public transfers`, logCtx);
44
- const calls = [];
45
- if (isStandardTokenContract(token)) {
46
- calls.push(...await timesParallel(privateTransfersPerTx, ()=>token.methods.transfer(recipient, TRANSFER_AMOUNT).request()));
47
- calls.push(...await timesParallel(publicTransfersPerTx, ()=>token.methods.transfer_in_public(sender, recipient, TRANSFER_AMOUNT, 0).request()));
48
- } else {
49
- calls.push(...await timesParallel(privateTransfersPerTx, ()=>token.methods.transfer(TRANSFER_AMOUNT, sender, recipient).request()));
50
- }
28
+ const calls = isStandardTokenContract(token) ? [
29
+ times(privateTransfersPerTx, ()=>token.methods.transfer(recipient, TRANSFER_AMOUNT)),
30
+ times(publicTransfersPerTx, ()=>token.methods.transfer_in_public(this.defaultAccountAddress, recipient, TRANSFER_AMOUNT, 0))
31
+ ].flat() : times(privateTransfersPerTx, ()=>token.methods.transfer(TRANSFER_AMOUNT, this.defaultAccountAddress, recipient));
51
32
  const opts = this.getSendMethodOpts();
52
33
  const batch = new BatchCall(wallet, calls);
53
34
  this.log.verbose(`Simulating transaction with ${calls.length}`, logCtx);
54
- await batch.simulate();
35
+ await batch.simulate({
36
+ from: this.defaultAccountAddress
37
+ });
55
38
  this.log.verbose(`Proving transaction`, logCtx);
56
39
  const provenTx = await batch.prove(opts);
57
- this.log.verbose(`Sending tx`, logCtx);
58
- const tx = provenTx.send();
59
- const txHash = await tx.getTxHash();
60
- if (followChain === 'NONE') {
61
- this.log.info(`Transaction ${txHash} sent, not waiting for it to be mined`);
62
- return;
63
- }
64
- this.log.verbose(`Awaiting tx ${txHash} to be on the ${followChain} chain (timeout ${txMinedWaitSeconds}s)`, logCtx);
65
- const receipt = await tx.wait({
66
- timeout: txMinedWaitSeconds,
67
- provenTimeout: txMinedWaitSeconds,
68
- proven: followChain === 'PROVEN'
69
- });
70
- this.log.info(`Tx #${this.attempts} ${receipt.txHash} successfully mined in block ${receipt.blockNumber} (stats: ${this.successes}/${this.attempts} success)`, logCtx);
71
- this.successes++;
40
+ return provenTx.send();
72
41
  }
73
42
  async getBalances() {
74
43
  if (isStandardTokenContract(this.token)) {
75
44
  return {
76
- sender: await getBalances(this.token, this.wallet.getAddress()),
45
+ sender: await getBalances(this.token, this.defaultAccountAddress),
77
46
  recipient: await getBalances(this.token, this.recipient)
78
47
  };
79
48
  } else {
80
49
  return {
81
50
  sender: {
82
- privateBalance: await getPrivateBalance(this.token, this.wallet.getAddress()),
51
+ privateBalance: await getPrivateBalance(this.token, this.defaultAccountAddress),
83
52
  publicBalance: 0n
84
53
  },
85
54
  recipient: {
@@ -89,34 +58,4 @@ export class Bot {
89
58
  };
90
59
  }
91
60
  }
92
- getSendMethodOpts() {
93
- const sender = this.wallet.getAddress();
94
- const { l2GasLimit, daGasLimit, skipPublicSimulation } = this.config;
95
- const paymentMethod = new FeeJuicePaymentMethod(sender);
96
- let gasSettings, estimateGas;
97
- if (l2GasLimit !== undefined && l2GasLimit > 0 && daGasLimit !== undefined && daGasLimit > 0) {
98
- gasSettings = {
99
- gasLimits: Gas.from({
100
- l2Gas: l2GasLimit,
101
- daGas: daGasLimit
102
- })
103
- };
104
- estimateGas = false;
105
- this.log.verbose(`Using gas limits ${l2GasLimit} L2 gas ${daGasLimit} DA gas`);
106
- } else {
107
- estimateGas = true;
108
- this.log.verbose(`Estimating gas for transaction`);
109
- }
110
- const baseFeePadding = 2; // Send 3x the current base fee
111
- this.log.verbose(skipPublicSimulation ? `Skipping public simulation` : `Simulating public transfers`);
112
- return {
113
- fee: {
114
- estimateGas,
115
- paymentMethod,
116
- gasSettings,
117
- baseFeePadding
118
- },
119
- skipPublicSimulation
120
- };
121
- }
122
61
  }
package/dest/config.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type ConfigMappingsType } from '@aztec/foundation/config';
1
+ import { type ConfigMappingsType, SecretValue } from '@aztec/foundation/config';
2
2
  import { Fr } from '@aztec/foundation/fields';
3
3
  import { type ZodFor } from '@aztec/stdlib/schemas';
4
4
  import type { ComponentsVersions } from '@aztec/stdlib/versioning';
@@ -7,24 +7,30 @@ declare const BotFollowChain: readonly ["NONE", "PENDING", "PROVEN"];
7
7
  type BotFollowChain = (typeof BotFollowChain)[number];
8
8
  export declare enum SupportedTokenContracts {
9
9
  TokenContract = "TokenContract",
10
- EasyPrivateTokenContract = "EasyPrivateTokenContract"
10
+ PrivateTokenContract = "PrivateTokenContract"
11
11
  }
12
12
  export type BotConfig = {
13
13
  /** The URL to the Aztec node to check for tx pool status. */
14
14
  nodeUrl: string | undefined;
15
+ /** The URL to the Aztec node admin API to force-flush txs if configured. */
16
+ nodeAdminUrl: string | undefined;
15
17
  /** URL to the PXE for sending txs, or undefined if an in-proc PXE is used. */
16
18
  pxeUrl: string | undefined;
17
19
  /** Url of the ethereum host. */
18
20
  l1RpcUrls: string[] | undefined;
19
21
  /** The mnemonic for the account to bridge fee juice from L1. */
20
- l1Mnemonic: string | undefined;
22
+ l1Mnemonic: SecretValue<string> | undefined;
21
23
  /** The private key for the account to bridge fee juice from L1. */
22
- l1PrivateKey: string | undefined;
24
+ l1PrivateKey: SecretValue<string> | undefined;
25
+ /** How long to wait for L1 to L2 messages to become available on L2 */
26
+ l1ToL2MessageTimeoutSeconds: number;
23
27
  /** Signing private key for the sender account. */
24
- senderPrivateKey: Fr | undefined;
28
+ senderPrivateKey: SecretValue<Fr> | undefined;
29
+ /** Optional salt to use to instantiate the sender account */
30
+ senderSalt: Fr | undefined;
25
31
  /** Encryption secret for a recipient account. */
26
- recipientEncryptionSecret: Fr;
27
- /** Salt for the token contract deployment. */
32
+ recipientEncryptionSecret: SecretValue<Fr>;
33
+ /** Salt for the token contract instantiation. */
28
34
  tokenSalt: Fr;
29
35
  /** Every how many seconds should a new tx be sent. */
30
36
  txIntervalSeconds: number;
@@ -44,8 +50,6 @@ export type BotConfig = {
44
50
  maxPendingTxs: number;
45
51
  /** Whether to flush after sending each 'setup' transaction */
46
52
  flushSetupTransactions: boolean;
47
- /** Whether to skip public simulation of txs before sending them. */
48
- skipPublicSimulation: boolean;
49
53
  /** L2 gas limit for the tx (empty to have the bot trigger an estimate gas). */
50
54
  l2GasLimit: number | undefined;
51
55
  /** DA gas limit for the tx (empty to have the bot trigger an estimate gas). */
@@ -56,15 +60,20 @@ export type BotConfig = {
56
60
  maxConsecutiveErrors: number;
57
61
  /** Stops the bot if service becomes unhealthy */
58
62
  stopWhenUnhealthy: boolean;
63
+ /** Deploy an AMM contract and do swaps instead of transfers */
64
+ ammTxs: boolean;
59
65
  };
60
66
  export declare const BotConfigSchema: z.ZodEffects<z.ZodObject<{
61
67
  nodeUrl: z.ZodOptional<z.ZodString>;
68
+ nodeAdminUrl: z.ZodOptional<z.ZodString>;
62
69
  pxeUrl: z.ZodOptional<z.ZodString>;
63
70
  l1RpcUrls: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
64
- l1Mnemonic: z.ZodOptional<z.ZodString>;
65
- l1PrivateKey: z.ZodOptional<z.ZodString>;
66
- senderPrivateKey: z.ZodOptional<ZodFor<Fr>>;
67
- recipientEncryptionSecret: ZodFor<Fr>;
71
+ l1Mnemonic: z.ZodOptional<z.ZodType<SecretValue<string>, any, any>>;
72
+ l1PrivateKey: z.ZodOptional<z.ZodType<SecretValue<string>, any, any>>;
73
+ l1ToL2MessageTimeoutSeconds: z.ZodNumber;
74
+ senderPrivateKey: z.ZodOptional<z.ZodType<SecretValue<Fr>, any, any>>;
75
+ senderSalt: z.ZodOptional<ZodFor<Fr>>;
76
+ recipientEncryptionSecret: z.ZodType<SecretValue<Fr>, any, any>;
68
77
  tokenSalt: ZodFor<Fr>;
69
78
  txIntervalSeconds: z.ZodNumber;
70
79
  privateTransfersPerTx: z.ZodNumber;
@@ -75,14 +84,15 @@ export declare const BotConfigSchema: z.ZodEffects<z.ZodObject<{
75
84
  followChain: z.ZodEnum<["NONE", "PENDING", "PROVEN"]>;
76
85
  maxPendingTxs: z.ZodNumber;
77
86
  flushSetupTransactions: z.ZodBoolean;
78
- skipPublicSimulation: z.ZodBoolean;
79
87
  l2GasLimit: z.ZodOptional<z.ZodNumber>;
80
88
  daGasLimit: z.ZodOptional<z.ZodNumber>;
81
89
  contract: z.ZodNativeEnum<typeof SupportedTokenContracts>;
82
90
  maxConsecutiveErrors: z.ZodNumber;
83
91
  stopWhenUnhealthy: z.ZodBoolean;
92
+ ammTxs: z.ZodDefault<z.ZodBoolean>;
84
93
  }, "strip", z.ZodTypeAny, {
85
- recipientEncryptionSecret: Fr;
94
+ l1ToL2MessageTimeoutSeconds: number;
95
+ recipientEncryptionSecret: SecretValue<Fr>;
86
96
  tokenSalt: Fr;
87
97
  txIntervalSeconds: number;
88
98
  privateTransfersPerTx: number;
@@ -93,19 +103,22 @@ export declare const BotConfigSchema: z.ZodEffects<z.ZodObject<{
93
103
  followChain: "NONE" | "PENDING" | "PROVEN";
94
104
  maxPendingTxs: number;
95
105
  flushSetupTransactions: boolean;
96
- skipPublicSimulation: boolean;
97
106
  contract: SupportedTokenContracts;
98
107
  maxConsecutiveErrors: number;
99
108
  stopWhenUnhealthy: boolean;
109
+ ammTxs: boolean;
100
110
  nodeUrl?: string | undefined;
111
+ nodeAdminUrl?: string | undefined;
101
112
  pxeUrl?: string | undefined;
102
113
  l1RpcUrls?: string[] | undefined;
103
- l1Mnemonic?: string | undefined;
104
- l1PrivateKey?: string | undefined;
105
- senderPrivateKey?: Fr | undefined;
114
+ l1Mnemonic?: SecretValue<string> | undefined;
115
+ l1PrivateKey?: SecretValue<string> | undefined;
116
+ senderPrivateKey?: SecretValue<Fr> | undefined;
117
+ senderSalt?: Fr | undefined;
106
118
  l2GasLimit?: number | undefined;
107
119
  daGasLimit?: number | undefined;
108
120
  }, {
121
+ l1ToL2MessageTimeoutSeconds: number;
109
122
  txIntervalSeconds: number;
110
123
  privateTransfersPerTx: number;
111
124
  publicTransfersPerTx: number;
@@ -115,22 +128,25 @@ export declare const BotConfigSchema: z.ZodEffects<z.ZodObject<{
115
128
  followChain: "NONE" | "PENDING" | "PROVEN";
116
129
  maxPendingTxs: number;
117
130
  flushSetupTransactions: boolean;
118
- skipPublicSimulation: boolean;
119
131
  contract: SupportedTokenContracts;
120
132
  maxConsecutiveErrors: number;
121
133
  stopWhenUnhealthy: boolean;
122
134
  nodeUrl?: string | undefined;
135
+ nodeAdminUrl?: string | undefined;
123
136
  pxeUrl?: string | undefined;
124
137
  l1RpcUrls?: string[] | undefined;
125
- l1Mnemonic?: string | undefined;
126
- l1PrivateKey?: string | undefined;
138
+ l1Mnemonic?: any;
139
+ l1PrivateKey?: any;
127
140
  senderPrivateKey?: any;
141
+ senderSalt?: any;
128
142
  recipientEncryptionSecret?: any;
129
143
  tokenSalt?: any;
130
144
  l2GasLimit?: number | undefined;
131
145
  daGasLimit?: number | undefined;
146
+ ammTxs?: boolean | undefined;
132
147
  }>, {
133
- recipientEncryptionSecret: Fr;
148
+ l1ToL2MessageTimeoutSeconds: number;
149
+ recipientEncryptionSecret: SecretValue<Fr>;
134
150
  tokenSalt: Fr;
135
151
  txIntervalSeconds: number;
136
152
  privateTransfersPerTx: number;
@@ -141,19 +157,22 @@ export declare const BotConfigSchema: z.ZodEffects<z.ZodObject<{
141
157
  followChain: "NONE" | "PENDING" | "PROVEN";
142
158
  maxPendingTxs: number;
143
159
  flushSetupTransactions: boolean;
144
- skipPublicSimulation: boolean;
145
160
  contract: SupportedTokenContracts;
146
161
  maxConsecutiveErrors: number;
147
162
  stopWhenUnhealthy: boolean;
163
+ ammTxs: boolean;
148
164
  nodeUrl: string | undefined;
165
+ nodeAdminUrl: string | undefined;
149
166
  pxeUrl: string | undefined;
150
167
  l1RpcUrls: string[] | undefined;
151
- l1Mnemonic: string | undefined;
152
- l1PrivateKey: string | undefined;
153
- senderPrivateKey: Fr | undefined;
168
+ l1Mnemonic: SecretValue<string> | undefined;
169
+ l1PrivateKey: SecretValue<string> | undefined;
170
+ senderPrivateKey: SecretValue<Fr> | undefined;
171
+ senderSalt: Fr | undefined;
154
172
  l2GasLimit: number | undefined;
155
173
  daGasLimit: number | undefined;
156
174
  }, {
175
+ l1ToL2MessageTimeoutSeconds: number;
157
176
  txIntervalSeconds: number;
158
177
  privateTransfersPerTx: number;
159
178
  publicTransfersPerTx: number;
@@ -163,20 +182,22 @@ export declare const BotConfigSchema: z.ZodEffects<z.ZodObject<{
163
182
  followChain: "NONE" | "PENDING" | "PROVEN";
164
183
  maxPendingTxs: number;
165
184
  flushSetupTransactions: boolean;
166
- skipPublicSimulation: boolean;
167
185
  contract: SupportedTokenContracts;
168
186
  maxConsecutiveErrors: number;
169
187
  stopWhenUnhealthy: boolean;
170
188
  nodeUrl?: string | undefined;
189
+ nodeAdminUrl?: string | undefined;
171
190
  pxeUrl?: string | undefined;
172
191
  l1RpcUrls?: string[] | undefined;
173
- l1Mnemonic?: string | undefined;
174
- l1PrivateKey?: string | undefined;
192
+ l1Mnemonic?: any;
193
+ l1PrivateKey?: any;
175
194
  senderPrivateKey?: any;
195
+ senderSalt?: any;
176
196
  recipientEncryptionSecret?: any;
177
197
  tokenSalt?: any;
178
198
  l2GasLimit?: number | undefined;
179
199
  daGasLimit?: number | undefined;
200
+ ammTxs?: boolean | undefined;
180
201
  }>;
181
202
  export declare const botConfigMappings: ConfigMappingsType<BotConfig>;
182
203
  export declare function getBotConfigFromEnv(): BotConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EAMxB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAG9C,OAAO,EAAE,KAAK,MAAM,EAAW,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,QAAA,MAAM,cAAc,wCAAyC,CAAC;AAC9D,KAAK,cAAc,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtD,oBAAY,uBAAuB;IACjC,aAAa,kBAAkB;IAC/B,wBAAwB,6BAA6B;CACtD;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,6DAA6D;IAC7D,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,8EAA8E;IAC9E,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,gCAAgC;IAChC,SAAS,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAChC,gEAAgE;IAChE,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,mEAAmE;IACnE,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,kDAAkD;IAClD,gBAAgB,EAAE,EAAE,GAAG,SAAS,CAAC;IACjC,iDAAiD;IACjD,yBAAyB,EAAE,EAAE,CAAC;IAC9B,8CAA8C;IAC9C,SAAS,EAAE,EAAE,CAAC;IACd,sDAAsD;IACtD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,4DAA4D;IAC5D,qBAAqB,EAAE,MAAM,CAAC;IAC9B,2DAA2D;IAC3D,oBAAoB,EAAE,MAAM,CAAC;IAC7B,kCAAkC;IAClC,gBAAgB,EAAE,WAAW,CAAC;IAC9B,0EAA0E;IAC1E,OAAO,EAAE,OAAO,CAAC;IACjB,uEAAuE;IACvE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,4EAA4E;IAC5E,WAAW,EAAE,cAAc,CAAC;IAC5B,gFAAgF;IAChF,aAAa,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,sBAAsB,EAAE,OAAO,CAAC;IAChC,oEAAoE;IACpE,oBAAoB,EAAE,OAAO,CAAC;IAC9B,+EAA+E;IAC/E,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,+EAA+E;IAC/E,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,4BAA4B;IAC5B,QAAQ,EAAE,uBAAuB,CAAC;IAClC,yEAAyE;IACzE,oBAAoB,EAAE,MAAM,CAAC;IAC7B,iDAAiD;IACjD,iBAAiB,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoCK,CAAC;AAElC,eAAO,MAAM,iBAAiB,EAAE,kBAAkB,CAAC,SAAS,CAmI3D,CAAC;AAEF,wBAAgB,mBAAmB,IAAI,SAAS,CAE/C;AAED,wBAAgB,mBAAmB,IAAI,SAAS,CAE/C;AAED,wBAAgB,WAAW,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAKzD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EACvB,WAAW,EAQZ,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAG9C,OAAO,EAAE,KAAK,MAAM,EAAW,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,QAAA,MAAM,cAAc,wCAAyC,CAAC;AAC9D,KAAK,cAAc,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtD,oBAAY,uBAAuB;IACjC,aAAa,kBAAkB;IAC/B,oBAAoB,yBAAyB;CAC9C;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,6DAA6D;IAC7D,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,4EAA4E;IAC5E,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,8EAA8E;IAC9E,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,gCAAgC;IAChC,SAAS,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAChC,gEAAgE;IAChE,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;IAC5C,mEAAmE;IACnE,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;IAC9C,uEAAuE;IACvE,2BAA2B,EAAE,MAAM,CAAC;IACpC,kDAAkD;IAClD,gBAAgB,EAAE,WAAW,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;IAC9C,6DAA6D;IAC7D,UAAU,EAAE,EAAE,GAAG,SAAS,CAAC;IAC3B,iDAAiD;IACjD,yBAAyB,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;IAC3C,iDAAiD;IACjD,SAAS,EAAE,EAAE,CAAC;IACd,sDAAsD;IACtD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,4DAA4D;IAC5D,qBAAqB,EAAE,MAAM,CAAC;IAC9B,2DAA2D;IAC3D,oBAAoB,EAAE,MAAM,CAAC;IAC7B,kCAAkC;IAClC,gBAAgB,EAAE,WAAW,CAAC;IAC9B,0EAA0E;IAC1E,OAAO,EAAE,OAAO,CAAC;IACjB,uEAAuE;IACvE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,4EAA4E;IAC5E,WAAW,EAAE,cAAc,CAAC;IAC5B,gFAAgF;IAChF,aAAa,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,sBAAsB,EAAE,OAAO,CAAC;IAChC,+EAA+E;IAC/E,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,+EAA+E;IAC/E,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,4BAA4B;IAC5B,QAAQ,EAAE,uBAAuB,CAAC;IAClC,yEAAyE;IACzE,oBAAoB,EAAE,MAAM,CAAC;IAC7B,iDAAiD;IACjD,iBAAiB,EAAE,OAAO,CAAC;IAC3B,+DAA+D;IAC/D,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyCK,CAAC;AAElC,eAAO,MAAM,iBAAiB,EAAE,kBAAkB,CAAC,SAAS,CAmJ3D,CAAC;AAEF,wBAAgB,mBAAmB,IAAI,SAAS,CAE/C;AAED,wBAAgB,mBAAmB,IAAI,SAAS,CAE/C;AAED,wBAAgB,WAAW,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAKzD"}