@aztec/bot 0.76.4 → 0.77.0-testnet-ignition.21
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/bot.d.ts +4 -4
- package/dest/bot.d.ts.map +1 -1
- package/dest/bot.js +45 -24
- package/dest/config.d.ts +42 -20
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +72 -52
- package/dest/factory.d.ts +7 -2
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +131 -59
- package/dest/index.d.ts +1 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -2
- package/dest/interface.d.ts +1 -1
- package/dest/interface.d.ts.map +1 -1
- package/dest/interface.js +1 -2
- package/dest/rpc.d.ts +2 -2
- package/dest/rpc.d.ts.map +1 -1
- package/dest/rpc.js +7 -5
- package/dest/runner.d.ts +1 -1
- package/dest/runner.d.ts.map +1 -1
- package/dest/runner.js +151 -156
- package/dest/utils.d.ts +3 -3
- package/dest/utils.d.ts.map +1 -1
- package/dest/utils.js +5 -4
- package/package.json +13 -14
- package/src/bot.ts +8 -9
- package/src/config.ts +38 -13
- package/src/factory.ts +101 -19
- package/src/index.ts +1 -1
- package/src/interface.ts +1 -1
- package/src/rpc.ts +2 -2
- package/src/runner.ts +1 -1
- package/src/utils.ts +3 -3
package/src/factory.ts
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
import { getSchnorrAccount } from '@aztec/accounts/schnorr';
|
|
2
|
+
import { getDeployedTestAccountsWallets, getInitialTestAccounts } from '@aztec/accounts/testing';
|
|
2
3
|
import {
|
|
3
4
|
type AccountWallet,
|
|
5
|
+
AztecAddress,
|
|
6
|
+
type AztecNode,
|
|
4
7
|
BatchCall,
|
|
5
8
|
type DeployMethod,
|
|
6
9
|
type DeployOptions,
|
|
10
|
+
FeeJuicePaymentMethodWithClaim,
|
|
11
|
+
L1FeeJuicePortalManager,
|
|
12
|
+
type PXE,
|
|
7
13
|
createLogger,
|
|
8
14
|
createPXEClient,
|
|
15
|
+
retryUntil,
|
|
9
16
|
} from '@aztec/aztec.js';
|
|
10
|
-
import {
|
|
11
|
-
import { Fr
|
|
17
|
+
import { createEthereumChain, createL1Clients } from '@aztec/ethereum';
|
|
18
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
12
19
|
import { EasyPrivateTokenContract } from '@aztec/noir-contracts.js/EasyPrivateToken';
|
|
13
20
|
import { TokenContract } from '@aztec/noir-contracts.js/Token';
|
|
21
|
+
import type { FunctionCall } from '@aztec/stdlib/abi';
|
|
22
|
+
import { deriveSigningKey } from '@aztec/stdlib/keys';
|
|
14
23
|
import { makeTracedFetch } from '@aztec/telemetry-client';
|
|
15
24
|
|
|
16
25
|
import { type BotConfig, SupportedTokenContracts, getVersions } from './config.js';
|
|
@@ -28,6 +37,11 @@ export class BotFactory {
|
|
|
28
37
|
if (config.flushSetupTransactions && !dependencies.node) {
|
|
29
38
|
throw new Error(`Either a node client or node url must be provided if transaction flushing is requested`);
|
|
30
39
|
}
|
|
40
|
+
if (config.senderPrivateKey && !dependencies.node) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
`Either a node client or node url must be provided for bridging L1 fee juice to deploy an account with private key`,
|
|
43
|
+
);
|
|
44
|
+
}
|
|
31
45
|
if (!dependencies.pxe && !config.pxeUrl) {
|
|
32
46
|
throw new Error(`Either a PXE client or a PXE URL must be provided`);
|
|
33
47
|
}
|
|
@@ -60,27 +74,53 @@ export class BotFactory {
|
|
|
60
74
|
* @returns The sender wallet.
|
|
61
75
|
*/
|
|
62
76
|
private async setupAccount() {
|
|
77
|
+
if (this.config.senderPrivateKey) {
|
|
78
|
+
return await this.setupAccountWithPrivateKey(this.config.senderPrivateKey);
|
|
79
|
+
} else {
|
|
80
|
+
return await this.setupTestAccount();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private async setupAccountWithPrivateKey(privateKey: Fr) {
|
|
63
85
|
const salt = Fr.ONE;
|
|
64
|
-
const signingKey = deriveSigningKey(
|
|
65
|
-
const account = await getSchnorrAccount(this.pxe,
|
|
86
|
+
const signingKey = deriveSigningKey(privateKey);
|
|
87
|
+
const account = await getSchnorrAccount(this.pxe, privateKey, signingKey, salt);
|
|
66
88
|
const isInit = (await this.pxe.getContractMetadata(account.getAddress())).isContractInitialized;
|
|
67
89
|
if (isInit) {
|
|
68
90
|
this.log.info(`Account at ${account.getAddress().toString()} already initialized`);
|
|
69
91
|
const wallet = await account.register();
|
|
70
92
|
return wallet;
|
|
71
93
|
} else {
|
|
72
|
-
|
|
73
|
-
|
|
94
|
+
const address = account.getAddress();
|
|
95
|
+
this.log.info(`Deploying account at ${address}`);
|
|
96
|
+
|
|
97
|
+
const claim = await this.bridgeL1FeeJuice(address, 10n ** 22n);
|
|
98
|
+
|
|
99
|
+
const wallet = await account.getWallet();
|
|
100
|
+
const paymentMethod = new FeeJuicePaymentMethodWithClaim(wallet, claim);
|
|
101
|
+
const sentTx = account.deploy({ fee: { paymentMethod } });
|
|
74
102
|
const txHash = await sentTx.getTxHash();
|
|
75
103
|
this.log.info(`Sent tx with hash ${txHash.toString()}`);
|
|
76
|
-
|
|
77
|
-
this.log.verbose('Flushing transactions');
|
|
78
|
-
await this.node!.flushTxs();
|
|
79
|
-
}
|
|
104
|
+
await this.tryFlushTxs();
|
|
80
105
|
this.log.verbose('Waiting for account deployment to settle');
|
|
81
106
|
await sentTx.wait({ timeout: this.config.txMinedWaitSeconds });
|
|
82
|
-
|
|
107
|
+
this.log.info(`Account deployed at ${address}`);
|
|
108
|
+
return wallet;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private async setupTestAccount() {
|
|
113
|
+
let [wallet] = await getDeployedTestAccountsWallets(this.pxe);
|
|
114
|
+
if (wallet) {
|
|
115
|
+
this.log.info(`Using funded test account: ${wallet.getAddress()}`);
|
|
116
|
+
} else {
|
|
117
|
+
this.log.info('Registering funded test account');
|
|
118
|
+
const [account] = await getInitialTestAccounts();
|
|
119
|
+
const manager = await getSchnorrAccount(this.pxe, account.secret, account.signingKey, account.salt);
|
|
120
|
+
wallet = await manager.register();
|
|
121
|
+
this.log.info(`Funded test account registered: ${wallet.getAddress()}`);
|
|
83
122
|
}
|
|
123
|
+
return wallet;
|
|
84
124
|
}
|
|
85
125
|
|
|
86
126
|
/**
|
|
@@ -120,10 +160,7 @@ export class BotFactory {
|
|
|
120
160
|
const sentTx = deploy.send(deployOpts);
|
|
121
161
|
const txHash = await sentTx.getTxHash();
|
|
122
162
|
this.log.info(`Sent tx with hash ${txHash.toString()}`);
|
|
123
|
-
|
|
124
|
-
this.log.verbose('Flushing transactions');
|
|
125
|
-
await this.node!.flushTxs();
|
|
126
|
-
}
|
|
163
|
+
await this.tryFlushTxs();
|
|
127
164
|
this.log.verbose('Waiting for token setup to settle');
|
|
128
165
|
return sentTx.deployed({ timeout: this.config.txMinedWaitSeconds });
|
|
129
166
|
}
|
|
@@ -149,7 +186,7 @@ export class BotFactory {
|
|
|
149
186
|
if (privateBalance < MIN_BALANCE) {
|
|
150
187
|
this.log.info(`Minting private tokens for ${sender.toString()}`);
|
|
151
188
|
|
|
152
|
-
const from = sender; // we are setting from to sender here because
|
|
189
|
+
const from = sender; // we are setting from to sender here because we need a sender to calculate the tag
|
|
153
190
|
calls.push(
|
|
154
191
|
isStandardToken
|
|
155
192
|
? await token.methods.mint_to_private(from, sender, MINT_BALANCE).request()
|
|
@@ -167,11 +204,56 @@ export class BotFactory {
|
|
|
167
204
|
const sentTx = new BatchCall(token.wallet, calls).send();
|
|
168
205
|
const txHash = await sentTx.getTxHash();
|
|
169
206
|
this.log.info(`Sent tx with hash ${txHash.toString()}`);
|
|
207
|
+
await this.tryFlushTxs();
|
|
208
|
+
this.log.verbose('Waiting for token mint to settle');
|
|
209
|
+
await sentTx.wait({ timeout: this.config.txMinedWaitSeconds });
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
private async bridgeL1FeeJuice(recipient: AztecAddress, amount: bigint) {
|
|
213
|
+
const l1RpcUrls = this.config.l1RpcUrls;
|
|
214
|
+
if (!l1RpcUrls?.length) {
|
|
215
|
+
throw new Error('L1 Rpc url is required to bridge the fee juice to fund the deployment of the account.');
|
|
216
|
+
}
|
|
217
|
+
const mnemonicOrPrivateKey = this.config.l1PrivateKey || this.config.l1Mnemonic;
|
|
218
|
+
if (!mnemonicOrPrivateKey) {
|
|
219
|
+
throw new Error(
|
|
220
|
+
'Either a mnemonic or private key of an L1 account is required to bridge the fee juice to fund the deployment of the account.',
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const { l1ChainId } = await this.pxe.getNodeInfo();
|
|
225
|
+
const chain = createEthereumChain(l1RpcUrls, l1ChainId);
|
|
226
|
+
const { publicClient, walletClient } = createL1Clients(chain.rpcUrls, mnemonicOrPrivateKey, chain.chainInfo);
|
|
227
|
+
|
|
228
|
+
const portal = await L1FeeJuicePortalManager.new(this.pxe, publicClient, walletClient, this.log);
|
|
229
|
+
const claim = await portal.bridgeTokensPublic(recipient, amount, true /* mint */);
|
|
230
|
+
|
|
231
|
+
const isSynced = async () => await this.pxe.isL1ToL2MessageSynced(Fr.fromHexString(claim.messageHash));
|
|
232
|
+
await retryUntil(isSynced, `message ${claim.messageHash} sync`, 24, 1);
|
|
233
|
+
|
|
234
|
+
this.log.info(`Created a claim for ${amount} L1 fee juice to ${recipient}.`, claim);
|
|
235
|
+
|
|
236
|
+
// Progress by 2 L2 blocks so that the l1ToL2Message added above will be available to use on L2.
|
|
237
|
+
await this.advanceL2Block();
|
|
238
|
+
await this.advanceL2Block();
|
|
239
|
+
|
|
240
|
+
return claim;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
private async advanceL2Block() {
|
|
244
|
+
const initialBlockNumber = await this.node!.getBlockNumber();
|
|
245
|
+
await this.tryFlushTxs();
|
|
246
|
+
await retryUntil(async () => (await this.node!.getBlockNumber()) >= initialBlockNumber + 1);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
private async tryFlushTxs() {
|
|
170
250
|
if (this.config.flushSetupTransactions) {
|
|
171
251
|
this.log.verbose('Flushing transactions');
|
|
172
|
-
|
|
252
|
+
try {
|
|
253
|
+
await this.node!.flushTxs();
|
|
254
|
+
} catch (err) {
|
|
255
|
+
this.log.error(`Failed to flush transactions: ${err}`);
|
|
256
|
+
}
|
|
173
257
|
}
|
|
174
|
-
this.log.verbose('Waiting for token mint to settle');
|
|
175
|
-
await sentTx.wait({ timeout: this.config.txMinedWaitSeconds });
|
|
176
258
|
}
|
|
177
259
|
}
|
package/src/index.ts
CHANGED
package/src/interface.ts
CHANGED
package/src/rpc.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ApiHandler } from '@aztec/foundation/json-rpc/server';
|
|
2
2
|
import { createTracedJsonRpcServer } from '@aztec/telemetry-client';
|
|
3
3
|
|
|
4
4
|
import { BotRunnerApiSchema } from './interface.js';
|
|
5
|
-
import {
|
|
5
|
+
import type { BotRunner } from './runner.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Wraps a bot runner with a JSON RPC HTTP server.
|
package/src/runner.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { type TelemetryClient, type Traceable, type Tracer, makeTracedFetch, tra
|
|
|
4
4
|
|
|
5
5
|
import { Bot } from './bot.js';
|
|
6
6
|
import { type BotConfig, getVersions } from './config.js';
|
|
7
|
-
import {
|
|
7
|
+
import type { BotRunnerApi } from './interface.js';
|
|
8
8
|
|
|
9
9
|
export class BotRunner implements BotRunnerApi, Traceable {
|
|
10
10
|
private log = createLogger('bot');
|
package/src/utils.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import type { EasyPrivateTokenContract } from '@aztec/noir-contracts.js/EasyPrivateToken';
|
|
2
|
+
import type { TokenContract } from '@aztec/noir-contracts.js/Token';
|
|
3
|
+
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Gets the private and public balance of the given token for the given address.
|