@aztec/bot 0.0.0-test.1 → 0.0.1-commit.5476d83
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 +33 -0
- package/dest/amm_bot.d.ts.map +1 -0
- package/dest/amm_bot.js +97 -0
- package/dest/base_bot.d.ts +21 -0
- package/dest/base_bot.d.ts.map +1 -0
- package/dest/base_bot.js +80 -0
- package/dest/bot.d.ts +13 -18
- package/dest/bot.d.ts.map +1 -1
- package/dest/bot.js +24 -86
- package/dest/config.d.ts +82 -57
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +55 -32
- package/dest/factory.d.ts +31 -27
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +277 -132
- package/dest/index.d.ts +4 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +3 -1
- package/dest/interface.d.ts +12 -1
- package/dest/interface.d.ts.map +1 -1
- package/dest/interface.js +5 -0
- package/dest/rpc.d.ts +1 -7
- package/dest/rpc.d.ts.map +1 -1
- package/dest/rpc.js +0 -11
- package/dest/runner.d.ts +15 -11
- package/dest/runner.d.ts.map +1 -1
- package/dest/runner.js +33 -25
- package/dest/store/bot_store.d.ts +44 -0
- package/dest/store/bot_store.d.ts.map +1 -0
- package/dest/store/bot_store.js +107 -0
- package/dest/store/index.d.ts +2 -0
- package/dest/store/index.d.ts.map +1 -0
- package/dest/store/index.js +1 -0
- package/dest/utils.d.ts +8 -5
- package/dest/utils.d.ts.map +1 -1
- package/dest/utils.js +14 -5
- package/package.json +27 -23
- package/src/amm_bot.ts +124 -0
- package/src/base_bot.ts +96 -0
- package/src/bot.ts +52 -103
- package/src/config.ts +66 -38
- package/src/factory.ts +335 -146
- package/src/index.ts +3 -1
- package/src/interface.ts +9 -0
- package/src/rpc.ts +0 -13
- package/src/runner.ts +38 -21
- package/src/store/bot_store.ts +141 -0
- package/src/store/index.ts +1 -0
- package/src/utils.ts +17 -6
package/src/base_bot.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { AztecAddress } from '@aztec/aztec.js/addresses';
|
|
2
|
+
import {
|
|
3
|
+
BatchCall,
|
|
4
|
+
ContractFunctionInteraction,
|
|
5
|
+
type SendInteractionOptions,
|
|
6
|
+
SentTx,
|
|
7
|
+
waitForProven,
|
|
8
|
+
} from '@aztec/aztec.js/contracts';
|
|
9
|
+
import { createLogger } from '@aztec/aztec.js/log';
|
|
10
|
+
import { TxHash, TxReceipt } from '@aztec/aztec.js/tx';
|
|
11
|
+
import { Gas } from '@aztec/stdlib/gas';
|
|
12
|
+
import type { AztecNode } from '@aztec/stdlib/interfaces/client';
|
|
13
|
+
import type { TestWallet } from '@aztec/test-wallet/server';
|
|
14
|
+
|
|
15
|
+
import type { BotConfig } from './config.js';
|
|
16
|
+
|
|
17
|
+
export abstract class BaseBot {
|
|
18
|
+
protected log = createLogger('bot');
|
|
19
|
+
|
|
20
|
+
protected attempts: number = 0;
|
|
21
|
+
protected successes: number = 0;
|
|
22
|
+
|
|
23
|
+
protected constructor(
|
|
24
|
+
public readonly node: AztecNode,
|
|
25
|
+
public readonly wallet: TestWallet,
|
|
26
|
+
public readonly defaultAccountAddress: AztecAddress,
|
|
27
|
+
public config: BotConfig,
|
|
28
|
+
) {}
|
|
29
|
+
|
|
30
|
+
public async run(): Promise<TxReceipt | TxHash> {
|
|
31
|
+
this.attempts++;
|
|
32
|
+
const logCtx = { runId: Date.now() * 1000 + Math.floor(Math.random() * 1000) };
|
|
33
|
+
const { followChain, txMinedWaitSeconds } = this.config;
|
|
34
|
+
|
|
35
|
+
this.log.verbose(`Creating tx`, logCtx);
|
|
36
|
+
const tx = await this.createAndSendTx(logCtx);
|
|
37
|
+
|
|
38
|
+
const txHash = await tx.getTxHash();
|
|
39
|
+
|
|
40
|
+
if (followChain === 'NONE') {
|
|
41
|
+
this.log.info(`Transaction ${txHash.toString()} sent, not waiting for it to be mined`);
|
|
42
|
+
return txHash;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
this.log.verbose(
|
|
46
|
+
`Awaiting tx ${txHash.toString()} to be on the ${followChain} chain (timeout ${txMinedWaitSeconds}s)`,
|
|
47
|
+
logCtx,
|
|
48
|
+
);
|
|
49
|
+
const receipt = await tx.wait({
|
|
50
|
+
timeout: txMinedWaitSeconds,
|
|
51
|
+
});
|
|
52
|
+
if (followChain === 'PROVEN') {
|
|
53
|
+
await waitForProven(this.node, receipt, { provenTimeout: txMinedWaitSeconds });
|
|
54
|
+
}
|
|
55
|
+
this.successes++;
|
|
56
|
+
this.log.info(
|
|
57
|
+
`Tx #${this.attempts} ${receipt.txHash} successfully mined in block ${receipt.blockNumber} (stats: ${this.successes}/${this.attempts} success)`,
|
|
58
|
+
logCtx,
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
await this.onTxMined(receipt, logCtx);
|
|
62
|
+
|
|
63
|
+
return receipt;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
protected abstract createAndSendTx(logCtx: object): Promise<SentTx>;
|
|
67
|
+
|
|
68
|
+
protected onTxMined(_receipt: TxReceipt, _logCtx: object): Promise<void> {
|
|
69
|
+
// no-op
|
|
70
|
+
return Promise.resolve();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
protected async getSendMethodOpts(
|
|
74
|
+
interaction: ContractFunctionInteraction | BatchCall,
|
|
75
|
+
): Promise<SendInteractionOptions> {
|
|
76
|
+
const { l2GasLimit, daGasLimit, baseFeePadding } = this.config;
|
|
77
|
+
|
|
78
|
+
this.wallet.setBaseFeePadding(baseFeePadding);
|
|
79
|
+
|
|
80
|
+
let gasSettings;
|
|
81
|
+
if (l2GasLimit !== undefined && l2GasLimit > 0 && daGasLimit !== undefined && daGasLimit > 0) {
|
|
82
|
+
gasSettings = { gasLimits: Gas.from({ l2Gas: l2GasLimit, daGas: daGasLimit }) };
|
|
83
|
+
this.log.verbose(`Using gas limits ${l2GasLimit} L2 gas ${daGasLimit} DA gas`);
|
|
84
|
+
} else {
|
|
85
|
+
this.log.verbose(`Estimating gas for transaction`);
|
|
86
|
+
({ estimatedGas: gasSettings } = await interaction.simulate({
|
|
87
|
+
fee: { estimateGas: true },
|
|
88
|
+
from: this.defaultAccountAddress,
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
from: this.defaultAccountAddress,
|
|
93
|
+
fee: { gasSettings },
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
package/src/bot.ts
CHANGED
|
@@ -1,40 +1,46 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
type SendMethodOptions,
|
|
6
|
-
type Wallet,
|
|
7
|
-
createLogger,
|
|
8
|
-
} from '@aztec/aztec.js';
|
|
9
|
-
import { timesParallel } from '@aztec/foundation/collection';
|
|
10
|
-
import type { EasyPrivateTokenContract } from '@aztec/noir-contracts.js/EasyPrivateToken';
|
|
1
|
+
import type { AztecAddress } from '@aztec/aztec.js/addresses';
|
|
2
|
+
import { BatchCall, SentTx } from '@aztec/aztec.js/contracts';
|
|
3
|
+
import { times } from '@aztec/foundation/collection';
|
|
4
|
+
import type { PrivateTokenContract } from '@aztec/noir-contracts.js/PrivateToken';
|
|
11
5
|
import type { TokenContract } from '@aztec/noir-contracts.js/Token';
|
|
12
|
-
import type {
|
|
13
|
-
import {
|
|
14
|
-
import type { AztecNode, PXE } from '@aztec/stdlib/interfaces/client';
|
|
6
|
+
import type { AztecNode, AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
|
|
7
|
+
import type { TestWallet } from '@aztec/test-wallet/server';
|
|
15
8
|
|
|
9
|
+
import { BaseBot } from './base_bot.js';
|
|
16
10
|
import type { BotConfig } from './config.js';
|
|
17
11
|
import { BotFactory } from './factory.js';
|
|
12
|
+
import type { BotStore } from './store/index.js';
|
|
18
13
|
import { getBalances, getPrivateBalance, isStandardTokenContract } from './utils.js';
|
|
19
14
|
|
|
20
15
|
const TRANSFER_AMOUNT = 1;
|
|
21
16
|
|
|
22
|
-
export class Bot {
|
|
23
|
-
private log = createLogger('bot');
|
|
24
|
-
|
|
25
|
-
private attempts: number = 0;
|
|
26
|
-
private successes: number = 0;
|
|
27
|
-
|
|
17
|
+
export class Bot extends BaseBot {
|
|
28
18
|
protected constructor(
|
|
29
|
-
|
|
30
|
-
|
|
19
|
+
node: AztecNode,
|
|
20
|
+
wallet: TestWallet,
|
|
21
|
+
defaultAccountAddress: AztecAddress,
|
|
22
|
+
public readonly token: TokenContract | PrivateTokenContract,
|
|
31
23
|
public readonly recipient: AztecAddress,
|
|
32
|
-
|
|
33
|
-
) {
|
|
24
|
+
config: BotConfig,
|
|
25
|
+
) {
|
|
26
|
+
super(node, wallet, defaultAccountAddress, config);
|
|
27
|
+
}
|
|
34
28
|
|
|
35
|
-
static async create(
|
|
36
|
-
|
|
37
|
-
|
|
29
|
+
static async create(
|
|
30
|
+
config: BotConfig,
|
|
31
|
+
wallet: TestWallet,
|
|
32
|
+
aztecNode: AztecNode,
|
|
33
|
+
aztecNodeAdmin: AztecNodeAdmin | undefined,
|
|
34
|
+
store: BotStore,
|
|
35
|
+
): Promise<Bot> {
|
|
36
|
+
const { defaultAccountAddress, token, recipient } = await new BotFactory(
|
|
37
|
+
config,
|
|
38
|
+
wallet,
|
|
39
|
+
store,
|
|
40
|
+
aztecNode,
|
|
41
|
+
aztecNodeAdmin,
|
|
42
|
+
).setup();
|
|
43
|
+
return new Bot(aztecNode, wallet, defaultAccountAddress, token, recipient, config);
|
|
38
44
|
}
|
|
39
45
|
|
|
40
46
|
public updateConfig(config: Partial<BotConfig>) {
|
|
@@ -42,110 +48,53 @@ export class Bot {
|
|
|
42
48
|
this.config = { ...this.config, ...config };
|
|
43
49
|
}
|
|
44
50
|
|
|
45
|
-
|
|
46
|
-
this.
|
|
47
|
-
const logCtx = { runId: Date.now() * 1000 + Math.floor(Math.random() * 1000) };
|
|
48
|
-
const { privateTransfersPerTx, publicTransfersPerTx, feePaymentMethod, followChain, txMinedWaitSeconds } =
|
|
49
|
-
this.config;
|
|
51
|
+
protected async createAndSendTx(logCtx: object): Promise<SentTx> {
|
|
52
|
+
const { privateTransfersPerTx, publicTransfersPerTx, feePaymentMethod } = this.config;
|
|
50
53
|
const { token, recipient, wallet } = this;
|
|
51
|
-
const sender = wallet.getAddress();
|
|
52
54
|
|
|
53
55
|
this.log.verbose(
|
|
54
56
|
`Preparing tx with ${feePaymentMethod} fee with ${privateTransfersPerTx} private and ${publicTransfersPerTx} public transfers`,
|
|
55
57
|
logCtx,
|
|
56
58
|
);
|
|
57
59
|
|
|
58
|
-
const calls
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
)),
|
|
69
|
-
);
|
|
70
|
-
} else {
|
|
71
|
-
calls.push(
|
|
72
|
-
...(await timesParallel(privateTransfersPerTx, () =>
|
|
73
|
-
token.methods.transfer(TRANSFER_AMOUNT, sender, recipient).request(),
|
|
74
|
-
)),
|
|
75
|
-
);
|
|
76
|
-
}
|
|
60
|
+
const calls = isStandardTokenContract(token)
|
|
61
|
+
? [
|
|
62
|
+
times(privateTransfersPerTx, () => token.methods.transfer(recipient, TRANSFER_AMOUNT)),
|
|
63
|
+
times(publicTransfersPerTx, () =>
|
|
64
|
+
token.methods.transfer_in_public(this.defaultAccountAddress, recipient, TRANSFER_AMOUNT, 0),
|
|
65
|
+
),
|
|
66
|
+
].flat()
|
|
67
|
+
: times(privateTransfersPerTx, () =>
|
|
68
|
+
token.methods.transfer(TRANSFER_AMOUNT, this.defaultAccountAddress, recipient),
|
|
69
|
+
);
|
|
77
70
|
|
|
78
|
-
const opts = this.getSendMethodOpts();
|
|
79
71
|
const batch = new BatchCall(wallet, calls);
|
|
72
|
+
const opts = await this.getSendMethodOpts(batch);
|
|
80
73
|
|
|
81
74
|
this.log.verbose(`Simulating transaction with ${calls.length}`, logCtx);
|
|
82
|
-
await batch.simulate();
|
|
83
|
-
|
|
84
|
-
this.log.verbose(`Proving transaction`, logCtx);
|
|
85
|
-
const provenTx = await batch.prove(opts);
|
|
86
|
-
|
|
87
|
-
this.log.verbose(`Sending tx`, logCtx);
|
|
88
|
-
const tx = provenTx.send();
|
|
89
|
-
|
|
90
|
-
const txHash = await tx.getTxHash();
|
|
91
|
-
|
|
92
|
-
if (followChain === 'NONE') {
|
|
93
|
-
this.log.info(`Transaction ${txHash} sent, not waiting for it to be mined`);
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
75
|
+
await batch.simulate({ from: this.defaultAccountAddress });
|
|
96
76
|
|
|
97
|
-
this.log.verbose(
|
|
98
|
-
|
|
99
|
-
logCtx,
|
|
100
|
-
);
|
|
101
|
-
const receipt = await tx.wait({
|
|
102
|
-
timeout: txMinedWaitSeconds,
|
|
103
|
-
provenTimeout: txMinedWaitSeconds,
|
|
104
|
-
proven: followChain === 'PROVEN',
|
|
105
|
-
});
|
|
106
|
-
this.log.info(
|
|
107
|
-
`Tx #${this.attempts} ${receipt.txHash} successfully mined in block ${receipt.blockNumber} (stats: ${this.successes}/${this.attempts} success)`,
|
|
108
|
-
logCtx,
|
|
109
|
-
);
|
|
110
|
-
this.successes++;
|
|
77
|
+
this.log.verbose(`Sending transaction`, logCtx);
|
|
78
|
+
return batch.send(opts);
|
|
111
79
|
}
|
|
112
80
|
|
|
113
81
|
public async getBalances() {
|
|
114
82
|
if (isStandardTokenContract(this.token)) {
|
|
115
83
|
return {
|
|
116
|
-
sender: await getBalances(this.token, this.
|
|
117
|
-
recipient: await getBalances(this.token, this.recipient),
|
|
84
|
+
sender: await getBalances(this.token, this.defaultAccountAddress),
|
|
85
|
+
recipient: await getBalances(this.token, this.recipient, this.defaultAccountAddress),
|
|
118
86
|
};
|
|
119
87
|
} else {
|
|
120
88
|
return {
|
|
121
89
|
sender: {
|
|
122
|
-
privateBalance: await getPrivateBalance(this.token, this.
|
|
90
|
+
privateBalance: await getPrivateBalance(this.token, this.defaultAccountAddress),
|
|
123
91
|
publicBalance: 0n,
|
|
124
92
|
},
|
|
125
93
|
recipient: {
|
|
126
|
-
privateBalance: await getPrivateBalance(this.token, this.recipient),
|
|
94
|
+
privateBalance: await getPrivateBalance(this.token, this.recipient, this.defaultAccountAddress),
|
|
127
95
|
publicBalance: 0n,
|
|
128
96
|
},
|
|
129
97
|
};
|
|
130
98
|
}
|
|
131
99
|
}
|
|
132
|
-
|
|
133
|
-
private getSendMethodOpts(): SendMethodOptions {
|
|
134
|
-
const sender = this.wallet.getAddress();
|
|
135
|
-
const { l2GasLimit, daGasLimit, skipPublicSimulation } = this.config;
|
|
136
|
-
const paymentMethod = new FeeJuicePaymentMethod(sender);
|
|
137
|
-
|
|
138
|
-
let gasSettings, estimateGas;
|
|
139
|
-
if (l2GasLimit !== undefined && l2GasLimit > 0 && daGasLimit !== undefined && daGasLimit > 0) {
|
|
140
|
-
gasSettings = { gasLimits: Gas.from({ l2Gas: l2GasLimit, daGas: daGasLimit }) };
|
|
141
|
-
estimateGas = false;
|
|
142
|
-
this.log.verbose(`Using gas limits ${l2GasLimit} L2 gas ${daGasLimit} DA gas`);
|
|
143
|
-
} else {
|
|
144
|
-
estimateGas = true;
|
|
145
|
-
this.log.verbose(`Estimating gas for transaction`);
|
|
146
|
-
}
|
|
147
|
-
const baseFeePadding = 2; // Send 3x the current base fee
|
|
148
|
-
this.log.verbose(skipPublicSimulation ? `Skipping public simulation` : `Simulating public transfers`);
|
|
149
|
-
return { fee: { estimateGas, paymentMethod, gasSettings, baseFeePadding }, skipPublicSimulation };
|
|
150
|
-
}
|
|
151
100
|
}
|
package/src/config.ts
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type ConfigMappingsType,
|
|
3
|
+
SecretValue,
|
|
3
4
|
booleanConfigHelper,
|
|
4
5
|
getConfigFromMappings,
|
|
5
6
|
getDefaultConfig,
|
|
6
7
|
numberConfigHelper,
|
|
7
8
|
optionalNumberConfigHelper,
|
|
9
|
+
pickConfigMappings,
|
|
10
|
+
secretFrConfigHelper,
|
|
11
|
+
secretStringConfigHelper,
|
|
8
12
|
} from '@aztec/foundation/config';
|
|
9
13
|
import { Fr } from '@aztec/foundation/fields';
|
|
14
|
+
import { type DataStoreConfig, dataConfigMappings } from '@aztec/kv-store/config';
|
|
10
15
|
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
11
|
-
import {
|
|
16
|
+
import { protocolContractsHash } from '@aztec/protocol-contracts';
|
|
12
17
|
import { type ZodFor, schemas } from '@aztec/stdlib/schemas';
|
|
13
18
|
import type { ComponentsVersions } from '@aztec/stdlib/versioning';
|
|
14
19
|
|
|
@@ -19,25 +24,27 @@ type BotFollowChain = (typeof BotFollowChain)[number];
|
|
|
19
24
|
|
|
20
25
|
export enum SupportedTokenContracts {
|
|
21
26
|
TokenContract = 'TokenContract',
|
|
22
|
-
|
|
27
|
+
PrivateTokenContract = 'PrivateTokenContract',
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
export type BotConfig = {
|
|
26
31
|
/** The URL to the Aztec node to check for tx pool status. */
|
|
27
32
|
nodeUrl: string | undefined;
|
|
28
|
-
/** URL to the
|
|
29
|
-
|
|
33
|
+
/** The URL to the Aztec node admin API to force-flush txs if configured. */
|
|
34
|
+
nodeAdminUrl: string | undefined;
|
|
30
35
|
/** Url of the ethereum host. */
|
|
31
36
|
l1RpcUrls: string[] | undefined;
|
|
32
37
|
/** The mnemonic for the account to bridge fee juice from L1. */
|
|
33
|
-
l1Mnemonic: string | undefined;
|
|
38
|
+
l1Mnemonic: SecretValue<string> | undefined;
|
|
34
39
|
/** The private key for the account to bridge fee juice from L1. */
|
|
35
|
-
l1PrivateKey: string | undefined;
|
|
40
|
+
l1PrivateKey: SecretValue<string> | undefined;
|
|
41
|
+
/** How long to wait for L1 to L2 messages to become available on L2 */
|
|
42
|
+
l1ToL2MessageTimeoutSeconds: number;
|
|
36
43
|
/** Signing private key for the sender account. */
|
|
37
|
-
senderPrivateKey: Fr | undefined;
|
|
38
|
-
/**
|
|
39
|
-
|
|
40
|
-
/** Salt for the token contract
|
|
44
|
+
senderPrivateKey: SecretValue<Fr> | undefined;
|
|
45
|
+
/** Optional salt to use to instantiate the sender account */
|
|
46
|
+
senderSalt: Fr | undefined;
|
|
47
|
+
/** Salt for the token contract instantiation. */
|
|
41
48
|
tokenSalt: Fr;
|
|
42
49
|
/** Every how many seconds should a new tx be sent. */
|
|
43
50
|
txIntervalSeconds: number;
|
|
@@ -47,6 +54,8 @@ export type BotConfig = {
|
|
|
47
54
|
publicTransfersPerTx: number;
|
|
48
55
|
/** How to handle fee payments. */
|
|
49
56
|
feePaymentMethod: 'fee_juice';
|
|
57
|
+
/** 'How much is the bot willing to overpay vs. the current base fee' */
|
|
58
|
+
baseFeePadding: number;
|
|
50
59
|
/** True to not automatically setup or start the bot on initialization. */
|
|
51
60
|
noStart: boolean;
|
|
52
61
|
/** How long to wait for a tx to be mined before reporting an error. */
|
|
@@ -57,8 +66,6 @@ export type BotConfig = {
|
|
|
57
66
|
maxPendingTxs: number;
|
|
58
67
|
/** Whether to flush after sending each 'setup' transaction */
|
|
59
68
|
flushSetupTransactions: boolean;
|
|
60
|
-
/** Whether to skip public simulation of txs before sending them. */
|
|
61
|
-
skipPublicSimulation: boolean;
|
|
62
69
|
/** L2 gas limit for the tx (empty to have the bot trigger an estimate gas). */
|
|
63
70
|
l2GasLimit: number | undefined;
|
|
64
71
|
/** DA gas limit for the tx (empty to have the bot trigger an estimate gas). */
|
|
@@ -69,43 +76,52 @@ export type BotConfig = {
|
|
|
69
76
|
maxConsecutiveErrors: number;
|
|
70
77
|
/** Stops the bot if service becomes unhealthy */
|
|
71
78
|
stopWhenUnhealthy: boolean;
|
|
72
|
-
|
|
79
|
+
/** Deploy an AMM contract and do swaps instead of transfers */
|
|
80
|
+
ammTxs: boolean;
|
|
81
|
+
} & Pick<DataStoreConfig, 'dataDirectory' | 'dataStoreMapSizeKb'>;
|
|
73
82
|
|
|
74
83
|
export const BotConfigSchema = z
|
|
75
84
|
.object({
|
|
76
85
|
nodeUrl: z.string().optional(),
|
|
77
|
-
|
|
86
|
+
nodeAdminUrl: z.string().optional(),
|
|
78
87
|
l1RpcUrls: z.array(z.string()).optional(),
|
|
79
|
-
l1Mnemonic: z.string().optional(),
|
|
80
|
-
l1PrivateKey: z.string().optional(),
|
|
81
|
-
|
|
82
|
-
|
|
88
|
+
l1Mnemonic: schemas.SecretValue(z.string()).optional(),
|
|
89
|
+
l1PrivateKey: schemas.SecretValue(z.string()).optional(),
|
|
90
|
+
l1ToL2MessageTimeoutSeconds: z.number(),
|
|
91
|
+
senderPrivateKey: schemas.SecretValue(schemas.Fr).optional(),
|
|
92
|
+
senderSalt: schemas.Fr.optional(),
|
|
83
93
|
tokenSalt: schemas.Fr,
|
|
84
94
|
txIntervalSeconds: z.number(),
|
|
85
95
|
privateTransfersPerTx: z.number().int().nonnegative(),
|
|
86
96
|
publicTransfersPerTx: z.number().int().nonnegative(),
|
|
87
97
|
feePaymentMethod: z.literal('fee_juice'),
|
|
98
|
+
baseFeePadding: z.number().int().nonnegative(),
|
|
88
99
|
noStart: z.boolean(),
|
|
89
100
|
txMinedWaitSeconds: z.number(),
|
|
90
101
|
followChain: z.enum(BotFollowChain),
|
|
91
102
|
maxPendingTxs: z.number().int().nonnegative(),
|
|
92
103
|
flushSetupTransactions: z.boolean(),
|
|
93
|
-
skipPublicSimulation: z.boolean(),
|
|
94
104
|
l2GasLimit: z.number().int().nonnegative().optional(),
|
|
95
105
|
daGasLimit: z.number().int().nonnegative().optional(),
|
|
96
106
|
contract: z.nativeEnum(SupportedTokenContracts),
|
|
97
107
|
maxConsecutiveErrors: z.number().int().nonnegative(),
|
|
98
108
|
stopWhenUnhealthy: z.boolean(),
|
|
109
|
+
ammTxs: z.boolean().default(false),
|
|
110
|
+
dataDirectory: z.string().optional(),
|
|
111
|
+
dataStoreMapSizeKb: z.number().optional(),
|
|
99
112
|
})
|
|
100
113
|
.transform(config => ({
|
|
101
114
|
nodeUrl: undefined,
|
|
102
|
-
|
|
115
|
+
nodeAdminUrl: undefined,
|
|
103
116
|
l1RpcUrls: undefined,
|
|
117
|
+
senderSalt: undefined,
|
|
118
|
+
l2GasLimit: undefined,
|
|
119
|
+
daGasLimit: undefined,
|
|
104
120
|
l1Mnemonic: undefined,
|
|
105
121
|
l1PrivateKey: undefined,
|
|
106
122
|
senderPrivateKey: undefined,
|
|
107
|
-
|
|
108
|
-
|
|
123
|
+
dataDirectory: undefined,
|
|
124
|
+
dataStoreMapSizeKb: 1_024 * 1_024,
|
|
109
125
|
...config,
|
|
110
126
|
})) satisfies ZodFor<BotConfig>;
|
|
111
127
|
|
|
@@ -114,9 +130,9 @@ export const botConfigMappings: ConfigMappingsType<BotConfig> = {
|
|
|
114
130
|
env: 'AZTEC_NODE_URL',
|
|
115
131
|
description: 'The URL to the Aztec node to check for tx pool status.',
|
|
116
132
|
},
|
|
117
|
-
|
|
118
|
-
env: '
|
|
119
|
-
description: 'URL to the
|
|
133
|
+
nodeAdminUrl: {
|
|
134
|
+
env: 'AZTEC_NODE_ADMIN_URL',
|
|
135
|
+
description: 'The URL to the Aztec node admin API to force-flush txs if configured.',
|
|
120
136
|
},
|
|
121
137
|
l1RpcUrls: {
|
|
122
138
|
env: 'ETHEREUM_HOSTS',
|
|
@@ -126,25 +142,31 @@ export const botConfigMappings: ConfigMappingsType<BotConfig> = {
|
|
|
126
142
|
l1Mnemonic: {
|
|
127
143
|
env: 'BOT_L1_MNEMONIC',
|
|
128
144
|
description: 'The mnemonic for the account to bridge fee juice from L1.',
|
|
145
|
+
...secretStringConfigHelper(),
|
|
129
146
|
},
|
|
130
147
|
l1PrivateKey: {
|
|
131
148
|
env: 'BOT_L1_PRIVATE_KEY',
|
|
132
149
|
description: 'The private key for the account to bridge fee juice from L1.',
|
|
150
|
+
...secretStringConfigHelper(),
|
|
151
|
+
},
|
|
152
|
+
l1ToL2MessageTimeoutSeconds: {
|
|
153
|
+
env: 'BOT_L1_TO_L2_TIMEOUT_SECONDS',
|
|
154
|
+
description: 'How long to wait for L1 to L2 messages to become available on L2',
|
|
155
|
+
...numberConfigHelper(3600),
|
|
133
156
|
},
|
|
134
157
|
senderPrivateKey: {
|
|
135
158
|
env: 'BOT_PRIVATE_KEY',
|
|
136
159
|
description: 'Signing private key for the sender account.',
|
|
137
|
-
|
|
160
|
+
...secretFrConfigHelper(),
|
|
138
161
|
},
|
|
139
|
-
|
|
140
|
-
env: '
|
|
141
|
-
description: '
|
|
142
|
-
parseEnv: (val: string) => Fr.fromHexString(val),
|
|
143
|
-
defaultValue: Fr.fromHexString('0xcafecafe'),
|
|
162
|
+
senderSalt: {
|
|
163
|
+
env: 'BOT_ACCOUNT_SALT',
|
|
164
|
+
description: 'The salt to use to deploy the sender account.',
|
|
165
|
+
parseEnv: (val: string) => (val ? Fr.fromHexString(val) : undefined),
|
|
144
166
|
},
|
|
145
167
|
tokenSalt: {
|
|
146
168
|
env: 'BOT_TOKEN_SALT',
|
|
147
|
-
description: '
|
|
169
|
+
description: 'The salt to use to deploy the token contract.',
|
|
148
170
|
parseEnv: (val: string) => Fr.fromHexString(val),
|
|
149
171
|
defaultValue: Fr.fromHexString('1'),
|
|
150
172
|
},
|
|
@@ -169,6 +191,11 @@ export const botConfigMappings: ConfigMappingsType<BotConfig> = {
|
|
|
169
191
|
parseEnv: val => (val as 'fee_juice') || undefined,
|
|
170
192
|
defaultValue: 'fee_juice',
|
|
171
193
|
},
|
|
194
|
+
baseFeePadding: {
|
|
195
|
+
env: 'BOT_BASE_FEE_PADDING',
|
|
196
|
+
description: 'How much is the bot willing to overpay vs. the current base fee',
|
|
197
|
+
...numberConfigHelper(3),
|
|
198
|
+
},
|
|
172
199
|
noStart: {
|
|
173
200
|
env: 'BOT_NO_START',
|
|
174
201
|
description: 'True to not automatically setup or start the bot on initialization.',
|
|
@@ -200,11 +227,6 @@ export const botConfigMappings: ConfigMappingsType<BotConfig> = {
|
|
|
200
227
|
description: 'Make a request for the sequencer to build a block after each setup transaction.',
|
|
201
228
|
...booleanConfigHelper(false),
|
|
202
229
|
},
|
|
203
|
-
skipPublicSimulation: {
|
|
204
|
-
env: 'BOT_SKIP_PUBLIC_SIMULATION',
|
|
205
|
-
description: 'Whether to skip public simulation of txs before sending them.',
|
|
206
|
-
...booleanConfigHelper(false),
|
|
207
|
-
},
|
|
208
230
|
l2GasLimit: {
|
|
209
231
|
env: 'BOT_L2_GAS_LIMIT',
|
|
210
232
|
description: 'L2 gas limit for the tx (empty to have the bot trigger an estimate gas).',
|
|
@@ -240,6 +262,12 @@ export const botConfigMappings: ConfigMappingsType<BotConfig> = {
|
|
|
240
262
|
description: 'Stops the bot if service becomes unhealthy',
|
|
241
263
|
...booleanConfigHelper(false),
|
|
242
264
|
},
|
|
265
|
+
ammTxs: {
|
|
266
|
+
env: 'BOT_AMM_TXS',
|
|
267
|
+
description: 'Deploy an AMM and send swaps to it',
|
|
268
|
+
...booleanConfigHelper(false),
|
|
269
|
+
},
|
|
270
|
+
...pickConfigMappings(dataConfigMappings, ['dataStoreMapSizeKb', 'dataDirectory']),
|
|
243
271
|
};
|
|
244
272
|
|
|
245
273
|
export function getBotConfigFromEnv(): BotConfig {
|
|
@@ -252,7 +280,7 @@ export function getBotDefaultConfig(): BotConfig {
|
|
|
252
280
|
|
|
253
281
|
export function getVersions(): Partial<ComponentsVersions> {
|
|
254
282
|
return {
|
|
255
|
-
|
|
283
|
+
l2ProtocolContractsHash: protocolContractsHash.toString(),
|
|
256
284
|
l2CircuitsVkTreeRoot: getVKTreeRoot().toString(),
|
|
257
285
|
};
|
|
258
286
|
}
|