Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(kadena-cli): refactor account code to a service #2309

Merged
merged 1 commit into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import { z } from 'zod';
import { CHAIN_ID_RANGE_ERROR_MESSAGE } from '../../constants/account.js';
import { actionAskForDeployFaucet } from '../../prompts/genericActionPrompts.js';
import { account } from '../../prompts/index.js';
import { services } from '../../services/index.js';
import { createOption } from '../../utils/createOption.js';
import {
formatZodError,
generateAllChainIds,
} from '../../utils/globalHelpers.js';
import { isEmpty } from '../../utils/helpers.js';
import { log } from '../../utils/logger.js';
import type { IAliasAccountData } from './types.js';
import {
Expand All @@ -17,9 +19,7 @@ import {
formatZodFieldErrors,
isValidMaxAccountFundParams,
parseChainIdRange,
readAccountFromFile,
} from './utils/accountHelpers.js';
import { isEmpty } from './utils/addHelpers.js';

export const accountOptions = {
accountFromSelection: createOption({
Expand Down Expand Up @@ -83,7 +83,7 @@ export const accountOptions = {
option: new Option('-a, --account <account>', 'Account alias name'),
expand: async (accountAlias: string): Promise<IAliasAccountData | null> => {
try {
const accountDetails = await readAccountFromFile(accountAlias);
const accountDetails = await services.account.getByAlias(accountAlias);
return accountDetails;
} catch (error) {
if (error.message.includes('file not exist') === true) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import type { ChainId } from '@kadena/types';
import { KEYS_ALL_PRED_ERROR_MESSAGE } from '../../../constants/account.js';
import { networkDefaults } from '../../../constants/networks.js';
import { assertCommandError } from '../../../utils/command.util.js';
import { services } from '../../../services/index.js';
import type { CommandOption } from '../../../utils/createCommand.js';
import { isNotEmptyString } from '../../../utils/globalHelpers.js';
import { log } from '../../../utils/logger.js';
import type { options } from '../accountAddOptions.js';
import type { IAccountDetailsResult, Predicate } from '../types.js';
import { isValidForOnlyKeysAllPredicate } from '../utils/accountHelpers.js';
import { addAccount } from '../utils/addAccount.js';
import { displayAddAccountSuccess } from '../utils/addHelpers.js';
import { createAccountName } from '../utils/createAccountName.js';
import { getAccountDetails } from '../utils/getAccountDetails.js';
Expand Down Expand Up @@ -112,14 +111,13 @@ export const addAccountFromKey = async (
: predicate,
};

const result = await addAccount({
accountAlias,
accountName,
const result = await services.account.create({
alias: accountAlias,
name: accountName,
fungible,
...accountGuard,
predicate,
publicKeys: accountGuard.publicKeysConfig,
});

assertCommandError(result);

displayAddAccountSuccess(accountAlias, result.data);
displayAddAccountSuccess(result);
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,12 @@ import type { ChainId } from '@kadena/client';
import { networkDefaults } from '../../../constants/networks.js';
import { services } from '../../../services/index.js';
import type { IWallet } from '../../../services/wallet/wallet.types.js';
import {
CommandError,
assertCommandError,
} from '../../../utils/command.util.js';
import { CommandError } from '../../../utils/command.util.js';
import type { CommandOption } from '../../../utils/createCommand.js';
import { notEmpty } from '../../../utils/globalHelpers.js';
import { log } from '../../../utils/logger.js';
import { findFreeIndexes } from '../../wallets/utils/walletHelpers.js';
import type { options } from '../accountAddOptions.js';
import { addAccount } from '../utils/addAccount.js';
import { displayAddAccountSuccess } from '../utils/addHelpers.js';
import { createAccountName } from '../utils/createAccountName.js';

Expand Down Expand Up @@ -122,22 +118,18 @@ export const addAccountFromWallet = async (
networkConfig: networkDefaults.testnet,
});

const addAccountConfig = {
accountName,
accountAlias,
fungible,
publicKeysConfig: filteredPublicKeys,
predicate,
};

log.debug('create-account-add-from-wallet:action', {
...config,
accountName,
});

const result = await addAccount(addAccountConfig);

assertCommandError(result);
const result = await services.account.create({
alias: accountAlias,
name: accountName,
fungible: fungible,
publicKeys: filteredPublicKeys,
predicate,
});

displayAddAccountSuccess(config.accountAlias, result.data);
displayAddAccountSuccess(result);
};
Original file line number Diff line number Diff line change
@@ -1,64 +1,8 @@
import { join } from 'path';
import { NO_ACCOUNTS_FOUND_ERROR_MESSAGE } from '../../../constants/account.js';
import { services } from '../../../services/index.js';
import { KadenaError } from '../../../services/service-error.js';
import type { CommandResult } from '../../../utils/command.util.js';
import { assertCommandError } from '../../../utils/command.util.js';
import { createCommand } from '../../../utils/createCommand.js';
import { isNotEmptyString } from '../../../utils/globalHelpers.js';
import { log } from '../../../utils/logger.js';
import { accountOptions } from '../accountOptions.js';
import {
ensureAccountAliasFilesExists,
getAccountDirectory,
} from '../utils/accountHelpers.js';

async function deleteAccountDir(): Promise<CommandResult<null>> {
const accountDir = getAccountDirectory();
if (accountDir === null) {
throw new KadenaError('no_kadena_directory');
}

try {
await services.filesystem.deleteDirectory(accountDir);
return {
data: null,
status: 'success',
};
} catch (error) {
return {
status: 'error',
errors: ['Failed to delete all account aliases.'],
};
}
}

async function removeAccount(
accountAlias: string,
): Promise<CommandResult<null>> {
const accountDir = getAccountDirectory();
if (accountDir === null) {
throw new KadenaError('no_kadena_directory');
}

if (accountAlias === 'all') {
return await deleteAccountDir();
}

const filePath = join(accountDir, `${accountAlias}.yaml`);
if (await services.filesystem.fileExists(filePath)) {
await services.filesystem.deleteFile(filePath);
return {
data: null,
status: 'success',
};
} else {
return {
status: 'error',
errors: [`The account alias "${accountAlias}" does not exist`],
};
}
}

export const createAccountDeleteCommand = createCommand(
'delete',
Expand All @@ -68,11 +12,6 @@ export const createAccountDeleteCommand = createCommand(
accountOptions.accountDeleteConfirmation({ isOptional: false }),
],
async (option) => {
const isAccountAliasesExist = await ensureAccountAliasFilesExists();
if (!isAccountAliasesExist) {
return log.error(NO_ACCOUNTS_FOUND_ERROR_MESSAGE);
}

const { accountAlias } = await option.accountAlias();

if (!isNotEmptyString(accountAlias.trim())) {
Expand All @@ -92,8 +31,25 @@ export const createAccountDeleteCommand = createCommand(
return log.warning('The account alias will not be deleted.');
}

const result = await removeAccount(accountAlias);
assertCommandError(result);
if (accountAlias === 'all') {
const accounts = await services.account.list();
if (accounts.length === 0) {
return log.error(
'No account aliases found. To add an account use `kadena account add` command.',
);
}
for (const account of accounts) {
await services.account.delete(account.filepath);
}
} else {
const account = await services.account.getByAlias(accountAlias);
if (!account) {
return log.error(`Account "${accountAlias}" not found`);
}

await services.account.delete(account.filepath);
}

const deleteSuccessMsg =
accountAlias === 'all'
? 'All account aliases has been deleted'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import ora from 'ora';
import {
CHAIN_ID_ACTION_ERROR_MESSAGE,
MAX_FUND_AMOUNT,
NO_ACCOUNTS_FOUND_ERROR_MESSAGE,
} from '../../../constants/account.js';
import { FAUCET_MODULE_NAME } from '../../../constants/devnets.js';
import { assertCommandError } from '../../../utils/command.util.js';
Expand All @@ -12,10 +11,7 @@ import { globalOptions } from '../../../utils/globalOptions.js';
import { log } from '../../../utils/logger.js';
import { checkHealth } from '../../devnet/utils/network.js';
import { accountOptions } from '../accountOptions.js';
import {
ensureAccountAliasFilesExists,
sortChainIds,
} from '../utils/accountHelpers.js';
import { sortChainIds } from '../utils/accountHelpers.js';
import { fund } from '../utils/fund.js';
import {
deployFaucetsToChains,
Expand All @@ -36,12 +32,6 @@ export const createAccountFundCommand = createCommand(
accountOptions.deployFaucet(),
],
async (option) => {
const isAccountAliasesExist = await ensureAccountAliasFilesExists();

if (!isAccountAliasesExist) {
return log.error(NO_ACCOUNTS_FOUND_ERROR_MESSAGE);
}

const { account, accountConfig } = await option.account();
const { network, networkConfig } = await option.network({
allowedNetworkIds: ['testnet', 'development'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@ import type { Table } from 'cli-table3';
import type { Command } from 'commander';
import { parse } from 'node:path';
import { NO_ACCOUNTS_FOUND_ERROR_MESSAGE } from '../../../constants/account.js';
import { services } from '../../../services/index.js';
import { createCommand } from '../../../utils/createCommand.js';
import { isNotEmptyString } from '../../../utils/globalHelpers.js';
import { log } from '../../../utils/logger.js';
import { createTable } from '../../../utils/table.js';
import { accountOptions } from '../accountOptions.js';
import type { IAliasAccountData } from '../types.js';
import {
ensureAccountAliasFilesExists,
getAllAccounts,
readAccountFromFile,
} from '../utils/accountHelpers.js';

function generateTabularData(accounts: IAliasAccountData[]): Table {
const table = createTable({});
Expand Down Expand Up @@ -41,21 +37,6 @@ function generateTabularData(accounts: IAliasAccountData[]): Table {
return table;
}

async function accountList(
accountAlias: string,
): Promise<IAliasAccountData[] | undefined> {
try {
if (accountAlias === 'all') {
return await getAllAccounts();
} else {
const account = await readAccountFromFile(accountAlias);
return [account];
}
} catch (error) {
return;
}
}

export const createAccountListCommand: (
program: Command,
version: string,
Expand All @@ -64,29 +45,32 @@ export const createAccountListCommand: (
'List all available accounts',
[accountOptions.accountSelectWithAll()],
async (option) => {
const isAccountAliasesExist = await ensureAccountAliasFilesExists();

if (!isAccountAliasesExist) {
return log.warning(NO_ACCOUNTS_FOUND_ERROR_MESSAGE);
}

const { accountAlias } = await option.accountAlias();

log.debug('account-list:action', accountAlias);
log.debug('account-list:action', { accountAlias });

if (!isNotEmptyString(accountAlias)) {
return log.error('No account alias is selected');
}

const accountsDetails = await accountList(accountAlias);
if (accountAlias === 'all') {
const accountsDetails = await services.account.list();

if (!accountsDetails || accountsDetails.length === 0) {
return log.error(`Selected account alias "${accountAlias}" not found.`);
}
if (accountsDetails.length === 0) {
return log.warning(NO_ACCOUNTS_FOUND_ERROR_MESSAGE);
}

const data = generateTabularData(accountsDetails);
const accountsListJSONOutput =
accountsDetails.length === 1 ? accountsDetails[0] : accountsDetails;
log.output(data.toString(), accountsListJSONOutput);
const data = generateTabularData(accountsDetails);
log.output(data.toString(), accountsDetails);
} else {
const accountsDetails = await services.account.getByAlias(accountAlias);

if (!accountsDetails) {
return log.error(`Selected account alias "${accountAlias}" not found.`);
}

const data = generateTabularData([accountsDetails]);
log.output(data.toString(), accountsDetails);
}
},
);
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ describe('account add manual type', () => {
expect(await services.filesystem.fileExists(aliasFile)).toBe(true);
const content = await services.filesystem.readFile(aliasFile);
expect(jsYaml.load(content!)).toEqual({
alias: 'account-add-test-chain',
name: 'k:pubkey1',
fungible: 'coin',
publicKeys: ['publicKey1', 'publicKey2'],
Expand Down Expand Up @@ -112,6 +113,7 @@ describe('account add manual type', () => {
expect(await services.filesystem.fileExists(accountAliasFile)).toBe(true);
const content = await services.filesystem.readFile(accountAliasFile);
expect(jsYaml.load(content!)).toEqual({
alias: 'account-add-test',
name: 'w:FxlQEvb6qHb50NClEnpwbT2uoJHuAu39GTSwXmASH2k:keys-all',
fungible: 'coin',
publicKeys: ['pubkey1', 'pubkey2'],
Expand All @@ -126,6 +128,7 @@ describe('account add manual type', () => {
expect(await services.filesystem.fileExists(accountAliasFile)).toBe(true);
const content = await services.filesystem.readFile(accountAliasFile);
expect(jsYaml.load(content!)).toEqual({
alias: 'account-add-test',
name: 'k:pubkey1',
fungible: 'coin',
publicKeys: ['publicKey1', 'publicKey2'],
Expand Down Expand Up @@ -219,6 +222,7 @@ describe('account add type wallet', () => {
expect(await services.filesystem.fileExists(accountAliasFile)).toBe(true);
const content = await services.filesystem.readFile(accountAliasFile);
expect(jsYaml.load(content!)).toEqual({
alias: 'account-add-test',
name: 'w:FxlQEvb6qHb50NClEnpwbT2uoJHuAu39GTSwXmASH2k:keys-all',
fungible: 'coin',
publicKeys: [publicKey],
Expand Down Expand Up @@ -251,6 +255,7 @@ describe('account add type wallet', () => {
expect(await services.filesystem.fileExists(accountAliasFile)).toBe(true);
const content = await services.filesystem.readFile(accountAliasFile);
expect(jsYaml.load(content!)).toEqual({
alias: 'account-add-test',
name: 'w:FxlQEvb6qHb50NClEnpwbT2uoJHuAu39GTSwXmASH2k:keys-all',
fungible: 'coin',
publicKeys: [publicKey, generatedKey],
Expand Down
Loading
Loading