@aztec/bot 0.0.1-commit.d3ec352c → 0.0.1-commit.e61ad554
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 +11 -12
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +7 -7
- package/dest/factory.d.ts +1 -6
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +96 -62
- 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/dest/store/bot_store.js +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 +52 -50
- package/src/factory.ts +77 -42
- package/src/store/bot_store.ts +1 -1
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/
|
|
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 {
|
|
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
|
|
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. */
|
|
@@ -80,50 +80,52 @@ export type BotConfig = {
|
|
|
80
80
|
ammTxs: boolean;
|
|
81
81
|
} & Pick<DataStoreConfig, 'dataDirectory' | 'dataStoreMapSizeKb'>;
|
|
82
82
|
|
|
83
|
-
export const BotConfigSchema =
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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
|
-
|
|
195
|
-
env: '
|
|
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
|
@@ -7,18 +7,23 @@ 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';
|
|
13
14
|
import { FeeJuicePaymentMethodWithClaim } from '@aztec/aztec.js/fee';
|
|
15
|
+
import { deriveKeys } from '@aztec/aztec.js/keys';
|
|
14
16
|
import { createLogger } from '@aztec/aztec.js/log';
|
|
15
17
|
import { waitForL1ToL2MessageReady } from '@aztec/aztec.js/messaging';
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
+
import { waitForTx } from '@aztec/aztec.js/node';
|
|
19
|
+
import { createEthereumChain } from '@aztec/ethereum/chain';
|
|
20
|
+
import { createExtendedL1Client } from '@aztec/ethereum/client';
|
|
21
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
18
22
|
import { Timer } from '@aztec/foundation/timer';
|
|
19
23
|
import { AMMContract } from '@aztec/noir-contracts.js/AMM';
|
|
20
24
|
import { PrivateTokenContract } from '@aztec/noir-contracts.js/PrivateToken';
|
|
21
25
|
import { TokenContract } from '@aztec/noir-contracts.js/Token';
|
|
26
|
+
import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract';
|
|
22
27
|
import { GasSettings } from '@aztec/stdlib/gas';
|
|
23
28
|
import type { AztecNode, AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
|
|
24
29
|
import { deriveSigningKey } from '@aztec/stdlib/keys';
|
|
@@ -53,8 +58,8 @@ export class BotFactory {
|
|
|
53
58
|
node: AztecNode;
|
|
54
59
|
recipient: AztecAddress;
|
|
55
60
|
}> {
|
|
56
|
-
const recipient = (await this.wallet.createAccount()).address;
|
|
57
61
|
const defaultAccountAddress = await this.setupAccount();
|
|
62
|
+
const recipient = (await this.wallet.createAccount()).address;
|
|
58
63
|
const token = await this.setupToken(defaultAccountAddress);
|
|
59
64
|
await this.mintTokens(token, defaultAccountAddress);
|
|
60
65
|
return { wallet: this.wallet, defaultAccountAddress, token, node: this.aztecNode, recipient };
|
|
@@ -115,8 +120,8 @@ export class BotFactory {
|
|
|
115
120
|
contract: new SchnorrAccountContract(signingKey!),
|
|
116
121
|
};
|
|
117
122
|
const accountManager = await this.wallet.createAccount(accountData);
|
|
118
|
-
const
|
|
119
|
-
if (
|
|
123
|
+
const metadata = await this.wallet.getContractMetadata(accountManager.address);
|
|
124
|
+
if (metadata.isContractInitialized) {
|
|
120
125
|
this.log.info(`Account at ${accountManager.address.toString()} already initialized`);
|
|
121
126
|
const timer = new Timer();
|
|
122
127
|
const address = accountManager.address;
|
|
@@ -131,12 +136,18 @@ export class BotFactory {
|
|
|
131
136
|
|
|
132
137
|
const paymentMethod = new FeeJuicePaymentMethodWithClaim(accountManager.address, claim);
|
|
133
138
|
const deployMethod = await accountManager.getDeployMethod();
|
|
134
|
-
const maxFeesPerGas = (await this.aztecNode.
|
|
139
|
+
const maxFeesPerGas = (await this.aztecNode.getCurrentMinFees()).mul(1 + this.config.minFeePadding);
|
|
135
140
|
const gasSettings = GasSettings.default({ maxFeesPerGas });
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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
|
+
});
|
|
140
151
|
this.log.info(`Account deployed at ${address}`);
|
|
141
152
|
|
|
142
153
|
// Clean up the consumed bridge claim
|
|
@@ -164,33 +175,49 @@ export class BotFactory {
|
|
|
164
175
|
*/
|
|
165
176
|
private async setupToken(sender: AztecAddress): Promise<TokenContract | PrivateTokenContract> {
|
|
166
177
|
let deploy: DeployMethod<TokenContract | PrivateTokenContract>;
|
|
178
|
+
let tokenInstance: ContractInstanceWithAddress | undefined;
|
|
167
179
|
const deployOpts: DeployOptions = {
|
|
168
180
|
from: sender,
|
|
169
181
|
contractAddressSalt: this.config.tokenSalt,
|
|
170
182
|
universalDeploy: true,
|
|
171
183
|
};
|
|
184
|
+
let token: TokenContract | PrivateTokenContract;
|
|
172
185
|
if (this.config.contract === SupportedTokenContracts.TokenContract) {
|
|
173
186
|
deploy = TokenContract.deploy(this.wallet, sender, 'BotToken', 'BOT', 18);
|
|
187
|
+
tokenInstance = await deploy.getInstance(deployOpts);
|
|
188
|
+
token = TokenContract.at(tokenInstance.address, this.wallet);
|
|
174
189
|
} else if (this.config.contract === SupportedTokenContracts.PrivateTokenContract) {
|
|
175
|
-
|
|
190
|
+
// Generate keys for the contract since PrivateToken uses SinglePrivateMutable which requires keys
|
|
191
|
+
const tokenSecretKey = Fr.random();
|
|
192
|
+
const tokenPublicKeys = (await deriveKeys(tokenSecretKey)).publicKeys;
|
|
193
|
+
deploy = PrivateTokenContract.deployWithPublicKeys(tokenPublicKeys, this.wallet, MINT_BALANCE, sender);
|
|
176
194
|
deployOpts.skipInstancePublication = true;
|
|
177
195
|
deployOpts.skipClassPublication = true;
|
|
178
196
|
deployOpts.skipInitialization = false;
|
|
197
|
+
|
|
198
|
+
// Register the contract with the secret key before deployment
|
|
199
|
+
tokenInstance = await deploy.getInstance(deployOpts);
|
|
200
|
+
token = PrivateTokenContract.at(tokenInstance.address, this.wallet);
|
|
201
|
+
await this.wallet.registerContract(tokenInstance, PrivateTokenContract.artifact, tokenSecretKey);
|
|
179
202
|
} else {
|
|
180
203
|
throw new Error(`Unsupported token contract type: ${this.config.contract}`);
|
|
181
204
|
}
|
|
182
205
|
|
|
183
|
-
const address = (await deploy.getInstance(deployOpts)).address;
|
|
184
|
-
|
|
206
|
+
const address = tokenInstance?.address ?? (await deploy.getInstance(deployOpts)).address;
|
|
207
|
+
const metadata = await this.wallet.getContractMetadata(address);
|
|
208
|
+
if (metadata.isContractPublished) {
|
|
185
209
|
this.log.info(`Token at ${address.toString()} already deployed`);
|
|
186
|
-
|
|
210
|
+
await deploy.register();
|
|
187
211
|
} else {
|
|
188
212
|
this.log.info(`Deploying token contract at ${address.toString()}`);
|
|
189
|
-
const
|
|
190
|
-
const txHash = await sentTx.getTxHash();
|
|
213
|
+
const txHash = await deploy.send({ ...deployOpts, wait: NO_WAIT });
|
|
191
214
|
this.log.info(`Sent tx for token setup with hash ${txHash.toString()}`);
|
|
192
|
-
|
|
215
|
+
await this.withNoMinTxsPerBlock(async () => {
|
|
216
|
+
await waitForTx(this.aztecNode, txHash, { timeout: this.config.txMinedWaitSeconds });
|
|
217
|
+
return token;
|
|
218
|
+
});
|
|
193
219
|
}
|
|
220
|
+
return token;
|
|
194
221
|
}
|
|
195
222
|
|
|
196
223
|
/**
|
|
@@ -198,7 +225,7 @@ export class BotFactory {
|
|
|
198
225
|
* @param wallet - Wallet to deploy the token contract from.
|
|
199
226
|
* @returns The TokenContract instance.
|
|
200
227
|
*/
|
|
201
|
-
private setupTokenContract(
|
|
228
|
+
private async setupTokenContract(
|
|
202
229
|
deployer: AztecAddress,
|
|
203
230
|
contractAddressSalt: Fr,
|
|
204
231
|
name: string,
|
|
@@ -207,7 +234,8 @@ export class BotFactory {
|
|
|
207
234
|
): Promise<TokenContract> {
|
|
208
235
|
const deployOpts: DeployOptions = { from: deployer, contractAddressSalt, universalDeploy: true };
|
|
209
236
|
const deploy = TokenContract.deploy(this.wallet, deployer, name, ticker, decimals);
|
|
210
|
-
|
|
237
|
+
const instance = await this.registerOrDeployContract('Token - ' + name, deploy, deployOpts);
|
|
238
|
+
return TokenContract.at(instance.address, this.wallet);
|
|
211
239
|
}
|
|
212
240
|
|
|
213
241
|
private async setupAmmContract(
|
|
@@ -219,12 +247,14 @@ export class BotFactory {
|
|
|
219
247
|
): Promise<AMMContract> {
|
|
220
248
|
const deployOpts: DeployOptions = { from: deployer, contractAddressSalt, universalDeploy: true };
|
|
221
249
|
const deploy = AMMContract.deploy(this.wallet, token0.address, token1.address, lpToken.address);
|
|
222
|
-
const
|
|
250
|
+
const instance = await this.registerOrDeployContract('AMM', deploy, deployOpts);
|
|
251
|
+
const amm = AMMContract.at(instance.address, this.wallet);
|
|
223
252
|
|
|
224
253
|
this.log.info(`AMM deployed at ${amm.address}`);
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
|
|
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()}`);
|
|
228
258
|
this.log.info(`Liquidity token initialized`);
|
|
229
259
|
|
|
230
260
|
return amm;
|
|
@@ -283,23 +313,22 @@ export class BotFactory {
|
|
|
283
313
|
.getFunctionCall(),
|
|
284
314
|
});
|
|
285
315
|
|
|
286
|
-
const
|
|
316
|
+
const mintReceipt = await new BatchCall(this.wallet, [
|
|
287
317
|
token0.methods.mint_to_private(liquidityProvider, MINT_BALANCE),
|
|
288
318
|
token1.methods.mint_to_private(liquidityProvider, MINT_BALANCE),
|
|
289
|
-
]).send({ from: liquidityProvider });
|
|
319
|
+
]).send({ from: liquidityProvider, wait: { timeout: this.config.txMinedWaitSeconds } });
|
|
290
320
|
|
|
291
|
-
this.log.info(`Sent mint tx: ${
|
|
292
|
-
await mintTx.wait({ timeout: this.config.txMinedWaitSeconds });
|
|
321
|
+
this.log.info(`Sent mint tx: ${mintReceipt.txHash.toString()}`);
|
|
293
322
|
|
|
294
|
-
const
|
|
323
|
+
const addLiquidityReceipt = await amm.methods
|
|
295
324
|
.add_liquidity(amount0Max, amount1Max, amount0Min, amount1Min, authwitNonce)
|
|
296
325
|
.send({
|
|
297
326
|
from: liquidityProvider,
|
|
298
327
|
authWitnesses: [token0Authwit, token1Authwit],
|
|
328
|
+
wait: { timeout: this.config.txMinedWaitSeconds },
|
|
299
329
|
});
|
|
300
330
|
|
|
301
|
-
this.log.info(`Sent tx to add liquidity to the AMM: ${
|
|
302
|
-
await addLiquidityTx.wait({ timeout: this.config.txMinedWaitSeconds });
|
|
331
|
+
this.log.info(`Sent tx to add liquidity to the AMM: ${addLiquidityReceipt.txHash.toString()}`);
|
|
303
332
|
this.log.info(`Liquidity added`);
|
|
304
333
|
|
|
305
334
|
const [newT0Bal, newT1Bal, newLPBal] = await getPrivateBalances();
|
|
@@ -312,18 +341,22 @@ export class BotFactory {
|
|
|
312
341
|
name: string,
|
|
313
342
|
deploy: DeployMethod<T>,
|
|
314
343
|
deployOpts: DeployOptions,
|
|
315
|
-
): Promise<
|
|
316
|
-
const
|
|
317
|
-
|
|
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) {
|
|
318
349
|
this.log.info(`Contract ${name} at ${address.toString()} already deployed`);
|
|
319
|
-
|
|
350
|
+
await deploy.register();
|
|
320
351
|
} else {
|
|
321
352
|
this.log.info(`Deploying contract ${name} at ${address.toString()}`);
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
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
|
+
});
|
|
326
358
|
}
|
|
359
|
+
return instance;
|
|
327
360
|
}
|
|
328
361
|
|
|
329
362
|
/**
|
|
@@ -359,10 +392,12 @@ export class BotFactory {
|
|
|
359
392
|
this.log.info(`Skipping minting as ${minter.toString()} has enough tokens`);
|
|
360
393
|
return;
|
|
361
394
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
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
|
+
});
|
|
366
401
|
}
|
|
367
402
|
|
|
368
403
|
/**
|
package/src/store/bot_store.ts
CHANGED
|
@@ -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/
|
|
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
|
|