Skip to content
This repository has been archived by the owner on Apr 15, 2019. It is now read-only.

Commit

Permalink
Merge pull request #666 from LiskHQ/654-update_account_cmd_ts
Browse files Browse the repository at this point in the history
Update account command to typescript - Closes #654
  • Loading branch information
shuse2 authored Dec 11, 2018
2 parents 9aaa712 + 8b088af commit b159891
Show file tree
Hide file tree
Showing 17 changed files with 1,539 additions and 2,110 deletions.
3,233 changes: 1,279 additions & 1,954 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,7 @@
"/npm-shrinkwrap.json",
"/oclif.manifest.json",
"/dist",
"/docs",
"/default_config.json"
"/docs"
],
"dependencies": {
"@liskhq/lisk-api-client": "2.0.0",
Expand All @@ -119,9 +118,12 @@
"inquirer": "6.2.0",
"lockfile": "1.0.4",
"semver": "5.5.1",
"strip-ansi": "4.0.0"
"strip-ansi": "4.0.0",
"tslib": "1.9.3"
},
"devDependencies": {
"@oclif/dev-cli": "1.18.0",
"@oclif/test": "1.2.0",
"@types/bip39": "2.4.0",
"@types/chai": "4.1.5",
"@types/chai-as-promised": "7.1.0",
Expand All @@ -135,8 +137,6 @@
"@types/sinon": "5.0.5",
"@types/sinon-chai": "3.2.0",
"@types/strip-ansi": "3.0.0",
"@oclif/dev-cli": "1.18.0",
"@oclif/test": "1.2.0",
"chai": "4.1.2",
"chai-as-promised": "7.1.1",
"coveralls": "3.0.0",
Expand Down
92 changes: 58 additions & 34 deletions src/base.js → src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,59 +13,83 @@
* Removal or modification of this copyright notice is prohibited.
*
*/
import os from 'os';
import { Command, flags as flagParser } from '@oclif/command';
import os from 'os';
import { getConfig } from './utils/config';
import { handleEPIPE } from './utils/helpers';
import print from './utils/print';
import { print } from './utils/print';

export const defaultConfigFolder = '.lisk';

export default class BaseCommand extends Command {
async init() {
const { flags } = this.parse(this.constructor);
this.flags = flags;
const jsonDescription =
'Prints output in JSON format. You can change the default behaviour in your config.json file.';

const prettyDescription =
'Prints JSON in pretty format rather than condensed. Has no effect if the output is set to table. You can change the default behaviour in your config.json file.';

interface PrintFlags {
readonly json?: boolean;
readonly pretty?: boolean;
}

interface APIConfig {
readonly api: {
readonly network: string;
readonly nodes: ReadonlyArray<string>;
};
}

type UserConfig = PrintFlags & APIConfig;

export default abstract class BaseCommand extends Command {
static flags = {
json: flagParser.boolean({
char: 'j',
description: jsonDescription,
allowNo: true,
}),
pretty: flagParser.boolean({
description: prettyDescription,
allowNo: true,
}),
};

public printFlags: PrintFlags = {};
public userConfig: UserConfig = {
api: {
network: '',
nodes: [],
},
};

async finally(error?: Error | string): Promise<void> {
if (error) {
this.error(error instanceof Error ? error.message : error);
}
}

async init(): Promise<void> {
// Typing problem where constructor is not allow as Input<any> but it requires to be the type
// tslint:disable-next-line no-any
const { flags } = this.parse(this.constructor as unknown as flagParser.Input<any>);
this.printFlags = flags;

process.on('error', handleEPIPE);
process.stdout.on('error', handleEPIPE);

process.env.XDG_CONFIG_HOME =
process.env.LISK_COMMANDER_CONFIG_DIR ||
`${os.homedir()}/${defaultConfigFolder}`;
this.userConfig = getConfig(process.env.XDG_CONFIG_HOME);
}

async finally(error) {
if (error) {
this.error(error.message ? error.message : error);
}
}

print(result, readAgain = false) {
print(result: unknown, readAgain = false): void {
if (readAgain) {
this.userConfig = getConfig(process.env.XDG_CONFIG_HOME);
this.userConfig = getConfig(process.env.XDG_CONFIG_HOME as string);
}
print({
json: this.userConfig.json,
pretty: this.userConfig.pretty,
...this.flags,
...this.printFlags,
}).call(this, result);
}
}

const jsonDescription =
'Prints output in JSON format. You can change the default behaviour in your config.json file.';

const prettyDescription =
'Prints JSON in pretty format rather than condensed. Has no effect if the output is set to table. You can change the default behaviour in your config.json file.';

BaseCommand.flags = {
json: flagParser.boolean({
char: 'j',
description: jsonDescription,
allowNo: true,
}),
pretty: flagParser.boolean({
description: prettyDescription,
allowNo: true,
}),
};
57 changes: 33 additions & 24 deletions src/commands/account/create.js → src/commands/account/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,23 @@
* Removal or modification of this copyright notice is prohibited.
*
*/
import { getAddressFromPublicKey, getKeys } from '@liskhq/lisk-cryptography';
import { flags as flagParser } from '@oclif/command';
import * as cryptography from '@liskhq/lisk-cryptography';
import BaseCommand from '../../base';
import { createMnemonicPassphrase } from '../../utils/mnemonic';

const createAccount = () => {
interface AccountInfo {
readonly address: string;
readonly passphrase: string;
readonly privateKey: string;
readonly publicKey: string;
}

const createAccount = (): AccountInfo => {
const passphrase = createMnemonicPassphrase();
const { privateKey, publicKey } = cryptography.getKeys(passphrase);
const address = cryptography.getAddressFromPublicKey(publicKey);
const { privateKey, publicKey } = getKeys(passphrase);
const address = getAddressFromPublicKey(publicKey);

return {
passphrase,
privateKey,
Expand All @@ -31,31 +39,32 @@ const createAccount = () => {
};

export default class CreateCommand extends BaseCommand {
async run() {
static description = `
Returns a randomly-generated mnemonic passphrase with its corresponding public/private key pair and Lisk address.
`;

static examples = ['account:create', 'account:create --number=3'];

static flags = {
...BaseCommand.flags,
number: flagParser.string({
char: 'n',
description: 'Number of accounts to create.',
default: '1',
}),
};

async run(): Promise<void> {
const { flags: { number: numberStr } } = this.parse(CreateCommand);
const number = parseInt(numberStr, 10);
const numberOfAccounts = parseInt(numberStr as string, 10);
if (
numberStr !== number.toString() ||
!Number.isInteger(number) ||
number <= 0
numberStr !== numberOfAccounts.toString() ||
!Number.isInteger(numberOfAccounts) ||
numberOfAccounts <= 0
) {
throw new Error('Number flag must be an integer and greater than 0');
}
const accounts = new Array(number).fill().map(createAccount);
const accounts = new Array(numberOfAccounts).fill(0).map(createAccount);
this.print(accounts);
}
}

CreateCommand.flags = {
...BaseCommand.flags,
number: flagParser.string({
char: 'n',
description: 'Number of accounts to create.',
default: '1',
}),
};

CreateCommand.description = `
Returns a randomly-generated mnemonic passphrase with its corresponding public/private key pair and Lisk address.
`;
CreateCommand.examples = ['account:create', 'account:create --number=3'];
57 changes: 32 additions & 25 deletions src/commands/account/get.js → src/commands/account/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,39 @@ import BaseCommand from '../../base';
import { getAPIClient } from '../../utils/api';
import { query } from '../../utils/query';

interface Args {
readonly addresses: string;
}

export default class GetCommand extends BaseCommand {
async run() {
const { args: { addresses } } = this.parse(GetCommand);
const req = addresses.map(address => ({
static args = [
{
name: 'addresses',
required: true,
description: 'Comma-separated address(es) to get information about.',
},
];

static description = `
Gets account information from the blockchain.
`;

static examples = [
'account:get 3520445367460290306L',
'account:get 3520445367460290306L,2802325248134221536L',
];

static flags = {
...BaseCommand.flags,
};

async run(): Promise<void> {
const { args } = this.parse(GetCommand);
const { addresses: addressesStr }: Args = args;
const addresses = addressesStr
.split(',')
.filter(Boolean);
const req = addresses.map((address: string) => ({
query: {
limit: 1,
address,
Expand All @@ -35,25 +64,3 @@ export default class GetCommand extends BaseCommand {
this.print(results);
}
}

GetCommand.args = [
{
name: 'addresses',
required: true,
description: 'Comma-separated address(es) to get information about.',
parse: input => input.split(',').filter(Boolean),
},
];

GetCommand.flags = {
...BaseCommand.flags,
};

GetCommand.description = `
Gets account information from the blockchain.
`;

GetCommand.examples = [
'account:get 3520445367460290306L',
'account:get 3520445367460290306L,2802325248134221536L',
];
39 changes: 23 additions & 16 deletions src/commands/account/show.js → src/commands/account/show.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,21 @@
* Removal or modification of this copyright notice is prohibited.
*
*/
import * as cryptography from '@liskhq/lisk-cryptography';
import { getAddressFromPublicKey, getKeys } from '@liskhq/lisk-cryptography';
import { flags as flagParser } from '@oclif/command';
import BaseCommand from '../../base';
import { getInputsFromSources } from '../../utils/input';
import { ValidationError } from '../../utils/error';
import { flags as commonFlags } from '../../utils/flags';
import { getInputsFromSources } from '../../utils/input';

const processInput = ({ passphrase }: { readonly passphrase?: string }) => {
if (!passphrase) {
throw new ValidationError('Passphrase cannot be empty');
}

const { privateKey, publicKey } = getKeys(passphrase);
const address = getAddressFromPublicKey(publicKey);

const processInput = ({ passphrase }) => {
const { privateKey, publicKey } = cryptography.getKeys(passphrase);
const address = cryptography.getAddressFromPublicKey(publicKey);
return {
privateKey,
publicKey,
Expand All @@ -30,7 +36,18 @@ const processInput = ({ passphrase }) => {
};

export default class ShowCommand extends BaseCommand {
async run() {
static description = `
Shows account information for a given passphrase.
`;

static examples = ['account:show'];

static flags = {
...BaseCommand.flags,
passphrase: flagParser.string(commonFlags.passphrase),
};

async run(): Promise<void> {
const { flags: { passphrase: passphraseSource } } = this.parse(ShowCommand);
const input = await getInputsFromSources({
passphrase: {
Expand All @@ -41,13 +58,3 @@ export default class ShowCommand extends BaseCommand {
this.print(processInput(input));
}
}

ShowCommand.flags = {
...BaseCommand.flags,
passphrase: flagParser.string(commonFlags.passphrase),
};

ShowCommand.description = `
Shows account information for a given passphrase.
`;
ShowCommand.examples = ['account:show'];
Loading

0 comments on commit b159891

Please sign in to comment.