Skip to content
Open
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
96 changes: 2 additions & 94 deletions common/cli-utils.js
Original file line number Diff line number Diff line change
@@ -1,94 +1,2 @@
'use strict';

require('dotenv').config();

const fs = require('fs');
const { Option } = require('commander');

// A path to the chain configuration files
const CHAIN_CONFIG_PATH = `${__dirname}/../axelar-chains-config/info`;

// A list of available chain environments which are the names of the files in the CHAIN_CONFIG_PATH
const CHAIN_ENVIRONMENTS = fs.readdirSync(CHAIN_CONFIG_PATH).map((chainName) => chainName.split('.')[0]);

const addEnvOption = (program, defaultValue) => {
program.addOption(
new Option('-e, --env <env>', 'environment')
.choices(CHAIN_ENVIRONMENTS)
.default(defaultValue || 'testnet')
.makeOptionMandatory(true)
.env('ENV'),
);
};

const addBaseOptions = (program, options = {}) => {
addEnvOption(program);

program.addOption(new Option('-y, --yes', 'skip deployment prompt confirmation').env('YES'));
program.addOption(new Option('--parallel', 'run script parallely wrt chains'));
program.addOption(new Option('--gasOptions <gasOptions>', 'gas options cli override'));

if (!options.ignoreChainNames) {
program.addOption(
new Option('-n, --chainNames <chainNames>', 'chains to run the script over').makeOptionMandatory(true).env('CHAINS'),
);
program.addOption(new Option('--skipChains <skipChains>', 'chains to skip over'));
program.addOption(
new Option(
'--startFromChain <startFromChain>',
'start from a specific chain onwards in the config, useful when a cmd fails for an intermediate chain',
),
);
}

if (!options.ignorePrivateKey) {
program.addOption(new Option('-p, --privateKey <privateKey>', 'private key').makeOptionMandatory(true).env('PRIVATE_KEY'));
}

if (options.address) {
program.addOption(new Option('-a, --address <address>', 'override address'));
}

return program;
};

// `optionMethod` is a method such as `addBaseOptions`
// `options` is an option object for optionMethod
const addOptionsToCommands = (program, optionMethod, options) => {
if (program.commands.length > 0) {
program.commands.forEach((command) => {
optionMethod(command, options);
});
}
};

const addStoreOptions = (program) => {
program.addOption(
new Option(
'-a, --artifact-dir <artifactDir>',
'Path to the contract artifact directory to upload (required if --version is not used)',
).env('ARTIFACT_DIR'),
);

program.addOption(
new Option(
'-v, --version <contractVersion>',
'Specify a released version (X.Y.Z) or a commit hash to upload (required if --artifact-dir is not used)',
).env('CONTRACT_VERSION'),
);

program.hook('preAction', async (thisCommand) => {
const opts = thisCommand.opts();

if (!opts.artifactDir && !opts.version) {
throw new Error('Either --artifact-dir or --version is required');
}
});
};

module.exports = {
addEnvOption,
addBaseOptions,
addOptionsToCommands,
addStoreOptions,
};
// TODO Remove shim after TS migration
module.exports = require('../dist/common/cli-utils');
108 changes: 108 additions & 0 deletions common/cli-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { Command, Option } from 'commander';
import * as dotenv from 'dotenv';
import * as fs from 'fs';
import * as path from 'path';

dotenv.config();

// Resolve the path relative to the package root, accounting for both source and dist directories
const resolveFromRoot = (relativePath: string) => {
// Check if we're in dist directory
if (__dirname.includes('dist')) {
return path.join(__dirname, '../../', relativePath);
}
// We're in the source directory
return path.join(__dirname, '../', relativePath);
};

const CHAIN_CONFIG_PATH = resolveFromRoot('axelar-chains-config/info');
const CHAIN_ENVIRONMENTS = fs.readdirSync(CHAIN_CONFIG_PATH).map((chainName: string) => chainName.split('.')[0]);

interface BaseOptions {
ignoreChainNames?: boolean;
ignorePrivateKey?: boolean;
address?: boolean;
}

const addEnvOption = (program: Command, defaultValue?: string): void => {
program.addOption(
new Option('-e, --env <env>', 'environment')
.choices(CHAIN_ENVIRONMENTS)
.default(defaultValue ?? 'testnet')
.makeOptionMandatory(true)
.env('ENV'),
);
};

const addBaseOptions = (program: Command, options: BaseOptions = {}): Command => {
addEnvOption(program);

program.addOption(new Option('-y, --yes', 'skip deployment prompt confirmation').env('YES'));
program.addOption(new Option('--parallel', 'run script in parallel wrt chains'));
program.addOption(new Option('--gasOptions <gasOptions>', 'gas options cli override'));

if (!options.ignoreChainNames) {
program.addOption(
new Option('-n, --chainNames <chainNames>', 'chains to run the script over').makeOptionMandatory(true).env('CHAINS'),
);
program.addOption(new Option('--skipChains <skipChains>', 'chains to skip over'));
program.addOption(
new Option(
'--startFromChain <startFromChain>',
'start from a specific chain onwards in the config, useful when a cmd fails for an intermediate chain',
),
);
}

if (!options.ignorePrivateKey) {
program.addOption(new Option('-p, --privateKey <privateKey>', 'private key').makeOptionMandatory(true).env('PRIVATE_KEY'));
}

if (options.address) {
program.addOption(new Option('-a, --address <address>', 'override address'));
}

return program;
};

const addOptionsToCommands = <T>(program: Command, optionMethod: (command: Command, options: T) => void, options: T): void => {
if (program.commands.length > 0) {
program.commands.forEach((command) => {
optionMethod(command, options);
});
}
};

const addStoreOptions = (program: Command): void => {
program.addOption(
new Option(
'-a, --artifact-dir <artifactDir>',
'Path to the contract artifact directory to upload (required if --version is not used)',
).env('ARTIFACT_DIR'),
);

program.addOption(
new Option(
'-v, --version <contractVersion>',
'Specify a released version (X.Y.Z) or a commit hash to upload (required if --artifact-dir is not used)',
).env('CONTRACT_VERSION'),
);

program.hook('preAction', async (thisCommand) => {
const opts = thisCommand.opts();

if (!opts.artifactDir && !opts.version) {
throw new Error('Either --artifact-dir or --version is required');
}
});
};

export { addEnvOption, addBaseOptions, addOptionsToCommands, addStoreOptions };
export type { BaseOptions };

module.exports = {
addEnvOption,
addBaseOptions,
addOptionsToCommands,
addStoreOptions,
};
71 changes: 2 additions & 69 deletions evm/cli-utils.js
Original file line number Diff line number Diff line change
@@ -1,69 +1,2 @@
const { Option } = require('commander');
const { addBaseOptions, ...exportedCliUtils } = require('../common/cli-utils');

const addEvmOptions = (program, options = {}) => {
addBaseOptions(program, options);

program.addOption(new Option('-v, --verify', 'verify the deployed contract on the explorer').env('VERIFY'));

if (options.artifactPath) {
program.addOption(new Option('--artifactPath <artifactPath>', 'artifact path'));
}

if (options.contractName) {
program.addOption(new Option('-c, --contractName <contractName>', 'contract name').makeOptionMandatory(true));
}

if (options.deployMethod) {
program.addOption(
new Option('-m, --deployMethod <deployMethod>', 'deployment method')
.choices(['create', 'create2', 'create3'])
.default(options.deployMethod),
);
}

if (options.salt) {
program.addOption(new Option('-s, --salt <salt>', 'salt to use for create2 deployment').env('SALT'));
}

if (options.skipExisting) {
program.addOption(new Option('-x, --skipExisting', 'skip existing if contract was already deployed on chain').env('SKIP_EXISTING'));
}

if (options.upgrade) {
program.addOption(new Option('-u, --upgrade', 'upgrade a deployed contract').env('UPGRADE'));
}

if (options.predictOnly) {
program.addOption(new Option('--predictOnly', 'output the predicted changes only').env('PREDICT_ONLY'));
}

return program;
};

const addTopUpOptions = (program) => {
program.addOption(new Option('-t, --target <target>', 'target balance for each account').makeOptionMandatory(true));
program.addOption(
new Option('--threshold <threshold>', 'top up accounts only if the balance is below this threshold').makeOptionMandatory(true),
);
program.addOption(new Option('-u, --units', 'amounts are set in smallest unit'));
program.addOption(
new Option(
'--addresses-to-derive <addresses-to-derive>',
'number of addresses to derive from mnemonic. Derived addresses will be added to the list of addresses to fund set by using --addresses option',
).env('DERIVE_ACCOUNTS'),
);
program.addOption(
new Option('--addresses <addresses>', 'comma separated list of addresses to top up')
.default([])
.argParser((addresses) => addresses.split(',').map((address) => address.trim())),
);
program.addOption(new Option('-m, --mnemonic <mnemonic>', 'mnemonic').env('MNEMONIC'));
};

module.exports = {
...exportedCliUtils,
addBaseOptions,
addEvmOptions,
addTopUpOptions,
};
// TODO Remove shim after TS migration
module.exports = require('../dist/evm/cli-utils');
84 changes: 84 additions & 0 deletions evm/cli-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { Command, Option } from 'commander';

import { BaseOptions, addBaseOptions, addEnvOption, addOptionsToCommands, addStoreOptions } from '../common/cli-utils';

interface EvmOptions extends BaseOptions {
artifactPath?: boolean;
contractName?: boolean;
deployMethod?: string;
salt?: boolean;
skipExisting?: boolean;
upgrade?: boolean;
predictOnly?: boolean;
}

const addEvmOptions = (program: Command, options: EvmOptions = {}): Command => {
addBaseOptions(program, options);

program.addOption(new Option('-v, --verify', 'verify the deployed contract on the explorer').env('VERIFY'));

if (options.artifactPath) {
program.addOption(new Option('--artifactPath <artifactPath>', 'artifact path'));
}

if (options.contractName) {
program.addOption(new Option('-c, --contractName <contractName>', 'contract name').makeOptionMandatory(true));
}

if (options.deployMethod) {
program.addOption(
new Option('-m, --deployMethod <deployMethod>', 'deployment method')
.choices(['create', 'create2', 'create3'])
.default(options.deployMethod),
);
}

if (options.salt) {
program.addOption(new Option('-s, --salt <salt>', 'salt to use for create2 deployment').env('SALT'));
}

if (options.skipExisting) {
program.addOption(new Option('-x, --skipExisting', 'skip existing if contract was already deployed on chain').env('SKIP_EXISTING'));
}

if (options.upgrade) {
program.addOption(new Option('-u, --upgrade', 'upgrade a deployed contract').env('UPGRADE'));
}

if (options.predictOnly) {
program.addOption(new Option('--predictOnly', 'output the predicted changes only').env('PREDICT_ONLY'));
}

return program;
};

const addTopUpOptions = (program: Command): void => {
program.addOption(new Option('-t, --target <target>', 'target balance for each account').makeOptionMandatory(true));
program.addOption(
new Option('--threshold <threshold>', 'top up accounts only if the balance is below this threshold').makeOptionMandatory(true),
);
program.addOption(new Option('-u, --units', 'amounts are set in smallest unit'));
program.addOption(
new Option(
'--addresses-to-derive <addresses-to-derive>',
'number of addresses to derive from mnemonic. Derived addresses will be added to the list of addresses to fund set by using --addresses option',
).env('DERIVE_ACCOUNTS'),
);
program.addOption(
new Option('--addresses <addresses>', 'comma separated list of addresses to top up')
.default([])
.argParser((addresses: string): string[] => addresses.split(',').map((address) => address.trim())),
);
program.addOption(new Option('-m, --mnemonic <mnemonic>', 'mnemonic').env('MNEMONIC'));
};

module.exports = {
addEnvOption,
addBaseOptions,
addOptionsToCommands,
addStoreOptions,
addEvmOptions,
addTopUpOptions,
};

export type { BaseOptions, EvmOptions };
2 changes: 1 addition & 1 deletion evm/governance.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const {
writeJSON,
isKeccak256Hash,
} = require('./utils.js');
const { addBaseOptions } = require('./cli-utils.js');
const { addBaseOptions } = require('./cli-utils.ts');
const { getWallet } = require('./sign-utils.js');
const IAxelarServiceGovernance = require('@axelar-network/axelar-gmp-sdk-solidity/interfaces/IAxelarServiceGovernance.json');
const AxelarGateway = require('@axelar-network/axelar-cgp-solidity/artifacts/contracts/AxelarGateway.sol/AxelarGateway.json');
Expand Down
2 changes: 1 addition & 1 deletion evm/load-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const { loadConfig, printInfo, printWarn, printError, printHighlight, callAxelarscanApi, printDivider } = require('../common/index.js');
const { Command, Option } = require('commander');
const { addBaseOptions } = require('../common/cli-utils.js');
const { addBaseOptions } = require('../common/cli-utils.ts');

const { deriveAccounts } = require('./utils.js');

Expand Down
4 changes: 2 additions & 2 deletions evm/top-up.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { loadConfig, printInfo } = require('../common/index.js');
const { addBaseOptions } = require('../common/cli-utils.js');
const { addTopUpOptions } = require('./cli-utils.js');
const { addBaseOptions } = require('../common/cli-utils.ts');
const { addTopUpOptions } = require('./cli-utils.ts');

const { getWallet } = require('./sign-utils.js');
const { getContractJSON, deriveAccounts, printWalletInfo } = require('./utils.js');
Expand Down
2 changes: 1 addition & 1 deletion hedera/fund-whbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const { Command, Option } = require('commander');
const { ethers } = require('hardhat');
const { Wallet, getDefaultProvider } = ethers;
const { addSkipPromptOption } = require('./cli-utils.js');
const { addBaseOptions } = require('../common/cli-utils.js');
const { addBaseOptions } = require('../common/cli-utils.ts');
const { loadConfig, prompt, printInfo, printError } = require('../common/utils.js');

// Basic WHBAR ABI for deposit, transfer, and balanceOf functions
Expand Down
Loading