@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/dest/amm_bot.d.ts +3 -4
- package/dest/amm_bot.d.ts.map +1 -1
- package/dest/amm_bot.js +5 -1
- package/dest/base_bot.d.ts +3 -3
- package/dest/base_bot.d.ts.map +1 -1
- package/dest/base_bot.js +5 -5
- package/dest/bot.d.ts +3 -3
- package/dest/bot.d.ts.map +1 -1
- package/dest/bot.js +5 -2
- package/dest/config.d.ts +8 -8
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +3 -3
- package/dest/factory.d.ts +1 -6
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +83 -58
- package/dest/runner.js +412 -30
- package/dest/store/bot_store.d.ts +2 -2
- package/dest/store/bot_store.d.ts.map +1 -1
- package/package.json +14 -14
- package/src/amm_bot.ts +4 -4
- package/src/base_bot.ts +6 -10
- package/src/bot.ts +4 -3
- package/src/config.ts +5 -5
- package/src/factory.ts +62 -38
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
|
|
58
|
-
|
|
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
|
-
|
|
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
|
-
|
|
197
|
-
env: '
|
|
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
|
|
122
|
-
if (
|
|
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.
|
|
139
|
+
const maxFeesPerGas = (await this.aztecNode.getCurrentMinFees()).mul(1 + this.config.minFeePadding);
|
|
138
140
|
const gasSettings = GasSettings.default({ maxFeesPerGas });
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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
|
-
|
|
207
|
+
const metadata = await this.wallet.getContractMetadata(address);
|
|
208
|
+
if (metadata.isContractPublished) {
|
|
196
209
|
this.log.info(`Token at ${address.toString()} already deployed`);
|
|
197
|
-
|
|
210
|
+
await deploy.register();
|
|
198
211
|
} else {
|
|
199
212
|
this.log.info(`Deploying token contract at ${address.toString()}`);
|
|
200
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
237
|
-
|
|
238
|
-
|
|
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
|
|
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: ${
|
|
303
|
-
await mintTx.wait({ timeout: this.config.txMinedWaitSeconds });
|
|
321
|
+
this.log.info(`Sent mint tx: ${mintReceipt.txHash.toString()}`);
|
|
304
322
|
|
|
305
|
-
const
|
|
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: ${
|
|
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<
|
|
327
|
-
const
|
|
328
|
-
|
|
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
|
-
|
|
350
|
+
await deploy.register();
|
|
331
351
|
} else {
|
|
332
352
|
this.log.info(`Deploying contract ${name} at ${address.toString()}`);
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
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
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
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
|
/**
|