@aztec/bot 0.0.1-commit.24de95ac → 0.0.1-commit.3469e52

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/src/config.ts CHANGED
@@ -10,11 +10,11 @@ import {
10
10
  secretFrConfigHelper,
11
11
  secretStringConfigHelper,
12
12
  } from '@aztec/foundation/config';
13
- import { Fr } from '@aztec/foundation/fields';
13
+ import { Fr } from '@aztec/foundation/curves/bn254';
14
14
  import { type DataStoreConfig, dataConfigMappings } from '@aztec/kv-store/config';
15
15
  import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
16
16
  import { protocolContractsHash } from '@aztec/protocol-contracts';
17
- import { type ZodFor, schemas } from '@aztec/stdlib/schemas';
17
+ import { schemas, zodFor } from '@aztec/stdlib/schemas';
18
18
  import type { ComponentsVersions } from '@aztec/stdlib/versioning';
19
19
 
20
20
  import { z } from 'zod';
@@ -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 base fee' */
58
- baseFeePadding: number;
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. */
@@ -80,50 +80,52 @@ export type BotConfig = {
80
80
  ammTxs: boolean;
81
81
  } & Pick<DataStoreConfig, 'dataDirectory' | 'dataStoreMapSizeKb'>;
82
82
 
83
- export const BotConfigSchema = z
84
- .object({
85
- nodeUrl: z.string().optional(),
86
- nodeAdminUrl: z.string().optional(),
87
- l1RpcUrls: z.array(z.string()).optional(),
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(),
93
- tokenSalt: schemas.Fr,
94
- txIntervalSeconds: z.number(),
95
- privateTransfersPerTx: z.number().int().nonnegative(),
96
- publicTransfersPerTx: z.number().int().nonnegative(),
97
- feePaymentMethod: z.literal('fee_juice'),
98
- baseFeePadding: z.number().int().nonnegative(),
99
- noStart: z.boolean(),
100
- txMinedWaitSeconds: z.number(),
101
- followChain: z.enum(BotFollowChain),
102
- maxPendingTxs: z.number().int().nonnegative(),
103
- flushSetupTransactions: z.boolean(),
104
- l2GasLimit: z.number().int().nonnegative().optional(),
105
- daGasLimit: z.number().int().nonnegative().optional(),
106
- contract: z.nativeEnum(SupportedTokenContracts),
107
- maxConsecutiveErrors: z.number().int().nonnegative(),
108
- stopWhenUnhealthy: z.boolean(),
109
- ammTxs: z.boolean().default(false),
110
- dataDirectory: z.string().optional(),
111
- dataStoreMapSizeKb: z.number().optional(),
112
- })
113
- .transform(config => ({
114
- nodeUrl: undefined,
115
- nodeAdminUrl: undefined,
116
- l1RpcUrls: undefined,
117
- senderSalt: undefined,
118
- l2GasLimit: undefined,
119
- daGasLimit: undefined,
120
- l1Mnemonic: undefined,
121
- l1PrivateKey: undefined,
122
- senderPrivateKey: undefined,
123
- dataDirectory: undefined,
124
- dataStoreMapSizeKb: 1_024 * 1_024,
125
- ...config,
126
- })) satisfies ZodFor<BotConfig>;
83
+ export const BotConfigSchema = zodFor<BotConfig>()(
84
+ z
85
+ .object({
86
+ nodeUrl: z.string().optional(),
87
+ nodeAdminUrl: z.string().optional(),
88
+ l1RpcUrls: z.array(z.string()).optional(),
89
+ l1Mnemonic: schemas.SecretValue(z.string()).optional(),
90
+ l1PrivateKey: schemas.SecretValue(z.string()).optional(),
91
+ l1ToL2MessageTimeoutSeconds: z.number(),
92
+ senderPrivateKey: schemas.SecretValue(schemas.Fr).optional(),
93
+ senderSalt: schemas.Fr.optional(),
94
+ tokenSalt: schemas.Fr,
95
+ txIntervalSeconds: z.number(),
96
+ privateTransfersPerTx: z.number().int().nonnegative(),
97
+ publicTransfersPerTx: z.number().int().nonnegative(),
98
+ feePaymentMethod: z.literal('fee_juice'),
99
+ minFeePadding: z.number().int().nonnegative(),
100
+ noStart: z.boolean(),
101
+ txMinedWaitSeconds: z.number(),
102
+ followChain: z.enum(BotFollowChain),
103
+ maxPendingTxs: z.number().int().nonnegative(),
104
+ flushSetupTransactions: z.boolean(),
105
+ l2GasLimit: z.number().int().nonnegative().optional(),
106
+ daGasLimit: z.number().int().nonnegative().optional(),
107
+ contract: z.nativeEnum(SupportedTokenContracts),
108
+ maxConsecutiveErrors: z.number().int().nonnegative(),
109
+ stopWhenUnhealthy: z.boolean(),
110
+ ammTxs: z.boolean().default(false),
111
+ dataDirectory: z.string().optional(),
112
+ dataStoreMapSizeKb: z.number().optional(),
113
+ })
114
+ .transform(config => ({
115
+ nodeUrl: undefined,
116
+ nodeAdminUrl: undefined,
117
+ l1RpcUrls: undefined,
118
+ senderSalt: undefined,
119
+ l2GasLimit: undefined,
120
+ daGasLimit: undefined,
121
+ l1Mnemonic: undefined,
122
+ l1PrivateKey: undefined,
123
+ senderPrivateKey: undefined,
124
+ dataDirectory: undefined,
125
+ dataStoreMapSizeKb: 1_024 * 1_024,
126
+ ...config,
127
+ })),
128
+ );
127
129
 
128
130
  export const botConfigMappings: ConfigMappingsType<BotConfig> = {
129
131
  nodeUrl: {
@@ -191,8 +193,8 @@ export const botConfigMappings: ConfigMappingsType<BotConfig> = {
191
193
  parseEnv: val => (val as 'fee_juice') || undefined,
192
194
  defaultValue: 'fee_juice',
193
195
  },
194
- baseFeePadding: {
195
- env: 'BOT_BASE_FEE_PADDING',
196
+ minFeePadding: {
197
+ env: 'BOT_MIN_FEE_PADDING',
196
198
  description: 'How much is the bot willing to overpay vs. the current base fee',
197
199
  ...numberConfigHelper(3),
198
200
  },
package/src/factory.ts CHANGED
@@ -11,14 +11,17 @@ import {
11
11
  import { L1FeeJuicePortalManager } from '@aztec/aztec.js/ethereum';
12
12
  import type { L2AmountClaim } from '@aztec/aztec.js/ethereum';
13
13
  import { FeeJuicePaymentMethodWithClaim } from '@aztec/aztec.js/fee';
14
+ import { deriveKeys } from '@aztec/aztec.js/keys';
14
15
  import { createLogger } from '@aztec/aztec.js/log';
15
16
  import { waitForL1ToL2MessageReady } from '@aztec/aztec.js/messaging';
16
- import { createEthereumChain, createExtendedL1Client } from '@aztec/ethereum';
17
- import { Fr } from '@aztec/foundation/fields';
17
+ import { createEthereumChain } from '@aztec/ethereum/chain';
18
+ import { createExtendedL1Client } from '@aztec/ethereum/client';
19
+ import { Fr } from '@aztec/foundation/curves/bn254';
18
20
  import { Timer } from '@aztec/foundation/timer';
19
21
  import { AMMContract } from '@aztec/noir-contracts.js/AMM';
20
22
  import { PrivateTokenContract } from '@aztec/noir-contracts.js/PrivateToken';
21
23
  import { TokenContract } from '@aztec/noir-contracts.js/Token';
24
+ import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract';
22
25
  import { GasSettings } from '@aztec/stdlib/gas';
23
26
  import type { AztecNode, AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
24
27
  import { deriveSigningKey } from '@aztec/stdlib/keys';
@@ -46,15 +49,28 @@ export class BotFactory {
46
49
  * Initializes a new bot by setting up the sender account, registering the recipient,
47
50
  * deploying the token contract, and minting tokens if necessary.
48
51
  */
49
- public async setup() {
50
- const recipient = (await this.wallet.createAccount()).address;
52
+ public async setup(): Promise<{
53
+ wallet: TestWallet;
54
+ defaultAccountAddress: AztecAddress;
55
+ token: TokenContract | PrivateTokenContract;
56
+ node: AztecNode;
57
+ recipient: AztecAddress;
58
+ }> {
51
59
  const defaultAccountAddress = await this.setupAccount();
60
+ const recipient = (await this.wallet.createAccount()).address;
52
61
  const token = await this.setupToken(defaultAccountAddress);
53
62
  await this.mintTokens(token, defaultAccountAddress);
54
63
  return { wallet: this.wallet, defaultAccountAddress, token, node: this.aztecNode, recipient };
55
64
  }
56
65
 
57
- public async setupAmm() {
66
+ public async setupAmm(): Promise<{
67
+ wallet: TestWallet;
68
+ defaultAccountAddress: AztecAddress;
69
+ amm: AMMContract;
70
+ token0: TokenContract;
71
+ token1: TokenContract;
72
+ node: AztecNode;
73
+ }> {
58
74
  const defaultAccountAddress = await this.setupAccount();
59
75
  const token0 = await this.setupTokenContract(defaultAccountAddress, this.config.tokenSalt, 'BotToken0', 'BOT0');
60
76
  const token1 = await this.setupTokenContract(defaultAccountAddress, this.config.tokenSalt, 'BotToken1', 'BOT1');
@@ -102,8 +118,8 @@ export class BotFactory {
102
118
  contract: new SchnorrAccountContract(signingKey!),
103
119
  };
104
120
  const accountManager = await this.wallet.createAccount(accountData);
105
- const isInit = (await this.wallet.getContractMetadata(accountManager.address)).isContractInitialized;
106
- if (isInit) {
121
+ const metadata = await this.wallet.getContractMetadata(accountManager.address);
122
+ if (metadata.isContractInitialized) {
107
123
  this.log.info(`Account at ${accountManager.address.toString()} already initialized`);
108
124
  const timer = new Timer();
109
125
  const address = accountManager.address;
@@ -118,7 +134,7 @@ export class BotFactory {
118
134
 
119
135
  const paymentMethod = new FeeJuicePaymentMethodWithClaim(accountManager.address, claim);
120
136
  const deployMethod = await accountManager.getDeployMethod();
121
- const maxFeesPerGas = (await this.aztecNode.getCurrentBaseFees()).mul(1 + this.config.baseFeePadding);
137
+ const maxFeesPerGas = (await this.aztecNode.getCurrentMinFees()).mul(1 + this.config.minFeePadding);
122
138
  const gasSettings = GasSettings.default({ maxFeesPerGas });
123
139
  const sentTx = deployMethod.send({ from: AztecAddress.ZERO, fee: { gasSettings, paymentMethod } });
124
140
  const txHash = await sentTx.getTxHash();
@@ -151,6 +167,7 @@ export class BotFactory {
151
167
  */
152
168
  private async setupToken(sender: AztecAddress): Promise<TokenContract | PrivateTokenContract> {
153
169
  let deploy: DeployMethod<TokenContract | PrivateTokenContract>;
170
+ let tokenInstance: ContractInstanceWithAddress | undefined;
154
171
  const deployOpts: DeployOptions = {
155
172
  from: sender,
156
173
  contractAddressSalt: this.config.tokenSalt,
@@ -159,16 +176,24 @@ export class BotFactory {
159
176
  if (this.config.contract === SupportedTokenContracts.TokenContract) {
160
177
  deploy = TokenContract.deploy(this.wallet, sender, 'BotToken', 'BOT', 18);
161
178
  } else if (this.config.contract === SupportedTokenContracts.PrivateTokenContract) {
162
- deploy = PrivateTokenContract.deploy(this.wallet, MINT_BALANCE, sender);
179
+ // Generate keys for the contract since PrivateToken uses SinglePrivateMutable which requires keys
180
+ const tokenSecretKey = Fr.random();
181
+ const tokenPublicKeys = (await deriveKeys(tokenSecretKey)).publicKeys;
182
+ deploy = PrivateTokenContract.deployWithPublicKeys(tokenPublicKeys, this.wallet, MINT_BALANCE, sender);
163
183
  deployOpts.skipInstancePublication = true;
164
184
  deployOpts.skipClassPublication = true;
165
185
  deployOpts.skipInitialization = false;
186
+
187
+ // Register the contract with the secret key before deployment
188
+ tokenInstance = await deploy.getInstance(deployOpts);
189
+ await this.wallet.registerContract(tokenInstance, PrivateTokenContract.artifact, tokenSecretKey);
166
190
  } else {
167
191
  throw new Error(`Unsupported token contract type: ${this.config.contract}`);
168
192
  }
169
193
 
170
- const address = (await deploy.getInstance(deployOpts)).address;
171
- if ((await this.wallet.getContractMetadata(address)).isContractPublished) {
194
+ const address = tokenInstance?.address ?? (await deploy.getInstance(deployOpts)).address;
195
+ const metadata = await this.wallet.getContractMetadata(address);
196
+ if (metadata.isContractPublished) {
172
197
  this.log.info(`Token at ${address.toString()} already deployed`);
173
198
  return deploy.register();
174
199
  } else {
@@ -301,7 +326,8 @@ export class BotFactory {
301
326
  deployOpts: DeployOptions,
302
327
  ): Promise<T> {
303
328
  const address = (await deploy.getInstance(deployOpts)).address;
304
- if ((await this.wallet.getContractMetadata(address)).isContractPublished) {
329
+ const metadata = await this.wallet.getContractMetadata(address);
330
+ if (metadata.isContractPublished) {
305
331
  this.log.info(`Contract ${name} at ${address.toString()} already deployed`);
306
332
  return deploy.register();
307
333
  } else {
@@ -1,6 +1,6 @@
1
1
  import { AztecAddress } from '@aztec/aztec.js/addresses';
2
2
  import type { L2AmountClaim } from '@aztec/aztec.js/ethereum';
3
- import { Fr } from '@aztec/foundation/fields';
3
+ import { Fr } from '@aztec/foundation/curves/bn254';
4
4
  import { type Logger, createLogger } from '@aztec/foundation/log';
5
5
  import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
6
6