Skip to content

Commit

Permalink
Merge branch 'naynay/file-restructure' into mixmix/deploy_cli
Browse files Browse the repository at this point in the history
  • Loading branch information
mixmix committed Sep 19, 2024
2 parents 5273952 + 0cfb8f8 commit ecb807b
Show file tree
Hide file tree
Showing 66 changed files with 1,653 additions and 998 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/cla.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
steps:
- name: "CLA Assistant"
if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
uses: contributor-assistant/github-action@v2.4.0
uses: entropyxyz/contributor-assistant-github-action@c5f4628ffe1edb97724edb64e0dd4795394d33e5 # exemptRepoOrgMembers
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Required, so that the bot in this repository has `write` permissions to Contents of remote repo.
Expand All @@ -47,5 +47,6 @@ jobs:
path-to-document: 'https://github.com/entropyxyz/.github/blob/main/legal/cla/v1/cla.md'
branch: 'main'
allowlist: dependabot[bot]
exemptRepoOrgMembers: true
remote-organization-name: entropyxyz
remote-repository-name: .github
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ Version header format: `[version] Name - year-month-day (entropy-core compatibil
- new: './src/transfer' - new file structure for our CLI/TUI flows
- new: './src/transfer/command.ts' - main entry file for transfer command for tui/cli
- new: './src/transfer/utils.ts' - utilities and helper methods for all things transfer
- new: './src/accounts' - new file structure for our CLI/TUI flows
- new: './src/accounts/command.ts' - main entry file for accounts command for tui/cli
- new: './src/accounts/utils.ts' - utilities and helper methods for all things accounts

### Changed

Expand All @@ -43,6 +46,8 @@ Version header format: `[version] Name - year-month-day (entropy-core compatibil
- merged user + dev program folders + tests
- removed flows/balance/*.ts directory with file restructure
- removed flows/entropyTransfer/*.ts directory with file restructure
- removed flows/manage-accounts/*/*.ts directory with file restructure
- removed flows/register/*.ts directory with file restructure


### Broke
Expand Down
11 changes: 11 additions & 0 deletions dev/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,14 @@ git push origin main --tags
```

go create a release on github if possible.


## Deploying new faucet
<!-- TO-DO: Cleanup requirements -->
#### Requirements
- faucet program
- build from repo or use binary in tests/programs/faucet_program.wasm
- configuration and aux data schema
- program mod account with funds to deploy
- child funded accounts to be used as issuers of funds for faucet
- child accounts must be registered with deployed faucet program
130 changes: 130 additions & 0 deletions src/account/command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import Entropy from "@entropyxyz/sdk"
import { Command, Option } from 'commander'
import { EntropyAccount } from "./main";
import { selectAndPersistNewAccount } from "./utils";
import { ACCOUNTS_CONTENT } from './constants'
import * as config from '../config'
import { cliWrite, currentAccountAddressOption, endpointOption, loadEntropy, passwordOption } from "../common/utils-cli";
import { findAccountByAddressOrName } from "src/common/utils";

export function entropyAccountCommand () {
return new Command('account')
.description('Commands to work with accounts on the Entropy Network')
.addCommand(entropyAccountCreate())
.addCommand(entropyAccountImport())
.addCommand(entropyAccountList())
.addCommand(entropyAccountRegister())
}

function entropyAccountCreate () {
return new Command('create')
.alias('new')
.description('Create a new entropy account from scratch. Output is JSON of form {name, address}')
.addOption(passwordOption())
.argument('<name>', 'A user friendly name for your new account.')
.addOption(
new Option(
'--path',
'Derivation path'
).default(ACCOUNTS_CONTENT.path.default)
)
.action(async (name, opts) => {
const { path } = opts
const newAccount = await EntropyAccount.create({ name, path })

await selectAndPersistNewAccount(newAccount)

cliWrite({
name: newAccount.name,
address: newAccount.address
})
process.exit(0)
})
}

function entropyAccountImport () {
return new Command('import')
.description('Import an existing entropy account from seed. Output is JSON of form {name, address}')
.addOption(passwordOption())
.argument('<name>', 'A user friendly name for your new account.')
.argument('<seed>', 'The seed for the account you are importing')
.addOption(
new Option(
'--path',
'Derivation path'
).default(ACCOUNTS_CONTENT.path.default)
)
.action(async (name, seed, opts) => {
const { path } = opts
const newAccount = await EntropyAccount.import({ name, seed, path })

await selectAndPersistNewAccount(newAccount)

cliWrite({
name: newAccount.name,
address: newAccount.address
})
process.exit(0)
})
}

function entropyAccountList () {
return new Command('list')
.alias('ls')
.description('List all accounts. Output is JSON of form [{ name, address, verifyingKeys }]')
.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 storedConfig = await config.get()
const accounts = EntropyAccount.list(storedConfig)
cliWrite(accounts)
process.exit(0)
})
}

/* register */
function entropyAccountRegister () {
return new Command('register')
.description('Register an entropy account with a program')
.addOption(passwordOption())
.addOption(endpointOption())
.addOption(currentAccountAddressOption())
// Removing these options for now until we update the design to accept program configs
// .addOption(
// new Option(
// '-pointer, --pointer',
// 'Program pointer of program to be used for registering'
// )
// )
// .addOption(
// new Option(
// '-data, --program-data',
// 'Path to file containing program data in JSON format'
// )
// )
.action(async (opts) => {
const { account, endpoint, /* password */ } = opts
const storedConfig = await config.get()
const { accounts } = storedConfig
const accountToRegister = findAccountByAddressOrName(accounts, account)
if (!accountToRegister) {
throw new Error('AccountError: Unable to register non-existent account')
}

const entropy: Entropy = await loadEntropy(accountToRegister.address, endpoint)
const accountService = new EntropyAccount(entropy, endpoint)
const updatedAccount = await accountService.registerAccount(accountToRegister)

const arrIdx = accounts.indexOf(accountToRegister)
accounts.splice(arrIdx, 1, updatedAccount)
await config.set({
...storedConfig,
accounts,
selectedAccount: updatedAccount.address
})

const verifyingKeys = updatedAccount?.data?.registration?.verifyingKeys
const verifyingKey = verifyingKeys[verifyingKeys.length - 1]
cliWrite(verifyingKey)
process.exit(0)
})
}
36 changes: 36 additions & 0 deletions src/account/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
export const FLOW_CONTEXT = 'ENTROPY_ACCOUNTS'

export const ACCOUNTS_CONTENT = {
seed: {
name: 'seed',
message: 'Enter seed:',
invalidSeed: 'Seed provided is not valid'
},
path: {
name: 'path',
message: 'derivation path:',
default: 'none',
},
importKey: {
name: 'importKey',
message: 'Would you like to import your own seed?',
default: false
},
name: {
name: 'name',
default: 'My Key',
},
selectAccount: {
name: "selectedAccount",
message: "Choose account:",
},
interactionChoice: {
name: 'interactionChoice',
choices: [
{ name: 'Create/Import Account', value: 'create-import' },
{ name: 'Select Account', value: 'select-account' },
{ name: 'List Accounts', value: 'list-account' },
{ name: 'Exit to Main Menu', value: 'exit' }
]
}
}
92 changes: 92 additions & 0 deletions src/account/interaction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import inquirer from "inquirer";
import Entropy from "@entropyxyz/sdk";

import { EntropyAccount } from './main'
import { selectAndPersistNewAccount } from "./utils";
import { findAccountByAddressOrName, print } from "../common/utils"
import { EntropyConfig } from "../config/types";
import * as config from "../config";

import {
manageAccountsQuestions,
newAccountQuestions,
selectAccountQuestions
} from "./utils"

/*
* @returns partialConfigUpdate | "exit" | undefined
*/
export async function entropyAccount (endpoint: string, storedConfig: EntropyConfig) {
const { accounts } = storedConfig
const { interactionChoice } = await inquirer.prompt(manageAccountsQuestions)

switch (interactionChoice) {

case 'create-import': {
const answers = await inquirer.prompt(newAccountQuestions)
const { name, path, importKey } = answers
let { seed } = answers
if (importKey && seed.includes('#debug')) {
// isDebugMode = true
seed = seed.split('#debug')[0]
}

const newAccount = seed
? await EntropyAccount.import({ seed, name, path })
: await EntropyAccount.create({ name, path })

await selectAndPersistNewAccount(newAccount)
return
}

case 'select-account': {
if (!accounts.length) {
console.error('There are currently no accounts available, please create or import a new account using the Manage Accounts feature')
return
}
const { selectedAccount } = await inquirer.prompt(selectAccountQuestions(accounts))
await config.set({
...storedConfig,
selectedAccount: selectedAccount.address
})

print('Current selected account is ' + selectedAccount)
return
}

case 'list-account': {
try {
EntropyAccount.list({ accounts })
.forEach((account) => print(account))
} catch (error) {
console.error(error.message.split('AccountsError: ')[1])
}
return
}

case 'exit': {
return 'exit'
}

default:
throw new Error('AccountsError: Unknown interaction action')
}
}

export async function entropyRegister (entropy: Entropy, endpoint: string, storedConfig: EntropyConfig): Promise<Partial<EntropyConfig>> {
const accountService = new EntropyAccount(entropy, endpoint)

const { accounts, selectedAccount } = storedConfig
const currentAccount = findAccountByAddressOrName(accounts, selectedAccount)
if (!currentAccount) {
print("No account selected to register")
return;
}
print("Attempting to register the address:", currentAccount.address)
const updatedAccount = await accountService.registerAccount(currentAccount)
const arrIdx = accounts.indexOf(currentAccount)
accounts.splice(arrIdx, 1, updatedAccount)
print("Your address", updatedAccount.address, "has been successfully registered.")

return { accounts, selectedAccount }
}
Loading

0 comments on commit ecb807b

Please sign in to comment.