Skip to content

Commit

Permalink
add deploy to CLI, including start of CLI refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
mixmix committed Aug 1, 2024
1 parent df36f05 commit 9698d82
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 43 deletions.
1 change: 1 addition & 0 deletions aux-data-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
1 change: 1 addition & 0 deletions config-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
1 change: 1 addition & 0 deletions some.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
55 changes: 14 additions & 41 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 <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 <password>',
description || 'Password for the account'
)
}
const program = new Command()

/* no command */
program
Expand All @@ -62,14 +32,22 @@ program
launchTui(options)
})

/* Install commands */
// entropyAccount(program)
// entropyBalance(program)
// entropySession(program)
// entropySign(program)
entropyProgram(program)
// entropyTransfar(program)

/* list */
program.command('list')
.alias('ls')
.description('List all accounts. Output is JSON of form [{ name, address, data }]')
.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)
})

Expand All @@ -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)
})

Expand All @@ -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()
70 changes: 70 additions & 0 deletions src/cli/commands/entropy-program.ts
Original file line number Diff line number Diff line change
@@ -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)
})
}
1 change: 1 addition & 0 deletions src/cli/commands/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './entropy-program'
50 changes: 50 additions & 0 deletions src/cli/util.ts
Original file line number Diff line number Diff line change
@@ -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 <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 <password>',
description || 'Password for the account'
)
}

export function aliasOrAddressOption () {
return new Option(
'-a, --address <aliasOrAddress>',
'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)
}

9 changes: 7 additions & 2 deletions src/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
)
}

0 comments on commit 9698d82

Please sign in to comment.