Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions yarn-project/aztec.js/src/account_manager/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ export class AccountManager {
return this.completeAddress;
}

/**
* Gets the address for this given account.
* Does not require the account to be deployed or registered.
* @returns The address.
*/
public getAddress() {
return this.getCompleteAddress().address;
}

/**
* Returns the contract instance definition associated with this account.
* Does not require the account to be deployed or registered.
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/aztec.js/src/contract/contract_base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export class ContractBase {
/** The Application Binary Interface for the contract. */
public readonly artifact: ContractArtifact,
/** The wallet used for interacting with this contract. */
protected wallet: Wallet,
public wallet: Wallet,
) {
artifact.functions.forEach((f: FunctionArtifact) => {
const interactionFunction = (...args: any[]) => {
Expand Down
10 changes: 10 additions & 0 deletions yarn-project/aztec.js/src/contract/deploy_method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,16 @@ export class DeployMethod<TContract extends ContractBase = Contract> extends Bas
return this.functionCalls;
}

/**
* Register this contract in the PXE and returns the Contract object.
* @param options - Deployment options.
*/
public async register(options: DeployOptions = {}): Promise<TContract> {
const instance = this.getInstance(options);
await this.wallet.registerContract({ artifact: this.artifact, instance });
return this.postDeployCtor(instance.address, this.wallet);
}

/**
* Returns calls for registration of the class and deployment of the instance, depending on the provided options.
* @param options - Deployment options.
Expand Down
3 changes: 3 additions & 0 deletions yarn-project/aztec.js/src/wallet/base_wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ export abstract class BaseWallet implements Wallet {
isContractPubliclyDeployed(address: AztecAddress): Promise<boolean> {
return this.pxe.isContractPubliclyDeployed(address);
}
isContractInitialized(address: AztecAddress): Promise<boolean> {
return this.pxe.isContractInitialized(address);
}
getPXEInfo(): Promise<PXEInfo> {
return this.pxe.getPXEInfo();
}
Expand Down
1 change: 1 addition & 0 deletions yarn-project/aztec/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@aztec/aztec-node": "workspace:^",
"@aztec/aztec.js": "workspace:^",
"@aztec/bb-prover": "workspace:^",
"@aztec/bot": "workspace:^",
"@aztec/builder": "workspace:^",
"@aztec/circuit-types": "workspace:^",
"@aztec/circuits.js": "workspace:^",
Expand Down
5 changes: 4 additions & 1 deletion yarn-project/aztec/src/cli/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export function injectAztecCommands(program: Command, userLog: LogFn, debugLogge
.option('-o, --prover-node [options]', cliTexts.proverNode)
.option('-p2p, --p2p-bootstrap [options]', cliTexts.p2pBootstrap)
.option('-t, --txe [options]', cliTexts.txe)
.option('--bot [options]', cliTexts.bot)
.action(async options => {
// list of 'stop' functions to call when process ends
const signalHandlers: Array<() => Promise<void>> = [];
Expand Down Expand Up @@ -66,10 +67,12 @@ export function injectAztecCommands(program: Command, userLog: LogFn, debugLogge
signalHandlers.push(stop);
services = [{ node: nodeServer }, { pxe: pxeServer }];
} else {
// Start Aztec Node
if (options.node) {
const { startNode } = await import('./cmds/start_node.js');
services = await startNode(options, signalHandlers, userLog);
} else if (options.bot) {
const { startBot } = await import('./cmds/start_bot.js');
services = await startBot(options, signalHandlers, userLog);
} else if (options.proverNode) {
const { startProverNode } = await import('./cmds/start_prover_node.js');
services = await startProverNode(options, signalHandlers, userLog);
Expand Down
43 changes: 43 additions & 0 deletions yarn-project/aztec/src/cli/cmds/start_bot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { type BotConfig, BotRunner, createBotRunnerRpcServer, getBotConfigFromEnv } from '@aztec/bot';
import { type PXE } from '@aztec/circuit-types';
import { type ServerList } from '@aztec/foundation/json-rpc/server';
import { type LogFn } from '@aztec/foundation/log';

import { mergeEnvVarsAndCliOptions, parseModuleOptions } from '../util.js';

export async function startBot(
options: any,
signalHandlers: (() => Promise<void>)[],
userLog: LogFn,
): Promise<ServerList> {
// Services that will be started in a single multi-rpc server
const services: ServerList = [];

const { proverNode, archiver, sequencer, p2pBootstrap, txe, prover } = options;
if (proverNode || archiver || sequencer || p2pBootstrap || txe || prover) {
userLog(
`Starting a bot with --prover-node, --prover, --archiver, --sequencer, --p2p-bootstrap, or --txe is not supported.`,
);
process.exit(1);
}

await addBot(options, services, signalHandlers);
return services;
}

export async function addBot(
options: any,
services: ServerList,
signalHandlers: (() => Promise<void>)[],
deps: { pxe?: PXE } = {},
) {
const envVars = getBotConfigFromEnv();
const cliOptions = parseModuleOptions(options.bot);
const config = mergeEnvVarsAndCliOptions<BotConfig>(envVars, cliOptions);

const botRunner = new BotRunner(config, { pxe: deps.pxe });
const botServer = createBotRunnerRpcServer(botRunner);
await botRunner.start();
services.push({ bot: botServer });
signalHandlers.push(botRunner.stop);
}
23 changes: 11 additions & 12 deletions yarn-project/aztec/src/cli/cmds/start_node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ import {
createAztecNodeRpcServer,
getConfigEnvVars as getNodeConfigEnvVars,
} from '@aztec/aztec-node';
import { type PXE } from '@aztec/circuit-types';
import { NULL_KEY } from '@aztec/ethereum';
import { type ServerList } from '@aztec/foundation/json-rpc/server';
import { type LogFn } from '@aztec/foundation/log';
import { createProvingJobSourceServer } from '@aztec/prover-client/prover-agent';
import { type PXEServiceConfig, createPXERpcServer, getPXEServiceConfig } from '@aztec/pxe';
import {
createAndStartTelemetryClient,
getConfigEnvVars as getTelemetryClientConfig,
} from '@aztec/telemetry-client/start';

import { mnemonicToAccount, privateKeyToAccount } from 'viem/accounts';

import { MNEMONIC, createAztecNode, createAztecPXE, deployContractsToL1 } from '../../sandbox.js';
import { MNEMONIC, createAztecNode, deployContractsToL1 } from '../../sandbox.js';
import { mergeEnvVarsAndCliOptions, parseModuleOptions } from '../util.js';

const { DEPLOY_AZTEC_CONTRACTS } = process.env;
Expand Down Expand Up @@ -108,18 +108,17 @@ export const startNode = async (
// Add node stop function to signal handlers
signalHandlers.push(node.stop);

// Create a PXE client that connects to the node.
// Add a PXE client that connects to this node if requested
let pxe: PXE | undefined;
if (options.pxe) {
const pxeCliOptions = parseModuleOptions(options.pxe);
const pxeConfig = mergeEnvVarsAndCliOptions<PXEServiceConfig>(getPXEServiceConfig(), pxeCliOptions);
const pxe = await createAztecPXE(node, pxeConfig);
const pxeServer = createPXERpcServer(pxe);

// Add PXE to services list
services.push({ pxe: pxeServer });
const { addPXE } = await import('./start_pxe.js');
pxe = await addPXE(options, services, signalHandlers, userLog, { node });
}

// Add PXE stop function to signal handlers
signalHandlers.push(pxe.stop);
// Add a txs bot if requested
if (options.bot) {
const { addBot } = await import('./start_bot.js');
await addBot(options, services, signalHandlers, { pxe });
}

return services;
Expand Down
48 changes: 25 additions & 23 deletions yarn-project/aztec/src/cli/cmds/start_pxe.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,40 @@
import { createAztecNodeClient } from '@aztec/circuit-types';
import { type AztecNode, createAztecNodeClient } from '@aztec/circuit-types';
import { type ServerList } from '@aztec/foundation/json-rpc/server';
import { type LogFn } from '@aztec/foundation/log';
import { type PXEServiceConfig, createPXERpcServer, createPXEService, getPXEServiceConfig } from '@aztec/pxe';

import { mergeEnvVarsAndCliOptions, parseModuleOptions } from '../util.js';

const { AZTEC_NODE_URL } = process.env;

export const startPXE = async (options: any, signalHandlers: (() => Promise<void>)[], userLog: LogFn) => {
// Services that will be started in a single multi-rpc server
export async function startPXE(options: any, signalHandlers: (() => Promise<void>)[], userLog: LogFn) {
const services: ServerList = [];
// Starting a PXE with a remote node.
// get env vars first
const pxeConfigEnvVars = getPXEServiceConfig();
// get config from options
const pxeCliOptions = parseModuleOptions(options.pxe);
await addPXE(options, services, signalHandlers, userLog, {});
return services;
}

// Determine node url from options or env vars
const nodeUrl = pxeCliOptions.nodeUrl || AZTEC_NODE_URL;
// throw if no Aztec Node URL is provided
if (!nodeUrl) {
export async function addPXE(
options: any,
services: ServerList,
signalHandlers: (() => Promise<void>)[],
userLog: LogFn,
deps: { node?: AztecNode } = {},
) {
const pxeCliOptions = parseModuleOptions(options.pxe);
const pxeConfig = mergeEnvVarsAndCliOptions<PXEServiceConfig>(getPXEServiceConfig(), pxeCliOptions);
const nodeUrl = pxeCliOptions.nodeUrl ?? process.env.AZTEC_NODE_URL;
if (!nodeUrl && !deps.node) {
userLog('Aztec Node URL (nodeUrl | AZTEC_NODE_URL) option is required to start PXE without --node option');
throw new Error('Aztec Node URL (nodeUrl | AZTEC_NODE_URL) option is required to start PXE without --node option');
process.exit(1);
}

// merge env vars and cli options
const pxeConfig = mergeEnvVarsAndCliOptions<PXEServiceConfig>(pxeConfigEnvVars, pxeCliOptions);

// create a node client
const node = createAztecNodeClient(nodeUrl);

const node = deps.node ?? createAztecNodeClient(nodeUrl);
const pxe = await createPXEService(node, pxeConfig);
const pxeServer = createPXERpcServer(pxe);

// Add PXE to services list
services.push({ pxe: pxeServer });

// Add PXE stop function to signal handlers
signalHandlers.push(pxe.stop);
return services;
};

return pxe;
}
10 changes: 10 additions & 0 deletions yarn-project/aztec/src/cli/texts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,14 @@ export const cliTexts = {
'Starts a TXE with options\n' +
'Available options are listed below as cliProperty:ENV_VARIABLE_NAME.\n' +
'txePort:TXE_PORT - number - The port on which the TXE should listen for connections. Default: 8081\n',
bot:
'Starts a bot that sends token transfer txs at regular intervals, using a local or remote PXE\n' +
'Available options are listed below as cliProperty:ENV_VARIABLE_NAME.\n' +
'feePaymentMethod:BOT_FEE_PAYMENT_METHOD - native | none - How to pay for fees for each tx.\n' +
'senderPrivateKey:BOT_PRIVATE_KEY - hex - Private key for sending txs.\n' +
'tokenSalt:BOT_TOKEN_SALT - hex - Deployment salt for the token contract.\n' +
'recipientEncryptionSecret:BOT_RECIPIENT_ENCRYPTION_SECRET - hex - Encryption secret key for the recipient account.\n' +
'txIntervalSeconds:BOT_TX_INTERVAL_SECONDS - number - Interval between txs are started. Too low a value may result in multiple txs in flight at a time. \n' +
'privateTransfersPerTx:BOT_PRIVATE_TRANSFERS_PER_TX - number - How many private transfers to execute per tx. \n' +
'publicTransfersPerTx:BOT_PUBLIC_TRANSFERS_PER_TX - number - How many public transfers to execute per tx.\n',
};
8 changes: 6 additions & 2 deletions yarn-project/aztec/src/cli/util.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { type ArchiverConfig } from '@aztec/archiver';
import { type AztecNodeConfig } from '@aztec/aztec-node';
import { type AccountManager, type Fr } from '@aztec/aztec.js';
import { type BotConfig } from '@aztec/bot';
import { type L1ContractAddresses, l1ContractsNames } from '@aztec/ethereum';
import { EthAddress } from '@aztec/foundation/eth-address';
import { type ServerList } from '@aztec/foundation/json-rpc/server';
import { type LogFn, createConsoleLogger } from '@aztec/foundation/log';
import { type P2PConfig } from '@aztec/p2p';
import { type ProverNodeConfig } from '@aztec/prover-node';
import { type PXEService, type PXEServiceConfig } from '@aztec/pxe';

export interface ServiceStarter<T = any> {
Expand Down Expand Up @@ -66,8 +68,10 @@ export const parseModuleOptions = (options: string): Record<string, string> => {
}, {});
};

export const mergeEnvVarsAndCliOptions = <T extends AztecNodeConfig | PXEServiceConfig | P2PConfig | ArchiverConfig>(
envVars: AztecNodeConfig | PXEServiceConfig | P2PConfig | ArchiverConfig,
export const mergeEnvVarsAndCliOptions = <
T extends AztecNodeConfig | PXEServiceConfig | P2PConfig | ArchiverConfig | BotConfig | ProverNodeConfig,
>(
envVars: AztecNodeConfig | PXEServiceConfig | P2PConfig | ArchiverConfig | BotConfig | ProverNodeConfig,
cliOptions: Record<string, string>,
contractsRequired = false,
userLog = createConsoleLogger(),
Expand Down
3 changes: 3 additions & 0 deletions yarn-project/aztec/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
{
"path": "../bb-prover"
},
{
"path": "../bot"
},
{
"path": "../builder"
},
Expand Down
1 change: 1 addition & 0 deletions yarn-project/bot/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('@aztec/foundation/eslint');
3 changes: 3 additions & 0 deletions yarn-project/bot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Transactions Bot

Simple bot that connects to a PXE to send txs on a recurring basis.
84 changes: 84 additions & 0 deletions yarn-project/bot/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
{
"name": "@aztec/bot",
"version": "0.1.0",
"type": "module",
"exports": {
".": "./dest/index.js"
},
"inherits": [
"../package.common.json"
],
"scripts": {
"build": "yarn clean && tsc -b",
"build:dev": "tsc -b --watch",
"clean": "rm -rf ./dest .tsbuildinfo",
"formatting": "run -T prettier --check ./src && run -T eslint ./src",
"formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src",
"bb": "node --no-warnings ./dest/bb/index.js",
"test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests"
},
"jest": {
"moduleNameMapper": {
"^(\\.{1,2}/.*)\\.[cm]?js$": "$1"
},
"testRegex": "./src/.*\\.test\\.(js|mjs|ts)$",
"rootDir": "./src",
"transform": {
"^.+\\.tsx?$": [
"@swc/jest",
{
"jsc": {
"parser": {
"syntax": "typescript",
"decorators": true
}
}
}
]
},
"extensionsToTreatAsEsm": [
".ts"
],
"reporters": [
[
"default",
{
"summaryThreshold": 9999
}
]
]
},
"dependencies": {
"@aztec/accounts": "workspace:^",
"@aztec/aztec.js": "workspace:^",
"@aztec/circuit-types": "workspace:^",
"@aztec/circuits.js": "workspace:^",
"@aztec/entrypoints": "workspace:^",
"@aztec/foundation": "workspace:^",
"@aztec/noir-contracts.js": "workspace:^",
"@aztec/protocol-contracts": "workspace:^",
"@aztec/types": "workspace:^",
"source-map-support": "^0.5.21",
"tslib": "^2.4.0"
},
"devDependencies": {
"@jest/globals": "^29.5.0",
"@types/jest": "^29.5.0",
"@types/memdown": "^3.0.0",
"@types/node": "^18.7.23",
"@types/source-map-support": "^0.5.10",
"jest": "^29.5.0",
"jest-mock-extended": "^3.0.3",
"ts-node": "^10.9.1",
"typescript": "^5.0.4"
},
"files": [
"dest",
"src",
"!*.test.*"
],
"types": "./dest/index.d.ts",
"engines": {
"node": ">=18"
}
}
Loading