UNPKG

@kadena/kadena-cli

Version:

Kadena CLI tool to interact with the Kadena blockchain (manage keys, transactions, etc.)

210 lines 11.2 kB
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { CHAIN_ID_ACTION_ERROR_MESSAGE, CHAIN_ID_RANGE_ERROR_MESSAGE, } from '../../../constants/account.js'; import { accountDetailsSuccessData, pollTxResponseMock, } from '../../../mocks/data/accountDetails.js'; import { devNetConfigMock } from '../../../mocks/network.js'; import { server, useMswDynamicHandler, useMswHandler, } from '../../../mocks/server.js'; import { mockPrompts, runCommand } from '../../../utils/test.util.js'; import * as fundHelpers from '../utils/fundHelpers.js'; import * as getAccountDetailsHelpers from '../utils/getAccountDetails.js'; import * as devnetHelpers from './../../devnet/utils/network.js'; describe('account fund', () => { beforeEach(async () => { vi.spyOn(getAccountDetailsHelpers, 'getAccountDetails').mockImplementation(() => { return Promise.resolve(accountDetailsSuccessData.result.data); }); // Pre add the account alias file to make sure account alias exists await runCommand('account add --from=key --account-alias=account-add-test-manual --account-name=accountName --fungible=coin --network=testnet --chain-id=1 --public-keys=publicKey1 --quiet'); useMswHandler({ response: { result: { data: 'Write succeeded', status: 'success', }, }, }); useMswHandler({ endpoint: 'poll', response: pollTxResponseMock, }); useMswHandler({ endpoint: 'send', response: { requestKeys: ['requestKey-1', 'requestKey-2'], }, }); useMswHandler({ network: devNetConfigMock, endpoint: 'local', response: { result: { data: 'Write succeeded', status: 'success', }, }, }); useMswHandler({ network: devNetConfigMock, endpoint: 'poll', response: pollTxResponseMock, }); useMswHandler({ network: devNetConfigMock, endpoint: 'send', response: { requestKeys: ['requestKey-1', 'requestKey-2'], }, }); }); afterEach(() => { server.resetHandlers(); }); it('should fund an account when account already exists on chain', async () => { mockPrompts({ select: { 'Select an account (alias - account name):': 'account-add-test-manual', 'Select a network:': 'testnet', }, input: { 'Enter a ChainId (0-19) (comma or hyphen separated e.g 0,1,2 or 1-5 or all):': '1', 'Enter an amount:': '20', }, }); const res = await runCommand('account fund'); expect(res.stderr).toContain('Account "accountName" funded with 20 coin(s) on Chain ID(s) "1" in testnet04 network.'); expect(res.stderr).toContain('https://explorer.chainweb.com/testnet/tx/requestKey-1'); }); it('should fund an account when options passed in cli', async () => { const res = await runCommand('account fund --account=account-add-test-manual --amount=1 --network=testnet --chain-ids=1 --quiet'); expect(res.stderr).toContain('Account "accountName" funded with 1 coin(s) on Chain ID(s) "1" in testnet04 network.'); expect(res.stderr).toContain('https://explorer.chainweb.com/testnet/tx/requestKey-1'); }); it('should create an account and fund when account does not exist on chain', async () => { vi.spyOn(getAccountDetailsHelpers, 'getAccountDetails').mockImplementation(() => { return Promise.resolve(undefined); }); useMswDynamicHandler({ method: 'post', getResponse: async (request) => { const data = (await request.json()); const parsedCMD = JSON.parse(data.cmd); if (parsedCMD.payload.exec.code.includes('coin.details') === true) { return [ { error: 'with-read: row not found: qwerty' }, { status: 404 }, ]; } return [ { result: { data: 'Write succeeded', status: 'success', }, }, { status: 200 }, ]; }, }); mockPrompts({ select: { 'Select an account (alias - account name):': 'account-add-test-manual', 'Select a network:': 'testnet', }, input: { 'Enter a ChainId (0-19) (comma or hyphen separated e.g 0,1,2 or 1-5 or all):': '1', 'Enter an amount:': '5', }, }); const res = await runCommand('account fund'); expect(res.stderr).toContain('Account "accountName" does not exist on Chain ID(s) 1. So the account will be created on these Chain ID(s)'); expect(res.stderr).toContain('Account "accountName" funded with 5 coin(s) on Chain ID(s) "1" in testnet04 network.'); }); it('should throw max amount error when user tries to enter more than max amount split for multi chains', async () => { const res = await runCommand('account fund --account=account-add-test-manual --amount=20 --network=testnet --chain-ids=0,1,2 --quiet'); expect(res.stderr).toContain('Error: -m, --amount "With 3 chains to fund, the max amount per chain is 6 coin(s)."'); }); it('should exit with invalid chain id error message when user passes invalid chain id with quiet flag', async () => { const res = await runCommand('account fund --account=account-add-test-manual --amount=1 --network=testnet --chain-ids=-1 --quiet'); expect(res.stderr).toContain(CHAIN_ID_RANGE_ERROR_MESSAGE); expect(res.stderr).toContain(CHAIN_ID_ACTION_ERROR_MESSAGE); }); it('should exit with account details missing when user passes account alias which is not created', async () => { const res = await runCommand('account fund --account=some-random-account-alias --amount=1 --network=testnet --chain-ids=2'); expect(res.stderr).toContain('Account details are missing'); }); it('should not fund an account when user tries to fund it on mainnet', async () => { const res = await runCommand('account fund --account=account-add-test-manual --amount=1 --network=mainnet --chain-ids=1'); expect(res.stderr).toContain('Fundings are not allowed on "mainnet01" network.'); }); it('should not fund an account when user tries to fund other than coin fungible with quiet flag', async () => { await runCommand('account add --from=key --account-alias=kdx-account --account-name=accountName --fungible=kdx --network=testnet --chain-id=1 --public-keys=publicKey1 --quiet'); const res = await runCommand('account fund --account=kdx-account --amount=1 --network=testnet --chain-ids=1'); expect(res.stderr).toContain(`You can't fund an account other than "coin" fungible.`); }); it('should fund an account in devnet', async () => { const mockCheckHealth = vi .spyOn(devnetHelpers, 'checkHealth') .mockResolvedValue(true); const mockFindMissingModule = vi .spyOn(fundHelpers, 'findMissingModuleDeployments') .mockResolvedValue([]); const res = await runCommand('account fund --account=account-add-test-manual --amount=1 --network=devnet --chain-ids=1'); expect(res.stderr).toContain('Chain ID "1" : http://localhost:8080/explorer/development/tx/requestKey-1'); expect(res.stderr).toContain('Account "accountName" funded with 1 coin(s) on Chain ID(s) "1" in development network.'); mockCheckHealth.mockRestore(); mockFindMissingModule.mockRestore(); }); it('should gracefully exit when development server is not running', async () => { const mockCheckHealth = vi .spyOn(devnetHelpers, 'checkHealth') .mockResolvedValue(false); const res = await runCommand('account fund --account=account-add-test-manual --amount=1 --network=devnet --chain-ids=1'); expect(res.stderr).toContain('Devnet host "http://localhost:8080" is not running.'); mockCheckHealth.mockRestore(); }); it('should exit without funding when user select "no" for deploy faucet prompt', async () => { mockPrompts({ select: { 'Do you wish to deploy faucet module?': 'no', }, }); const mockCheckHealth = vi .spyOn(devnetHelpers, 'checkHealth') .mockResolvedValue(true); const mockdeployFaucetsToChains = vi.spyOn(fundHelpers, 'deployFaucetsToChains'); const mockFindMissingModule = vi .spyOn(fundHelpers, 'findMissingModuleDeployments') .mockResolvedValue(['1']); const res = await runCommand('account fund --account=account-add-test-manual --amount=5 --network=devnet --chain-ids=1'); expect(res.stderr).toContain('Faucet module unavailable on chain "1" in the "devnet" network.'); expect(mockdeployFaucetsToChains).not.toHaveBeenCalled(); expect(res.stderr).toContain('To fund your account on chain "1" in the "devnet" network, deploy the faucet using the --deploy-faucet option.'); expect(res.stderr).not.toContain('Account "accountName" funded with 5 coin(s) on Chain ID(s) "1" in development network.'); mockCheckHealth.mockRestore(); mockFindMissingModule.mockRestore(); mockdeployFaucetsToChains.mockRestore(); }); it('should deploy faucet and fund account when user select "yes" to deploy faucet', async () => { mockPrompts({ select: { 'Do you wish to deploy faucet module?': 'yes', }, }); const mockCheckHealth = vi .spyOn(devnetHelpers, 'checkHealth') .mockResolvedValue(true); const mockdeployFaucetsToChains = vi .spyOn(fundHelpers, 'deployFaucetsToChains') .mockResolvedValue([['1'], []]); const mockFindMissingModule = vi .spyOn(fundHelpers, 'findMissingModuleDeployments') .mockResolvedValue(['1']); const res = await runCommand('account fund --account=account-add-test-manual --amount=5 --network=devnet --chain-ids=1'); expect(res.stderr).toContain('Faucet module unavailable on chain "1" in the "devnet" network.'); expect(mockdeployFaucetsToChains).toHaveBeenCalled(); expect(res.stderr).toContain('Account "accountName" funded with 5 coin(s) on Chain ID(s) "1" in development network.'); mockCheckHealth.mockRestore(); mockFindMissingModule.mockRestore(); mockdeployFaucetsToChains.mockRestore(); }); }); //# sourceMappingURL=accountFund.test.js.map