@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 +2 -1
- package/dest/amm_bot.d.ts.map +1 -1
- package/dest/amm_bot.js +31 -7
- package/dest/base_bot.d.ts +1 -0
- package/dest/base_bot.d.ts.map +1 -1
- package/dest/base_bot.js +5 -0
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +18 -7
- package/package.json +11 -13
- package/src/amm_bot.ts +28 -9
- package/src/base_bot.ts +8 -0
- package/src/factory.ts +27 -6
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;
|
package/dest/amm_bot.d.ts.map
CHANGED
|
@@ -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;
|
|
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
|
|
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.
|
|
20
|
-
|
|
21
|
-
|
|
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:
|
|
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(
|
|
28
|
-
const swapExactTokensInteraction = amm.methods.swap_exact_tokens_for_tokens(
|
|
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
|
}
|
package/dest/base_bot.d.ts
CHANGED
|
@@ -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
|
package/dest/base_bot.d.ts.map
CHANGED
|
@@ -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;
|
|
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;
|
package/dest/factory.d.ts.map
CHANGED
|
@@ -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;
|
|
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,
|
|
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
|
|
306
|
-
const portal = await L1FeeJuicePortalManager.new(this.pxe,
|
|
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.
|
|
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.
|
|
56
|
-
"@aztec/aztec.js": "0.
|
|
57
|
-
"@aztec/entrypoints": "0.
|
|
58
|
-
"@aztec/ethereum": "0.
|
|
59
|
-
"@aztec/foundation": "0.
|
|
60
|
-
"@aztec/noir-contracts.js": "0.
|
|
61
|
-
"@aztec/noir-protocol-circuits-types": "0.
|
|
62
|
-
"@aztec/protocol-contracts": "0.
|
|
63
|
-
"@aztec/stdlib": "0.
|
|
64
|
-
"@aztec/telemetry-client": "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
|
|
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.
|
|
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
|
-
|
|
41
|
-
const amountIn =
|
|
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:
|
|
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(
|
|
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
|
-
|
|
55
|
-
|
|
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,
|
|
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
|
|
369
|
+
const extendedClient = createExtendedL1Client(chain.rpcUrls, mnemonicOrPrivateKey, chain.chainInfo);
|
|
349
370
|
|
|
350
|
-
const portal = await L1FeeJuicePortalManager.new(this.pxe,
|
|
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
|
|