Skip to content

Commit

Permalink
fix(chain): height calculation, improve markup, remove confusing timeout
Browse files Browse the repository at this point in the history
  • Loading branch information
davidyuk committed Apr 17, 2023
1 parent 651ba1a commit 4f5329d
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 71 deletions.
38 changes: 7 additions & 31 deletions src/actions/chain.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import {
printBlock, print, printUnderscored, printTransaction, printValidation,
} from '../utils/print';
import { getBlock } from '../utils/helpers';
import CliError from '../utils/CliError';

// ## Retrieve `node` version
export async function version(options) {
Expand Down Expand Up @@ -85,45 +84,22 @@ export async function top({ json, ...options }) {
printBlock(await sdk.api.getTopHeader(), json, true);
}

// # Play by `limit`
async function playWithLimit(limit, blockHash, sdk, json) {
if (!limit) return;
const block = await getBlock(blockHash, sdk);

await new Promise((resolve) => { setTimeout(resolve, 1000); });
printBlock(block, json);
await playWithLimit(limit - 1, block.prevHash, sdk, json);
}

// # Play by `height`
async function playWithHeight(height, blockHash, sdk, json) {
const block = await getBlock(blockHash, sdk);
if (parseInt(block.height) < height) return;

await new Promise((resolve) => { setTimeout(resolve, 1000); });
printBlock(block, json);
await playWithHeight(height, block.prevHash, sdk, json);
}

// ## This function `Play`(print all block) from `top` block to some condition(reach some `height` or `limit`)
// ## This function `Play` (print all block) from `top` block to some condition (reach some `height` or `limit`)
export async function play(options) {
let { height, limit, json } = options;
limit = +limit;
height = +height;
const sdk = initSdk(options);

// Get top block from `node`. It is a start point for play.
const topHeader = await sdk.api.getTopHeader();

if (height && height > parseInt(topHeader.height)) {
throw new CliError('Height is bigger then height of top block');
}

printBlock(topHeader, json);
let block = await sdk.api.getTopHeader();

// Play by `height` or by `limit` using `top` block as start point
if (height) await playWithHeight(height, topHeader.prevHash, sdk, json);
else await playWithLimit(limit - 1, topHeader.prevHash, sdk, json);
while (height ? block.height >= height : limit) {
if (!height) limit -= 1;
printBlock(block, json);
block = await getBlock(block.prevHash, sdk); // eslint-disable-line no-await-in-loop
}
}

// ## Send 'transaction' to the chain
Expand Down
6 changes: 3 additions & 3 deletions src/commands/chain.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ const program = new Command().name('aecli chain');
// ## Initialize `options`
const addCommonOptions = (p) => p
.addOption(nodeOption)
.option('-L --limit [playlimit]', 'Limit for play command', 10)
.addOption(forceOption)
.addOption(jsonOption);

Expand Down Expand Up @@ -73,13 +72,14 @@ addCommonOptions(program

// ## Initialize `play` command
//
// You can use this command to get list of block by some condition(by `limit` or `height`)
// You can use this command to get list of block by some condition (by `limit` or `height`)
//
// Example: `aecli chain play --limit 10` --> print 10 blocks starting from top
//
// Example: `aecli chain play --height` --> print blocks until reach some height starting from top
// Example: `aecli chain play --height 100` --> print blocks until reach height 100 starting from top
addCommonOptions(program
.command('play')
.option('-L --limit [playlimit]', 'Limit for play command', 10)
.option('-P --height [playToHeight]', 'Play to selected height')
.description('Real-time block monitoring')
.action(Chain.play));
Expand Down
16 changes: 6 additions & 10 deletions src/utils/print.js
Original file line number Diff line number Diff line change
Expand Up @@ -294,13 +294,10 @@ export function printBlockTransactions(ts, json, tabs = 0) {
return;
}
const tabsString = getTabs(tabs);
ts.forEach(
(tx) => {
print(`${tabsString}---------------- TX ----------------`);
printTransaction(tx, false, tabs + 1);
print(`${tabsString}--------------------------------------`);
},
);
ts.forEach((tx) => {
print(`${tabsString}<<--------------- Transaction --------------->>`);
printTransaction(tx, false, tabs);
});
}

export function printBlock(block, json, isRoot = false) {
Expand All @@ -313,7 +310,8 @@ export function printBlock(block, json, isRoot = false) {
const tabString = getTabs(tabs);

const reverseEncoding = Object.fromEntries(Object.entries(Encoding).map(([k, v]) => [v, k]));
print(`${tabString}<<--------------- ${reverseEncoding[encoding]} --------------->>`);
const name = reverseEncoding[encoding].replace('Hash', '');
print(`${tabString}<<--------------- ${name} --------------->>`);

printUnderscored(`${tabString}Block hash`, block.hash);
printUnderscored(`${tabString}Block height`, block.height);
Expand All @@ -328,8 +326,6 @@ export function printBlock(block, json, isRoot = false) {
const txCount = block.transactions?.length ?? 0;
printUnderscored(`${tabString}Transactions`, txCount);
if (txCount) printBlockTransactions(block.transactions, false, tabs + 1);

print(`${tabString}<<------------------------------------->>`);
}

// ##OTHER
Expand Down
24 changes: 14 additions & 10 deletions test/chain.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

import { before, describe, it } from 'mocha';
import { expect } from 'chai';
import { executeProgram, parseBlock, getSdk } from './index';
import { executeProgram, getSdk } from './index';
import chainProgram from '../src/commands/chain';

const executeChain = (args) => executeProgram(chainProgram, args);
Expand All @@ -36,7 +36,7 @@ describe('Chain Module', () => {

const res = await executeChain(['top']);
expect(res).to.equal(`
<<--------------- ${resJson.hash.startsWith('mh_') ? 'MicroBlockHash' : 'KeyBlockHash'} --------------->>
<<--------------- ${resJson.hash.startsWith('mh_') ? 'MicroBlock' : 'KeyBlock'} --------------->>
Block hash ______________________________ ${resJson.hash}
Block height ____________________________ ${resJson.height}
State hash ______________________________ ${resJson.stateHash}
Expand All @@ -48,7 +48,6 @@ Previous key block hash _________________ ${resJson.prevKeyHash}
Version _________________________________ 5
Target __________________________________ ${resJson.target ?? 'N/A'}
Transactions ____________________________ 0
<<------------------------------------->>
`.trim());
});

Expand Down Expand Up @@ -89,15 +88,20 @@ Syncing _________________________________ false
`.trim());
});

it('plays', async () => {
it('plays by limit', async () => {
const res = await executeChain(['play', '--limit', '4']);
res.split('<<------------------------------------->>').length.should.equal(5);
const blockCount = (output) => (output.match(/(Key|Micro)Block/g) || []).length;
expect(blockCount(res)).to.be.equal(4);
});

const parsed = res.split('<<------------------------------------->>').map(parseBlock);
parsed[0].previousBlockHash.should.equal(parsed[1].blockHash);
parsed[1].previousBlockHash.should.equal(parsed[2].blockHash);
parsed[2].previousBlockHash.should.equal(parsed[3].blockHash);
}).timeout(10000);
it('plays by height', async () => {
const res = await executeChain(['play', '--height', await sdk.getHeight() - 4]);
const heights = res
.split('\n')
.filter((l) => l.includes('Block height'))
.map((l) => +l.split(' ').at(-1));
expect(new Set(heights).size).to.be.equal(5);
});

it('calculates ttl', async () => {
const height = await sdk.getHeight();
Expand Down
15 changes: 0 additions & 15 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,21 +124,6 @@ export async function getSdk() {
return sdk;
}

export const parseBlock = (res) => Object.fromEntries(res
.trim()
.split('\n')
.map((a) => a.trim())
.filter((a) => !a.startsWith('<<--') && !a.startsWith('--'))
.map((a) => a.split(/ [_]+ /))
.map(([key, value]) => [
key
.toLowerCase()
.split(' ')
.map((el, i) => (i === 0 ? el : el[0].toUpperCase() + el.slice(1)))
.join(''),
value,
]));

export function randomName(length = 18) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const random = new Array(length).fill()
Expand Down
4 changes: 2 additions & 2 deletions test/tx.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
import { before, describe, it } from 'mocha';
import { expect } from 'chai';
import {
executeProgram, parseBlock, randomName, getSdk, networkId,
executeProgram, randomName, getSdk, networkId,
} from './index';
import txProgram from '../src/commands/tx';
import accountProgram from '../src/commands/account';
Expand Down Expand Up @@ -121,7 +121,7 @@ Signed __________________________________ ${responseJson.signedTx}
accountProgram,
['sign', WALLET_NAME, txEncoded, '--password', 'test', '--json', '--networkId', networkId],
);
const broadcast = parseBlock(await executeProgram(chainProgram, ['broadcast', signedTx]));
const broadcast = await executeProgram(chainProgram, ['broadcast', signedTx, '--json']);
expect(+broadcast.blockHeight).to.be.above(0);
const txHash = buildTxHash(signedTx);

Expand Down

0 comments on commit 4f5329d

Please sign in to comment.