Skip to content

Commit

Permalink
feat: cli wallet improvements (#10425)
Browse files Browse the repository at this point in the history
`cli-wallet` now supports an integrated PXE, so it can connect to a
real-er network directly. A new command was also added to register a
recipient so the new note discovery and syncing process is supported.

Also found a bug in the synchronizer that prevented PXE from recovering
when starting from a pre-seeded db (it always set its own header to the
one of the genesis block, regardless of stored state)
  • Loading branch information
Thunkar authored Dec 9, 2024
1 parent 676f673 commit cc8bd80
Show file tree
Hide file tree
Showing 20 changed files with 277 additions and 61 deletions.
1 change: 1 addition & 0 deletions yarn-project/aztec.js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export {
generatePublicKey,
readFieldCompressedString,
waitForPXE,
waitForNode,
type AztecAddressLike,
type EthAddressLike,
type EventSelectorLike,
Expand Down
1 change: 1 addition & 0 deletions yarn-project/aztec.js/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export * from './abi_types.js';
export * from './cheat_codes.js';
export * from './authwit.js';
export * from './pxe.js';
export * from './node.js';
export * from './anvil_test_watcher.js';
export * from './field_compressed_string.js';
export * from './portal_manager.js';
17 changes: 17 additions & 0 deletions yarn-project/aztec.js/src/utils/node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { type AztecNode } from '@aztec/circuit-types';
import { type DebugLogger } from '@aztec/foundation/log';
import { retryUntil } from '@aztec/foundation/retry';

export const waitForNode = async (node: AztecNode, logger?: DebugLogger) => {
await retryUntil(async () => {
try {
logger?.verbose('Attempting to contact Aztec node...');
await node.getNodeInfo();
logger?.verbose('Contacted Aztec node');
return true;
} catch (error) {
logger?.verbose('Failed to contact Aztec Node');
}
return undefined;
}, 'RPC Get Node Info');
};
1 change: 1 addition & 0 deletions yarn-project/cli-wallet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"@aztec/foundation": "workspace:^",
"@aztec/kv-store": "workspace:^",
"@aztec/noir-contracts.js": "workspace:^",
"@aztec/pxe": "workspace:^",
"commander": "^12.1.0",
"inquirer": "^10.1.8",
"source-map-support": "^0.5.21",
Expand Down
34 changes: 29 additions & 5 deletions yarn-project/cli-wallet/src/bin/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { Fr, computeSecretHash, fileURLToPath } from '@aztec/aztec.js';
import { LOCALHOST } from '@aztec/cli/cli-utils';
import { type LogFn, createConsoleLogger, createDebugLogger } from '@aztec/foundation/log';
import { AztecLmdbStore } from '@aztec/kv-store/lmdb';
import { type PXEService } from '@aztec/pxe';

import { Argument, Command } from 'commander';
import { Argument, Command, Option } from 'commander';
import { readFileSync } from 'fs';
import { dirname, resolve } from 'path';
import { dirname, join, resolve } from 'path';

import { injectCommands } from '../cmds/index.js';
import { Aliases, WalletDB } from '../storage/wallet_db.js';
import { createAliasOption } from '../utils/options/index.js';
import { PXEWrapper } from '../utils/pxe_wrapper.js';

const userLog = createConsoleLogger();
const debugLogger = createDebugLogger('aztec:wallet');
Expand Down Expand Up @@ -66,18 +69,39 @@ async function main() {
const walletVersion: string = JSON.parse(readFileSync(packageJsonPath).toString()).version;

const db = WalletDB.getInstance();
const pxeWrapper = new PXEWrapper();

const program = new Command('wallet');
program
.description('Aztec wallet')
.version(walletVersion)
.option('-d, --data-dir <string>', 'Storage directory for wallet data', WALLET_DATA_DIRECTORY)
.hook('preSubcommand', command => {
const dataDir = command.optsWithGlobals().dataDir;
.addOption(
new Option('--remote-pxe', 'Connect to an external PXE RPC server, instead of the local one')
.env('REMOTE_PXE')
.default(false)
.conflicts('rpc-url'),
)
.addOption(
new Option('-n, --node-url <string>', 'URL of the Aztec node to connect to')
.env('AZTEC_NODE_URL')
.default(`http://${LOCALHOST}:8080`),
)
.hook('preSubcommand', async command => {
const { dataDir, remotePxe, nodeUrl } = command.optsWithGlobals();
if (!remotePxe) {
debugLogger.info('Using local PXE service');
await pxeWrapper.init(nodeUrl, join(dataDir, 'pxe'));
}
db.init(AztecLmdbStore.open(dataDir));
})
.hook('postAction', async () => {
if (pxeWrapper.getPXE()) {
await (pxeWrapper.getPXE() as PXEService).stop();
}
});

injectCommands(program, userLog, debugLogger, db);
injectCommands(program, userLog, debugLogger, db, pxeWrapper);
injectInternalCommands(program, userLog, db);
await program.parseAsync(process.argv);
}
Expand Down
13 changes: 5 additions & 8 deletions yarn-project/cli-wallet/src/cmds/bridge_fee_juice.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { L1FeeJuicePortalManager, createCompatibleClient } from '@aztec/aztec.js';
import { L1FeeJuicePortalManager, type PXE } from '@aztec/aztec.js';
import { prettyPrintJSON } from '@aztec/cli/utils';
import { createEthereumChain, createL1Clients } from '@aztec/ethereum';
import { type AztecAddress } from '@aztec/foundation/aztec-address';
Expand All @@ -8,7 +8,7 @@ import { type DebugLogger, type LogFn } from '@aztec/foundation/log';
export async function bridgeL1FeeJuice(
amount: bigint,
recipient: AztecAddress,
rpcUrl: string,
pxe: PXE,
l1RpcUrl: string,
chainId: number,
privateKey: string | undefined,
Expand All @@ -24,15 +24,12 @@ export async function bridgeL1FeeJuice(
const chain = createEthereumChain(l1RpcUrl, chainId);
const { publicClient, walletClient } = createL1Clients(chain.rpcUrl, privateKey ?? mnemonic, chain.chainInfo);

// Prepare L2 client
const client = await createCompatibleClient(rpcUrl, debugLogger);

const {
protocolContractAddresses: { feeJuice: feeJuiceAddress },
} = await client.getPXEInfo();
} = await pxe.getPXEInfo();

// Setup portal manager
const portal = await L1FeeJuicePortalManager.new(client, publicClient, walletClient, debugLogger);
const portal = await L1FeeJuicePortalManager.new(pxe, publicClient, walletClient, debugLogger);
const { claimAmount, claimSecret, messageHash, messageLeafIndex } = await portal.bridgeTokensPublic(
recipient,
amount,
Expand Down Expand Up @@ -69,7 +66,7 @@ export async function bridgeL1FeeJuice(
const delayedCheck = (delay: number) => {
return new Promise(resolve => {
setTimeout(async () => {
const witness = await client.getL1ToL2MembershipWitness(
const witness = await pxe.getL1ToL2MembershipWitness(
feeJuiceAddress,
Fr.fromString(messageHash),
claimSecret,
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/cli-wallet/src/cmds/create_account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ export async function createAccount(
client,
undefined /* address, we don't have it yet */,
undefined /* db, as we want to create from scratch */,
accountType,
secretKey,
accountType,
Fr.ZERO,
publicKey,
);
Expand Down
Loading

0 comments on commit cc8bd80

Please sign in to comment.