blocke
Version:
Command-line tool to query the blockchain for a variety of cryptos. View blocks, transactions, and accounts (where applicable).
350 lines (317 loc) • 12.2 kB
JavaScript
/*
Copyright (C) 2017 BikBikBikBikBik
This file is part of blocke.
blocke is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
blocke is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with blocke. If not, see <http://www.gnu.org/licenses/>.
*/
const { Account, Block, Network, Transaction } = require('../../../lib/type-mapper/models');
const assert = require('../../chai-setup');
const equal = require('deep-equal');
const random = require('../../random-generator');
const _ = require('underscore');
describe('lib/type-mapper/models', function() {
function createType(type, values) {
const accountCreator = (address, confirmedBalance, unconfirmedBalance, tokenBalances) => new Account(address, confirmedBalance, unconfirmedBalance, tokenBalances);
const blockCreator = (difficulty, hash, number, time, transactionCount) => new Block(difficulty, hash, number, time, transactionCount);
const networkCreator = (difficulty, hashRate, height, lastBlockTime) => new Network(difficulty, hashRate, height, lastBlockTime);
const transactionCreator = (amountSent, blockHash, hash, recipients, senders, time) => new Transaction(amountSent, blockHash, hash, recipients, senders, time);
const typeCreator = (() => {
switch (type) {
case 'Account':
return accountCreator;
case 'Block':
return blockCreator;
case 'Network Info':
return networkCreator;
case 'Transaction':
return transactionCreator;
}
})();
return typeCreator.apply(null, values);
}
/*
*
* ToString generators
*
*/
function accountToString(address, confirmedBalance, unconfirmedBalance, tokenBalances) {
const sortedTokens = _.sortBy(tokenBalances, 'symbol');
const tokenBalanceStrings = _.map(sortedTokens, (token) => `${token.balance} ${token.symbol}`);
return `Address: ${address}\n` +
(unconfirmedBalance > 0 ? (
`Confirmed Balance: ${confirmedBalance}\n` +
`Unconfirmed Balance: ${unconfirmedBalance}\n` +
`Total Balance: ${confirmedBalance + unconfirmedBalance}`)
: (`Balance: ${confirmedBalance}`)) +
(tokenBalanceStrings.length > 0 ? `\nToken Balances: ${tokenBalanceStrings.join('\n ')}` : '');
}
function blockToString(difficulty, hash, number, time, transactionCount) {
return `Hash: ${hash}\n` +
`Number: ${number}\n` +
`# Transactions: ${transactionCount}\n` +
(difficulty > 0 ? `Difficulty: ${difficulty}\n` : '') +
`Time: ${time.toString()}`;
}
function getToStringForType(type) {
switch (type) {
case 'Account':
return accountToString;
case 'Block':
return blockToString;
case 'Network Info':
return networkToString;
case 'Transaction':
return transactionToString;
}
}
function networkToString(difficulty, hashRate, height, lastBlockTime) {
return (difficulty > 0 ? `Difficulty: ${difficulty}\n` : '') +
(hashRate > 0 ? `Hash Rate: ${hashRate}\n` : '') +
`Height: ${height}` +
(lastBlockTime !== undefined ? `\nLast Block Time: ${lastBlockTime.toString()}` : '');
}
function transactionToString(amountSent, blockHash, hash, recipients, senders, time) {
const recipientsStrings = _.map(recipients, (recipient) => `${recipient.address} (${recipient.amount})`);
const sendersStrings = _.map(senders, (sender) => `${sender.address} (${sender.amount})`);
return `Amount Sent: ${amountSent}\n` +
(sendersStrings.length > 0 ? `Senders: ${sendersStrings.join('\n ')}\n` : '') +
(recipientsStrings.length > 0 ? `Recipients: ${recipientsStrings.join('\n ')}\n` : '') +
`Block Hash: ${blockHash}\n` +
`Hash: ${hash}\n` +
(time !== undefined ? `Time: ${time.toString()}` : '');
}
/*
*
* Field validators
*
*/
function getValidatorForType(type) {
switch (type) {
case 'Account':
return validateAccount;
case 'Block':
return validateBlock;
case 'Network Info':
return validateNetwork;
case 'Transaction':
return validateTransaction;
}
}
function validateAccount(instance, address, confirmedBalance, unconfirmedBalance, tokenBalances) {
assert.equal(instance._address, address);
assert.equal(instance._confirmedBalance, confirmedBalance);
assert.deepEqual(instance._tokenBalances, Array.isArray(tokenBalances) ? tokenBalances : []);
assert.equal(instance._unconfirmedBalance, typeof(unconfirmedBalance) === 'number' ? unconfirmedBalance : 0);
}
function validateBlock(instance, difficulty, hash, number, time, transactionCount) {
assert.equal(instance._difficulty, difficulty);
assert.equal(instance._hash, hash);
assert.equal(instance._number, number);
assert.equal(instance._time, time);
assert.equal(instance._transactionCount, transactionCount);
}
function validateNetwork(instance, difficulty, hashRate, height, lastBlockTime) {
assert.equal(instance._difficulty, difficulty);
assert.equal(instance._hashRate, hashRate);
assert.equal(instance._height, height);
assert.equal(instance._lastBlockTime, lastBlockTime);
}
function validateTransaction(instance, amountSent, blockHash, hash, recipients, senders, time) {
assert.equal(instance._amountSent, amountSent);
assert.equal(instance._blockHash, blockHash);
assert.equal(instance._hash, hash);
assert.deepEqual(instance._recipients, Array.isArray(recipients) ? recipients : [recipients]);
assert.deepEqual(instance._senders, Array.isArray(senders) ? senders : [senders]);
assert.equal(instance._time, time);
}
/*
*
* Test Data
*
*/
const tests = [
{
type: 'Account',
values: [ random.generateRandomHashString(32), random.generateRandomIntInclusive(1, 1000), 0, [] ],
extraTestInfo: 'Token balance is empty'
},
{
type: 'Account',
values: [
random.generateRandomHashString(32),
random.generateRandomIntInclusive(1, 1000),
0,
[ { balance: random.generateRandomIntInclusive(1, 1000), symbol: random.generateRandomHashString(3) }, { balance: random.generateRandomIntInclusive(1, 1000), symbol: random.generateRandomHashString(3) } ]
],
extraTestInfo: 'Token balance is non-empty'
},
{
type: 'Account',
values: [ random.generateRandomHashString(32), random.generateRandomIntInclusive(1, 1000), random.generateRandomIntInclusive(1, 1000) ],
extraTestInfo: 'Unconfirmed balance value supplied'
},
{
type: 'Account',
values: [ random.generateRandomHashString(32), random.generateRandomIntInclusive(1, 1000) ],
extraTestInfo: 'Unconfirmed balance value not supplied'
},
{
type: 'Block',
values: [
random.generateRandomIntInclusive(10000, 10000000000),
random.generateRandomHashString(32),
random.generateRandomIntInclusive(1, 1000000),
new Date(random.generateRandomIntInclusive(100000, 10000000) * 1000),
random.generateRandomIntInclusive(1, 100)
],
extraTestInfo: 'Difficulty is non-zero'
},
{
type: 'Block',
values: [
0,
random.generateRandomHashString(32),
random.generateRandomIntInclusive(1, 1000000),
new Date(random.generateRandomIntInclusive(100000, 10000000) * 1000),
random.generateRandomIntInclusive(1, 100)
],
extraTestInfo: 'Difficulty is zero'
},
{
type: 'Network Info',
values: [
random.generateRandomIntInclusive(100000, 10000000),
random.generateRandomIntInclusive(100000, 10000000),
random.generateRandomIntInclusive(100000, 10000000),
new Date(random.generateRandomIntInclusive(100000, 10000000) * 1000)
],
extraTestInfo: 'All fields populated'
},
{
type: 'Network Info',
values: [
0,
random.generateRandomIntInclusive(100000, 10000000),
random.generateRandomIntInclusive(100000, 10000000),
new Date(random.generateRandomIntInclusive(100000, 10000000) * 1000)
],
extraTestInfo: 'Difficulty is zero'
},
{
type: 'Network Info',
values: [
random.generateRandomIntInclusive(100000, 10000000),
0,
random.generateRandomIntInclusive(100000, 10000000),
new Date(random.generateRandomIntInclusive(100000, 10000000) * 1000)
],
extraTestInfo: 'Hash rate is zero'
},
{
type: 'Network Info',
values: [
random.generateRandomIntInclusive(100000, 10000000),
random.generateRandomIntInclusive(100000, 10000000),
random.generateRandomIntInclusive(100000, 10000000)
],
extraTestInfo: 'Time is undefined'
},
{
type: 'Transaction',
values: [
random.generateRandomIntInclusive(1, 10000),
random.generateRandomHashString(32),
random.generateRandomHashString(32),
[
{ address: random.generateRandomHashString(32), amount: random.generateRandomIntInclusive(1, 1000) },
{ address: random.generateRandomHashString(32), amount: random.generateRandomIntInclusive(1, 1000) }
],
[
{ address: random.generateRandomHashString(32), amount: random.generateRandomIntInclusive(1, 1000) },
{ address: random.generateRandomHashString(32), amount: random.generateRandomIntInclusive(1, 1000) }
],
new Date(random.generateRandomIntInclusive(100000, 10000000) * 1000),
],
extraTestInfo: 'All fields populated'
},
{
type: 'Transaction',
values: [
random.generateRandomIntInclusive(1, 10000),
random.generateRandomHashString(32),
random.generateRandomHashString(32),
[
{ address: random.generateRandomHashString(32), amount: random.generateRandomIntInclusive(1, 1000) },
{ address: random.generateRandomHashString(32), amount: random.generateRandomIntInclusive(1, 1000) }
],
[
{ address: random.generateRandomHashString(32), amount: random.generateRandomIntInclusive(1, 1000) },
{ address: random.generateRandomHashString(32), amount: random.generateRandomIntInclusive(1, 1000) }
]
],
extraTestInfo: 'Time is undefined'
},
{
type: 'Transaction',
values: [
random.generateRandomIntInclusive(1, 10000),
random.generateRandomHashString(32),
random.generateRandomHashString(32),
[],
[
{ address: random.generateRandomHashString(32), amount: random.generateRandomIntInclusive(1, 1000) },
{ address: random.generateRandomHashString(32), amount: random.generateRandomIntInclusive(1, 1000) }
],
new Date(random.generateRandomIntInclusive(100000, 10000000) * 1000),
],
extraTestInfo: 'Zero recipients'
},
{
type: 'Transaction',
values: [
random.generateRandomIntInclusive(1, 10000),
random.generateRandomHashString(32),
random.generateRandomHashString(32),
[
{ address: random.generateRandomHashString(32), amount: random.generateRandomIntInclusive(1, 1000) },
{ address: random.generateRandomHashString(32), amount: random.generateRandomIntInclusive(1, 1000) }
],
[],
new Date(random.generateRandomIntInclusive(100000, 10000000) * 1000),
],
extraTestInfo: 'Zero senders'
}
];
/*
*
* All models
*
*/
const testGroups = _.groupBy(tests, 'type');
_.each(testGroups, (testGroup, type) => {
describe(type, function() {
testGroup.forEach((test) => {
it(`should return formatted output from toString (${test.extraTestInfo})`, function() {
const instance = createType(test.type, test.values);
const toString = getToStringForType(test.type);
assert.equal(instance.toString(), toString.apply(null, test.values));
});
});
testGroup.forEach((test) => {
it(`should save all constructor inputs internally (${test.extraTestInfo})`, function() {
const instance = createType(test.type, test.values);
const validator = getValidatorForType(test.type);
validator.apply(null, [instance].concat(test.values));
});
});
});
});
});