Skip to content

Commit

Permalink
QA file-restructure (#247)
Browse files Browse the repository at this point in the history
* WIP: QA file-restructure

* fixes

* more tweaks

* Update src/config/encoding.ts

* Update tests/qa.sh

* fixups

* rm commander.test.ts

* fix cli opts bug with multiple accountOptions

* drop async argParser function! (unsupported)

* tweeeks

* add setSelectedAccount

* push verifyingKeys into admin account

* revert: push verifyingKeys into registration keyring account

* reverting changes from new sdk

* Update src/config/types.ts

---------

Co-authored-by: Nayyir Jutha <nayyir.jutha@gmail.com>
  • Loading branch information
mixmix and rh0delta authored Oct 22, 2024
1 parent fe685b8 commit f5a1fd9
Show file tree
Hide file tree
Showing 14 changed files with 194 additions and 34 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"@entropyxyz/sdk": "^0.2.3",
"ansi-colors": "^4.1.3",
"cli-progress": "^3.12.0",
"commander": "^12.0.0",
"commander": "^12.1.0",
"env-paths": "^3.0.0",
"inquirer": "8.0.0",
"mkdirp": "^3.0.1",
Expand Down
20 changes: 16 additions & 4 deletions src/account/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ export function entropyAccountCommand () {
.addCommand(entropyAccountImport())
.addCommand(entropyAccountList())
.addCommand(entropyAccountRegister())
// .addCommand(entropyAccountAlias())
// IDEA: support aliases for remote accounts (those we don't have seeds for)
// this would make transfers safer/ easier from CLI
}

function entropyAccountCreate () {
Expand All @@ -34,7 +37,8 @@ function entropyAccountCreate () {

cliWrite({
name: newAccount.name,
address: newAccount.address
address: newAccount.address,
verifyingKeys: []
})
process.exit(0)
})
Expand All @@ -59,7 +63,8 @@ function entropyAccountImport () {

cliWrite({
name: newAccount.name,
address: newAccount.address
address: newAccount.address,
verifyingKeys: []
})
process.exit(0)
})
Expand All @@ -70,8 +75,15 @@ function entropyAccountList () {
.alias('ls')
.description('List all accounts. Output is JSON of form [{ name, address, verifyingKeys }]')
.action(async () => {
const storedConfig = await config.get()
const accounts = EntropyAccount.list(storedConfig)
// 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 config.get()
.then(storedConfig => EntropyAccount.list(storedConfig))
.catch((err) => {
if (err.message.includes('currently no accounts')) return []

throw err
})

cliWrite(accounts)
process.exit(0)
})
Expand Down
55 changes: 45 additions & 10 deletions src/account/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { FLOW_CONTEXT } from "./constants";
import { AccountCreateParams, AccountImportParams, AccountRegisterParams } from "./types";

import { EntropyBase } from "../common/entropy-base";
import { EntropyAccountConfig } from "../config/types";
import { EntropyAccountConfig, EntropyAccountConfigFormatted } from "../config/types";

export class EntropyAccount extends EntropyBase {
constructor (entropy: Entropy, endpoint: string) {
Expand All @@ -19,26 +19,28 @@ export class EntropyAccount extends EntropyBase {
return EntropyAccount.import({ name, seed, path })
}

// WARNING: #create depends on #import => be careful modifying this function
static async import ({ name, seed, path }: AccountImportParams ): Promise<EntropyAccountConfig> {
// WARNING: #create currently depends on this => be careful modifying this function

await wasmGlobalsReady()
const keyring = new Keyring({ seed, path, debug: true })

const fullAccount = keyring.getAccount()
// TODO: sdk should create account on constructor
const { admin } = keyring.getAccount()
const data = fixData(fullAccount)
const maybeEncryptedData = data
// const maybeEncryptedData = password ? passwordFlow.encrypt(data, password) : data

const data = fullAccount
const { admin } = keyring.getAccount()
delete admin.pair

return {
name,
address: admin.address,
data
data: maybeEncryptedData,
}
}

static list ({ accounts }: { accounts: EntropyAccountConfig[] }) {
static list ({ accounts }: { accounts: EntropyAccountConfig[] }): EntropyAccountConfigFormatted[] {
if (!accounts.length)
throw new Error(
'AccountsError: There are currently no accounts available, please create or import a new account using the Manage Accounts feature'
Expand All @@ -47,7 +49,7 @@ export class EntropyAccount extends EntropyBase {
return accounts.map((account: EntropyAccountConfig) => ({
name: account.name,
address: account.address,
verifyingKeys: account?.data?.admin?.verifyingKeys
verifyingKeys: account?.data?.registration?.verifyingKeys || []
}))
}

Expand Down Expand Up @@ -88,7 +90,7 @@ export class EntropyAccount extends EntropyBase {
dispatchError.asModule
)
const { docs, name, section } = decoded

msg = `${section}.${name}: ${docs.join(' ')}`
} else {
// Other, CannotLookup, BadOrigin, no extra info
Expand All @@ -105,3 +107,36 @@ export class EntropyAccount extends EntropyBase {
})
}
}

// TODO: there is a bug in SDK that is munting this data
function fixData (data) {
if (data.admin?.pair) {
const { addressRaw, secretKey, publicKey } = data.admin.pair
Object.assign(data.admin.pair, {
addressRaw: objToUint8Array(addressRaw),
secretKey: objToUint8Array(secretKey),
publicKey: objToUint8Array(publicKey)
})
}

if (data.registration?.pair) {
const { addressRaw, secretKey, publicKey } = data.registration.pair
Object.assign(data.registration.pair, {
addressRaw: objToUint8Array(addressRaw),
secretKey: objToUint8Array(secretKey),
publicKey: objToUint8Array(publicKey)
})
}

return data
}

function objToUint8Array (input) {
if (input instanceof Uint8Array) return input

const values: any = Object.entries(input)
.sort((a, b) => Number(a[0]) - Number(b[0])) // sort entries by keys
.map(entry => entry[1])

return new Uint8Array(values)
}
8 changes: 5 additions & 3 deletions src/account/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,22 @@ export async function selectAndPersistNewAccount (newAccount: EntropyAccountConf
accounts.push(newAccount)
await config.set({
...storedConfig,
selectedAccount: newAccount.address
selectedAccount: newAccount.name
})
}

export async function addVerifyingKeyToAccountAndSelect (verifyingKey: string, accountNameOrAddress: string) {
const storedConfig = await config.get()
const account = findAccountByAddressOrName(storedConfig.accounts, accountNameOrAddress)
const { accounts } = storedConfig

const account = findAccountByAddressOrName(accounts, accountNameOrAddress)
if (!account) throw Error(`Unable to persist verifyingKey "${verifyingKey}" to unknown account "${accountNameOrAddress}"`)

// persist to config, set selectedAccount
account.data.registration.verifyingKeys.push(verifyingKey)
await config.set({
...storedConfig,
selectedAccount: account.address
setSelectedAccount: account.name
})
}

Expand Down
17 changes: 12 additions & 5 deletions src/balance/command.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
import { Command } from "commander";
import Entropy from "@entropyxyz/sdk";
import { cliWrite, endpointOption, loadEntropy } from "src/common/utils-cli";

import { EntropyBalance } from "./main";
import { endpointOption, cliWrite, loadEntropy } from "../common/utils-cli";
import { findAccountByAddressOrName } from "../common/utils";
import * as config from "../config";

export function entropyBalanceCommand () {
const balanceCommand = new Command('balance')
balanceCommand
.description('Command to retrieive the balance of an account on the Entropy Network')
.argument('address', 'Account address whose balance you want to query')
.argument('account <address|name>', 'Account address whose balance you want to query')
.addOption(endpointOption())
.action(async (address, opts) => {
const entropy: Entropy = await loadEntropy(address, opts.endpoint)
.action(async (account, opts) => {
const entropy: Entropy = await loadEntropy(account, opts.endpoint)
const BalanceService = new EntropyBalance(entropy, opts.endpoint)

const { accounts } = await config.get()
const address = findAccountByAddressOrName(accounts, account)?.address

const balance = await BalanceService.getBalance(address)
cliWrite(`${balance.toLocaleString('en-US')} BITS`)
process.exit(0)
})

return balanceCommand
}
2 changes: 2 additions & 0 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@ program
.env('DEV_MODE')
.hideHelp()
)

.addCommand(entropyBalanceCommand())
.addCommand(entropyAccountCommand())
.addCommand(entropyTransferCommand())
.addCommand(entropySignCommand())
.addCommand(entropyProgramCommand())

.action(async (opts: EntropyTuiOptions) => {
const { account, endpoint } = opts
const entropy = account
Expand Down
3 changes: 2 additions & 1 deletion src/common/utils-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ export function endpointOption () {
return endpoint
})
.default('ws://testnet.entropy.xyz:9944/')
// NOTE: argParser is only run IF an option is provided, so this cannot be 'test-net'
// NOTE: default cannot be "test-net" as argParser only runs if the -e/--endpoint flag
// or ENTROPY_ENDPOINT env set
}

export function accountOption () {
Expand Down
11 changes: 8 additions & 3 deletions src/config/encoding.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
const PREFIX = 'data:application/UI8A;base64,'
// was a UInt8Array, but is stored as base64

export function serialize (config) {
export function serialize (config: object) {
return JSON.stringify(config, replacer, 2)
}

export function deserialize (config) {
return JSON.parse(config, reviver)
export function deserialize (config: string) {
try {
return JSON.parse(config, reviver)
} catch (err) {
console.log('broken config:', config)
throw err
}
}

function replacer (_key: string, value: any) {
Expand Down
5 changes: 4 additions & 1 deletion src/sign/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ export class EntropySign extends EntropyBase {
const signatureHexString = u8aToHex(signature)
this.logger.log(`Signature: ${signatureHexString}`)

return { signature: signatureHexString, verifyingKey: this.entropy.signingManager.verifyingKey }
return {
signature: signatureHexString,
verifyingKey: this.entropy.signingManager.verifyingKey
}
} catch (error) {
this.logger.error('Error signing message', error)
throw error
Expand Down
7 changes: 5 additions & 2 deletions src/transfer/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@ import { accountOption, endpointOption, loadEntropy } from "src/common/utils-cli
import { EntropyTransfer } from "./main"

export function entropyTransferCommand () {
const transferCommand = new Command('tranfer')
const transferCommand = new Command('transfer')
transferCommand
.description('Transfer funds between two Entropy accounts.') // TODO: name the output
.argument('destination', 'Account address funds will be sent to')
.argument('amount', 'Amount of funds to be moved')
.argument('amount', 'Amount of funds to be moved (in "tokens")')
.addOption(accountOption())
.addOption(endpointOption())
.action(async (destination, amount, opts) => {
// TODO: destination as <name|address> ?
const entropy = await loadEntropy(opts.account, opts.endpoint)
const transferService = new EntropyTransfer(entropy, opts.endpoint)

await transferService.transfer(destination, amount)

// cliWrite(??) // TODO: write the output
process.exit(0)
})
Expand Down
2 changes: 1 addition & 1 deletion src/transfer/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class EntropyTransfer extends EntropyBase {
dispatchError.asModule
)
const { docs, name, section } = decoded

msg = `${section}.${name}: ${docs.join(' ')}`
} else {
// Other, CannotLookup, BadOrigin, no extra info
Expand Down
4 changes: 2 additions & 2 deletions tests/account.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ test('Account - list', async t => {
address: charlieStashAddress,
data: {
seed: charlieStashSeed,
admin: {
registration: {
verifyingKeys: ['this-is-a-verifying-key'],
seed: charlieStashSeed,
address: charlieStashAddress,
Expand All @@ -41,7 +41,7 @@ test('Account - list', async t => {
t.deepEqual(accountsArray, [{
name: account.name,
address: account.address,
verifyingKeys: account?.data?.admin?.verifyingKeys
verifyingKeys: account?.data?.registration?.verifyingKeys
}])

// Resetting accounts on config to test for empty list
Expand Down
Loading

0 comments on commit f5a1fd9

Please sign in to comment.