Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: register-public-key & CLI update to use options instead of args #1397

Merged
merged 7 commits into from
Aug 4, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
32 changes: 15 additions & 17 deletions yarn-project/aztec-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,10 @@ Syntax:
aztec-cli deploy <contractAbi> [options]
```

- `contractAbi`: Path to the compiled Noir contract's ABI file in JSON format.
- `constructorArgs` (optional): Contract constructor arguments.

Options:

- `-c, --contract-abi <fileLocation>`: Path to the compiled Noir contract's ABI file in JSON format.
- `-a, --args <constructorArgs...>` (optional): Contract constructor arguments Default: [].
- `-u, --rpc-url <string>`: URL of the Aztec RPC. Default: `http://localhost:8080`.
- `-k, --public-key <string>`: Public key of the deployer. If not provided, it will check the RPC for existing ones.

Expand All @@ -156,7 +155,7 @@ This command deploys a compiled Noir contract to Aztec. It requires the path to
Example usage:

```shell
aztec-cli deploy path/to/contract.abi.json ...args
aztec-cli deploy -c path/to/contract.abi.json -a ...args
```

### check-deploy
Expand All @@ -169,18 +168,17 @@ Syntax:
aztec-cli check-deploy <contractAddress> [options]
```

- `contractAddress`: An Aztec address to check if the contract has been deployed to.

Options:

- `-ca, --contract-address <address>`: An Aztec address to check if the contract has been deployed to.
- `-u, --rpc-url <string>`: URL of the Aztec RPC. Default: `http://localhost:8080`.

This command checks if a contract is deployed to the specified Aztec address. It verifies if the contract is present at the given address and displays the result.

Example usage:

```shell
aztec-cli check-deploy 0x123456789abcdef123456789abcdef12345678
aztec-cli check-deploy -ca 0x123456789abcdef123456789abcdef12345678
```

### get-tx-receipt
Expand Down Expand Up @@ -278,7 +276,7 @@ Example usage:
aztec-cli get-account-public-key 0x123456789abcdef123456789abcdef12345678
```

### call-fn
### send

Calls a function on an Aztec contract.

Expand All @@ -288,13 +286,13 @@ Syntax:
aztec-cli call-fn <contractAbi> <contractAddress> <functionName> [functionArgs...] [options]
```

- `contractAbi`: The compiled contract's ABI in JSON format.
- `contractAddress`: Address of the contract.
- `functionName`: Name of the function to call.
- `functionArgs` (optional): Function arguments.

Options:

- `'-a, --args [functionArgs...]` (optional): Function arguments. Default: [].
- `-c, --contract-abi <fileLocation>`: The compiled contract's ABI in JSON format.
- `-ca, --contract-address <address>`: Address of the contract.
- `-k, --private-key <string>`: The sender's private key.
- `-u, --rpcUrl <string>`: URL of the Aztec RPC. Default: `http://localhost:8080`.

Expand All @@ -303,7 +301,7 @@ This command calls a function on an Aztec contract. It requires the contract's A
Example usage:

```shell
aztec-cli call-fn path/to/contract.abi.json 0x123456789abcdef123456789abcdef12345678 transfer 100
aztec-cli send transfer -ca 0x123456789abcdef123456789abcdef12345678 -a 100 -c path/to/abi.json
```

### view-fn
Expand All @@ -313,16 +311,16 @@ Simulates the execution of a view (read-only) function on a deployed contract, w
Syntax:

```shell
aztec-cli view-fn <contractAbi> <contractAddress> <functionName> [functionArgs...] [options]
aztec-cli call <contractAbi> <contractAddress> <functionName> [functionArgs...] [options]
```

- `contractAbi`: The compiled contract's ABI in JSON format.
- `contractAddress`: Address of the contract.
- `functionName`: Name of the function to view.
- `functionArgs` (optional): Function arguments.

Options:

- `'-a, --args [functionArgs...]` (optional): Function arguments. Default: [].
- `-c, --contract-abi <fileLocation>`: The compiled contract's ABI in JSON format.
- `-ca, --contract-address <address>`: Address of the contract.
- `-f, --from <string>`: Public key of the transaction viewer. If empty, it will try to find an account in the RPC.
- `-u, --rpcUrl <string>`: URL of the Aztec RPC. Default: `http://localhost:8080`.

Expand All @@ -331,7 +329,7 @@ This command simulates the execution of a view function on a deployed contract w
Example usage:

```shell
aztec-cli view-fn path/to/contract.abi.json 0x123456789abcdef123456789abcdef12345678 balanceOf 0xabcdef1234567890abcdef1234567890abcdef12
aztec-cli call balanceOf -c path/to/contract.abi.json -ca 0x123456789abcdef123456789abcdef12345678 -a balanceOf 0xabcdef1234567890abcdef1234567890abcdef12
```

### parse-parameter-struct
Expand Down
106 changes: 66 additions & 40 deletions yarn-project/aztec-cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { Command } from 'commander';
import { mnemonicToAccount } from 'viem/accounts';

import { encodeArgs, parseStructString } from './cli_encoder.js';
import { deployAztecContracts, getContractAbi, getTxSender, prepTx } from './utils.js';
import { deployAztecContracts, getAbiFunction, getContractAbi, getTxSender, prepTx } from './utils.js';

const accountCreationSalt = Fr.ZERO;

Expand All @@ -46,8 +46,8 @@ async function main() {
program
.command('deploy-l1-contracts')
.description('Deploys all necessary Ethereum contracts for Aztec.')
.argument(
'[rpcUrl]',
.option(
'-u, --rpc-url <string>',
'Url of the ethereum host. Chain identifiers localhost and testnet can be used',
ETHEREUM_HOST || 'http://localhost:8545',
)
Expand All @@ -58,9 +58,15 @@ async function main() {
'The mnemonic to use in deployment',
'test test test test test test test test test test test junk',
)
.action(async (rpcUrl: string, options) => {
.action(async options => {
const { rollupAddress, registryAddress, inboxAddress, outboxAddress, contractDeploymentEmitterAddress } =
await deployAztecContracts(rpcUrl, options.apiKey ?? '', options.privateKey, options.mnemonic, debugLogger);
await deployAztecContracts(
options.rpcUrl,
options.apiKey ?? '',
options.privateKey,
options.mnemonic,
debugLogger,
);
log('\n');
log(`Rollup Address: ${rollupAddress.toString()}`);
log(`Registry Address: ${registryAddress.toString()}`);
Expand Down Expand Up @@ -105,7 +111,7 @@ async function main() {
const wallet = await createAccounts(
client,
SchnorrSingleKeyAccountContractAbi,
new PrivateKey(privateKey),
privateKey && new PrivateKey(privateKey),
accountCreationSalt,
1,
);
Expand All @@ -118,16 +124,16 @@ async function main() {
program
.command('deploy')
.description('Deploys a compiled Noir contract to Aztec.')
.argument('<contractAbi>', "A compiled Noir contract's ABI in JSON format", undefined)
.argument('[constructorArgs...]', 'Contract constructor arguments', [])
.option('-c, --contract-abi <fileLocation>', "A compiled Noir contract's ABI in JSON format", undefined)
.option('-a, --args <constructorArgs...>', 'Contract constructor arguments', [])
.option('-u, --rpc-url <string>', 'URL of the Aztec RPC', AZTEC_RPC_HOST || 'http://localhost:8080')
.option(
'-k, --public-key <string>',
'Public key of the deployer. If not provided, it will check the RPC for existing ones.',
PUBLIC_KEY,
)
.action(async (contractFile: string, args: string[], options: any) => {
const contractAbi = getContractAbi(contractFile, log);
.action(async (options: any) => {
const contractAbi = getContractAbi(options.contractAbi, log);
const constructorAbi = contractAbi.functions.find(({ name }) => name === 'constructor');

const client = createAztecRpcClient(options.rpcUrl);
Expand All @@ -146,7 +152,14 @@ async function main() {

const deployer = new ContractDeployer(contractAbi, client);

const tx = deployer.deploy(...encodeArgs(args, constructorAbi!.parameters), publicKey.toBigInts()).send();
const constructor = getAbiFunction(contractAbi, 'constructor');
if (constructor.parameters.length !== options.args.length) {
throw Error(
`Invalid number of args passed. Expected ${constructor.parameters.length}; Received: ${options.args.length}`,
);
}

const tx = deployer.deploy(...encodeArgs(options.args, constructorAbi!.parameters), publicKey.toBigInts()).send();
await tx.isMined();
const receipt = await tx.getReceipt();
log(`\nAztec Contract deployed at ${receipt.contractAddress?.toString()}\n`);
Expand All @@ -155,19 +168,19 @@ async function main() {
program
.command('check-deploy')
.description('Checks if a contract is deployed to the specified Aztec address.')
.argument('<contractAddress>', 'An Aztec address to check if contract has been deployed to.')
.option('-u, --rpc-url <string>', 'URL of the Aztec RPC', AZTEC_RPC_HOST || 'http://localhost:8080')
.action(async (_contractAddress, options) => {
.option('-ca, --contract-address <address>', 'An Aztec address to check if contract has been deployed to.')
.option('-u, --rpc-url <url>', 'URL of the Aztec RPC', AZTEC_RPC_HOST || 'http://localhost:8080')
.action(async options => {
const client = createAztecRpcClient(options.rpcUrl);
const address = AztecAddress.fromString(_contractAddress);
const address = AztecAddress.fromString(options.contractAddress);
const isDeployed = await client.isContractDeployed(address);
log(`\n${isDeployed.toString()}\n`);
});

program
.command('get-tx-receipt')
.description('Gets the receipt for the specified transaction hash.')
.argument('<txHash>', 'A TX hash to get the receipt for.')
.description('Gets the receipt for the specified transaction hash.')
.option('-u, --rpc-url <string>', 'URL of the Aztec RPC', AZTEC_RPC_HOST || 'http://localhost:8080')
.action(async (_txHash, options) => {
const client = createAztecRpcClient(options.rpcUrl);
Expand All @@ -186,15 +199,15 @@ async function main() {
.argument('<contractAddress>', 'Aztec address of the contract.')
.option('-u, --rpc-url <string>', 'URL of the Aztec RPC', AZTEC_RPC_HOST || 'http://localhost:8080')
.option('-b, --include-bytecode', "Include the contract's public function bytecode, if any.")
.action(async (_contractAddress, options) => {
.action(async (contractAddress, options) => {
const client = createAztecRpcClient(options.rpcUrl);
const address = AztecAddress.fromString(_contractAddress);
const address = AztecAddress.fromString(contractAddress);
const contractDataOrInfo = options.includeBytecode
? await client.getContractData(address)
: await client.getContractInfo(address);

if (!contractDataOrInfo) {
log(`No contract data found at ${_contractAddress}`);
log(`No contract data found at ${contractAddress}`);
return;
}
let contractData: ContractData;
Expand Down Expand Up @@ -277,22 +290,29 @@ async function main() {
program
.command('send')
.description('Calls a function on an Aztec contract.')
.argument('<contractAbi>', "The compiled contract's ABI in JSON format", undefined)
.argument('<contractAddress>', 'Address of the contract')
.argument('<functionName>', 'Name of Function to view')
.argument('[functionArgs...]', 'Function arguments', [])
.option('-a, --args [functionArgs...]', 'Function arguments', [])
.option('-c, --contract-abi <fileLocation>', "A compiled Noir contract's ABI in JSON format", undefined)
.option('-ca, --contract-address <address>', 'Aztec address of the contract.')
.option('-k, --private-key <string>', "The sender's private key.", PRIVATE_KEY)
.option('-u, --rpcUrl <string>', 'URL of the Aztec RPC', AZTEC_RPC_HOST || 'http://localhost:8080')

.action(async (contractFile, _contractAddress, functionName, _functionArgs, options) => {
.action(async (functionName, options) => {
const { contractAddress, functionArgs, contractAbi } = prepTx(
contractFile,
_contractAddress,
options.contractAbi,
options.contractAddress,
functionName,
_functionArgs,
options.args,
log,
);

const fnAbi = getAbiFunction(contractAbi, functionName);
if (fnAbi.parameters.length !== options.args.length) {
throw Error(
`Invalid number of args passed. Expected ${fnAbi.parameters.length}; Received: ${options.args.length}`,
);
}

const client = createAztecRpcClient(options.rpcUrl);
const wallet = await getAccountWallet(
client,
Expand All @@ -319,20 +339,26 @@ async function main() {
.description(
'Simulates the execution of a view (read-only) function on a deployed contract, without modifying state.',
)
.argument('<contractAbi>', "The compiled contract's ABI in JSON format", undefined)
.argument('<contractAddress>', 'Address of the contract')
.argument('<functionName>', 'Name of Function to view')
.argument('[functionArgs...]', 'Function arguments', [])
.option('-a, --args [functionArgs...]', 'Function arguments', [])
.option('-c, --contract-abi <fileLocation>', "A compiled Noir contract's ABI in JSON format", undefined)
.option('-ca, --contract-address <address>', 'Aztec address of the contract.')
.option('-f, --from <string>', 'Public key of the TX viewer. If empty, will try to find account in RPC.')
.option('-u, --rpcUrl <string>', 'URL of the Aztec RPC', AZTEC_RPC_HOST || 'http://localhost:8080')
.action(async (contractFile, _contractAddress, functionName, _functionArgs, options) => {
const { contractAddress, functionArgs } = prepTx(
contractFile,
_contractAddress,
.action(async (functionName, options) => {
const { contractAddress, functionArgs, contractAbi } = prepTx(
options.contractAbi,
options.contractAddress,
functionName,
_functionArgs,
options.args,
log,
);
const fnAbi = getAbiFunction(contractAbi, functionName);
if (fnAbi.parameters.length !== options.args.length) {
throw Error(
`Invalid number of args passed. Expected ${fnAbi.parameters.length}; Received: ${options.args.length}`,
);
}
const client = createAztecRpcClient(options.rpcUrl);
const from = await getTxSender(client, options.from);
const result = await client.viewTx(functionName, functionArgs, contractAddress, from);
Expand All @@ -344,16 +370,16 @@ async function main() {
.command('parse-parameter-struct')
.description("Helper for parsing an encoded string into a contract's parameter struct.")
.argument('<encodedString>', 'The encoded hex string')
.argument('<contractAbi>', "The compiled contract's ABI in JSON format")
.argument('<parameterName>', 'The name of the struct parameter to decode into')
.action((encodedString, contractFile, parameterName) => {
const contractAbi = getContractAbi(contractFile, log);
.option('-c, --contract-abi <fileLocation>', "A compiled Noir contract's ABI in JSON format", undefined)
.option('-p, --parameter <parameterName>', 'The name of the struct parameter to decode into')
.action((encodedString, options) => {
const contractAbi = getContractAbi(options.contractAbi, log);
const parameterAbitype = contractAbi.functions
.map(({ parameters }) => parameters)
.flat()
.find(({ name, type }) => name === parameterName && type.kind === 'struct');
.find(({ name, type }) => name === options.parameter && type.kind === 'struct');
if (!parameterAbitype) {
log(`No struct parameter found with name ${parameterName}`);
log(`No struct parameter found with name ${options.parameter}`);
return;
}
const data = parseStructString(encodedString, parameterAbitype.type as StructType);
Expand Down
20 changes: 15 additions & 5 deletions yarn-project/aztec-cli/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@ import { mnemonicToAccount, privateKeyToAccount } from 'viem/accounts';

import { encodeArgs } from './cli_encoder.js';

/**
* Helper to get an ABI function or throw error if it doesn't exist.
* @param abi - Contract's ABI in JSON format.
* @param fnName - Function name to be found.
* @returns The function's ABI.
*/
export function getAbiFunction(abi: ContractAbi, fnName: string) {
const fn = abi.functions.find(({ name }) => name === fnName);
if (!fn) {
throw Error(`Function ${fnName} not found in contract ABI.`);
}
return fn;
}

/**
* Function to execute the 'deployRollupContracts' command.
* @param rpcUrl - The RPC URL of the ethereum node.
Expand Down Expand Up @@ -92,11 +106,7 @@ export function prepTx(
throw new Error(`Unable to parse contract address ${_contractAddress}.`);
}
const contractAbi = getContractAbi(contractFile, log);
const functionAbi = contractAbi.functions.find(({ name }) => name === functionName);
if (!functionAbi) {
throw new Error(`Function ${functionName} not found on contract ABI.`);
}

const functionAbi = getAbiFunction(contractAbi, functionName);
const functionArgs = encodeArgs(_functionArgs, functionAbi.parameters);

return { contractAddress, functionArgs, contractAbi };
Expand Down
19 changes: 16 additions & 3 deletions yarn-project/noir-contracts/scripts/types.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,27 @@ ROOT=$(pwd)

write_import() {
CONTRACT_NAME=$1
NAME=`echo $CONTRACT_NAME | sed -r 's/(^|_)(.)/\U\2/g'`

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nicely done

if [ "$(uname)" = "Darwin" ]; then
# sed \U doesn't work on mac
NAME=$(echo $CONTRACT_NAME | perl -pe 's/(^|_)(\w)/\U$2/g')
else
NAME=`echo $CONTRACT_NAME | sed -r 's/(^|_)(.)/\U\2/g'`
fi

echo "import ${NAME}Json from './${CONTRACT_NAME}_contract.json' assert { type: 'json' };" >> "$artifacts_dir/index.ts";
}

write_export() {
CONTRACT_NAME=$1
NAME=`echo $CONTRACT_NAME | sed -r 's/(^|_)(.)/\U\2/g'`

if [ "$(uname)" = "Darwin" ]; then
# sed \U doesn't work on mac
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we just always use perl for simplicity?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep don't know why I didn't think of that 😬

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not supported in CI :(

NAME=$(echo $CONTRACT_NAME | perl -pe 's/(^|_)(\w)/\U$2/g')
else
NAME=`echo $CONTRACT_NAME | sed -r 's/(^|_)(.)/\U\2/g'`
fi


# artifacts
echo "export const ${NAME}ContractAbi = ${NAME}Json as ContractAbi;" >> "$artifacts_dir/index.ts";
echo "Written typescript for $NAME"
Expand Down