From 9698d821b9e0b4eb3968e330b0ef26e6fd2f647a Mon Sep 17 00:00:00 2001 From: mixmix Date: Thu, 1 Aug 2024 16:54:00 +1200 Subject: [PATCH] add deploy to CLI, including start of CLI refactor --- aux-data-schema.json | 1 + config-schema.json | 1 + some.json | 1 + src/cli.ts | 55 ++++++----------------- src/cli/commands/entropy-program.ts | 70 +++++++++++++++++++++++++++++ src/cli/commands/index.ts | 1 + src/cli/util.ts | 50 +++++++++++++++++++++ src/common/utils.ts | 9 +++- 8 files changed, 145 insertions(+), 43 deletions(-) create mode 100644 aux-data-schema.json create mode 100644 config-schema.json create mode 100644 some.json create mode 100644 src/cli/commands/entropy-program.ts create mode 100644 src/cli/commands/index.ts create mode 100644 src/cli/util.ts diff --git a/aux-data-schema.json b/aux-data-schema.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/aux-data-schema.json @@ -0,0 +1 @@ +{} diff --git a/config-schema.json b/config-schema.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/config-schema.json @@ -0,0 +1 @@ +{} diff --git a/some.json b/some.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/some.json @@ -0,0 +1 @@ +{} diff --git a/src/cli.ts b/src/cli.ts index f8dab60c..ec5e8cb1 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -3,47 +3,17 @@ /* NOTE: calling this file entropy.ts helps commander parse process.argv */ import { Command, Option } from 'commander' import launchTui from './tui' -import * as config from './config' import { EntropyTuiOptions } from './types' import { cliGetBalance } from './flows/balance/cli' import { cliListAccounts } from './flows/manage-accounts/cli' import { cliEntropyTransfer } from './flows/entropyTransfer/cli' import { cliSign } from './flows/sign/cli' -import { stringify } from './common/utils' -const program = new Command() - -function endpointOption (){ - return new Option( - '-e, --endpoint ', - [ - 'Runs entropy with the given endpoint and ignores network endpoints in config.', - 'Can also be given a stored endpoint name from config eg: `entropy --endpoint test-net`.' - ].join(' ') - ) - .env('ENDPOINT') - .argParser(aliasOrEndpoint => { - /* see if it's a raw endpoint */ - if (aliasOrEndpoint.match(/^wss?:\/\//)) return aliasOrEndpoint - - /* look up endpoint-alias */ - const storedConfig = config.getSync() - const endpoint = storedConfig.endpoints[aliasOrEndpoint] - if (!endpoint) throw Error('unknown endpoint alias: ' + aliasOrEndpoint) - - return endpoint - }) - .default('ws://testnet.entropy.xyz:9944/') - // NOTE: argParser is only run IF an option is provided, so this cannot be 'test-net' -} +import { cliWrite, passwordOption, endpointOption } from './cli/util' +import { entropyProgram } from './cli/commands' -function passwordOption (description?: string) { - return new Option( - '-p, --password ', - description || 'Password for the account' - ) -} +const program = new Command() /* no command */ program @@ -62,6 +32,14 @@ program launchTui(options) }) +/* Install commands */ +// entropyAccount(program) +// entropyBalance(program) +// entropySession(program) +// entropySign(program) +entropyProgram(program) +// entropyTransfar(program) + /* list */ program.command('list') .alias('ls') @@ -69,7 +47,7 @@ program.command('list') .action(async () => { // TODO: test if it's an encrypted account, if no password provided, throw because later on there's no protection from a prompt coming up const accounts = await cliListAccounts() - writeOut(accounts) + cliWrite(accounts) process.exit(0) }) @@ -81,7 +59,7 @@ program.command('balance') .addOption(endpointOption()) .action(async (address, opts) => { const balance = await cliGetBalance({ address, ...opts }) - writeOut(balance) + cliWrite(balance) process.exit(0) }) @@ -108,13 +86,8 @@ program.command('sign') .addOption(endpointOption()) .action(async (address, message, opts) => { const signature = await cliSign({ address, message, ...opts }) - writeOut(signature) + cliWrite(signature) process.exit(0) }) -function writeOut (result) { - const prettyResult = stringify(result) - process.stdout.write(prettyResult) -} - program.parse() diff --git a/src/cli/commands/entropy-program.ts b/src/cli/commands/entropy-program.ts new file mode 100644 index 00000000..f126bdb1 --- /dev/null +++ b/src/cli/commands/entropy-program.ts @@ -0,0 +1,70 @@ +import { Command } from 'commander' +import { aliasOrAddressOption, cliWrite, endpointOption } from '../util' +import { initializeEntropy } from "../../common/initializeEntropy" +import { getSelectedAccount } from "../../common/utils" +import * as config from "../../config" + +import { deployProgram } from '../../flows/programs/deploy' + +async function getEntropy ({ address, endpoint }) { + const storedConfig = await config.get() + const selectedAccount = getSelectedAccount(storedConfig.accounts, address) + + return initializeEntropy({ + keyMaterial: selectedAccount.data, + endpoint + }) +} + +export function entropyProgram (rootCommand: Command) { + const programCommand = rootCommand.command('program') + .description('Commands for working with programs deployed to the Entropy Network') + + entropyProgramDeploy(programCommand) + // entropyProgramGet(program) + // entropyProgramRemove(program) +} + +function entropyProgramDeploy (programCommand: Command) { + programCommand.command('deploy') + .description([ + 'Deploys a program to the Entropy network.', + 'Requires funds.' + ].join(' ')) + .argument( + 'bytecode', + [ + 'The path to your program bytecode.', + 'Must be a .wasm file.' + ].join(' ') + ) + .argument( + 'configurationSchema', + [ + 'The path to the JSON Schema for validating configurations passed in by users installing this program.', + 'Must be a .json file.' + ].join(' ') + ) + .argument( + 'auxillaryDataSchema', + [ + 'The path to the JSON Schema for validating auxillary data passed to the program on calls to "sign".', + 'Must be a .json file.' + ].join(' ') + ) + .addOption(aliasOrAddressOption()) + .addOption(endpointOption()) + + .action(async (bytecodePath, configurationSchemaPath, auxillaryDataSchemaPath, opts) => { + const entropy = await getEntropy(opts) + + const pointer = await deployProgram(entropy, { + bytecodePath, + configurationSchemaPath, + auxillaryDataSchemaPath + }) + cliWrite(pointer) + + process.exit(0) + }) +} diff --git a/src/cli/commands/index.ts b/src/cli/commands/index.ts new file mode 100644 index 00000000..223af11e --- /dev/null +++ b/src/cli/commands/index.ts @@ -0,0 +1 @@ +export * from './entropy-program' diff --git a/src/cli/util.ts b/src/cli/util.ts new file mode 100644 index 00000000..f03ca322 --- /dev/null +++ b/src/cli/util.ts @@ -0,0 +1,50 @@ +import { Option } from 'commander' +import * as config from '../config' +import { stringify } from '../common/utils' + +export function cliWrite (result) { + const prettyResult = stringify(result) + process.stdout.write(prettyResult) +} + +export function endpointOption () { + return new Option( + '-e, --endpoint ', + [ + 'Runs entropy with the given endpoint and ignores network endpoints in config.', + 'Can also be given a stored endpoint name from config eg: `entropy --endpoint test-net`.' + ].join(' ') + ) + .env('ENDPOINT') + .argParser(aliasOrEndpoint => { + /* see if it's a raw endpoint */ + if (aliasOrEndpoint.match(/^wss?:\/\//)) return aliasOrEndpoint + + /* look up endpoint-alias */ + const storedConfig = config.getSync() + const endpoint = storedConfig.endpoints[aliasOrEndpoint] + if (!endpoint) throw Error('unknown endpoint alias: ' + aliasOrEndpoint) + + return endpoint + }) + .default('ws://testnet.entropy.xyz:9944/') + // NOTE: argParser is only run IF an option is provided, so this cannot be 'test-net' +} + +export function passwordOption (description?: string) { + return new Option( + '-p, --password ', + description || 'Password for the account' + ) +} + +export function aliasOrAddressOption () { + return new Option( + '-a, --address ', + 'The alias or address of the verifying key to use for this command. Can be an alias or hex address.' + // TODO: describe default behaviour when "sessions" are introduced? + ) + // QUESTION: as this is a function, this could be a viable way to set the VK? + // .default(process.env.ENTROPY_SESSION) +} + diff --git a/src/common/utils.ts b/src/common/utils.ts index ace2af19..d51e3dd2 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -65,6 +65,11 @@ export function accountChoicesWithOther (accounts: EntropyAccountConfig[]) { .concat([{ name: "Other", value: null }]) } -export function getSelectedAccount (accounts: EntropyAccountConfig[], address: string) { - return accounts.find(account => account.address === address) +export function getSelectedAccount (accounts: EntropyAccountConfig[], aliasOrAddress: string) { + if (!aliasOrAddress || !aliasOrAddress.length) throw Error('aliasOrAddress required') + + return ( + accounts.find(account => account.address === aliasOrAddress) || + accounts.find(account => account.name === aliasOrAddress) + ) }