From fb4057f71e368f76a64a22ba674e4354b92959c1 Mon Sep 17 00:00:00 2001 From: Mike the Tike Date: Fri, 7 May 2021 13:45:02 +0200 Subject: [PATCH 1/2] Fix cucumber test --- .circleci/config.yml | 3 + applications/utils/washing_machine.js | 12 +- integration_tests/.eslintrc.json | 15 + integration_tests/cucumber.js | 6 +- integration_tests/features/Reorgs.feature | 21 +- .../features/WalletTransfer.feature | 7 +- integration_tests/features/support/steps.js | 2126 +++++++++-------- integration_tests/features/support/world.js | 263 +- integration_tests/generate_report.js | 16 +- integration_tests/helpers/baseNodeClient.js | 304 +-- integration_tests/helpers/baseNodeProcess.js | 210 +- integration_tests/helpers/config.js | 144 +- .../helpers/mergeMiningProxyClient.js | 96 +- .../helpers/mergeMiningProxyProcess.js | 176 +- .../helpers/miningNodeProcess.js | 176 +- .../helpers/transactionBuilder.js | 196 +- integration_tests/helpers/util.js | 250 +- integration_tests/helpers/walletClient.js | 286 +-- integration_tests/helpers/walletProcess.js | 202 +- integration_tests/package-lock.json | 1469 +++++++++++- integration_tests/package.json | 5 + 21 files changed, 3755 insertions(+), 2228 deletions(-) create mode 100644 integration_tests/.eslintrc.json diff --git a/.circleci/config.yml b/.circleci/config.yml index 467adce6f8..9eaacd05f9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -92,6 +92,9 @@ commands: - run: name: Check formatting command: cd integration_tests && npm run check-fmt + - run: + name: Check eslint + command: cd integration_tests && npx eslint . - run: name: Pre-build base node command: cargo build --release --bin tari_base_node diff --git a/applications/utils/washing_machine.js b/applications/utils/washing_machine.js index 732631a125..d674a02807 100644 --- a/applications/utils/washing_machine.js +++ b/applications/utils/washing_machine.js @@ -53,7 +53,17 @@ async function doSend(senderClient, receiverClient, amount) { }); console.log("Split:", split_result); } - // TODO wait for split to be mined + + // wait for balance to become available + for (let i = 0; i< 20*60; i++) { + + let newBalance = await senderClient.getBalance(); + console.log(`Waiting for new balance (spender) ${newBalance.available_balance} to be more than required amount: ${amount}. Pending ${newBalance.pending_balance}`); + if (parseInt(newBalance.available_balance) >= amount) { + break; + } + await sleep(1000); + } let senderBalance = await senderClient.getBalance(); console.log("Sender: ", senderBalance); let balance = await receiverClient.getBalance(); diff --git a/integration_tests/.eslintrc.json b/integration_tests/.eslintrc.json new file mode 100644 index 0000000000..36f559cdf3 --- /dev/null +++ b/integration_tests/.eslintrc.json @@ -0,0 +1,15 @@ +{ + "env": { + "browser": true, + "commonjs": true, + "es2021": true + }, + "extends": [ + "standard" + ], + "parserOptions": { + "ecmaVersion": 12 + }, + "rules": { + } +} diff --git a/integration_tests/cucumber.js b/integration_tests/cucumber.js index 988c7217a3..2ae23c74a3 100644 --- a/integration_tests/cucumber.js +++ b/integration_tests/cucumber.js @@ -1,4 +1,4 @@ module.exports = { - default: "", - critical: "--format @cucumber/pretty-formatter --tags @critical", -}; + default: '', + critical: '--format @cucumber/pretty-formatter --tags @critical' +} diff --git a/integration_tests/features/Reorgs.feature b/integration_tests/features/Reorgs.feature index aa3a22164b..8e3e9daf49 100644 --- a/integration_tests/features/Reorgs.feature +++ b/integration_tests/features/Reorgs.feature @@ -3,22 +3,20 @@ Feature: Reorgs @critical Scenario: Simple reorg to stronger chain - Given I have a seed node SA - And I have a base node B connected to seed SA + Given I have a base node B And I have wallet WB connected to base node B And I have mining node BM connected to base node B and wallet WB - When I stop SA - And mining node BM mines 3 blocks - Given I have a base node C connected to seed SA + And mining node BM mines 3 blocks with min difficulty 1 and max difficulty 1 + Given I have a base node C And I have wallet WC connected to base node C And I have mining node CM connected to base node C and wallet WC - And mining node CM mines 15 blocks + And mining node CM mines 10 blocks with min difficulty 1 and max difficulty 9999999999 Then node B is at height 3 - And node C is at height 15 - When I start SA - Then node B is at height 15 - And node C is at height 15 - And node SA is at height 15 + And node C is at height 10 + Given I have a base node SA connected to nodes B,C + Then node SA is at height 10 + And node B is at height 10 + And node C is at height 10 @critical Scenario: Node rolls back reorg on invalid block @@ -39,6 +37,7 @@ Feature: Reorgs Given I have a base node NODE1 connected to all seed nodes When I mine a block on NODE1 with coinbase CB1 Given I have a base node NODE2 connected to node NODE1 + Then all nodes are at height 1 And I stop NODE1 When I mine 19 blocks on NODE2 And node NODE2 is at height 20 diff --git a/integration_tests/features/WalletTransfer.feature b/integration_tests/features/WalletTransfer.feature index 5c7b3a292f..3549806456 100644 --- a/integration_tests/features/WalletTransfer.feature +++ b/integration_tests/features/WalletTransfer.feature @@ -5,7 +5,7 @@ Feature: Wallet Transfer # Add a 2nd node otherwise initial sync will not succeed And I have 1 base nodes connected to all seed nodes And I have wallet Wallet_A connected to all seed nodes - And I have a merge mining proxy PROXY connected to NODE and Wallet_A with default config + And I have a merge mining proxy PROXY connected to NODE and Wallet_A with default config And I have mining node MINER connected to base node NODE and wallet Wallet_A And I have wallet Wallet_B connected to all seed nodes And I have wallet Wallet_C connected to all seed nodes @@ -28,8 +28,9 @@ Feature: Wallet Transfer When I merge mine 5 blocks via PROXY Then all nodes are at height 5 # Ensure the coinbase lock heights have expired + And I have mining node MINER connected to base node NODE and wallet WC And mining node MINER mines 3 blocks When I transfer 50000 uT to self from wallet Wallet_A at fee 25 And mining node MINER mines 5 blocks - Then all nodes are at height 15 - Then all wallets detect all transactions as Mined_Confirmed + Then all nodes are at height 13 + Then wallet Wallet_A detects all transactions as Mined_Confirmed diff --git a/integration_tests/features/support/steps.js b/integration_tests/features/support/steps.js index 7ad49cff71..5f6d848b38 100644 --- a/integration_tests/features/support/steps.js +++ b/integration_tests/features/support/steps.js @@ -1,816 +1,822 @@ // features/support/steps.js -const assert = require("assert"); -const { Given, When, Then } = require("cucumber"); -const MergeMiningProxyProcess = require("../../helpers/mergeMiningProxyProcess"); -const MiningNodeProcess = require("../../helpers/miningNodeProcess"); -const WalletProcess = require("../../helpers/walletProcess"); -const expect = require("chai").expect; +const assert = require('assert') +const { Given, When, Then } = require('cucumber') +const MergeMiningProxyProcess = require('../../helpers/mergeMiningProxyProcess') +const MiningNodeProcess = require('../../helpers/miningNodeProcess') +const WalletProcess = require('../../helpers/walletProcess') +const expect = require('chai').expect const { waitFor, getTransactionOutputHash, sleep, - consoleLogTransactionDetails, consoleLogBalance, consoleLogCoinbaseDetails, - withTimeout, -} = require("../../helpers/util"); -const TransactionBuilder = require("../../helpers/transactionBuilder"); -let lastResult; + withTimeout +} = require('../../helpers/util') +const TransactionBuilder = require('../../helpers/transactionBuilder') +let lastResult Given(/I have a seed node (.*)/, { timeout: 20 * 1000 }, async function (name) { - return await this.createSeedNode(name); - // Write code here that turns the phrase above into concrete actions -}); + return await this.createSeedNode(name) +}) -Given("I have {int} seed nodes", { timeout: 20 * 1000 }, async function (n) { - let promises = []; +Given('I have {int} seed nodes', { timeout: 20 * 1000 }, async function (n) { + const promises = [] for (let i = 0; i < n; i++) { - promises.push(this.createSeedNode(`SeedNode${i}`)); + promises.push(this.createSeedNode(`SeedNode${i}`)) } - await Promise.all(promises); -}); + await Promise.all(promises) +}) Given( /I have a base node (.*) connected to all seed nodes/, { timeout: 20 * 1000 }, async function (name) { - await create_node(name, this.seedAddresses(), this); + await this.createAndAddNode(name, this.seedAddresses()) } -); +) Given( /I have a base node (.*) connected to seed (.*)/, { timeout: 20 * 1000 }, async function (name, seedNode) { - await create_node(name, this.seeds[seedNode].peerAddress(), this); + await this.createAndAddNode(name, this.seeds[seedNode].peerAddress()) } -); +) + +Given( + /I have a base node (.*) connected to nodes (.*)/, + { timeout: 20 * 1000 }, + async function (name, nodes) { + const addresses = [] + nodes = nodes.split(',') + for (let i = 0; i < nodes.length; i++) { + addresses.push(this.nodes[nodes[i]].peerAddress()) + } + await this.createAndAddNode(name, addresses) + } +) + Given( /I have a base node (.*) connected to node (.*)/, { timeout: 20 * 1000 }, async function (name, node) { - await create_node(name, this.nodes[node].peerAddress(), this); + await this.createAndAddNode(name, this.nodes[node].peerAddress()) } -); +) + +Given( + /I have a base node (\S+)$/, + { timeout: 20 * 1000 }, + async function (name) { + await this.createAndAddNode(name) + } +) Given( /I have a SHA3 miner (.*) connected to seed node (.*)/, { timeout: 40 * 1000 }, async function (name, seed) { - //add the base_node - await create_node(name, this.seeds[seed].peerAddress(), this); - let node = this.getNode(name); + // add the base_node + await this.createAndAddNode(name, this.seeds[seed].peerAddress(), this) + const node = this.getNode(name) // Add the wallet connected to the above base node - await create_wallet(name, node.peerAddress(), this); + await this.createAndAddWallet(name, node.peerAddress(), this) - //Now lets add a standalone miner to both - let wallet = this.getWallet(name); + // Now lets add a standalone miner to both + const wallet = this.getWallet(name) const miningNode = new MiningNodeProcess( name, node.getGrpcAddress(), wallet.getGrpcAddress() - ); - this.addMiningNode(name, miningNode); + ) + this.addMiningNode(name, miningNode) } -); +) Given( /I have a SHA3 miner (.*) connected to node (.*)/, { timeout: 40 * 1000 }, async function (name, basenode) { - //add the base_node - await create_node(name, this.nodes[basenode].peerAddress(), this); - let node = this.getNode(name); + // add the base_node + await this.createAndAddNode(name, this.nodes[basenode].peerAddress(), this) + const node = this.getNode(name) // Add the wallet connected to the above base node - await create_wallet(name, node.peerAddress(), this); + await this.createAndAddWallet(name, node.peerAddress(), this) - //Now lets add a standalone miner to both - let wallet = this.getWallet(name); + // Now lets add a standalone miner to both + const wallet = this.getWallet(name) const miningNode = new MiningNodeProcess( name, node.getGrpcAddress(), wallet.getGrpcAddress() - ); - this.addMiningNode(name, miningNode); + ) + this.addMiningNode(name, miningNode) } -); +) Given( /I have a SHA3 miner (.*) connected to all seed nodes/, { timeout: 40 * 1000 }, async function (name) { - //add the base_node - await create_node(name, this.seedAddresses(), this); - let node = this.getNode(name); + // add the base_node + await this.createAndAddNode(name, this.seedAddresses(), this) + const node = this.getNode(name) // Add the wallet connected to the above base node - await create_wallet(name, node.peerAddress(), this); + await this.createAndAddWallet(name, node.peerAddress(), this) - //Now lets add a standalone miner to both + // Now lets add a standalone miner to both - let wallet = this.getWallet(name); + const wallet = this.getWallet(name) const miningNode = new MiningNodeProcess( name, node.getGrpcAddress(), wallet.getGrpcAddress() - ); - this.addMiningNode(name, miningNode); + ) + this.addMiningNode(name, miningNode) } -); - -async function create_node(name, addresses, ctx) { - const node = ctx.createNode(name); - node.setPeerSeeds([addresses]); - await node.startNew(); - ctx.addNode(name, node); - await sleep(1000); -} +) Given( /I connect node (.*) to node (.*) and wait (.*) seconds/, { timeout: 1200 * 1000 }, async function (nodeNameA, nodeNameB, waitSeconds) { - expect(waitSeconds < 1190).to.equal(true); + expect(waitSeconds < 1190).to.equal(true) console.log( - "Connecting", + 'Connecting', nodeNameA, - "to", + 'to', nodeNameB, - ", waiting for", + ', waiting for', waitSeconds, - "seconds" - ); - nodeA = this.getNode(nodeNameA); - nodeB = this.getNode(nodeNameB); - nodeA.setPeerSeeds([nodeB.peerAddress()]); - await this.stopNode(nodeNameA); - await this.startNode(nodeNameA); - await sleep(waitSeconds * 1000); + 'seconds' + ) + const nodeA = this.getNode(nodeNameA) + const nodeB = this.getNode(nodeNameB) + nodeA.setPeerSeeds([nodeB.peerAddress()]) + await this.stopNode(nodeNameA) + await this.startNode(nodeNameA) } -); +) Given( /I have a pruned node (.*) connected to node (.*) with pruning horizon set to (.*)/, { timeout: 20 * 1000 }, async function (name, node, horizon) { - const miner = this.createNode(name, { horizon }); - miner.setPeerSeeds([this.nodes[node].peerAddress()]); - await miner.startNew(); - this.addNode(name, miner); - await sleep(1000); + const miner = this.createNode(name, { horizon }) + miner.setPeerSeeds([this.nodes[node].peerAddress()]) + await miner.startNew() + this.addNode(name, miner) + await sleep(1000) } -); +) Given( /I have a lagging delayed node (.*) connected to node (.*) with blocks_behind_before_considered_lagging (\d+)/, { timeout: 20 * 1000 }, async function (name, node, delay) { const miner = this.createNode(name, { - blocks_behind_before_considered_lagging: delay, - }); - miner.setPeerSeeds([this.nodes[node].peerAddress()]); - await miner.startNew(); - this.addNode(name, miner); - await sleep(1000); + blocks_behind_before_considered_lagging: delay + }) + miner.setPeerSeeds([this.nodes[node].peerAddress()]) + await miner.startNew() + this.addNode(name, miner) + await sleep(1000) } -); +) Given( /I have a base node (.*) unconnected/, { timeout: 20 * 1000 }, async function (name) { - const node = this.createNode(name); - await node.startNew(); - this.addNode(name, node); + const node = this.createNode(name) + await node.startNew() + this.addNode(name, node) } -); +) Given( - "I have {int} base nodes connected to all seed nodes", + 'I have {int} base nodes connected to all seed nodes', { timeout: 190 * 1000 }, async function (n) { - let promises = []; + const promises = [] for (let i = 0; i < n; i++) { - const miner = this.createNode(`BaseNode${i}`); - miner.setPeerSeeds([this.seedAddresses()]); + const miner = this.createNode(`BaseNode${i}`) + miner.setPeerSeeds([this.seedAddresses()]) promises.push( miner.startNew().then(() => this.addNode(`BaseNode${i}`, miner)) - ); + ) } - await Promise.all(promises); + await Promise.all(promises) } -); +) Given( /I have stress-test wallet (.*) connected to the seed node (.*) with broadcast monitoring timeout (.*)/, { timeout: 20 * 1000 }, async function (walletName, seedName, timeout) { - let wallet = new WalletProcess( + const wallet = new WalletProcess( walletName, { broadcastMonitoringTimeout: timeout }, this.logFilePathWallet - ); - wallet.setPeerSeeds([this.seeds[seedName].peerAddress()]); - await wallet.startNew(); - this.addWallet(walletName, wallet); + ) + wallet.setPeerSeeds([this.seeds[seedName].peerAddress()]) + await wallet.startNew() + this.addWallet(walletName, wallet) } -); +) Given( /I have stress-test wallet (.*) connected to all the seed nodes with broadcast monitoring timeout (.*)/, { timeout: 20 * 1000 }, async function (name, timeout) { - let wallet = new WalletProcess( + const wallet = new WalletProcess( name, { broadcastMonitoringTimeout: timeout }, this.logFilePathWallet - ); - wallet.setPeerSeeds([this.seedAddresses()]); - await wallet.startNew(); - this.addWallet(name, wallet); + ) + wallet.setPeerSeeds([this.seedAddresses()]) + await wallet.startNew() + this.addWallet(name, wallet) } -); +) Given( /I have wallet (.*) connected to seed node (.*)/, { timeout: 20 * 1000 }, async function (walletName, seedName) { - await create_wallet(walletName, this.seeds[seedName].peerAddress(), this); + await this.createAndAddWallet(walletName, this.seeds[seedName].peerAddress()) } -); +) Given( /I have wallet (.*) connected to base node (.*)/, { timeout: 20 * 1000 }, async function (walletName, nodeName) { - await create_wallet(walletName, this.nodes[nodeName].peerAddress(), this); + await this.createAndAddWallet(walletName, this.nodes[nodeName].peerAddress()) } -); +) Given( /I have wallet (.*) connected to all seed nodes/, { timeout: 20 * 1000 }, async function (name) { - await create_wallet(name, this.seedAddresses(), this); + await this.createAndAddWallet(name, this.seedAddresses()) } -); +) + -async function create_wallet(name, node_addresses, ctx) { - let wallet = new WalletProcess(name, {}, ctx.logFilePathWallet); - wallet.setPeerSeeds([node_addresses]); - await wallet.startNew(); - ctx.addWallet(name, wallet); -} Given( /I have non-default wallet (.*) connected to all seed nodes using (.*)/, { timeout: 20 * 1000 }, async function (name, mechanism) { // mechanism: DirectOnly, StoreAndForwardOnly, DirectAndStoreAndForward - let wallet = new WalletProcess( + const wallet = new WalletProcess( name, { routingMechanism: mechanism }, this.logFilePathWallet - ); - console.log(wallet.name, wallet.options); - wallet.setPeerSeeds([this.seedAddresses()]); - await wallet.startNew(); - this.addWallet(name, wallet); + ) + console.log(wallet.name, wallet.options) + wallet.setPeerSeeds([this.seedAddresses()]) + await wallet.startNew() + this.addWallet(name, wallet) } -); +) Given( /I have (.*) non-default wallets connected to all seed nodes using (.*)/, { timeout: 190 * 1000 }, async function (n, mechanism) { // mechanism: DirectOnly, StoreAndForwardOnly, DirectAndStoreAndForward - let promises = []; + const promises = [] for (let i = 0; i < n; i++) { if (i < 10) { const wallet = new WalletProcess( - "Wallet_0" + String(i), + 'Wallet_0' + String(i), { routingMechanism: mechanism }, this.logFilePathWallet - ); - console.log(wallet.name, wallet.options); - wallet.setPeerSeeds([this.seedAddresses()]); + ) + console.log(wallet.name, wallet.options) + wallet.setPeerSeeds([this.seedAddresses()]) promises.push( wallet .startNew() - .then(() => this.addWallet("Wallet_0" + String(i), wallet)) - ); + .then(() => this.addWallet('Wallet_0' + String(i), wallet)) + ) } else { const wallet = new WalletProcess( - "Wallet_0" + String(i), + 'Wallet_0' + String(i), { routingMechanism: mechanism }, this.logFilePathWallet - ); - console.log(wallet.name, wallet.options); - wallet.setPeerSeeds([this.seedAddresses()]); + ) + console.log(wallet.name, wallet.options) + wallet.setPeerSeeds([this.seedAddresses()]) promises.push( wallet .startNew() - .then(() => this.addWallet("Wallet_" + String(i), wallet)) - ); + .then(() => this.addWallet('Wallet_' + String(i), wallet)) + ) } } - await Promise.all(promises); + await Promise.all(promises) } -); +) Given( /I recover wallet (.*) into wallet (.*) connected to all seed nodes/, { timeout: 120 * 1000 }, async function (walletNameA, walletNameB) { - let seedWords = this.getWallet(walletNameA).getSeedWords(); + const seedWords = this.getWallet(walletNameA).getSeedWords() console.log( - "Recover " + + 'Recover ' + walletNameA + - " into " + + ' into ' + walletNameB + - ", seed words:\n " + + ', seed words:\n ' + seedWords - ); - let walletB = new WalletProcess( + ) + const walletB = new WalletProcess( walletNameB, {}, this.logFilePathWallet, seedWords - ); - walletB.setPeerSeeds([this.seedAddresses()]); - walletB.startNew(); // Do not 'await' here - this.addWallet(walletNameB, walletB); + ) + walletB.setPeerSeeds([this.seedAddresses()]) + walletB.startNew() // Do not 'await' here + this.addWallet(walletNameB, walletB) } -); +) Given( /I have a merge mining proxy (.*) connected to (.*) and (.*) with default config/, { timeout: 20 * 1000 }, async function (mmProxy, node, wallet) { - let baseNode = this.getNode(node); - let walletNode = this.getWallet(wallet); + const baseNode = this.getNode(node) + const walletNode = this.getWallet(wallet) const proxy = new MergeMiningProxyProcess( mmProxy, baseNode.getGrpcAddress(), walletNode.getGrpcAddress(), this.logFilePathProxy, true - ); - await proxy.startNew(); - this.addProxy(mmProxy, proxy); + ) + await proxy.startNew() + this.addProxy(mmProxy, proxy) } -); +) Given( /I have a merge mining proxy (.*) connected to (.*) and (.*) with origin submission disabled/, { timeout: 20 * 1000 }, async function (mmProxy, node, wallet) { - let baseNode = this.getNode(node); - let walletNode = this.getWallet(wallet); + const baseNode = this.getNode(node) + const walletNode = this.getWallet(wallet) const proxy = new MergeMiningProxyProcess( mmProxy, baseNode.getGrpcAddress(), walletNode.getGrpcAddress(), this.logFilePathProxy, false - ); - await proxy.startNew(); - this.addProxy(mmProxy, proxy); + ) + await proxy.startNew() + this.addProxy(mmProxy, proxy) } -); +) Given( /I have a merge mining proxy (.*) connected to (.*) and (.*) with origin submission enabled/, { timeout: 20 * 1000 }, async function (mmProxy, node, wallet) { - let baseNode = this.getNode(node); - let walletNode = this.getWallet(wallet); + const baseNode = this.getNode(node) + const walletNode = this.getWallet(wallet) const proxy = new MergeMiningProxyProcess( mmProxy, baseNode.getGrpcAddress(), walletNode.getGrpcAddress(), this.logFilePathProxy, true - ); - await proxy.startNew(); - this.addProxy(mmProxy, proxy); + ) + await proxy.startNew() + this.addProxy(mmProxy, proxy) } -); +) Given( /I have mining node (.*) connected to base node (.*) and wallet (.*)/, - function (miner, node, wallet) { - let baseNode = this.getNode(node); - let walletNode = this.getWallet(wallet); + async function (miner, node, wallet) { + const baseNode = this.getNode(node) + const walletNode = await this.getOrCreateWallet(wallet) const miningNode = new MiningNodeProcess( miner, baseNode.getGrpcAddress(), walletNode.getGrpcAddress(), true - ); - this.addMiningNode(miner, miningNode); + ) + this.addMiningNode(miner, miningNode) } -); +) Given( /I have mine-before-tip mining node (.*) connected to base node (.*) and wallet (.*)/, function (miner, node, wallet) { - let baseNode = this.getNode(node); - let walletNode = this.getWallet(wallet); + const baseNode = this.getNode(node) + const walletNode = this.getWallet(wallet) const miningNode = new MiningNodeProcess( miner, baseNode.getGrpcAddress(), walletNode.getGrpcAddress(), false - ); - this.addMiningNode(miner, miningNode); + ) + this.addMiningNode(miner, miningNode) } -); +) When(/I ask for a block height from proxy (.*)/, async function (mmProxy) { - lastResult = "NaN"; - let proxy = this.getProxy(mmProxy); - let proxyClient = proxy.createClient(); - let height = await proxyClient.getHeight(); - lastResult = height; -}); + lastResult = 'NaN' + const proxy = this.getProxy(mmProxy) + const proxyClient = proxy.createClient() + const height = await proxyClient.getHeight() + lastResult = height +}) -Then("Proxy response height is valid", function () { - assert(Number.isInteger(lastResult), true); -}); +Then('Proxy response height is valid', function () { + assert(Number.isInteger(lastResult), true) +}) When(/I ask for a block template from proxy (.*)/, async function (mmProxy) { - lastResult = {}; - let proxy = this.getProxy(mmProxy); - let proxyClient = proxy.createClient(); - let template = await proxyClient.getBlockTemplate(); - lastResult = template; -}); - -Then("Proxy response block template is valid", function () { - assert(typeof lastResult === "object" && lastResult !== null, true); - assert(typeof lastResult["_aux"] !== "undefined", true); - assert(lastResult["status"], "OK"); -}); + lastResult = {} + const proxy = this.getProxy(mmProxy) + const proxyClient = proxy.createClient() + const template = await proxyClient.getBlockTemplate() + lastResult = template +}) + +Then('Proxy response block template is valid', function () { + assert(typeof lastResult === 'object' && lastResult !== null, true) + assert(typeof lastResult._aux !== 'undefined', true) + assert(lastResult.status, 'OK') +}) When(/I submit a block through proxy (.*)/, async function (mmProxy) { - let blockTemplateBlob = lastResult["blocktemplate_blob"]; - let proxy = this.getProxy(mmProxy); - let proxyClient = proxy.createClient(); - let result = await proxyClient.submitBlock(blockTemplateBlob); - lastResult = result; -}); + const blockTemplateBlob = lastResult.blocktemplate_blob + const proxy = this.getProxy(mmProxy) + const proxyClient = proxy.createClient() + const result = await proxyClient.submitBlock(blockTemplateBlob) + lastResult = result +}) Then( - "Proxy response block submission is valid with submitting to origin", + 'Proxy response block submission is valid with submitting to origin', function () { assert( - typeof lastResult["result"] === "object" && lastResult["result"] !== null, + typeof lastResult.result === 'object' && lastResult.result !== null, true - ); - assert(typeof lastResult["result"]["_aux"] !== "undefined", true); - assert(lastResult["result"]["status"], "OK"); + ) + assert(typeof lastResult.result._aux !== 'undefined', true) + assert(lastResult.result.status, 'OK') } -); +) Then( - "Proxy response block submission is valid without submitting to origin", + 'Proxy response block submission is valid without submitting to origin', function () { - assert(lastResult["result"] !== null, true); - assert(lastResult["status"], "OK"); + assert(lastResult.result !== null, true) + assert(lastResult.status, 'OK') } -); +) When( /I ask for the last block header from proxy (.*)/, async function (mmProxy) { - let proxy = this.getProxy(mmProxy); - let proxyClient = proxy.createClient(); - let result = await proxyClient.getLastBlockHeader(); - lastResult = result; + const proxy = this.getProxy(mmProxy) + const proxyClient = proxy.createClient() + const result = await proxyClient.getLastBlockHeader() + lastResult = result } -); +) -Then("Proxy response for last block header is valid", function () { - assert(typeof lastResult === "object" && lastResult !== null, true); - assert(typeof lastResult["result"]["_aux"] !== "undefined", true); - assert(lastResult["result"]["status"], "OK"); - lastResult = lastResult["result"]["block_header"]["hash"]; -}); +Then('Proxy response for last block header is valid', function () { + assert(typeof lastResult === 'object' && lastResult !== null, true) + assert(typeof lastResult.result._aux !== 'undefined', true) + assert(lastResult.result.status, 'OK') + lastResult = lastResult.result.block_header.hash +}) When( /I ask for a block header by hash using last block header from proxy (.*)/, async function (mmProxy) { - let proxy = this.getProxy(mmProxy); - let proxyClient = proxy.createClient(); - let result = await proxyClient.getBlockHeaderByHash(lastResult); - lastResult = result; + const proxy = this.getProxy(mmProxy) + const proxyClient = proxy.createClient() + const result = await proxyClient.getBlockHeaderByHash(lastResult) + lastResult = result } -); +) -Then("Proxy response for block header by hash is valid", function () { - assert(typeof lastResult === "object" && lastResult !== null, true); - assert(lastResult["result"]["status"], "OK"); -}); +Then('Proxy response for block header by hash is valid', function () { + assert(typeof lastResult === 'object' && lastResult !== null, true) + assert(lastResult.result.status, 'OK') +}) When(/I start (.*)/, { timeout: 20 * 1000 }, async function (name) { - await this.startNode(name); -}); + await this.startNode(name) +}) When(/I stop (.*)/, async function (name) { - await this.stopNode(name); -}); + await this.stopNode(name) +}) Then( /node (.*) is at height (\d+)/, { timeout: 120 * 1000 }, async function (name, height) { - let client = this.getClient(name); - await waitFor(async () => client.getTipHeight(), height, 115 * 1000); - expect(await client.getTipHeight()).to.equal(height); + const client = this.getClient(name) + await waitFor(async () => client.getTipHeight(), height, 115 * 1000) + expect(await client.getTipHeight()).to.equal(height) } -); +) Then( /node (.*) is at the same height as node (.*)/, { timeout: 120 * 1000 }, async function (nodeA, nodeB) { - expectedHeight = parseInt(await this.getClient(nodeB).getTipHeight()); + expectedHeight = parseInt(await this.getClient(nodeB).getTipHeight()) await waitFor( async () => this.getClient(nodeA).getTipHeight(), expectedHeight, 115 * 1000 - ); - currentHeight = await this.getClient(nodeA).getTipHeight(); + ) + currentHeight = await this.getClient(nodeA).getTipHeight() console.log( `Node ${nodeA} is at tip: ${currentHeight} (should be`, expectedHeight, - `)` - ); - expect(currentHeight).to.equal(expectedHeight); + ')' + ) + expect(currentHeight).to.equal(expectedHeight) } -); +) Then( - "all nodes are on the same chain at height {int}", + 'all nodes are on the same chain at height {int}', { timeout: 1200 * 1000 }, async function (height) { - let tipHash = null; + let tipHash = null await this.forEachClientAsync(async (client, name) => { - await waitFor(async () => client.getTipHeight(), height, 115 * 1000); - const currTip = await client.getTipHeader(); - expect(currTip.height).to.equal(height); + await waitFor(async () => client.getTipHeight(), height, 115 * 1000) + const currTip = await client.getTipHeader() + expect(currTip.height).to.equal(height) if (!tipHash) { - tipHash = currTip.hash.toString("hex"); - console.log(`Node ${name} is at tip: ${tipHash}`); + tipHash = currTip.hash.toString('hex') + console.log(`Node ${name} is at tip: ${tipHash}`) } else { - let currTipHash = currTip.hash.toString("hex"); + const currTipHash = currTip.hash.toString('hex') console.log( `Node ${name} is at tip: ${currTipHash} (should be ${tipHash})` - ); - expect(currTipHash).to.equal(tipHash); + ) + expect(currTipHash).to.equal(tipHash) } - }); + }) } -); +) Then( - "all nodes are at height {int}", + 'all nodes are at height {int}', { timeout: 1200 * 1000 }, async function (height) { await this.forEachClientAsync(async (client, name) => { - await waitFor(async () => client.getTipHeight(), height, 115 * 1000); - const currTip = await client.getTipHeight(); - console.log(`Node ${name} is at tip: ${currTip} (should be ${height})`); - expect(currTip).to.equal(height); - }); + await waitFor(async () => client.getTipHeight(), height, 115 * 1000) + const currTip = await client.getTipHeight() + console.log(`Node ${name} is at tip: ${currTip} (should be ${height})`) + expect(currTip).to.equal(height) + }) } -); +) Then( - "all nodes are at current tip height", + 'all nodes are at current tip height', { timeout: 1200 * 1000 }, async function () { - let height = parseInt(this.tipHeight); - console.log("Wait for all nodes to reach height of", height); + const height = parseInt(this.tipHeight) + console.log('Wait for all nodes to reach height of', height) await this.forEachClientAsync(async (client, name) => { - await waitFor(async () => client.getTipHeight(), height, 1200 * 1000); - const currTip = await client.getTipHeight(); - console.log(`Node ${name} is at tip: ${currTip} (expected ${height})`); - expect(currTip).to.equal(height); - }); + await waitFor(async () => client.getTipHeight(), height, 1200 * 1000) + const currTip = await client.getTipHeight() + console.log(`Node ${name} is at tip: ${currTip} (expected ${height})`) + expect(currTip).to.equal(height) + }) } -); +) Then( /all nodes are at the same height as node (.*)/, { timeout: 1200 * 1000 }, async function (nodeB) { - expectedHeight = parseInt(await this.getClient(nodeB).getTipHeight()); - console.log("Wait for all nodes to reach height of", expectedHeight); + expectedHeight = parseInt(await this.getClient(nodeB).getTipHeight()) + console.log('Wait for all nodes to reach height of', expectedHeight) await this.forEachClientAsync(async (client, name) => { await waitFor( async () => client.getTipHeight(), expectedHeight, 1200 * 1000 - ); - const currTip = await client.getTipHeight(); + ) + const currTip = await client.getTipHeight() console.log( `Node ${name} is at tip: ${currTip} (should be`, expectedHeight, - `)` - ); - expect(currTip).to.equal(expectedHeight); - }); + ')' + ) + expect(currTip).to.equal(expectedHeight) + }) } -); +) Then( /meddling with block template data from node (.*) for wallet (.*) is not allowed/, async function (baseNodeName, walletName) { - let baseNodeClient = this.getClient(baseNodeName); - let walletClient = this.getWallet(walletName).getClient(); + const baseNodeClient = this.getClient(baseNodeName) + const walletClient = this.getWallet(walletName).getClient() // No meddling with data // - Current tip - let currHeight = await baseNodeClient.getTipHeight(); + const currHeight = await baseNodeClient.getTipHeight() // - New block - let newBlock = await baseNodeClient.mineBlockBeforeSubmit(walletClient, 0); + let newBlock = await baseNodeClient.mineBlockBeforeSubmit(walletClient, 0) // console.log("\nNew block:\n"); // console.dir(newBlock, { depth: null }); // - Submit block to base node - let response = await baseNodeClient.submitMinedBlock(newBlock); + let response = await baseNodeClient.submitMinedBlock(newBlock) // - Verify new height - expect(await baseNodeClient.getTipHeight()).to.equal(currHeight + 1); + expect(await baseNodeClient.getTipHeight()).to.equal(currHeight + 1) // Meddle with data - kernel_mmr_size // - New block - newBlock = await baseNodeClient.mineBlockBeforeSubmit(walletClient, 0); + newBlock = await baseNodeClient.mineBlockBeforeSubmit(walletClient, 0) // - Change kernel_mmr_size newBlock.block.header.kernel_mmr_size = - parseInt(newBlock.block.header.kernel_mmr_size) + 1; + parseInt(newBlock.block.header.kernel_mmr_size) + 1 // - Try to submit illegal block to base node try { - response = await baseNodeClient.submitMinedBlock(newBlock); - expect("Meddling with MMR size for Kernel not detected!").to.equal(""); + response = await baseNodeClient.submitMinedBlock(newBlock) + expect('Meddling with MMR size for Kernel not detected!').to.equal('') } catch (err) { console.log( - "\nMeddle with kernel_mmr_size - error details (as expected):\n", + '\nMeddle with kernel_mmr_size - error details (as expected):\n', err.details - ); + ) expect( err.details.includes( - "Block validation error: MMR size for Kernel does not match." + 'Block validation error: MMR size for Kernel does not match.' ) - ).to.equal(true); + ).to.equal(true) } // Meddle with data - output_mmr_size // - New block - newBlock = await baseNodeClient.mineBlockBeforeSubmit(walletClient, 0); + newBlock = await baseNodeClient.mineBlockBeforeSubmit(walletClient, 0) // - Change output_mmr_size newBlock.block.header.output_mmr_size = - parseInt(newBlock.block.header.output_mmr_size) + 1; + parseInt(newBlock.block.header.output_mmr_size) + 1 // - Try to submit illegal block to base node try { - response = await baseNodeClient.submitMinedBlock(newBlock); - expect("Meddling with MMR size for UTXO not detected!").to.equal(""); + response = await baseNodeClient.submitMinedBlock(newBlock) + expect('Meddling with MMR size for UTXO not detected!').to.equal('') } catch (err) { console.log( - "Meddle with output_mmr_size - error details (as expected):\n", + 'Meddle with output_mmr_size - error details (as expected):\n', err.details - ); + ) expect( err.details.includes( - "Block validation error: MMR size for UTXO does not match." + 'Block validation error: MMR size for UTXO does not match.' ) - ).to.equal(true); + ).to.equal(true) } } -); +) When( /I create a transaction (.*) spending (.*) to (.*)/, function (txnName, inputs, output) { - let txInputs = inputs.split(",").map((input) => this.outputs[input]); - let txn = new TransactionBuilder(); - txInputs.forEach((txIn) => txn.addInput(txIn)); - let txOutput = txn.addOutput(txn.getSpendableAmount()); - this.addOutput(output, txOutput); - this.transactions[txnName] = txn.build(); + const txInputs = inputs.split(',').map((input) => this.outputs[input]) + const txn = new TransactionBuilder() + txInputs.forEach((txIn) => txn.addInput(txIn)) + const txOutput = txn.addOutput(txn.getSpendableAmount()) + this.addOutput(output, txOutput) + this.transactions[txnName] = txn.build() } -); +) When( /I create a custom fee transaction (.*) spending (.*) to (.*) with fee (\d+)/, function (txnName, inputs, output, fee) { - let txInputs = inputs.split(",").map((input) => this.outputs[input]); - let txn = new TransactionBuilder(); - txn.changeFee(fee); - txInputs.forEach((txIn) => txn.addInput(txIn)); - let txOutput = txn.addOutput(txn.getSpendableAmount()); - this.addOutput(output, txOutput); - this.transactions[txnName] = txn.build(); + const txInputs = inputs.split(',').map((input) => this.outputs[input]) + const txn = new TransactionBuilder() + txn.changeFee(fee) + txInputs.forEach((txIn) => txn.addInput(txIn)) + const txOutput = txn.addOutput(txn.getSpendableAmount()) + this.addOutput(output, txOutput) + this.transactions[txnName] = txn.build() } -); +) When(/I submit transaction (.*) to (.*)/, async function (txn, node) { this.lastResult = await this.getClient(node).submitTransaction( this.transactions[txn] - ); - expect(this.lastResult.result).to.equal("ACCEPTED"); -}); + ) + expect(this.lastResult.result).to.equal('ACCEPTED') +}) When(/I submit locked transaction (.*) to (.*)/, async function (txn, node) { this.lastResult = await this.getClient(node).submitTransaction( this.transactions[txn] - ); - expect(this.lastResult.result).to.equal("REJECTED"); -}); + ) + expect(this.lastResult.result).to.equal('REJECTED') +}) When(/I spend outputs (.*) via (.*)/, async function (inputs, node) { - let txInputs = inputs.split(",").map((input) => this.outputs[input]); - console.log(txInputs); - let txn = new TransactionBuilder(); - txInputs.forEach((txIn) => txn.addInput(txIn)); - console.log(txn.getSpendableAmount()); - let output = txn.addOutput(txn.getSpendableAmount()); - console.log(output); - this.lastResult = await this.getClient(node).submitTransaction(txn.build()); - expect(this.lastResult.result).to.equal("ACCEPTED"); -}); + const txInputs = inputs.split(',').map((input) => this.outputs[input]) + console.log(txInputs) + const txn = new TransactionBuilder() + txInputs.forEach((txIn) => txn.addInput(txIn)) + console.log(txn.getSpendableAmount()) + const output = txn.addOutput(txn.getSpendableAmount()) + console.log(output) + this.lastResult = await this.getClient(node).submitTransaction(txn.build()) + expect(this.lastResult.result).to.equal('ACCEPTED') +}) Then(/(.*) has (.*) in (.*) state/, async function (node, txn, pool) { - let client = this.getClient(node); - let sig = this.transactions[txn].body.kernels[0].excess_sig; + const client = this.getClient(node) + const sig = this.transactions[txn].body.kernels[0].excess_sig await waitFor( async () => client.transactionStateResult(sig), pool, 1200 * 1000 - ); + ) this.lastResult = await this.getClient(node).transactionState( this.transactions[txn].body.kernels[0].excess_sig - ); - console.log(`Node ${node} response is: ${this.lastResult.result}`); - expect(this.lastResult.result).to.equal(pool); -}); + ) + console.log(`Node ${node} response is: ${this.lastResult.result}`) + expect(this.lastResult.result).to.equal(pool) +}) Then( /(.*) is in the (.*) of all nodes/, { timeout: 1200 * 1000 }, async function (txn, pool) { - let sig = this.transactions[txn].body.kernels[0].excess_sig; + const sig = this.transactions[txn].body.kernels[0].excess_sig await this.forEachClientAsync(async (client, name) => { await waitFor( async () => client.transactionStateResult(sig), pool, 1200 * 1000 - ); - this.lastResult = await client.transactionState(sig); - console.log(`Node ${name} response is: ${this.lastResult.result}`); - expect(this.lastResult.result).to.equal(pool); - }); + ) + this.lastResult = await client.transactionState(sig) + console.log(`Node ${name} response is: ${this.lastResult.result}`) + expect(this.lastResult.result).to.equal(pool) + }) } -); +) Then(/(.*) is in the mempool/, function (txn) { - expect(this.lastResult.result).to.equal("ACCEPTED"); -}); + expect(this.lastResult.result).to.equal('ACCEPTED') +}) Then(/(.*) should not be in the mempool/, function (txn) { - expect(this.lastResult.result).to.equal("REJECTED"); -}); + expect(this.lastResult.result).to.equal('REJECTED') +}) When(/I save the tip on (.*) as (.*)/, async function (node, name) { - let client = this.getClient(node); - let header = await client.getTipHeader(); - this.headers[name] = header; -}); + const client = this.getClient(node) + const header = await client.getTipHeader() + this.headers[name] = header +}) Then(/node (.*) is at tip (.*)/, async function (node, name) { - let client = this.getClient(node); - let header = await client.getTipHeader(); + const client = this.getClient(node) + const header = await client.getTipHeader() // console.log("headers:", this.headers); - const existingHeader = this.headers[name]; - expect(existingHeader).to.not.be.null; - expect(existingHeader.hash.toString("hex")).to.equal( - header.hash.toString("hex") - ); -}); + const existingHeader = this.headers[name] + expect(existingHeader).to.not.be.null + expect(existingHeader.hash.toString('hex')).to.equal( + header.hash.toString('hex') + ) +}) When( /I mine a block on (.*) with coinbase (.*)/, { timeout: 600 * 1000 }, async function (name, coinbaseName) { await this.mineBlock(name, 0, (candidate) => { - this.addOutput(coinbaseName, candidate.originalTemplate.coinbase); - return candidate; - }); - this.tipHeight += 1; + this.addOutput(coinbaseName, candidate.originalTemplate.coinbase) + return candidate + }) + this.tipHeight += 1 } -); +) When( /I mine (\d+) custom weight blocks on (.*) with weight (\d+)/, @@ -818,72 +824,72 @@ When( async function (numBlocks, name, weight) { for (let i = 0; i < numBlocks; i++) { // If a block cannot be mined quickly enough (or the process has frozen), timeout. - await withTimeout(60 * 1000, this.mineBlock(name, parseInt(weight))); + await withTimeout(60 * 1000, this.mineBlock(name, parseInt(weight))) } - this.tipHeight += parseInt(numBlocks); + this.tipHeight += parseInt(numBlocks) } -); +) When( - /mining node (.*) mines (\d+) blocks/, + /mining node (.*) mines (\d+) blocks with min difficulty (\d+) and max difficulty (\d+)/, { timeout: 600 * 1000 }, - async function (miner, numBlocks) { - let miningNode = this.getMiningNode(miner); - await miningNode.init(numBlocks, 1, 100000); - await miningNode.startNew(); + async function (miner, numBlocks, min, max) { + const miningNode = this.getMiningNode(miner) + await miningNode.init(numBlocks, min, max, miningNode.mineOnTipOnly) + await miningNode.startNew() } -); +) When( - /mining node (.*) mines (\d+) blocks with min difficulty (\d+) and max difficulty (\d+)/, + /mining node (.*) mines (\d+) blocks$/, { timeout: 600 * 1000 }, - async function (miner, numBlocks, min, max) { - let miningNode = this.getMiningNode(miner); - await miningNode.init(numBlocks, min, max, miningNode.mineOnTipOnly); - await miningNode.startNew(); + async function (miner, numBlocks) { + const miningNode = this.getMiningNode(miner) + await miningNode.init(numBlocks, 1, 100000) + await miningNode.startNew() } -); +) When( /I update the parent of block (.*) to be an orphan/, async function (block) { - //TODO + // TODO } -); +) When( /I mine (\d+) blocks on (.*)/, { timeout: -1 }, async function (numBlocks, name) { for (let i = 0; i < numBlocks; i++) { - await withTimeout(60 * 1000, this.mineBlock(name, 0)); + await withTimeout(60 * 1000, this.mineBlock(name, 0)) } - this.tipHeight += parseInt(numBlocks); + this.tipHeight += parseInt(numBlocks) } -); +) When( /I mine (\d+) blocks using wallet (.*) on (.*)/, { timeout: 600 * 1000 }, async function (numBlocks, walletName, nodeName) { - let nodeClient = this.getClient(nodeName); - let walletClient = this.getWallet(walletName).getClient(); + const nodeClient = this.getClient(nodeName) + const walletClient = this.getWallet(walletName).getClient() for (let i = 0; i < numBlocks; i++) { - await nodeClient.mineBlock(walletClient); + await nodeClient.mineBlock(walletClient) } } -); +) When( /I merge mine (.*) blocks via (.*)/, { timeout: 600 * 1000 }, async function (numBlocks, mmProxy) { for (let i = 0; i < numBlocks; i++) { - await this.mergeMineBlock(mmProxy, 0); + await this.mergeMineBlock(mmProxy, 0) } - this.tipHeight += parseInt(numBlocks); + this.tipHeight += parseInt(numBlocks) } -); +) When( /I mine but don't submit a block (.*) on (.*)/, @@ -892,455 +898,455 @@ When( nodeName, null, (block) => { - this.saveBlock(blockName, block); - return false; + this.saveBlock(blockName, block) + return false }, 0 - ); + ) } -); +) When(/I submit block (.*) to (.*)/, async function (blockName, nodeName) { - await this.submitBlock(blockName, nodeName); -}); + await this.submitBlock(blockName, nodeName) +}) When( /I mine a block on (.*) based on height (\d+)/, async function (node, atHeight) { - let client = this.getClient(node); - let template = client.getPreviousBlockTemplate(atHeight); - let candidate = await client.getMinedCandidateBlock(0, template); + const client = this.getClient(node) + const template = client.getPreviousBlockTemplate(atHeight) + const candidate = await client.getMinedCandidateBlock(0, template) await client.submitBlock( candidate.template, (block) => { - return block; + return block }, (error) => { // Expect an error - console.log(error); - return false; + console.log(error) + return false } - ); + ) } -); +) When( /I mine a block on (.*) at height (\d+) with an invalid MMR/, async function (node, atHeight) { - let client = this.getClient(node); - let template = client.getPreviousBlockTemplate(atHeight); - let candidate = await client.getMinedCandidateBlock(0, template); + const client = this.getClient(node) + const template = client.getPreviousBlockTemplate(atHeight) + const candidate = await client.getMinedCandidateBlock(0, template) await client .submitBlock(candidate.template, (block) => { // console.log("Candidate:", block); - block.block.header.output_mr[0] = 1; + block.block.header.output_mr[0] = 1 // block.block.header.height = atHeight + 1; // block.block.header.prev_hash = candidate.header.hash; - return block; + return block }) .catch((err) => { - console.log("Received expected error. This is fine actually:", err); - }); + console.log('Received expected error. This is fine actually:', err) + }) } -); +) Then( /the UTXO (.*) has been mined according to (.*)/, async function (outputName, nodeName) { - let client = this.getClient(nodeName); - let hash = getTransactionOutputHash(this.outputs[outputName].output); - let lastResult = await client.fetchMatchingUtxos([hash]); - expect(lastResult[0].output.commitment.toString("hex")).to.equal( - this.outputs[outputName].output.commitment.toString("hex") - ); + const client = this.getClient(nodeName) + const hash = getTransactionOutputHash(this.outputs[outputName].output) + const lastResult = await client.fetchMatchingUtxos([hash]) + expect(lastResult[0].output.commitment.toString('hex')).to.equal( + this.outputs[outputName].output.commitment.toString('hex') + ) } -); +) -Then("I receive an error containing {string}", function (string) { +Then('I receive an error containing {string}', function (string) { // TODO -}); +}) Then(/(.*) should have (\d+) peers/, async function (nodeName, peerCount) { - await sleep(500); - let client = this.getClient(nodeName); - let peers = await client.getPeers(); + await sleep(500) + const client = this.getClient(nodeName) + const peers = await client.getPeers() // we add a non existing node when the node starts before adding any actual peers. So the count should always be 1 higher - expect(peers.length).to.equal(peerCount + 1); -}); + expect(peers.length).to.equal(peerCount + 1) +}) -When("I print the world", function () { - console.log(this); -}); +When('I print the world', function () { + console.log(this) +}) When( /I wait for wallet (.*) to have at least (.*) uT/, { timeout: 250 * 1000 }, async function (wallet, amount) { - let walletClient = this.getWallet(wallet).getClient(); - console.log("\n"); + const walletClient = this.getWallet(wallet).getClient() + console.log('\n') console.log( - "Waiting for " + wallet + " balance to be at least " + amount + " uT" - ); - let balance = await walletClient.getBalance(); - consoleLogBalance(balance); - if (parseInt(balance["available_balance"]) < parseInt(amount)) { + 'Waiting for ' + wallet + ' balance to be at least ' + amount + ' uT' + ) + const balance = await walletClient.getBalance() + consoleLogBalance(balance) + if (parseInt(balance.available_balance) < parseInt(amount)) { await waitFor( async () => walletClient.isBalanceAtLeast(amount), true, 240 * 1000, 5 * 1000, 5 - ); + ) if (!walletClient.isBalanceAtLeast(amount)) { - console.log("Balance not adequate!"); + console.log('Balance not adequate!') } - consoleLogBalance(await walletClient.getBalance()); + consoleLogBalance(await walletClient.getBalance()) } } -); +) Then( /wallet (.*) and wallet (.*) have the same balance/, { timeout: 60 * 1000 }, async function (walletNameA, walletNameB) { - let walletClientA = this.getWallet(walletNameA).getClient(); - let balanceA = await walletClientA.getBalance(); - console.log("\n"); - console.log(walletNameA, "balance:"); - consoleLogBalance(balanceA); - let walletClientB = this.getWallet(walletNameB).getClient(); + const walletClientA = this.getWallet(walletNameA).getClient() + const balanceA = await walletClientA.getBalance() + console.log('\n') + console.log(walletNameA, 'balance:') + consoleLogBalance(balanceA) + const walletClientB = this.getWallet(walletNameB).getClient() await waitFor( - async () => walletClientB.isBalanceAtLeast(balanceA["available_balance"]), + async () => walletClientB.isBalanceAtLeast(balanceA.available_balance), true, 55 * 1000, 5 * 1000, 5 - ); - let balanceB = await walletClientB.getBalance(); - console.log(walletNameB, "balance:"); - consoleLogBalance(balanceB); - expect(balanceA["available_balance"]).to.equal( - balanceB["available_balance"] - ); - } -); - -async function send_tari(sourceWallet, destWallet, tariAmount, feePerGram) { - let sourceWalletClient = sourceWallet.getClient(); - let destInfo = await destWallet.getClient().identify(); + ) + const balanceB = await walletClientB.getBalance() + console.log(walletNameB, 'balance:') + consoleLogBalance(balanceB) + expect(balanceA.available_balance).to.equal( + balanceB.available_balance + ) + } +) + +async function send_tari (sourceWallet, destWallet, tariAmount, feePerGram) { + const sourceWalletClient = sourceWallet.getClient() + const destInfo = await destWallet.getClient().identify() console.log( sourceWallet.name + - " sending " + + ' sending ' + tariAmount + - "uT to " + + 'uT to ' + destWallet.name + - " `" + - destInfo["public_key"] + - "`" - ); - let success = false; - let retries = 1; - let retries_limit = 25; - let lastResult; + ' `' + + destInfo.public_key + + '`' + ) + let success = false + let retries = 1 + const retries_limit = 25 + let lastResult while (!success && retries <= retries_limit) { lastResult = await sourceWalletClient.transfer({ recipients: [ { - address: destInfo["public_key"], + address: destInfo.public_key, amount: tariAmount, fee_per_gram: feePerGram, - message: "msg", - }, - ], - }); - success = lastResult.results[0]["is_success"]; + message: 'msg' + } + ] + }) + success = lastResult.results[0].is_success if (!success) { - let wait_seconds = 5; + const wait_seconds = 5 console.log( - " " + - lastResult.results[0]["failure_message"] + - ", trying again after " + + ' ' + + lastResult.results[0].failure_message + + ', trying again after ' + wait_seconds + - "s (" + + 's (' + retries + - " of " + + ' of ' + retries_limit + - ")" - ); - await sleep(wait_seconds * 1000); - retries++; + ')' + ) + await sleep(wait_seconds * 1000) + retries++ } } - return lastResult; + return lastResult } When( /I send (.*) uT from wallet (.*) to wallet (.*) at fee (.*)/, { timeout: 25 * 5 * 1000 }, async function (tariAmount, source, dest, feePerGram) { - let sourceInfo = await this.getWallet(source).getClient().identify(); - let destInfo = await this.getWallet(dest).getClient().identify(); + const sourceInfo = await this.getWallet(source).getClient().identify() + const destInfo = await this.getWallet(dest).getClient().identify() this.lastResult = await send_tari( this.getWallet(source), this.getWallet(dest), tariAmount, feePerGram - ); - expect(this.lastResult.results[0]["is_success"]).to.equal(true); + ) + expect(this.lastResult.results[0].is_success).to.equal(true) this.addTransaction( - sourceInfo["public_key"], - this.lastResult.results[0]["transaction_id"] - ); + sourceInfo.public_key, + this.lastResult.results[0].transaction_id + ) this.addTransaction( - destInfo["public_key"], - this.lastResult.results[0]["transaction_id"] - ); + destInfo.public_key, + this.lastResult.results[0].transaction_id + ) console.log( " Transaction '" + - this.lastResult.results[0]["transaction_id"] + + this.lastResult.results[0].transaction_id + "' is_success(" + - this.lastResult.results[0]["is_success"] + - ")" - ); + this.lastResult.results[0].is_success + + ')' + ) } -); +) When( /I multi-send (.*) transactions of (.*) uT from wallet (.*) to wallet (.*) at fee (.*)/, { timeout: 25 * 5 * 1000 }, async function (number, tariAmount, source, dest, fee) { - console.log("\n"); - let sourceInfo = await this.getWallet(source).getClient().identify(); - let destInfo = await this.getWallet(dest).getClient().identify(); + console.log('\n') + const sourceInfo = await this.getWallet(source).getClient().identify() + const destInfo = await this.getWallet(dest).getClient().identify() for (let i = 0; i < number; i++) { this.lastResult = await send_tari( this.getWallet(source), this.getWallet(dest), tariAmount, fee - ); - expect(this.lastResult.results[0]["is_success"]).to.equal(true); + ) + expect(this.lastResult.results[0].is_success).to.equal(true) this.addTransaction( - sourceInfo["public_key"], - this.lastResult.results[0]["transaction_id"] - ); + sourceInfo.public_key, + this.lastResult.results[0].transaction_id + ) this.addTransaction( - destInfo["public_key"], - this.lastResult.results[0]["transaction_id"] - ); - //console.log(" Transaction '" + this.lastResult.results[0]["transaction_id"] + "' is_success(" + + destInfo.public_key, + this.lastResult.results[0].transaction_id + ) + // console.log(" Transaction '" + this.lastResult.results[0]["transaction_id"] + "' is_success(" + // this.lastResult.results[0]["is_success"] + ")"); } } -); +) When( /I multi-send (.*) uT from wallet (.*) to all wallets at fee (.*)/, { timeout: 25 * 5 * 1000 }, async function (tariAmount, source, fee) { - let sourceWalletClient = this.getWallet(source).getClient(); - let sourceInfo = await sourceWalletClient.identify(); + const sourceWalletClient = this.getWallet(source).getClient() + const sourceInfo = await sourceWalletClient.identify() for (const wallet in this.wallets) { if (this.getWallet(source).name === this.getWallet(wallet).name) { - continue; + continue } - let destInfo = await this.getWallet(wallet).getClient().identify(); + const destInfo = await this.getWallet(wallet).getClient().identify() this.lastResult = await send_tari( this.getWallet(source), this.getWallet(wallet), tariAmount, fee - ); - expect(this.lastResult.results[0]["is_success"]).to.equal(true); + ) + expect(this.lastResult.results[0].is_success).to.equal(true) this.addTransaction( - sourceInfo["public_key"], - this.lastResult.results[0]["transaction_id"] - ); + sourceInfo.public_key, + this.lastResult.results[0].transaction_id + ) this.addTransaction( - destInfo["public_key"], - this.lastResult.results[0]["transaction_id"] - ); - //console.log(" Transaction '" + this.lastResult.results[0]["transaction_id"] + "' is_success(" + + destInfo.public_key, + this.lastResult.results[0].transaction_id + ) + // console.log(" Transaction '" + this.lastResult.results[0]["transaction_id"] + "' is_success(" + // this.lastResult.results[0]["is_success"] + ")"); } } -); +) When( /I transfer (.*) uT from (.*) to (.*) and (.*) at fee (.*)/, { timeout: 25 * 5 * 1000 }, async function (tariAmount, source, dest1, dest2, feePerGram) { - let sourceClient = this.getWallet(source).getClient(); - let destClient1 = this.getWallet(dest1).getClient(); - let destClient2 = this.getWallet(dest2).getClient(); + const sourceClient = this.getWallet(source).getClient() + const destClient1 = this.getWallet(dest1).getClient() + const destClient2 = this.getWallet(dest2).getClient() - let sourceInfo = await sourceClient.identify(); - let dest1Info = await destClient1.identify(); - let dest2Info = await destClient2.identify(); + const sourceInfo = await sourceClient.identify() + const dest1Info = await destClient1.identify() + const dest2Info = await destClient2.identify() console.log( - "Starting transfer of", + 'Starting transfer of', tariAmount, - "to", + 'to', dest1, - "and to", + 'and to', dest2 - ); - let success = false; - let retries = 1; - let retries_limit = 25; + ) + let success = false + let retries = 1 + const retries_limit = 25 while (!success && retries <= retries_limit) { lastResult = await sourceClient.transfer({ recipients: [ { - address: dest1Info["public_key"], + address: dest1Info.public_key, amount: tariAmount, fee_per_gram: feePerGram, - message: "msg", + message: 'msg' }, { - address: dest2Info["public_key"], + address: dest2Info.public_key, amount: tariAmount, fee_per_gram: feePerGram, - message: "msg", - }, - ], - }); + message: 'msg' + } + ] + }) success = - lastResult.results[0]["is_success"] && - lastResult.results[1]["is_success"]; + lastResult.results[0].is_success && + lastResult.results[1].is_success if (!success) { - let wait_seconds = 5; + const wait_seconds = 5 console.log( - " " + - lastResult.results[0]["failure_message"] + - ", trying again after " + + ' ' + + lastResult.results[0].failure_message + + ', trying again after ' + wait_seconds + - "s (" + + 's (' + retries + - " of " + + ' of ' + retries_limit + - ")" - ); - await sleep(wait_seconds * 1000); - retries++; + ')' + ) + await sleep(wait_seconds * 1000) + retries++ } } if (success) { this.addTransaction( - sourceInfo["public_key"], - lastResult.results[0]["transaction_id"] - ); + sourceInfo.public_key, + lastResult.results[0].transaction_id + ) this.addTransaction( - sourceInfo["public_key"], - lastResult.results[1]["transaction_id"] - ); + sourceInfo.public_key, + lastResult.results[1].transaction_id + ) this.addTransaction( - dest1Info["public_key"], - lastResult.results[0]["transaction_id"] - ); + dest1Info.public_key, + lastResult.results[0].transaction_id + ) this.addTransaction( - dest2Info["public_key"], - lastResult.results[1]["transaction_id"] - ); + dest2Info.public_key, + lastResult.results[1].transaction_id + ) } - expect(success).to.equal(true); + expect(success).to.equal(true) } -); +) When( /I transfer (.*) uT to self from wallet (.*) at fee (.*)/, { timeout: 25 * 5 * 1000 }, async function (tariAmount, source, feePerGram) { - let sourceInfo = await this.getWallet(source).getClient().identify(); + const sourceInfo = await this.getWallet(source).getClient().identify() this.lastResult = await send_tari( this.getWallet(source), this.getWallet(source), tariAmount, feePerGram - ); - expect(this.lastResult.results[0]["is_success"]).to.equal(true); + ) + expect(this.lastResult.results[0].is_success).to.equal(true) this.addTransaction( - sourceInfo["public_key"], - this.lastResult.results[0]["transaction_id"] - ); + sourceInfo.public_key, + this.lastResult.results[0].transaction_id + ) console.log( " Transaction '" + - this.lastResult.results[0]["transaction_id"] + + this.lastResult.results[0].transaction_id + "' is_success(" + - this.lastResult.results[0]["is_success"] + - ")" - ); + this.lastResult.results[0].is_success + + ')' + ) } -); +) When( /I transfer (.*) uT from (.*) to ([A-Za-z0-9,]+) at fee (.*)/, async function (amount, source, dests, feePerGram) { - let wallet = this.getWallet(source); - let client = wallet.getClient(); - let destWallets = dests - .split(",") - .map((dest) => this.getWallet(dest).getClient()); - - console.log("Starting Transfer of", amount, "to"); - let recipients = destWallets.map((w) => ({ + const wallet = this.getWallet(source) + const client = wallet.getClient() + const destWallets = dests + .split(',') + .map((dest) => this.getWallet(dest).getClient()) + + console.log('Starting Transfer of', amount, 'to') + const recipients = destWallets.map((w) => ({ address: w.public_key, amount: amount, fee_per_gram: feePerGram, - message: "msg", - })); - let output = await client.transfer({ recipients }); - console.log("output", output); - lastResult = output; + message: 'msg' + })) + const output = await client.transfer({ recipients }) + console.log('output', output) + lastResult = output } -); +) When(/I wait (.*) seconds/, { timeout: 600 * 1000 }, async function (int) { - console.log("Waiting for", int, "seconds"); - await sleep(int * 1000); - console.log("Waiting finished"); -}); + console.log('Waiting for', int, 'seconds') + await sleep(int * 1000) + console.log('Waiting finished') +}) Then( /Batch transfer of (.*) transactions was a success from (.*) to ([A-Za-z0-9,]+)/, async function (txCount, walletListStr) { - let clients = walletListStr.split(",").map((s) => { - let wallet = this.getWallet(s); - return wallet.getClient(); - }); + const clients = walletListStr.split(',').map((s) => { + const wallet = this.getWallet(s) + return wallet.getClient() + }) - let resultObj = lastResult.results; - console.log(resultObj); + const resultObj = lastResult.results + console.log(resultObj) for (let i = 0; i < txCount; i++) { - let successCount = 0; - let obj = resultObj[i]; + let successCount = 0 + const obj = resultObj[i] if (!obj.is_success) { - console.log(obj.transaction_id, "failed"); - assert(obj.is_success, true); + console.log(obj.transaction_id, 'failed') + assert(obj.is_success, true) } else { console.log( - "Transaction", - obj["transaction_id"], - "passed from original request succeeded" - ); - let req = { - transaction_ids: [obj.transaction_id.toString()], - }; - console.log(req); - for (let client of clients) { + 'Transaction', + obj.transaction_id, + 'passed from original request succeeded' + ) + const req = { + transaction_ids: [obj.transaction_id.toString()] + } + console.log(req) + for (const client of clients) { try { - let tx = await client.getTransactionInfo(req); - successCount++; - console.log(tx); + const tx = await client.getTransactionInfo(req) + successCount++ + console.log(tx) } catch (err) { console.log( obj.transaction_id.toString(), - "not found in :", + 'not found in :', await client.identify() - ); + ) } } } @@ -1348,11 +1354,11 @@ Then( console.log( `Number of successful transactions is ${successCount} of ${txCount}` - ); - assert(successCount === txCount); - console.log("All transactions found"); + ) + assert(successCount === txCount) + console.log('All transactions found') } -); +) Then( /wallet (.*) detects all transactions are at least Pending/, @@ -1360,50 +1366,50 @@ Then( async function (walletName) { // Note: This initial step can take a long time if network conditions are not favourable // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed - let wallet = this.getWallet(walletName); - let walletClient = wallet.getClient(); - let walletInfo = await walletClient.identify(); + const wallet = this.getWallet(walletName) + const walletClient = wallet.getClient() + const walletInfo = await walletClient.identify() - let txIds = this.transactionsMap.get(walletInfo["public_key"]); + const txIds = this.transactionsMap.get(walletInfo.public_key) if (txIds === undefined) { - console.log("\nNo transactions for " + walletName + "!"); - expect(false).to.equal(true); + console.log('\nNo transactions for ' + walletName + '!') + expect(false).to.equal(true) } console.log( - "\nDetecting", + '\nDetecting', txIds.length, - "transactions as at least Pending: ", + 'transactions as at least Pending: ', walletName, txIds - ); + ) for (i = 0; i < txIds.length; i++) { console.log( - "(" + + '(' + (i + 1) + - "/" + + '/' + txIds.length + - ") - " + + ') - ' + wallet.name + - ": Waiting for TxId:" + + ': Waiting for TxId:' + txIds[i] + - " to register at least Pending in the wallet ..." - ); + ' to register at least Pending in the wallet ...' + ) await waitFor( async () => wallet.getClient().isTransactionAtLeastPending(txIds[i]), true, 3700 * 1000, 5 * 1000, 5 - ); - let transactionPending = await wallet + ) + const transactionPending = await wallet .getClient() - .isTransactionAtLeastPending(txIds[i]); - //let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); - //consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(transactionPending).to.equal(true); + .isTransactionAtLeastPending(txIds[i]) + // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); + // consoleLogTransactionDetails(txnDetails, txIds[i]); + expect(transactionPending).to.equal(true) } } -); +) Then( /all wallets detect all transactions are at least Pending/, @@ -1412,102 +1418,102 @@ Then( // Note: This initial step to register pending can take a long time if network conditions are not favourable // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed for (const walletName in this.wallets) { - let wallet = this.getWallet(walletName); - let walletClient = wallet.getClient(); - let walletInfo = await walletClient.identify(); + const wallet = this.getWallet(walletName) + const walletClient = wallet.getClient() + const walletInfo = await walletClient.identify() - let txIds = this.transactionsMap.get(walletInfo["public_key"]); + const txIds = this.transactionsMap.get(walletInfo.public_key) if (txIds === undefined) { - console.log("\nNo transactions for " + walletName + "!"); - expect(false).to.equal(true); + console.log('\nNo transactions for ' + walletName + '!') + expect(false).to.equal(true) } console.log( - "\nDetecting", + '\nDetecting', txIds.length, - "transactions as at least Pending: ", + 'transactions as at least Pending: ', walletName, txIds - ); + ) for (i = 0; i < txIds.length; i++) { console.log( - "(" + + '(' + (i + 1) + - "/" + + '/' + txIds.length + - ") - " + + ') - ' + wallet.name + - ": Waiting for TxId:" + + ': Waiting for TxId:' + txIds[i] + - " to register at least Pending in the wallet ..." - ); + ' to register at least Pending in the wallet ...' + ) await waitFor( async () => wallet.getClient().isTransactionAtLeastPending(txIds[i]), true, 3700 * 1000, 5 * 1000, 5 - ); - let transactionPending = await wallet + ) + const transactionPending = await wallet .getClient() - .isTransactionAtLeastPending(txIds[i]); - //let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); - //consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(transactionPending).to.equal(true); + .isTransactionAtLeastPending(txIds[i]) + // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); + // consoleLogTransactionDetails(txnDetails, txIds[i]); + expect(transactionPending).to.equal(true) } } } -); +) Then( /wallet (.*) detects all transactions are at least Completed/, { timeout: 1200 * 1000 }, async function (walletName) { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed - let wallet = this.getWallet(walletName); - let walletClient = wallet.getClient(); - let walletInfo = await walletClient.identify(); + const wallet = this.getWallet(walletName) + const walletClient = wallet.getClient() + const walletInfo = await walletClient.identify() - let txIds = this.transactionsMap.get(walletInfo["public_key"]); + const txIds = this.transactionsMap.get(walletInfo.public_key) if (txIds === undefined) { - console.log("\nNo transactions for " + walletName + "!"); - expect(false).to.equal(true); + console.log('\nNo transactions for ' + walletName + '!') + expect(false).to.equal(true) } console.log( - "\nDetecting", + '\nDetecting', txIds.length, - "transactions as at least Completed: ", + 'transactions as at least Completed: ', walletName, txIds - ); + ) for (i = 0; i < txIds.length; i++) { // Get details console.log( - "(" + + '(' + (i + 1) + - "/" + + '/' + txIds.length + - ") - " + + ') - ' + wallet.name + - ": Waiting for TxId:" + + ': Waiting for TxId:' + txIds[i] + - " to register at least Completed in the wallet ..." - ); + ' to register at least Completed in the wallet ...' + ) await waitFor( async () => wallet.getClient().isTransactionAtLeastCompleted(txIds[i]), true, 600 * 1000, 5 * 1000, 5 - ); - let transactionCompleted = await wallet + ) + const transactionCompleted = await wallet .getClient() - .isTransactionAtLeastCompleted(txIds[i]); - //let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); - //consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(transactionCompleted).to.equal(true); + .isTransactionAtLeastCompleted(txIds[i]) + // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); + // consoleLogTransactionDetails(txnDetails, txIds[i]); + expect(transactionCompleted).to.equal(true) } } -); +) Then( /all wallets detect all transactions are at least Completed/, @@ -1515,35 +1521,35 @@ Then( async function () { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed for (const walletName in this.wallets) { - let wallet = this.getWallet(walletName); - let walletClient = wallet.getClient(); - let walletInfo = await walletClient.identify(); + const wallet = this.getWallet(walletName) + const walletClient = wallet.getClient() + const walletInfo = await walletClient.identify() - let txIds = this.transactionsMap.get(walletInfo["public_key"]); + const txIds = this.transactionsMap.get(walletInfo.public_key) if (txIds === undefined) { - console.log("\nNo transactions for " + walletName + "!"); - expect(false).to.equal(true); + console.log('\nNo transactions for ' + walletName + '!') + expect(false).to.equal(true) } console.log( - "\nDetecting", + '\nDetecting', txIds.length, - "transactions as at least Completed: ", + 'transactions as at least Completed: ', walletName, txIds - ); + ) for (i = 0; i < txIds.length; i++) { // Get details console.log( - "(" + + '(' + (i + 1) + - "/" + + '/' + txIds.length + - ") - " + + ') - ' + wallet.name + - ": Waiting for TxId:" + + ': Waiting for TxId:' + txIds[i] + - " to register at least Completed in the wallet ..." - ); + ' to register at least Completed in the wallet ...' + ) await waitFor( async () => wallet.getClient().isTransactionAtLeastCompleted(txIds[i]), @@ -1551,68 +1557,68 @@ Then( 1100 * 1000, 5 * 1000, 5 - ); - let transactionCompleted = await wallet + ) + const transactionCompleted = await wallet .getClient() - .isTransactionAtLeastCompleted(txIds[i]); - //let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); - //consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(transactionCompleted).to.equal(true); + .isTransactionAtLeastCompleted(txIds[i]) + // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); + // consoleLogTransactionDetails(txnDetails, txIds[i]); + expect(transactionCompleted).to.equal(true) } } } -); +) Then( /wallet (.*) detects all transactions are at least Broadcast/, { timeout: 1200 * 1000 }, async function (walletName) { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed - let wallet = this.getWallet(walletName); - let walletClient = wallet.getClient(); - let walletInfo = await walletClient.identify(); + const wallet = this.getWallet(walletName) + const walletClient = wallet.getClient() + const walletInfo = await walletClient.identify() - let txIds = this.transactionsMap.get(walletInfo["public_key"]); + const txIds = this.transactionsMap.get(walletInfo.public_key) if (txIds === undefined) { - console.log("\nNo transactions for " + walletName + "!"); - expect(false).to.equal(true); + console.log('\nNo transactions for ' + walletName + '!') + expect(false).to.equal(true) } console.log( - "\nDetecting", + '\nDetecting', txIds.length, - "transactions as at least Broadcast: ", + 'transactions as at least Broadcast: ', walletName, txIds - ); + ) for (i = 0; i < txIds.length; i++) { // Get details console.log( - "(" + + '(' + (i + 1) + - "/" + + '/' + txIds.length + - ") - " + + ') - ' + wallet.name + - ": Waiting for TxId:" + + ': Waiting for TxId:' + txIds[i] + - " to register at least Broadcast in the wallet ..." - ); + ' to register at least Broadcast in the wallet ...' + ) await waitFor( async () => wallet.getClient().isTransactionAtLeastBroadcast(txIds[i]), true, 600 * 1000, 5 * 1000, 5 - ); - let transactionBroadcasted = await wallet + ) + const transactionBroadcasted = await wallet .getClient() - .isTransactionAtLeastBroadcast(txIds[i]); - //let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); - //consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(transactionBroadcasted).to.equal(true); + .isTransactionAtLeastBroadcast(txIds[i]) + // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); + // consoleLogTransactionDetails(txnDetails, txIds[i]); + expect(transactionBroadcasted).to.equal(true) } } -); +) Then( /all wallets detect all transactions are at least Broadcast/, @@ -1620,35 +1626,35 @@ Then( async function () { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed for (const walletName in this.wallets) { - let wallet = this.getWallet(walletName); - let walletClient = wallet.getClient(); - let walletInfo = await walletClient.identify(); + const wallet = this.getWallet(walletName) + const walletClient = wallet.getClient() + const walletInfo = await walletClient.identify() - let txIds = this.transactionsMap.get(walletInfo["public_key"]); + const txIds = this.transactionsMap.get(walletInfo.public_key) if (txIds === undefined) { - console.log("\nNo transactions for " + walletName + "!"); - expect(false).to.equal(true); + console.log('\nNo transactions for ' + walletName + '!') + expect(false).to.equal(true) } console.log( - "\nDetecting", + '\nDetecting', txIds.length, - "transactions as at least Broadcast: ", + 'transactions as at least Broadcast: ', walletName, txIds - ); + ) for (i = 0; i < txIds.length; i++) { // Get details console.log( - "(" + + '(' + (i + 1) + - "/" + + '/' + txIds.length + - ") - " + + ') - ' + wallet.name + - ": Waiting for TxId:" + + ': Waiting for TxId:' + txIds[i] + - " to register at least Broadcast in the wallet ..." - ); + ' to register at least Broadcast in the wallet ...' + ) await waitFor( async () => wallet.getClient().isTransactionAtLeastBroadcast(txIds[i]), @@ -1656,51 +1662,51 @@ Then( 1100 * 1000, 5 * 1000, 5 - ); - let transactionBroadcasted = await wallet + ) + const transactionBroadcasted = await wallet .getClient() - .isTransactionAtLeastBroadcast(txIds[i]); - //let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); - //consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(transactionBroadcasted).to.equal(true); + .isTransactionAtLeastBroadcast(txIds[i]) + // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); + // consoleLogTransactionDetails(txnDetails, txIds[i]); + expect(transactionBroadcasted).to.equal(true) } } } -); +) Then( /wallet (.*) detects all transactions are at least Mined_Unconfirmed/, { timeout: 1200 * 1000 }, async function (walletName) { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed - let wallet = this.getWallet(walletName); - let walletClient = wallet.getClient(); - let walletInfo = await walletClient.identify(); + const wallet = this.getWallet(walletName) + const walletClient = wallet.getClient() + const walletInfo = await walletClient.identify() - let txIds = this.transactionsMap.get(walletInfo["public_key"]); + const txIds = this.transactionsMap.get(walletInfo.public_key) if (txIds === undefined) { - console.log("\nNo transactions for " + walletName + "!"); - expect(false).to.equal(true); + console.log('\nNo transactions for ' + walletName + '!') + expect(false).to.equal(true) } console.log( - "\nDetecting", + '\nDetecting', txIds.length, - "transactions as at least Mined_Unconfirmed: ", + 'transactions as at least Mined_Unconfirmed: ', walletName, txIds - ); + ) for (i = 0; i < txIds.length; i++) { console.log( - "(" + + '(' + (i + 1) + - "/" + + '/' + txIds.length + - ") - " + + ') - ' + wallet.name + - ": Waiting for TxId:" + + ': Waiting for TxId:' + txIds[i] + - " to be detected as Mined_Unconfirmed in the wallet ..." - ); + ' to be detected as Mined_Unconfirmed in the wallet ...' + ) await waitFor( async () => wallet.getClient().isTransactionAtLeastMinedUnconfirmed(txIds[i]), @@ -1708,16 +1714,16 @@ Then( 600 * 1000, 5 * 1000, 5 - ); - let isTransactionAtLeastMinedUnconfirmed = await wallet + ) + const isTransactionAtLeastMinedUnconfirmed = await wallet .getClient() - .isTransactionAtLeastMinedUnconfirmed(txIds[i]); - //let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); - //consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(isTransactionAtLeastMinedUnconfirmed).to.equal(true); + .isTransactionAtLeastMinedUnconfirmed(txIds[i]) + // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); + // consoleLogTransactionDetails(txnDetails, txIds[i]); + expect(isTransactionAtLeastMinedUnconfirmed).to.equal(true) } } -); +) Then( /all wallets detect all transactions are at least Mined_Unconfirmed/, @@ -1725,33 +1731,33 @@ Then( async function () { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed for (const walletName in this.wallets) { - let wallet = this.getWallet(walletName); - let walletClient = wallet.getClient(); - let walletInfo = await walletClient.identify(); + const wallet = this.getWallet(walletName) + const walletClient = wallet.getClient() + const walletInfo = await walletClient.identify() - let txIds = this.transactionsMap.get(walletInfo["public_key"]); + const txIds = this.transactionsMap.get(walletInfo.public_key) if (txIds === undefined) { - console.log("\nNo transactions for " + walletName + "!"); - expect(false).to.equal(true); + console.log('\nNo transactions for ' + walletName + '!') + expect(false).to.equal(true) } console.log( - "\nDetecting", + '\nDetecting', txIds.length, - "transactions as at least Mined_Unconfirmed: ", + 'transactions as at least Mined_Unconfirmed: ', walletName, txIds - ); + ) for (i = 0; i < txIds.length; i++) { console.log( - "(" + + '(' + (i + 1) + - "/" + + '/' + txIds.length + - ") - " + + ') - ' + wallet.name + - ": Waiting for TxId:", - txIds[i] + " to be detected as Mined_Unconfirmed in the wallet ..." - ); + ': Waiting for TxId:', + txIds[i] + ' to be detected as Mined_Unconfirmed in the wallet ...' + ) await waitFor( async () => wallet.getClient().isTransactionAtLeastMinedUnconfirmed(txIds[i]), @@ -1759,67 +1765,67 @@ Then( 1100 * 1000, 5 * 1000, 5 - ); - let isTransactionAtLeastMinedUnconfirmed = await wallet + ) + const isTransactionAtLeastMinedUnconfirmed = await wallet .getClient() - .isTransactionAtLeastMinedUnconfirmed(txIds[i]); - //let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); - //consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(isTransactionAtLeastMinedUnconfirmed).to.equal(true); + .isTransactionAtLeastMinedUnconfirmed(txIds[i]) + // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); + // consoleLogTransactionDetails(txnDetails, txIds[i]); + expect(isTransactionAtLeastMinedUnconfirmed).to.equal(true) } } } -); +) Then( /wallet (.*) detects all transactions as Mined_Unconfirmed/, { timeout: 1200 * 1000 }, async function (walletName) { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed - let wallet = this.getWallet(walletName); - let walletClient = wallet.getClient(); - let walletInfo = await walletClient.identify(); + const wallet = this.getWallet(walletName) + const walletClient = wallet.getClient() + const walletInfo = await walletClient.identify() - let txIds = this.transactionsMap.get(walletInfo["public_key"]); + const txIds = this.transactionsMap.get(walletInfo.public_key) if (txIds === undefined) { - console.log("\nNo transactions for " + walletName + "!"); - expect(false).to.equal(true); + console.log('\nNo transactions for ' + walletName + '!') + expect(false).to.equal(true) } console.log( - "\nDetecting", + '\nDetecting', txIds.length, - "transactions as Mined_Unconfirmed: ", + 'transactions as Mined_Unconfirmed: ', walletName, txIds - ); + ) for (i = 0; i < txIds.length; i++) { console.log( - "(" + + '(' + (i + 1) + - "/" + + '/' + txIds.length + - ") - " + + ') - ' + wallet.name + - ": Waiting for TxId:" + + ': Waiting for TxId:' + txIds[i] + - " to be detected as Mined_Unconfirmed in the wallet ..." - ); + ' to be detected as Mined_Unconfirmed in the wallet ...' + ) await waitFor( async () => wallet.getClient().isTransactionMinedUnconfirmed(txIds[i]), true, 600 * 1000, 5 * 1000, 5 - ); - let isTransactionMinedUnconfirmed = await wallet + ) + const isTransactionMinedUnconfirmed = await wallet .getClient() - .isTransactionMinedUnconfirmed(txIds[i]); - //let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); - //consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(isTransactionMinedUnconfirmed).to.equal(true); + .isTransactionMinedUnconfirmed(txIds[i]) + // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); + // consoleLogTransactionDetails(txnDetails, txIds[i]); + expect(isTransactionMinedUnconfirmed).to.equal(true) } } -); +) Then( /all wallets detect all transactions as Mined_Unconfirmed/, @@ -1827,34 +1833,34 @@ Then( async function () { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed for (const walletName in this.wallets) { - let wallet = this.getWallet(walletName); - let walletClient = wallet.getClient(); - let walletInfo = await walletClient.identify(); + const wallet = this.getWallet(walletName) + const walletClient = wallet.getClient() + const walletInfo = await walletClient.identify() - let txIds = this.transactionsMap.get(walletInfo["public_key"]); + const txIds = this.transactionsMap.get(walletInfo.public_key) if (txIds === undefined) { - console.log("\nNo transactions for " + walletName + "!"); - expect(false).to.equal(true); + console.log('\nNo transactions for ' + walletName + '!') + expect(false).to.equal(true) } console.log( - "\nDetecting", + '\nDetecting', txIds.length, - "transactions as Mined_Unconfirmed: ", + 'transactions as Mined_Unconfirmed: ', walletName, txIds - ); + ) for (i = 0; i < txIds.length; i++) { console.log( - "(" + + '(' + (i + 1) + - "/" + + '/' + txIds.length + - ") - " + + ') - ' + wallet.name + - ": Waiting for TxId:" + + ': Waiting for TxId:' + txIds[i] + - " to be detected as Mined_Unconfirmed in the wallet ..." - ); + ' to be detected as Mined_Unconfirmed in the wallet ...' + ) await waitFor( async () => wallet.getClient().isTransactionMinedUnconfirmed(txIds[i]), @@ -1862,182 +1868,182 @@ Then( 1100 * 1000, 5 * 1000, 5 - ); - let isTransactionMinedUnconfirmed = await wallet + ) + const isTransactionMinedUnconfirmed = await wallet .getClient() - .isTransactionMinedUnconfirmed(txIds[i]); - //let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); - //consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(isTransactionMinedUnconfirmed).to.equal(true); + .isTransactionMinedUnconfirmed(txIds[i]) + // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); + // consoleLogTransactionDetails(txnDetails, txIds[i]); + expect(isTransactionMinedUnconfirmed).to.equal(true) } } } -); +) Then( /wallet (.*) detects all transactions as Mined_Confirmed/, { timeout: 1200 * 1000 }, async function (walletName) { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed - let wallet = this.getWallet(walletName); - let walletClient = wallet.getClient(); - let walletInfo = await walletClient.identify(); + const wallet = this.getWallet(walletName) + const walletClient = wallet.getClient() + const walletInfo = await walletClient.identify() - let txIds = this.transactionsMap.get(walletInfo["public_key"]); + const txIds = this.transactionsMap.get(walletInfo.public_key) if (txIds === undefined) { - console.log("\nNo transactions for " + walletName + "!"); - expect(false).to.equal(true); + console.log('\nNo transactions for ' + walletName + '!') + expect(false).to.equal(true) } console.log( - "\nDetecting", + '\nDetecting', txIds.length, - "transactions as Mined_Confirmed: ", + 'transactions as Mined_Confirmed: ', walletName, txIds - ); + ) for (i = 0; i < txIds.length; i++) { console.log( - "(" + + '(' + (i + 1) + - "/" + + '/' + txIds.length + - ") - " + + ') - ' + wallet.name + - ": Waiting for TxId:" + + ': Waiting for TxId:' + txIds[i] + - " to be detected as Mined_Confirmed in the wallet ..." - ); + ' to be detected as Mined_Confirmed in the wallet ...' + ) await waitFor( async () => wallet.getClient().isTransactionMinedConfirmed(txIds[i]), true, 600 * 1000, 5 * 1000, 5 - ); - let isTransactionMinedConfirmed = await wallet + ) + const isTransactionMinedConfirmed = await wallet .getClient() - .isTransactionMinedConfirmed(txIds[i]); - //let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); - //consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(isTransactionMinedConfirmed).to.equal(true); + .isTransactionMinedConfirmed(txIds[i]) + // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); + // consoleLogTransactionDetails(txnDetails, txIds[i]); + expect(isTransactionMinedConfirmed).to.equal(true) } } -); +) Then( /while mining via (.*) all transactions in wallet (.*) are found to be Mined_Confirmed/, { timeout: 1200 * 1000 }, async function (nodeName, walletName) { - let wallet = this.getWallet(walletName); - let walletClient = wallet.getClient(); - let walletInfo = await walletClient.identify(); - let nodeClient = this.getClient(nodeName); + const wallet = this.getWallet(walletName) + const walletClient = wallet.getClient() + const walletInfo = await walletClient.identify() + const nodeClient = this.getClient(nodeName) - let txIds = this.transactionsMap.get(walletInfo["public_key"]); + const txIds = this.transactionsMap.get(walletInfo.public_key) if (txIds === undefined) { - console.log("\nNo transactions for " + walletName + "!"); - expect(false).to.equal(true); + console.log('\nNo transactions for ' + walletName + '!') + expect(false).to.equal(true) } console.log( - "\nDetecting", + '\nDetecting', txIds.length, - "transactions as Mined_Confirmed: ", + 'transactions as Mined_Confirmed: ', walletName, txIds - ); + ) for (i = 0; i < txIds.length; i++) { console.log( - "(" + + '(' + (i + 1) + - "/" + + '/' + txIds.length + - ") - " + + ') - ' + wallet.name + - ": Waiting for TxId:" + + ': Waiting for TxId:' + txIds[i] + - " to be detected as Mined_Confirmed in the wallet ..." - ); + ' to be detected as Mined_Confirmed in the wallet ...' + ) await waitFor( async () => { if (await walletClient.isTransactionMinedConfirmed(txIds[i])) { - return true; + return true } else { - await nodeClient.mineBlock(walletClient); - this.tipHeight += 1; - return false; + await nodeClient.mineBlock(walletClient) + this.tipHeight += 1 + return false } }, true, 600 * 1000, 5 * 1000, 5 - ); - let isTransactionMinedConfirmed = await wallet + ) + const isTransactionMinedConfirmed = await wallet .getClient() - .isTransactionMinedConfirmed(txIds[i]); - //let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); - //consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(isTransactionMinedConfirmed).to.equal(true); + .isTransactionMinedConfirmed(txIds[i]) + // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); + // consoleLogTransactionDetails(txnDetails, txIds[i]); + expect(isTransactionMinedConfirmed).to.equal(true) } } -); +) Then( /while merge mining via (.*) all transactions in wallet (.*) are found to be Mined_Confirmed/, { timeout: 3600 * 1000 }, async function (mmProxy, walletName) { - let wallet = this.getWallet(walletName); - let walletClient = wallet.getClient(); - let walletInfo = await walletClient.identify(); + const wallet = this.getWallet(walletName) + const walletClient = wallet.getClient() + const walletInfo = await walletClient.identify() - let txIds = this.transactionsMap.get(walletInfo["public_key"]); + const txIds = this.transactionsMap.get(walletInfo.public_key) if (txIds === undefined) { - console.log("\nNo transactions for " + walletName + "!"); - expect(false).to.equal(true); + console.log('\nNo transactions for ' + walletName + '!') + expect(false).to.equal(true) } console.log( - "\nDetecting", + '\nDetecting', txIds.length, - "transactions as Mined_Confirmed: ", + 'transactions as Mined_Confirmed: ', walletName, txIds - ); + ) for (i = 0; i < txIds.length; i++) { console.log( - "(" + + '(' + (i + 1) + - "/" + + '/' + txIds.length + - ") - " + + ') - ' + wallet.name + - ": Waiting for TxId:" + + ': Waiting for TxId:' + txIds[i] + - " to be detected as Mined_Confirmed in the wallet ..." - ); + ' to be detected as Mined_Confirmed in the wallet ...' + ) await waitFor( async () => { if (await walletClient.isTransactionMinedConfirmed(txIds[i])) { - return true; + return true } else { - await this.mergeMineBlock(mmProxy); - this.tipHeight += 1; - return false; + await this.mergeMineBlock(mmProxy) + this.tipHeight += 1 + return false } }, true, 600 * 1000, 5 * 1000, 5 - ); - let isTransactionMinedConfirmed = await wallet + ) + const isTransactionMinedConfirmed = await wallet .getClient() - .isTransactionMinedConfirmed(txIds[i]); - //let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); - //consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(isTransactionMinedConfirmed).to.equal(true); + .isTransactionMinedConfirmed(txIds[i]) + // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); + // consoleLogTransactionDetails(txnDetails, txIds[i]); + expect(isTransactionMinedConfirmed).to.equal(true) } } -); +) Then( /all wallets detect all transactions as Mined_Confirmed/, @@ -2045,238 +2051,238 @@ Then( async function () { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed for (const walletName in this.wallets) { - let wallet = this.getWallet(walletName); - let walletClient = wallet.getClient(); - let walletInfo = await walletClient.identify(); + const wallet = this.getWallet(walletName) + const walletClient = wallet.getClient() + const walletInfo = await walletClient.identify() - let txIds = this.transactionsMap.get(walletInfo["public_key"]); + const txIds = this.transactionsMap.get(walletInfo.public_key) if (txIds === undefined) { - console.log("\nNo transactions for " + walletName + "!"); - expect(false).to.equal(true); + console.log('\nNo transactions for ' + walletName + '!') + expect(false).to.equal(true) } console.log( - "\nDetecting", + '\nDetecting', txIds.length, - "transactions as Mined_Confirmed: ", + 'transactions as Mined_Confirmed: ', walletName, txIds - ); + ) for (i = 0; i < txIds.length; i++) { console.log( - "(" + + '(' + (i + 1) + - "/" + + '/' + txIds.length + - ") - " + + ') - ' + wallet.name + - ": Waiting for TxId:" + + ': Waiting for TxId:' + txIds[i] + - " to be detected as Mined_Confirmed in the wallet ..." - ); + ' to be detected as Mined_Confirmed in the wallet ...' + ) await waitFor( async () => wallet.getClient().isTransactionMinedConfirmed(txIds[i]), true, 1100 * 1000, 5 * 1000, 5 - ); - let isTransactionMinedConfirmed = await wallet + ) + const isTransactionMinedConfirmed = await wallet .getClient() - .isTransactionMinedConfirmed(txIds[i]); - //let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); - //consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(isTransactionMinedConfirmed).to.equal(true); + .isTransactionMinedConfirmed(txIds[i]) + // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); + // consoleLogTransactionDetails(txnDetails, txIds[i]); + expect(isTransactionMinedConfirmed).to.equal(true) } } } -); +) When( /I list all coinbase transactions for wallet (.*)/, { timeout: 20 * 1000 }, async function (walletName) { - let wallet = this.getWallet(walletName); - let walletClient = wallet.getClient(); - console.log("\nListing all coinbase transactions: ", walletName); - let transactions = await walletClient.getAllCoinbaseTransactions(); + const wallet = this.getWallet(walletName) + const walletClient = wallet.getClient() + console.log('\nListing all coinbase transactions: ', walletName) + const transactions = await walletClient.getAllCoinbaseTransactions() if (transactions.length > 0) { for (i = 0; i < transactions.length; i++) { - consoleLogCoinbaseDetails(transactions[i]); + consoleLogCoinbaseDetails(transactions[i]) } } else { - console.log(" No coinbase transactions found!"); + console.log(' No coinbase transactions found!') } } -); +) Then( /wallet (.*) has (.*) coinbase transactions/, { timeout: 20 * 1000 }, async function (walletName, count) { - let walletClient = this.getWallet(walletName).getClient(); - let transactions = await walletClient.getAllCoinbaseTransactions(); - expect(transactions.length).to.equal(Number(count)); - this.resultStack.push([walletName, transactions.length]); + const walletClient = this.getWallet(walletName).getClient() + const transactions = await walletClient.getAllCoinbaseTransactions() + expect(transactions.length).to.equal(Number(count)) + this.resultStack.push([walletName, transactions.length]) } -); +) Then( /wallet (.*) detects at least (.*) coinbase transactions as Mined_Confirmed/, { timeout: 605 * 1000 }, async function (walletName, count) { - let walletClient = this.getWallet(walletName).getClient(); + const walletClient = this.getWallet(walletName).getClient() await waitFor( async () => walletClient.areCoinbasesConfirmedAtLeast(count), true, 600 * 1000, 5 * 1000, 5 - ); - let transactions = await walletClient.getAllSpendableCoinbaseTransactions(); - expect(transactions.length >= count).to.equal(true); + ) + const transactions = await walletClient.getAllSpendableCoinbaseTransactions() + expect(transactions.length >= count).to.equal(true) } -); +) Then( /the number of coinbase transactions for wallet (.*) and wallet (.*) are (.*) less/, { timeout: 20 * 1000 }, async function (walletNameA, walletNameB, count) { - let walletClientA = this.getWallet(walletNameA).getClient(); - let transactionsA = await walletClientA.getAllCoinbaseTransactions(); - let walletClientB = this.getWallet(walletNameB).getClient(); - let transactionsB = await walletClientB.getAllCoinbaseTransactions(); + const walletClientA = this.getWallet(walletNameA).getClient() + const transactionsA = await walletClientA.getAllCoinbaseTransactions() + const walletClientB = this.getWallet(walletNameB).getClient() + const transactionsB = await walletClientB.getAllCoinbaseTransactions() if (this.resultStack.length >= 2) { - let walletStats = [this.resultStack.pop(), this.resultStack.pop()]; + const walletStats = [this.resultStack.pop(), this.resultStack.pop()] console.log( - "\nCoinbase comparison: Expect this (current + deficit)", + '\nCoinbase comparison: Expect this (current + deficit)', transactionsA.length, transactionsB.length, Number(count), - "to equal this (previous)", + 'to equal this (previous)', walletStats[0][1], walletStats[1][1] - ); + ) expect( transactionsA.length + transactionsB.length + Number(count) - ).to.equal(walletStats[0][1] + walletStats[1][1]); + ).to.equal(walletStats[0][1] + walletStats[1][1]) } else { expect( - "\nCoinbase comparison: Not enough results saved on the stack!" - ).to.equal(""); + '\nCoinbase comparison: Not enough results saved on the stack!' + ).to.equal('') } } -); +) When(/I request the difficulties of a node (.*)/, async function (node) { - let client = this.getClient(node); - let difficulties = await client.getNetworkDifficulties(2, 0, 2); - this.lastResult = difficulties; -}); + const client = this.getClient(node) + const difficulties = await client.getNetworkDifficulties(2, 0, 2) + this.lastResult = difficulties +}) -Then("difficulties are available", function () { - assert(this.lastResult.length, 3); +Then('difficulties are available', function () { + assert(this.lastResult.length, 3) // check genesis block, chain in reverse height order - assert(this.lastResult[2]["difficulty"], "1"); - assert(this.lastResult[2]["estimated_hash_rate"], "0"); - assert(this.lastResult[2]["height"], "1"); - assert(this.lastResult[2]["pow_algo"], "0"); -}); + assert(this.lastResult[2].difficulty, '1') + assert(this.lastResult[2].estimated_hash_rate, '0') + assert(this.lastResult[2].height, '1') + assert(this.lastResult[2].pow_algo, '0') +}) When( /I coin split tari in wallet (.*) to produce (.*) UTXOs of (.*) uT each with fee_per_gram (.*) uT/, { timeout: 4800 * 1000 }, async function (walletName, splitNum, splitValue, feePerGram) { - console.log("\n"); - let numberOfSplits = Math.ceil(splitNum / 499); - let splitsLeft = splitNum; + console.log('\n') + const numberOfSplits = Math.ceil(splitNum / 499) + let splitsLeft = splitNum - let wallet = this.getWallet(walletName); - let walletClient = wallet.getClient(); - let walletInfo = await walletClient.identify(); + const wallet = this.getWallet(walletName) + const walletClient = wallet.getClient() + const walletInfo = await walletClient.identify() console.log( - "Performing", + 'Performing', numberOfSplits, - "coin splits to produce", + 'coin splits to produce', splitNum, - "outputs of", + 'outputs of', splitValue, - "uT" - ); + 'uT' + ) for (let i = 0; i < numberOfSplits; i++) { - let splits = Math.min(499, splitsLeft); - splitsLeft -= splits; - let result = await walletClient.coin_split({ + const splits = Math.min(499, splitsLeft) + splitsLeft -= splits + const result = await walletClient.coin_split({ amount_per_split: splitValue, split_count: splits, fee_per_gram: feePerGram, - message: "Cucumber coinsplit", - lockheight: 0, - }); + message: 'Cucumber coinsplit', + lockheight: 0 + }) console.log( - "Coin split", + 'Coin split', i + 1, - "/", + '/', numberOfSplits, - " completed with TxId: ", + ' completed with TxId: ', result - ); - this.addTransaction(walletInfo["public_key"], result["tx_id"]); - this.lastResult = result; + ) + this.addTransaction(walletInfo.public_key, result.tx_id) + this.lastResult = result } } -); +) When( /I send (.*) transactions of (.*) uT each from wallet (.*) to wallet (.*) at fee_per_gram (.*)/, { timeout: 10800 * 1000 }, async function (numTransactions, amount, sourceWallet, dest, feePerGram) { - console.log("\n"); - let sourceWalletClient = this.getWallet(sourceWallet).getClient(); - let sourceInfo = await sourceWalletClient.identify(); - let destInfo = await this.getWallet(dest).getClient().identify(); + console.log('\n') + const sourceWalletClient = this.getWallet(sourceWallet).getClient() + const sourceInfo = await sourceWalletClient.identify() + const destInfo = await this.getWallet(dest).getClient().identify() console.log( - "Sending", + 'Sending', numTransactions, - "transactions from", + 'transactions from', sourceWallet, - "to", + 'to', dest - ); + ) - let batch = 1; + let batch = 1 for (i = 0; i < numTransactions; i++) { - let message = - "Transaction from " + sourceWallet + " to " + dest + " " + i; - let result = await sourceWalletClient.transfer({ + const message = + 'Transaction from ' + sourceWallet + ' to ' + dest + ' ' + i + const result = await sourceWalletClient.transfer({ recipients: [ { - address: destInfo["public_key"], + address: destInfo.public_key, amount: amount, fee_per_gram: feePerGram, - message: message, - }, - ], - }); - expect(result.results[0]["is_success"]).to.equal(true); + message: message + } + ] + }) + expect(result.results[0].is_success).to.equal(true) this.addTransaction( - sourceInfo["public_key"], - result.results[0]["transaction_id"] - ); + sourceInfo.public_key, + result.results[0].transaction_id + ) this.addTransaction( - destInfo["public_key"], - result.results[0]["transaction_id"] - ); + destInfo.public_key, + result.results[0].transaction_id + ) if (i / 10 >= batch) { - batch++; - console.log(i, "/", numTransactions, " transactions sent"); + batch++ + console.log(i, '/', numTransactions, ' transactions sent') } - await sleep(50); + await sleep(50) } - console.log(numTransactions, " transactions successfully sent."); + console.log(numTransactions, ' transactions successfully sent.') } -); +) diff --git a/integration_tests/features/support/world.js b/integration_tests/features/support/world.js index 4c9cd4cc51..2f233320f0 100644 --- a/integration_tests/features/support/world.js +++ b/integration_tests/features/support/world.js @@ -1,206 +1,235 @@ -const { setWorldConstructor, After, BeforeAll } = require("cucumber"); +const { setWorldConstructor, After, BeforeAll } = require('cucumber') -const BaseNodeProcess = require("../../helpers/baseNodeProcess"); -const MergeMiningProxyProcess = require("../../helpers/mergeMiningProxyProcess"); -const WalletProcess = require("../../helpers/walletProcess"); -const MiningNodeProcess = require("../../helpers/miningNodeProcess"); +const BaseNodeProcess = require('../../helpers/baseNodeProcess') +const MergeMiningProxyProcess = require('../../helpers/mergeMiningProxyProcess') +const WalletProcess = require('../../helpers/walletProcess') +const MiningNodeProcess = require('../../helpers/miningNodeProcess') class CustomWorld { - constructor({ attach, log, parameters }) { - //this.variable = 0; - this.seeds = {}; - this.nodes = {}; - this.proxies = {}; - this.miners = {}; - this.wallets = {}; - this.clients = {}; - this.headers = {}; - this.outputs = {}; - this.testrun = `run${Date.now()}`; - this.lastResult = null; - this.blocks = {}; - this.transactions = {}; - this.peers = {}; - this.transactionsMap = new Map(); - this.resultStack = []; - this.tipHeight = 0; + constructor ({ attach, log, parameters }) { + // this.variable = 0; + this.seeds = {} + this.nodes = {} + this.proxies = {} + this.miners = {} + this.wallets = {} + this.clients = {} + this.headers = {} + this.outputs = {} + this.testrun = `run${Date.now()}` + this.lastResult = null + this.blocks = {} + this.transactions = {} + this.peers = {} + this.transactionsMap = new Map() + this.resultStack = [] + this.tipHeight = 0 this.logFilePathBaseNode = - parameters.logFilePathBaseNode || "./log4rs/base_node.yml"; - this.logFilePathProxy = parameters.logFilePathProxy || "./log4rs/proxy.yml"; + parameters.logFilePathBaseNode || './log4rs/base_node.yml' + this.logFilePathProxy = parameters.logFilePathProxy || './log4rs/proxy.yml' this.logFilePathWallet = - parameters.logFilePathWallet || "./log4rs/wallet.yml"; + parameters.logFilePathWallet || './log4rs/wallet.yml' } - async createSeedNode(name) { - let proc = new BaseNodeProcess( + async createSeedNode (name) { + const proc = new BaseNodeProcess( `seed-${name}`, null, this.logFilePathBaseNode - ); - await proc.startNew(); - this.seeds[name] = proc; - this.clients[name] = proc.createGrpcClient(); + ) + await proc.startNew() + this.seeds[name] = proc + this.clients[name] = proc.createGrpcClient() } - seedAddresses() { - let res = []; + seedAddresses () { + const res = [] for (const property in this.seeds) { - res.push(this.seeds[property].peerAddress()); + res.push(this.seeds[property].peerAddress()) } - return res; + return res } /// Create but don't add the node - createNode(name, options) { - return new BaseNodeProcess(name, options, this.logFilePathBaseNode); + createNode (name, options) { + return new BaseNodeProcess(name, options, this.logFilePathBaseNode) } - addNode(name, process) { - this.nodes[name] = process; - this.clients[name] = process.createGrpcClient(); + + async createAndAddNode (name, addresses) { + const node = this.createNode(name) + if (Array.isArray(addresses)) { + node.setPeerSeeds(addresses) + } else { + node.setPeerSeeds([addresses]) + } + await node.startNew() + this.addNode(name, node) + } + + + addNode (name, process) { + this.nodes[name] = process + this.clients[name] = process.createGrpcClient() } - addMiningNode(name, process) { - this.miners[name] = process; + addMiningNode (name, process) { + this.miners[name] = process } - addProxy(name, process) { - this.proxies[name] = process; + addProxy (name, process) { + this.proxies[name] = process } - addWallet(name, process) { - this.wallets[name] = process; + async createAndAddWallet (name, nodeAddresses) { + const wallet = new WalletProcess(name, {}, this.logFilePathWallet) + wallet.setPeerSeeds([nodeAddresses]) + await wallet.startNew() + this.addWallet(name, wallet) } - addOutput(name, output) { - this.outputs[name] = output; + addWallet (name, process) { + this.wallets[name] = process } - async mineBlock(name, weight, beforeSubmit, onError) { + addOutput (name, output) { + this.outputs[name] = output + } + + async mineBlock (name, weight, beforeSubmit, onError) { await this.clients[name].mineBlockWithoutWallet( beforeSubmit, weight, onError - ); + ) } - async mergeMineBlock(name, weight) { - let client = this.proxies[name].createClient(); - await client.mineBlock(weight); + async mergeMineBlock (name, weight) { + const client = this.proxies[name].createClient() + await client.mineBlock(weight) } - saveBlock(name, block) { - this.blocks[name] = block; + saveBlock (name, block) { + this.blocks[name] = block } - async submitBlock(blockName, nodeName) { - let result = await this.clients[nodeName] + async submitBlock (blockName, nodeName) { + const result = await this.clients[nodeName] .submitBlock(this.blocks[blockName].block) .catch((err) => { - console.log("submit block erro", err); - }); + console.log('submit block erro', err) + }) // console.log(result); } - getClient(name) { - return this.clients[name]; + getClient (name) { + return this.clients[name] } - getNode(name) { - return this.nodes[name] || this.seeds[name]; + getNode (name) { + return this.nodes[name] || this.seeds[name] } - getMiningNode(name) { - return this.miners[name]; + getMiningNode (name) { + return this.miners[name] } - getWallet(name) { - return this.wallets[name]; + getWallet (name) { + return this.wallets[name] + } + + async getOrCreateWallet(name) { + const wallet = this.getWallet(name) + if (wallet) { + return wallet + } + await this.createAndAddWallet(name, this.seedAddresses()) + return this.getWallet(name) } - getProxy(name) { - return this.proxies[name]; + getProxy (name) { + return this.proxies[name] } - async forEachClientAsync(f) { - let promises = []; + async forEachClientAsync (f) { + const promises = [] for (const property in this.seeds) { - promises.push(f(this.getClient(property), property)); + promises.push(f(this.getClient(property), property)) } for (const property in this.nodes) { - promises.push(f(this.getClient(property), property)); + promises.push(f(this.getClient(property), property)) } - await Promise.all(promises); + await Promise.all(promises) } - async stopNode(name) { - const node = this.seeds[name] || this.nodes[name]; - await node.stop(); + async stopNode (name) { + const node = this.seeds[name] || this.nodes[name] + await node.stop() } - async startNode(name) { - const node = this.seeds[name] || this.nodes[name]; - await node.start(); + async startNode (name) { + const node = this.seeds[name] || this.nodes[name] + await node.start() } - addTransaction(pubKey, txId) { + addTransaction (pubKey, txId) { if (!this.transactionsMap.has(pubKey)) { - this.transactionsMap.set(pubKey, []); + this.transactionsMap.set(pubKey, []) } - this.transactionsMap.get(pubKey).push(txId); + this.transactionsMap.get(pubKey).push(txId) } } -setWorldConstructor(CustomWorld); +setWorldConstructor(CustomWorld) BeforeAll({ timeout: 1200000 }, async function () { - const baseNode = new BaseNodeProcess("compile"); - console.log("Compiling base node..."); - await baseNode.startNew(); - await baseNode.stop(); + const baseNode = new BaseNodeProcess('compile') + console.log('Compiling base node...') + await baseNode.startNew() + await baseNode.stop() const mmProxy = new MergeMiningProxyProcess( - "compile", - "127.0.0.1:9999", - "127.0.0.1:9998" - ); - console.log("Compiling mmproxy..."); - await mmProxy.startNew(); - await mmProxy.stop(); - - const wallet = new WalletProcess("compile"); - console.log("Compiling wallet..."); - await wallet.startNew(); - await wallet.stop(); + 'compile', + '127.0.0.1:9999', + '127.0.0.1:9998' + ) + console.log('Compiling mmproxy...') + await mmProxy.startNew() + await mmProxy.stop() + + const wallet = new WalletProcess('compile') + console.log('Compiling wallet...') + await wallet.startNew() + await wallet.stop() const miningNode = new MiningNodeProcess( - "compile", - "127.0.0.1:9999", - "127.0.0.1:9998" - ); - console.log("Compiling mining node..."); - await miningNode.startNew(); - await miningNode.stop(); + 'compile', + '127.0.0.1:9999', + '127.0.0.1:9998' + ) + console.log('Compiling mining node...') + await miningNode.init(1, 1, 1, true) + await miningNode.compile() - console.log("Finished compilation."); -}); + console.log('Finished compilation.') +}) After(async function () { - console.log("Stopping nodes"); + console.log('Stopping nodes') for (const key in this.seeds) { - await this.stopNode(key); + await this.stopNode(key) } for (const key in this.nodes) { - await this.stopNode(key); + await this.stopNode(key) } for (const key in this.proxies) { - await this.proxies[key].stop(); + await this.proxies[key].stop() } for (const key in this.wallets) { - await this.wallets[key].stop(); + await this.wallets[key].stop() } for (const key in this.miners) { - await this.miners[key].stop(); + await this.miners[key].stop() } -}); +}) diff --git a/integration_tests/generate_report.js b/integration_tests/generate_report.js index f84a55b5e3..8c4215323a 100644 --- a/integration_tests/generate_report.js +++ b/integration_tests/generate_report.js @@ -1,12 +1,12 @@ -var reporter = require("cucumber-html-reporter"); +const reporter = require('cucumber-html-reporter') -var options = { - theme: "bootstrap", - jsonFile: "temp/output.json", - output: "temp/reports/cucumber_report.html", +const options = { + theme: 'bootstrap', + jsonFile: 'temp/output.json', + output: 'temp/reports/cucumber_report.html', reportSuiteAsScenarios: true, scenarioTimestamp: true, - launchReport: true, + launchReport: true // metadata: { // "App Version":"0.3.2", // "Test Environment": "STAGING", @@ -15,6 +15,6 @@ var options = { // "Parallel": "Scenarios", // "Executed": "Remote" // } -}; +} -reporter.generate(options); +reporter.generate(options) diff --git a/integration_tests/helpers/baseNodeClient.js b/integration_tests/helpers/baseNodeClient.js index 8e56ad0c2c..1920bf439d 100644 --- a/integration_tests/helpers/baseNodeClient.js +++ b/integration_tests/helpers/baseNodeClient.js @@ -1,263 +1,263 @@ -const expect = require("chai").expect; -const grpc = require("grpc"); -const protoLoader = require("@grpc/proto-loader"); -const grpc_promise = require("grpc-promise"); -const TransactionBuilder = require("./transactionBuilder"); -const { SHA3 } = require("sha3"); -const { toLittleEndian } = require("./util"); -const cloneDeep = require("clone-deep"); +const expect = require('chai').expect +const grpc = require('grpc') +const protoLoader = require('@grpc/proto-loader') +const grpc_promise = require('grpc-promise') +const TransactionBuilder = require('./transactionBuilder') +const { SHA3 } = require('sha3') +const { toLittleEndian } = require('./util') +const cloneDeep = require('clone-deep') class BaseNodeClient { - constructor(clientOrPort) { - if (typeof clientOrPort === "number") { - this.client = this.createGrpcClient(clientOrPort); + constructor (clientOrPort) { + if (typeof clientOrPort === 'number') { + this.client = this.createGrpcClient(clientOrPort) } else { - this.client = clientOrPort; + this.client = clientOrPort } - this.blockTemplates = {}; + this.blockTemplates = {} } - createGrpcClient(port) { + createGrpcClient (port) { const PROTO_PATH = - __dirname + "/../../applications/tari_app_grpc/proto/base_node.proto"; + __dirname + '/../../applications/tari_app_grpc/proto/base_node.proto' const packageDefinition = protoLoader.loadSync(PROTO_PATH, { keepCase: true, longs: String, enums: String, defaults: true, - oneofs: true, - }); - const protoDescriptor = grpc.loadPackageDefinition(packageDefinition); - const tari = protoDescriptor.tari.rpc; - let client = new tari.BaseNode( - "127.0.0.1:" + port, + oneofs: true + }) + const protoDescriptor = grpc.loadPackageDefinition(packageDefinition) + const tari = protoDescriptor.tari.rpc + const client = new tari.BaseNode( + '127.0.0.1:' + port, grpc.credentials.createInsecure() - ); - grpc_promise.promisifyAll(client); - return client; + ) + grpc_promise.promisifyAll(client) + return client } - getHeaderAt(height) { + getHeaderAt (height) { return this.client .listHeaders() .sendMessage({ from_height: height, num_headers: 1 }) .then((header) => { - console.log("Header:", header); - return header; - }); + console.log('Header:', header) + return header + }) } - getNetworkDifficulties(tip, start, end) { + getNetworkDifficulties (tip, start, end) { return this.client .getNetworkDifficulty() - .sendMessage({ from_tip: tip, start_height: start, end_height: end }); + .sendMessage({ from_tip: tip, start_height: start, end_height: end }) } - getPeers() { + getPeers () { return this.client .getPeers() .sendMessage({}) .then((peers) => { - console.log("Got ", peers.length, " peers:"); - return peers; - }); + console.log('Got ', peers.length, ' peers:') + return peers + }) } - getTipHeader() { + getTipHeader () { return this.client .listHeaders() .sendMessage({ from_height: 0, num_headers: 1 }) .then((headers) => { - const header = headers[0]; + const header = headers[0] return Object.assign(header, { - height: +header.height, - }); - }); + height: +header.height + }) + }) } - getTipHeight() { + getTipHeight () { return this.client .getTipInfo() .sendMessage({}) - .then((tip) => parseInt(tip.metadata.height_of_longest_chain)); + .then((tip) => parseInt(tip.metadata.height_of_longest_chain)) } - getPreviousBlockTemplate(height) { - return cloneDeep(this.blockTemplates["height" + height]); + getPreviousBlockTemplate (height) { + return cloneDeep(this.blockTemplates['height' + height]) } - getBlockTemplate(weight) { + getBlockTemplate (weight) { return this.client .getNewBlockTemplate() .sendMessage({ algo: { pow_algo: 2 }, max_weight: weight }) .then((template) => { - let res = { + const res = { minerData: template.miner_data, - block: template.new_block_template, - }; + block: template.new_block_template + } this.blockTemplates[ - "height" + template.new_block_template.header.height - ] = cloneDeep(res); - return res; - }); + 'height' + template.new_block_template.header.height + ] = cloneDeep(res) + return res + }) } - submitBlockWithCoinbase(template, coinbase) { - const cb = coinbase; - template.body.outputs = template.body.outputs.concat(cb.outputs); - template.body.kernels = template.body.kernels.concat(cb.kernels); + submitBlockWithCoinbase (template, coinbase) { + const cb = coinbase + template.body.outputs = template.body.outputs.concat(cb.outputs) + template.body.kernels = template.body.kernels.concat(cb.kernels) return this.client .getNewBlock() .sendMessage(template) .then((b) => { - return this.client.submitBlock().sendMessage(b.block); - }); + return this.client.submitBlock().sendMessage(b.block) + }) } - submitTemplate(template, beforeSubmit) { + submitTemplate (template, beforeSubmit) { return this.client .getNewBlock() .sendMessage(template.template) .then((b) => { - //console.log("Sha3 diff", this.getSha3Difficulty(b.block.header)); + // console.log("Sha3 diff", this.getSha3Difficulty(b.block.header)); if (beforeSubmit) { - b = beforeSubmit({ block: b, originalTemplate: template }); + b = beforeSubmit({ block: b, originalTemplate: template }) if (!b) { - return Promise.resolve(); + return Promise.resolve() } - b = b.block; + b = b.block } - return this.client.submitBlock().sendMessage(b.block); - }); + return this.client.submitBlock().sendMessage(b.block) + }) } - submitBlock(b) { - return this.client.submitBlock().sendMessage(b.block); + submitBlock (b) { + return this.client.submitBlock().sendMessage(b.block) } - submitTransaction(txn) { + submitTransaction (txn) { return this.client .submitTransaction() .sendMessage({ transaction: txn }) .then((res) => { - return res; - }); + return res + }) } - transactionState(txn) { + transactionState (txn) { return this.client .transactionState() .sendMessage({ excess_sig: txn }) .then((res) => { - return res; - }); + return res + }) } - transactionStateResult(txn) { + transactionStateResult (txn) { return this.client .transactionState() .sendMessage({ excess_sig: txn }) .then((res) => { - return res.result; - }); + return res.result + }) } - fetchMatchingUtxos(hashes) { + fetchMatchingUtxos (hashes) { return this.client .fetchMatchingUtxos() .sendMessage({ hashes: hashes }) .then((result) => { - return result; - }); + return result + }) } - async mineBlockBeforeSubmit(walletClient, weight) { + async mineBlockBeforeSubmit (walletClient, weight) { // Empty template from base node - let emptyTemplate = await this.client + const emptyTemplate = await this.client .getNewBlockTemplate() - .sendMessage({ algo: { pow_algo: 2 }, max_weight: weight }); + .sendMessage({ algo: { pow_algo: 2 }, max_weight: weight }) // Coinbase from wallet - let coinbase = await walletClient.client.inner.getCoinbase().sendMessage({ + const coinbase = await walletClient.client.inner.getCoinbase().sendMessage({ reward: emptyTemplate.miner_data.reward, fee: emptyTemplate.miner_data.total_fees, - height: emptyTemplate.new_block_template.header.height, - }); + height: emptyTemplate.new_block_template.header.height + }) // New block from base node including coinbase - let block = emptyTemplate.new_block_template; + const block = emptyTemplate.new_block_template block.body.outputs = block.body.outputs.concat( coinbase.transaction.body.outputs - ); + ) block.body.kernels = block.body.kernels.concat( coinbase.transaction.body.kernels - ); - let newBlock = await this.client.getNewBlock().sendMessage(block); - return newBlock; + ) + const newBlock = await this.client.getNewBlock().sendMessage(block) + return newBlock } - async submitMinedBlock(newBlock) { - let response = await this.client.submitBlock().sendMessage(newBlock.block); - return response; + async submitMinedBlock (newBlock) { + const response = await this.client.submitBlock().sendMessage(newBlock.block) + return response } - mineBlock(walletClient, weight) { + mineBlock (walletClient, weight) { if (!walletClient) { - return this.mineBlockWithoutWallet(weight); + return this.mineBlockWithoutWallet(weight) } - let currHeight; - let block; + let currHeight + let block return this.client .getTipInfo() .sendMessage({}) .then((tip) => { - currHeight = parseInt(tip.metadata.height_of_longest_chain); + currHeight = parseInt(tip.metadata.height_of_longest_chain) return this.client .getNewBlockTemplate() - .sendMessage({ algo: { pow_algo: 2 }, max_weight: weight }); + .sendMessage({ algo: { pow_algo: 2 }, max_weight: weight }) }) .then((template) => { - block = template.new_block_template; - let height = block.header.height; + block = template.new_block_template + const height = block.header.height return walletClient.client.inner.getCoinbase().sendMessage({ reward: template.miner_data.reward, fee: template.miner_data.total_fees, - height: height, - }); + height: height + }) }) .then((coinbase) => { - const cb = coinbase.transaction; - block.body.outputs = block.body.outputs.concat(cb.body.outputs); - block.body.kernels = block.body.kernels.concat(cb.body.kernels); - return this.client.getNewBlock().sendMessage(block); + const cb = coinbase.transaction + block.body.outputs = block.body.outputs.concat(cb.body.outputs) + block.body.kernels = block.body.kernels.concat(cb.body.kernels) + return this.client.getNewBlock().sendMessage(block) }) .then((b) => { - return this.client.submitBlock().sendMessage(b.block); + return this.client.submitBlock().sendMessage(b.block) }) .then((empty) => { - return this.client.getTipInfo().sendMessage({}); + return this.client.getTipInfo().sendMessage({}) }) .then((tipInfo) => { expect(tipInfo.metadata.height_of_longest_chain).to.equal( - currHeight + 1 + "" - ); - }); + currHeight + 1 + '' + ) + }) } - async getMinedCandidateBlock(weight, existingBlockTemplate) { - let builder = new TransactionBuilder(); - let blockTemplate = - existingBlockTemplate || (await this.getBlockTemplate(weight)); + async getMinedCandidateBlock (weight, existingBlockTemplate) { + const builder = new TransactionBuilder() + const blockTemplate = + existingBlockTemplate || (await this.getBlockTemplate(weight)) const privateKey = Buffer.from( toLittleEndian(blockTemplate.block.header.height, 256) - ).toString("hex"); - let cb = builder.generateCoinbase( + ).toString('hex') + const cb = builder.generateCoinbase( parseInt(blockTemplate.minerData.reward), privateKey, parseInt(blockTemplate.minerData.total_fees), parseInt(blockTemplate.block.header.height) + 2 - ); - let template = blockTemplate.block; - template.body.outputs = template.body.outputs.concat(cb.outputs); - template.body.kernels = template.body.kernels.concat(cb.kernels); + ) + const template = blockTemplate.block + template.body.outputs = template.body.outputs.concat(cb.outputs) + template.body.kernels = template.body.kernels.concat(cb.kernels) return { template: template, coinbase: { @@ -265,58 +265,58 @@ class BaseNodeClient { privateKey: privateKey, amount: parseInt(blockTemplate.minerData.reward) + - parseInt(blockTemplate.minerData.total_fees), - }, - }; + parseInt(blockTemplate.minerData.total_fees) + } + } } - async mineBlockWithoutWallet(beforeSubmit, weight, onError) { - let template = await this.getMinedCandidateBlock(weight); + async mineBlockWithoutWallet (beforeSubmit, weight, onError) { + const template = await this.getMinedCandidateBlock(weight) return this.submitTemplate(template, beforeSubmit).then( async () => { // let tip = await this.getTipHeight(); // console.log("Node is at tip:", tip); }, (err) => { - console.log("err submitting block:", err); + console.log('err submitting block:', err) if (onError) { if (!onError(err)) { - throw err; + throw err } // handled } else { - throw err; + throw err } } - ); + ) } - getSha3Difficulty(header) { - const hash = new SHA3(256); - hash.update(toLittleEndian(header.version, 16)); - hash.update(toLittleEndian(parseInt(header.height), 64)); - hash.update(header.prev_hash); - let timestamp = parseInt(header.timestamp.seconds); - hash.update(toLittleEndian(timestamp, 64)); - hash.update(header.output_mr); - hash.update(header.range_proof_mr); - hash.update(header.kernel_mr); - hash.update(header.total_kernel_offset); - hash.update(toLittleEndian(parseInt(header.nonce), 64)); - hash.update(toLittleEndian(header.pow.pow_algo)); + getSha3Difficulty (header) { + const hash = new SHA3(256) + hash.update(toLittleEndian(header.version, 16)) + hash.update(toLittleEndian(parseInt(header.height), 64)) + hash.update(header.prev_hash) + const timestamp = parseInt(header.timestamp.seconds) + hash.update(toLittleEndian(timestamp, 64)) + hash.update(header.output_mr) + hash.update(header.range_proof_mr) + hash.update(header.kernel_mr) + hash.update(header.total_kernel_offset) + hash.update(toLittleEndian(parseInt(header.nonce), 64)) + hash.update(toLittleEndian(header.pow.pow_algo)) hash.update( toLittleEndian(parseInt(header.pow.accumulated_monero_difficulty), 64) - ); + ) hash.update( toLittleEndian(parseInt(header.pow.accumulated_blake_difficulty), 64) - ); - hash.update(header.pow.pow_data); - let first_round = hash.digest(); - let hash2 = new SHA3(256); - hash2.update(first_round); - let res = hash2.digest("hex"); - return res; + ) + hash.update(header.pow.pow_data) + const first_round = hash.digest() + const hash2 = new SHA3(256) + hash2.update(first_round) + const res = hash2.digest('hex') + return res } } -module.exports = BaseNodeClient; +module.exports = BaseNodeClient diff --git a/integration_tests/helpers/baseNodeProcess.js b/integration_tests/helpers/baseNodeProcess.js index f6a31f3410..ad13fcd473 100644 --- a/integration_tests/helpers/baseNodeProcess.js +++ b/integration_tests/helpers/baseNodeProcess.js @@ -1,184 +1,184 @@ -const { spawn } = require("child_process"); -const { expect } = require("chai"); -const fs = require("fs"); -const path = require("path"); -const BaseNodeClient = require("./baseNodeClient"); -const { getFreePort } = require("./util"); -const dateFormat = require("dateformat"); -const { createEnv } = require("./config"); - -let outputProcess; +const { spawn } = require('child_process') +const { expect } = require('chai') +const fs = require('fs') +const path = require('path') +const BaseNodeClient = require('./baseNodeClient') +const { getFreePort } = require('./util') +const dateFormat = require('dateformat') +const { createEnv } = require('./config') + +let outputProcess class BaseNodeProcess { - constructor(name, options, logFilePath, nodeFile) { - this.name = name; - this.logFilePath = logFilePath ? path.resolve(logFilePath) : logFilePath; - this.nodeFile = nodeFile; - this.options = options; + constructor (name, options, logFilePath, nodeFile) { + this.name = name + this.logFilePath = logFilePath ? path.resolve(logFilePath) : logFilePath + this.nodeFile = nodeFile + this.options = options } - async init() { - this.port = await getFreePort(19000, 25000); - this.grpcPort = await getFreePort(19000, 25000); - this.name = `Basenode${this.port}-${this.name}`; - this.nodeFile = this.nodeFile || "nodeid.json"; + async init () { + this.port = await getFreePort(19000, 25000) + this.grpcPort = await getFreePort(19000, 25000) + this.name = `Basenode${this.port}-${this.name}` + this.nodeFile = this.nodeFile || 'nodeid.json' this.baseDir = `./temp/base_nodes/${dateFormat( new Date(), - "yyyymmddHHMM" - )}/${this.name}`; - const args = ["--base-path", ".", "--init", "--create-id"]; + 'yyyymmddHHMM' + )}/${this.name}` + const args = ['--base-path', '.', '--init', '--create-id'] if (this.logFilePath) { - args.push("--log-config", this.logFilePath); + args.push('--log-config', this.logFilePath) } - await this.run(await this.compile(), args); + await this.run(await this.compile(), args) // console.log("Port:", this.port); // console.log("GRPC:", this.grpcPort); // console.log(`Starting node ${this.name}...`); } - async compile() { + async compile () { if (!outputProcess) { - await this.run("cargo", [ - "build", - "--release", - "--bin", - "tari_base_node", - "-Z", - "unstable-options", - "--out-dir", - __dirname + "/../temp/out", - ]); - outputProcess = __dirname + "/../temp/out/tari_base_node"; + await this.run('cargo', [ + 'build', + '--release', + '--bin', + 'tari_base_node', + '-Z', + 'unstable-options', + '--out-dir', + __dirname + '/../temp/out' + ]) + outputProcess = __dirname + '/../temp/out/tari_base_node' } - return outputProcess; + return outputProcess } - ensureNodeInfo() { + ensureNodeInfo () { while (true) { - if (fs.existsSync(this.baseDir + "/" + this.nodeFile)) { - break; + if (fs.existsSync(this.baseDir + '/' + this.nodeFile)) { + break } } this.nodeInfo = JSON.parse( - fs.readFileSync(this.baseDir + "/" + this.nodeFile, "utf8") - ); + fs.readFileSync(this.baseDir + '/' + this.nodeFile, 'utf8') + ) } - peerAddress() { - this.ensureNodeInfo(); - const addr = this.nodeInfo.public_key + "::" + this.nodeInfo.public_address; + peerAddress () { + this.ensureNodeInfo() + const addr = this.nodeInfo.public_key + '::' + this.nodeInfo.public_address // console.log("Peer:", addr); - return addr; + return addr } - setPeerSeeds(addresses) { - this.peerSeeds = addresses.join(","); + setPeerSeeds (addresses) { + this.peerSeeds = addresses.join(',') } - getGrpcAddress() { - let address = "127.0.0.1:" + this.grpcPort; + getGrpcAddress () { + const address = '127.0.0.1:' + this.grpcPort // console.log("Base Node GRPC Address:",address); - return address; + return address } - run(cmd, args, saveFile) { + run (cmd, args, saveFile) { return new Promise((resolve, reject) => { if (!fs.existsSync(this.baseDir)) { - fs.mkdirSync(this.baseDir, { recursive: true }); - fs.mkdirSync(this.baseDir + "/log", { recursive: true }); + fs.mkdirSync(this.baseDir, { recursive: true }) + fs.mkdirSync(this.baseDir + '/log', { recursive: true }) } - let envs = createEnv( + const envs = createEnv( this.name, false, this.nodeFile, - "127.0.0.1", - "8082", - "8081", - "127.0.0.1", + '127.0.0.1', + '8082', + '8081', + '127.0.0.1', this.grpcPort, this.port, - "127.0.0.1:8080", + '127.0.0.1:8080', this.options, this.peerSeeds - ); + ) - var ps = spawn(cmd, args, { + const ps = spawn(cmd, args, { cwd: this.baseDir, // shell: true, - env: { ...process.env, ...envs }, - }); + env: { ...process.env, ...envs } + }) - ps.stdout.on("data", (data) => { - //console.log(`stdout: ${data}`); - fs.appendFileSync(`${this.baseDir}/log/stdout.log`, data.toString()); + ps.stdout.on('data', (data) => { + // console.log(`stdout: ${data}`); + fs.appendFileSync(`${this.baseDir}/log/stdout.log`, data.toString()) if ( data .toString() .match(/Copyright 2019-2020. The Tari Development Community/) ) { - resolve(ps); + resolve(ps) } - }); + }) - ps.stderr.on("data", (data) => { - console.error(`stderr: ${data}`); - fs.appendFileSync(`${this.baseDir}/log/stderr.log`, data.toString()); - }); + ps.stderr.on('data', (data) => { + console.error(`stderr: ${data}`) + fs.appendFileSync(`${this.baseDir}/log/stderr.log`, data.toString()) + }) - ps.on("close", (code) => { - let ps = this.ps; - this.ps = null; + ps.on('close', (code) => { + const ps = this.ps + this.ps = null if (code) { - console.log(`child process exited with code ${code}`); - reject(`child process exited with code ${code}`); + console.log(`child process exited with code ${code}`) + reject(`child process exited with code ${code}`) } else { - resolve(ps); + resolve(ps) } - }); + }) - expect(ps.error).to.be.an("undefined"); - this.ps = ps; - }); + expect(ps.error).to.be.an('undefined') + this.ps = ps + }) } - async startNew() { - await this.init(); - return await this.start(); + async startNew () { + await this.init() + return await this.start() } - async startAndConnect() { - await this.startNew(); - return this.createGrpcClient(); + async startAndConnect () { + await this.startNew() + return this.createGrpcClient() } - async start() { - const args = ["--base-path", "."]; + async start () { + const args = ['--base-path', '.'] if (this.logFilePath) { - args.push("--log-config", this.logFilePath); + args.push('--log-config', this.logFilePath) } - return await this.run(await this.compile(), args); + return await this.run(await this.compile(), args) } - stop() { + stop () { return new Promise((resolve) => { if (!this.ps) { - return resolve(); + return resolve() } - this.ps.on("close", (code) => { + this.ps.on('close', (code) => { if (code) { - console.log(`child process exited with code ${code}`); + console.log(`child process exited with code ${code}`) } - resolve(); - }); - this.ps.kill("SIGINT"); - }); + resolve() + }) + this.ps.kill('SIGINT') + }) } - createGrpcClient() { - return new BaseNodeClient(this.grpcPort); + createGrpcClient () { + return new BaseNodeClient(this.grpcPort) } } -module.exports = BaseNodeProcess; +module.exports = BaseNodeProcess diff --git a/integration_tests/helpers/config.js b/integration_tests/helpers/config.js index db367dd7f9..2cfdb7b914 100644 --- a/integration_tests/helpers/config.js +++ b/integration_tests/helpers/config.js @@ -1,71 +1,71 @@ -function mapEnvs(options) { - let res = {}; +function mapEnvs (options) { + const res = {} if (options.blocks_behind_before_considered_lagging) { res.TARI_BASE_NODE__LOCALNET__BLOCKS_BEHIND_BEFORE_CONSIDERED_LAGGING = - options.blocks_behind_before_considered_lagging; + options.blocks_behind_before_considered_lagging } if (options.pruningHorizon) { // In the config toml file: `base_node.network.pruning_horizon` with `network = localnet` - res.TARI_BASE_NODE__LOCALNET__PRUNING_HORIZON = options.pruningHorizon; + res.TARI_BASE_NODE__LOCALNET__PRUNING_HORIZON = options.pruningHorizon } - if ("num_confirmations" in options) { - res.TARI_WALLET__TRANSACTION_NUM_CONFIRMATIONS_REQUIRED = options.num_confirmations; + if ('num_confirmations' in options) { + res.TARI_WALLET__TRANSACTION_NUM_CONFIRMATIONS_REQUIRED = options.num_confirmations } if (options.routingMechanism) { // In the config toml file: `wallet.transaction_routing_mechanism` - res.TARI_WALLET__TRANSACTION_ROUTING_MECHANISM = options.routingMechanism; + res.TARI_WALLET__TRANSACTION_ROUTING_MECHANISM = options.routingMechanism } if (options.broadcastMonitoringTimeout) { res.TARI_WALLET__TRANSACTION_BROADCAST_MONITORING_TIMEOUT = - options.broadcastMonitoringTimeout; + options.broadcastMonitoringTimeout } else { - res.TARI_WALLET__TRANSACTION_BROADCAST_MONITORING_TIMEOUT = 3; + res.TARI_WALLET__TRANSACTION_BROADCAST_MONITORING_TIMEOUT = 3 } - if ("mineOnTipOnly" in options) { - res.TARI_MINING_NODE__MINE_ON_TIP_ONLY = options.mineOnTipOnly; + if ('mineOnTipOnly' in options) { + res.TARI_MINING_NODE__MINE_ON_TIP_ONLY = options.mineOnTipOnly } if (options.network) { - res.TARI_BASE_NODE__NETWORK = options.network; + res.TARI_BASE_NODE__NETWORK = options.network } if (options.transport) { - res.TARI_BASE_NODE__LOCALNET__TRANSPORT = options.transport; - res.TARI_BASE_NODE__STIBBONS__TRANSPORT = options.transport; + res.TARI_BASE_NODE__LOCALNET__TRANSPORT = options.transport + res.TARI_BASE_NODE__STIBBONS__TRANSPORT = options.transport } - return res; + return res } -function baseEnvs(peerSeeds = []) { - let envs = { +function baseEnvs (peerSeeds = []) { + const envs = { RUST_BACKTRACE: 1, - TARI_BASE_NODE__NETWORK: "localnet", - TARI_BASE_NODE__LOCALNET__DATA_DIR: "localnet", - TARI_BASE_NODE__LOCALNET__DB_TYPE: "lmdb", - TARI_BASE_NODE__LOCALNET__ORPHAN_STORAGE_CAPACITY: "10", - TARI_BASE_NODE__LOCALNET__PRUNING_HORIZON: "0", - TARI_BASE_NODE__LOCALNET__PRUNED_MODE_CLEANUP_INTERVAL: "10000", - TARI_BASE_NODE__LOCALNET__CORE_THREADS: "10", - TARI_BASE_NODE__LOCALNET__MAX_THREADS: "512", - TARI_BASE_NODE__LOCALNET__IDENTITY_FILE: "none.json", - TARI_BASE_NODE__LOCALNET__BASE_NODE_TOR_IDENTITY_FILE: "torid.json", - TARI_BASE_NODE__LOCALNET__WALLET_IDENTITY_FILE: "walletid.json", - TARI_BASE_NODE__LOCALNET__CONSOLE_WALLET_IDENTITY_FILE: "cwalletid.json", - TARI_BASE_NODE__LOCALNET__WALLET_TOR_IDENTITY_FILE: "wallettorid.json", - TARI_BASE_NODE__LOCALNET__CONSOLE_WALLET_TOR_IDENTITY_FILE: "none.json", + TARI_BASE_NODE__NETWORK: 'localnet', + TARI_BASE_NODE__LOCALNET__DATA_DIR: 'localnet', + TARI_BASE_NODE__LOCALNET__DB_TYPE: 'lmdb', + TARI_BASE_NODE__LOCALNET__ORPHAN_STORAGE_CAPACITY: '10', + TARI_BASE_NODE__LOCALNET__PRUNING_HORIZON: '0', + TARI_BASE_NODE__LOCALNET__PRUNED_MODE_CLEANUP_INTERVAL: '10000', + TARI_BASE_NODE__LOCALNET__CORE_THREADS: '10', + TARI_BASE_NODE__LOCALNET__MAX_THREADS: '512', + TARI_BASE_NODE__LOCALNET__IDENTITY_FILE: 'none.json', + TARI_BASE_NODE__LOCALNET__BASE_NODE_TOR_IDENTITY_FILE: 'torid.json', + TARI_BASE_NODE__LOCALNET__WALLET_IDENTITY_FILE: 'walletid.json', + TARI_BASE_NODE__LOCALNET__CONSOLE_WALLET_IDENTITY_FILE: 'cwalletid.json', + TARI_BASE_NODE__LOCALNET__WALLET_TOR_IDENTITY_FILE: 'wallettorid.json', + TARI_BASE_NODE__LOCALNET__CONSOLE_WALLET_TOR_IDENTITY_FILE: 'none.json', TARI_BASE_NODE__LOCALNET__ALLOW_TEST_ADDRESSES: true, TARI_BASE_NODE__LOCALNET__GRPC_ENABLED: true, TARI_BASE_NODE__LOCALNET__ENABLE_WALLET: false, - TARI_BASE_NODE__LOCALNET__DNS_SEEDS_NAME_SERVER: "1.1.1.1:53", - TARI_BASE_NODE__LOCALNET__DNS_SEEDS_USE_DNSSEC: "true", - TARI_BASE_NODE__LOCALNET__BLOCK_SYNC_STRATEGY: "ViaBestChainMetadata", - TARI_BASE_NODE__LOCALNET__NUM_MINING_THREADS: "1", - TARI_BASE_NODE__LOCALNET__ORPHAN_DB_CLEAN_OUT_THRESHOLD: "0", - TARI_BASE_NODE__LOCALNET__MAX_RANDOMX_VMS: "1", - TARI_BASE_NODE__LOCALNET__AUTO_PING_INTERVAL: "15", - TARI_BASE_NODE__LOCALNET__FLOOD_BAN_MAX_MSG_COUNT: "100000", + TARI_BASE_NODE__LOCALNET__DNS_SEEDS_NAME_SERVER: '1.1.1.1:53', + TARI_BASE_NODE__LOCALNET__DNS_SEEDS_USE_DNSSEC: 'true', + TARI_BASE_NODE__LOCALNET__BLOCK_SYNC_STRATEGY: 'ViaBestChainMetadata', + TARI_BASE_NODE__LOCALNET__NUM_MINING_THREADS: '1', + TARI_BASE_NODE__LOCALNET__ORPHAN_DB_CLEAN_OUT_THRESHOLD: '0', + TARI_BASE_NODE__LOCALNET__MAX_RANDOMX_VMS: '1', + TARI_BASE_NODE__LOCALNET__AUTO_PING_INTERVAL: '15', + TARI_BASE_NODE__LOCALNET__FLOOD_BAN_MAX_MSG_COUNT: '100000', TARI_MERGE_MINING_PROXY__LOCALNET__MONEROD_URL: - "http://18.133.55.120:38081", + 'http://18.133.55.120:38081', TARI_MERGE_MINING_PROXY__LOCALNET__MONEROD_USE_AUTH: false, TARI_MERGE_MINING_PROXY__LOCALNET__MONEROD_USERNAME: '""', TARI_MERGE_MINING_PROXY__LOCALNET__MONEROD_PASSWORD: '""', @@ -73,53 +73,53 @@ function baseEnvs(peerSeeds = []) { TARI_BASE_NODE__LOCALNET__DB_RESIZE_THRESHOLD_MB: 10, TARI_BASE_NODE__LOCALNET__DB_GROW_SIZE_MB: 20, TARI_MERGE_MINING_PROXY__LOCALNET__WAIT_FOR_INITIAL_SYNC_AT_STARTUP: false, - TARI_MINING_NODE__MINE_ON_TIP_ONLY: true, - }; + TARI_MINING_NODE__MINE_ON_TIP_ONLY: true + } if (peerSeeds.length != 0) { - envs.TARI_BASE_NODE__LOCALNET__PEER_SEEDS = peerSeeds; + envs.TARI_BASE_NODE__LOCALNET__PEER_SEEDS = peerSeeds } else { // Nowheresville envs.TARI_BASE_NODE__LOCALNET__PEER_SEEDS = [ - "5cfcf17f41b01980eb4fa03cec5ea12edbd3783496a2b5dabf99e4bf6410f460::/ip4/10.0.0.50/tcp/1", - ]; + '5cfcf17f41b01980eb4fa03cec5ea12edbd3783496a2b5dabf99e4bf6410f460::/ip4/10.0.0.50/tcp/1' + ] } - return envs; + return envs } -function createEnv( - name = "config_identity", +function createEnv ( + name = 'config_identity', isWallet = false, - nodeFile = "newnodeid.json", - walletGrpcAddress = "127.0.0.1", - walletGrpcPort = "8082", - walletPort = "8083", - baseNodeGrpcAddress = "127.0.0.1", - baseNodeGrpcPort = "8080", - baseNodePort = "8081", - proxyFullAddress = "127.0.0.1:8084", + nodeFile = 'newnodeid.json', + walletGrpcAddress = '127.0.0.1', + walletGrpcPort = '8082', + walletPort = '8083', + baseNodeGrpcAddress = '127.0.0.1', + baseNodeGrpcPort = '8080', + baseNodePort = '8081', + proxyFullAddress = '127.0.0.1:8084', options, peerSeeds = [], - txnSendingMechanism = "DirectAndStoreAndForward" + txnSendingMechanism = 'DirectAndStoreAndForward' ) { - const envs = baseEnvs(peerSeeds); - const network = options.network ? options.network.toUpperCase() : "LOCALHOST"; + const envs = baseEnvs(peerSeeds) + const network = (options && options.network) ? options.network.toUpperCase() : 'LOCALNET' - const configEnvs = {}; + const configEnvs = {} - configEnvs[`TARI_BASE_NODE__${network}__GRPC_BASE_NODE_ADDRESS`] = `${baseNodeGrpcAddress}:${baseNodeGrpcPort}`; - configEnvs[ `TARI_BASE_NODE__${network}__GRPC_CONSOLE_WALLET_ADDRESS`]= `${walletGrpcAddress}:${walletGrpcPort}`; - configEnvs[ `TARI_BASE_NODE__${network}__BASE_NODE_IDENTITY_FILE`]= `${nodeFile}`; - configEnvs[ `TARI_BASE_NODE__${network}__TCP_LISTENER_ADDRESS`]= - "/ip4/127.0.0.1/tcp/" + (isWallet ? `${walletPort}` : `${baseNodePort}`); - configEnvs[ `TARI_BASE_NODE__${network}__PUBLIC_ADDRESS`] = - "/ip4/127.0.0.1/tcp/" + (isWallet ? `${walletPort}` : `${baseNodePort}`); - configEnvs[ `TARI_MERGE_MINING_PROXY__${network}__PROXY_HOST_ADDRESS`]= `${proxyFullAddress}`; - configEnvs[ `TARI_BASE_NODE__${network}__TRANSPORT`]= "tcp"; + configEnvs[`TARI_BASE_NODE__${network}__GRPC_BASE_NODE_ADDRESS`] = `${baseNodeGrpcAddress}:${baseNodeGrpcPort}` + configEnvs[`TARI_BASE_NODE__${network}__GRPC_CONSOLE_WALLET_ADDRESS`] = `${walletGrpcAddress}:${walletGrpcPort}` + configEnvs[`TARI_BASE_NODE__${network}__BASE_NODE_IDENTITY_FILE`] = `${nodeFile}` + configEnvs[`TARI_BASE_NODE__${network}__TCP_LISTENER_ADDRESS`] = + '/ip4/127.0.0.1/tcp/' + (isWallet ? `${walletPort}` : `${baseNodePort}`) + configEnvs[`TARI_BASE_NODE__${network}__PUBLIC_ADDRESS`] = + '/ip4/127.0.0.1/tcp/' + (isWallet ? `${walletPort}` : `${baseNodePort}`) + configEnvs[`TARI_MERGE_MINING_PROXY__${network}__PROXY_HOST_ADDRESS`] = `${proxyFullAddress}` + configEnvs[`TARI_BASE_NODE__${network}__TRANSPORT`] = 'tcp' - return { ...envs, ...configEnvs, ...mapEnvs(options || {}) }; + return { ...envs, ...configEnvs, ...mapEnvs(options || {}) } } module.exports = { - createEnv, -}; + createEnv +} diff --git a/integration_tests/helpers/mergeMiningProxyClient.js b/integration_tests/helpers/mergeMiningProxyClient.js index 4e0f0b35e0..7af6f63068 100644 --- a/integration_tests/helpers/mergeMiningProxyClient.js +++ b/integration_tests/helpers/mergeMiningProxyClient.js @@ -1,70 +1,70 @@ -const axios = require("axios"); +const axios = require('axios') class MergeMiningProxyClient { - constructor(address) { - this.address = address; + constructor (address) { + this.address = address } - async getHeight() { - let res = await axios.get(`${this.address}/get_height`); - return res.data.height; + async getHeight () { + const res = await axios.get(`${this.address}/get_height`) + return res.data.height } - async getBlockTemplate() { - let res = await axios.post(`${this.address}/json_rpc`, { - jsonrpc: "2.0", - id: "0", - method: "getblocktemplate", + async getBlockTemplate () { + const res = await axios.post(`${this.address}/json_rpc`, { + jsonrpc: '2.0', + id: '0', + method: 'getblocktemplate', params: { wallet_address: - "55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt", - reserve_size: 60, - }, - }); - //console.log(res.data); - //console.log("Blocktemplate:",res.data.result.blocktemplate_blob); - return res.data.result; + '55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt', + reserve_size: 60 + } + }) + // console.log(res.data); + // console.log("Blocktemplate:",res.data.result.blocktemplate_blob); + return res.data.result } - async submitBlock(block) { - let res = await axios.post(`${this.address}/json_rpc`, { - jsonrpc: "2.0", - id: "0", - method: "submit_block", - params: [block], - }); - return res.data; + async submitBlock (block) { + const res = await axios.post(`${this.address}/json_rpc`, { + jsonrpc: '2.0', + id: '0', + method: 'submit_block', + params: [block] + }) + return res.data } - async getLastBlockHeader() { - let res = await axios.post(`${this.address}/json_rpc`, { - jsonrpc: "2.0", - id: "0", - method: "get_last_block_header", - }); - return res.data; + async getLastBlockHeader () { + const res = await axios.post(`${this.address}/json_rpc`, { + jsonrpc: '2.0', + id: '0', + method: 'get_last_block_header' + }) + return res.data } - async getBlockHeaderByHash(hash) { - let res = await axios.post(`${this.address}/json_rpc`, { - jsonrpc: "2.0", - id: "0", - method: "get_block_header_by_hash", + async getBlockHeaderByHash (hash) { + const res = await axios.post(`${this.address}/json_rpc`, { + jsonrpc: '2.0', + id: '0', + method: 'get_block_header_by_hash', params: { - hash: hash, - }, - }); - return res.data; + hash: hash + } + }) + return res.data } - async mineBlock() { + async mineBlock () { // Mines a block in the same way that xmrig would - let template = await this.getBlockTemplate(); - let height = await this.getHeight(); - let block = template.blocktemplate_blob; + const template = await this.getBlockTemplate() + const height = await this.getHeight() + const block = template.blocktemplate_blob // Need to insert a nonce into the template as xmrig would for it to be a valid block. - let result = await this.submitBlock(block); + const result = await this.submitBlock(block) } } -module.exports = MergeMiningProxyClient; +module.exports = MergeMiningProxyClient diff --git a/integration_tests/helpers/mergeMiningProxyProcess.js b/integration_tests/helpers/mergeMiningProxyProcess.js index 50f5a0c323..9c3c95d666 100644 --- a/integration_tests/helpers/mergeMiningProxyProcess.js +++ b/integration_tests/helpers/mergeMiningProxyProcess.js @@ -1,54 +1,54 @@ -const { getFreePort } = require("./util"); -const dateFormat = require("dateformat"); -const fs = require("fs"); -const path = require("path"); -const { spawnSync, spawn, execSync } = require("child_process"); -const { expect } = require("chai"); -const MergeMiningProxyClient = require("./mergeMiningProxyClient"); -const { createEnv } = require("./config"); -const { setWorldConstructor } = require("cucumber"); +const { getFreePort } = require('./util') +const dateFormat = require('dateformat') +const fs = require('fs') +const path = require('path') +const { spawnSync, spawn, execSync } = require('child_process') +const { expect } = require('chai') +const MergeMiningProxyClient = require('./mergeMiningProxyClient') +const { createEnv } = require('./config') +const { setWorldConstructor } = require('cucumber') -let outputProcess; +let outputProcess class MergeMiningProxyProcess { - constructor( + constructor ( name, baseNodeAddress, walletAddress, logFilePath, submitOrigin = true ) { - this.name = name; - this.nodeAddress = baseNodeAddress.split(":")[0]; - this.nodeGrpcPort = baseNodeAddress.split(":")[1]; - this.walletAddress = walletAddress.split(":")[0]; - this.walletGrpcPort = walletAddress.split(":")[1]; - this.submitOrigin = submitOrigin; - this.logFilePath = logFilePath ? path.resolve(logFilePath) : logFilePath; + this.name = name + this.nodeAddress = baseNodeAddress.split(':')[0] + this.nodeGrpcPort = baseNodeAddress.split(':')[1] + this.walletAddress = walletAddress.split(':')[0] + this.walletGrpcPort = walletAddress.split(':')[1] + this.submitOrigin = submitOrigin + this.logFilePath = logFilePath ? path.resolve(logFilePath) : logFilePath } - async init() { - this.port = await getFreePort(19000, 25000); - this.name = `MMProxy${this.port}-${this.name}`; + async init () { + this.port = await getFreePort(19000, 25000) + this.name = `MMProxy${this.port}-${this.name}` this.baseDir = `./temp/base_nodes/${dateFormat( new Date(), - "yyyymmddHHMM" - )}/${this.name}`; - //console.log("MergeMiningProxyProcess init - assign server GRPC:", this.grpcPort); + 'yyyymmddHHMM' + )}/${this.name}` + // console.log("MergeMiningProxyProcess init - assign server GRPC:", this.grpcPort); } - run(cmd, args, saveFile) { + run (cmd, args, saveFile) { return new Promise((resolve, reject) => { if (!fs.existsSync(this.baseDir)) { - fs.mkdirSync(this.baseDir, { recursive: true }); - fs.mkdirSync(this.baseDir + "/log", { recursive: true }); + fs.mkdirSync(this.baseDir, { recursive: true }) + fs.mkdirSync(this.baseDir + '/log', { recursive: true }) } - let proxyAddress = "127.0.0.1:" + this.port; - let envs = createEnv( + const proxyAddress = '127.0.0.1:' + this.port + const envs = createEnv( this.name, false, - "nodeid.json", + 'nodeid.json', this.walletAddress, this.walletGrpcPort, this.port, @@ -58,93 +58,93 @@ class MergeMiningProxyProcess { proxyAddress, [], [] - ); - var extraEnvs = { + ) + const extraEnvs = { TARI_MERGE_MINING_PROXY__LOCALNET__PROXY_SUBMIT_TO_ORIGIN: this - .submitOrigin, - }; - let completeEnvs = { ...envs, ...extraEnvs }; - var ps = spawn(cmd, args, { + .submitOrigin + } + const completeEnvs = { ...envs, ...extraEnvs } + const ps = spawn(cmd, args, { cwd: this.baseDir, // shell: true, - env: { ...process.env, ...completeEnvs }, - }); + env: { ...process.env, ...completeEnvs } + }) - ps.stdout.on("data", (data) => { - //console.log(`stdout: ${data}`); - fs.appendFileSync(`${this.baseDir}/log/stdout.log`, data.toString()); + ps.stdout.on('data', (data) => { + // console.log(`stdout: ${data}`); + fs.appendFileSync(`${this.baseDir}/log/stdout.log`, data.toString()) if (data.toString().match(/Listening on/)) { - resolve(ps); + resolve(ps) } - }); + }) - ps.stderr.on("data", (data) => { - console.error(`stderr: ${data}`); - fs.appendFileSync(`${this.baseDir}/log/stderr.log`, data.toString()); - }); + ps.stderr.on('data', (data) => { + console.error(`stderr: ${data}`) + fs.appendFileSync(`${this.baseDir}/log/stderr.log`, data.toString()) + }) - ps.on("close", (code) => { - let ps = this.ps; - this.ps = null; + ps.on('close', (code) => { + const ps = this.ps + this.ps = null if (code) { - console.log(`child process exited with code ${code}`); - reject(`child process exited with code ${code}`); + console.log(`child process exited with code ${code}`) + reject(`child process exited with code ${code}`) } else { - resolve(ps); + resolve(ps) } - }); + }) - expect(ps.error).to.be.an("undefined"); - this.ps = ps; - }); + expect(ps.error).to.be.an('undefined') + this.ps = ps + }) } - async startNew() { - await this.init(); - const args = ["--base-path", ".", "--init"]; + async startNew () { + await this.init() + const args = ['--base-path', '.', '--init'] if (this.logFilePath) { - args.push("--log-config", this.logFilePath); + args.push('--log-config', this.logFilePath) } - return await this.run(await this.compile(), args, true); + return await this.run(await this.compile(), args, true) } - async compile() { + async compile () { if (!outputProcess) { - await this.run("cargo", [ - "build", - "--release", - "--bin", - "tari_merge_mining_proxy", - "-Z", - "unstable-options", - "--out-dir", - __dirname + "/../temp/out", - ]); - outputProcess = __dirname + "/../temp/out/tari_merge_mining_proxy"; + await this.run('cargo', [ + 'build', + '--release', + '--bin', + 'tari_merge_mining_proxy', + '-Z', + 'unstable-options', + '--out-dir', + __dirname + '/../temp/out' + ]) + outputProcess = __dirname + '/../temp/out/tari_merge_mining_proxy' } - return outputProcess; + return outputProcess } - stop() { + stop () { return new Promise((resolve) => { if (!this.ps) { - return resolve(); + return resolve() } - this.ps.on("close", (code) => { + this.ps.on('close', (code) => { if (code) { - console.log(`child process exited with code ${code}`); + console.log(`child process exited with code ${code}`) } - resolve(); - }); - this.ps.kill("SIGINT"); - }); + resolve() + }) + this.ps.kill('SIGINT') + }) } - createClient() { - let address = "http://127.0.0.1:" + this.port; - //console.log("MergeMiningProxyProcess createClient - client address:", address); - return new MergeMiningProxyClient(address); + createClient () { + const address = 'http://127.0.0.1:' + this.port + // console.log("MergeMiningProxyProcess createClient - client address:", address); + return new MergeMiningProxyClient(address) } } -module.exports = MergeMiningProxyProcess; +module.exports = MergeMiningProxyProcess diff --git a/integration_tests/helpers/miningNodeProcess.js b/integration_tests/helpers/miningNodeProcess.js index a1ccc4ead8..38d595fc08 100644 --- a/integration_tests/helpers/miningNodeProcess.js +++ b/integration_tests/helpers/miningNodeProcess.js @@ -1,139 +1,139 @@ -const { getFreePort } = require("./util"); -const dateFormat = require("dateformat"); -const fs = require("fs"); -const { spawnSync, spawn, execSync } = require("child_process"); -const { expect } = require("chai"); -const { createEnv } = require("./config"); +const { getFreePort } = require('./util') +const dateFormat = require('dateformat') +const fs = require('fs') +const { spawnSync, spawn, execSync } = require('child_process') +const { expect } = require('chai') +const { createEnv } = require('./config') -let outputProcess; +let outputProcess class MiningNodeProcess { - constructor(name, baseNodeAddress, walletAddress, mineOnTipOnly = true) { - this.name = `MiningNode-${name}`; - this.maxBlocks = 1; - this.minDiff = 0; - this.maxDiff = 100000; - this.nodeAddress = baseNodeAddress.split(":")[0]; - this.nodeGrpcPort = baseNodeAddress.split(":")[1]; - this.walletAddress = walletAddress.split(":")[0]; - this.walletGrpcPort = walletAddress.split(":")[1]; - this.mineOnTipOnly = mineOnTipOnly; + constructor (name, baseNodeAddress, walletAddress, mineOnTipOnly = true) { + this.name = `MiningNode-${name}` + this.maxBlocks = 1 + this.minDiff = 0 + this.maxDiff = 100000 + this.nodeAddress = baseNodeAddress.split(':')[0] + this.nodeGrpcPort = baseNodeAddress.split(':')[1] + this.walletAddress = walletAddress.split(':')[0] + this.walletGrpcPort = walletAddress.split(':')[1] + this.mineOnTipOnly = mineOnTipOnly } - async init(maxBlocks, minDiff, maxDiff, mineOnTipOnly) { - this.maxBlocks = maxBlocks || this.maxBlocks; - this.minDiff = minDiff || this.minDiff; - this.maxDiff = maxDiff || this.maxDiff; + async init (maxBlocks, minDiff, maxDiff, mineOnTipOnly) { + this.maxBlocks = maxBlocks || this.maxBlocks + this.minDiff = minDiff || this.minDiff + this.maxDiff = maxDiff || this.maxDiff this.baseDir = `./temp/base_nodes/${dateFormat( new Date(), - "yyyymmddHHMM" - )}/${this.name}`; - this.mineOnTipOnly = mineOnTipOnly || this.mineOnTipOnly; + 'yyyymmddHHMM' + )}/${this.name}` + this.mineOnTipOnly = mineOnTipOnly || this.mineOnTipOnly } - run(cmd, args, saveFile) { + run (cmd, args, saveFile) { return new Promise((resolve, reject) => { if (!fs.existsSync(this.baseDir)) { - fs.mkdirSync(this.baseDir, { recursive: true }); - fs.mkdirSync(this.baseDir + "/log", { recursive: true }); + fs.mkdirSync(this.baseDir, { recursive: true }) + fs.mkdirSync(this.baseDir + '/log', { recursive: true }) } - let envs = createEnv( + const envs = createEnv( this.name, false, - "nodeid.json", + 'nodeid.json', this.walletAddress, this.walletGrpcPort, - "8080", + '8080', this.nodeAddress, this.nodeGrpcPort, this.baseNodePort, - "127.0.0.1:8084", + '127.0.0.1:8084', { mineOnTipOnly: this.mineOnTipOnly }, [] - ); + ) - var ps = spawn(cmd, args, { + const ps = spawn(cmd, args, { cwd: this.baseDir, // shell: true, - env: { ...process.env, ...envs }, - }); + env: { ...process.env, ...envs } + }) - ps.stdout.on("data", (data) => { - //console.log(`stdout: ${data}`); - fs.appendFileSync(`${this.baseDir}/log/stdout.log`, data.toString()); - resolve(ps); - }); + ps.stdout.on('data', (data) => { + // console.log(`stdout: ${data}`); + fs.appendFileSync(`${this.baseDir}/log/stdout.log`, data.toString()) + // resolve(ps); + }) - ps.stderr.on("data", (data) => { - console.error(`stderr: ${data}`); - fs.appendFileSync(`${this.baseDir}/log/stderr.log`, data.toString()); - }); + ps.stderr.on('data', (data) => { + console.error(`stderr: ${data}`) + fs.appendFileSync(`${this.baseDir}/log/stderr.log`, data.toString()) + }) - ps.on("close", (code) => { - let ps = this.ps; - this.ps = null; + ps.on('close', (code) => { + const ps = this.ps + this.ps = null if (code) { - console.log(`child process exited with code ${code}`); - reject(`child process exited with code ${code}`); + console.log(`child process exited with code ${code}`) + reject(`child process exited with code ${code}`) } else { - resolve(ps); + resolve(ps) } - }); + }) - expect(ps.error).to.be.an("undefined"); - this.ps = ps; - }); + expect(ps.error).to.be.an('undefined') + this.ps = ps + }) } - async startNew() { - await this.init(); + async startNew () { + await this.init() const args = [ - "--base-path", - ".", - "--init", - "--daemon", - "--max-blocks", + '--base-path', + '.', + '--init', + '--daemon', + '--max-blocks', this.maxBlocks, - "--min-difficulty", + '--min-difficulty', this.minDiff, - "--max-difficulty", - this.maxDiff, - ]; - return await this.run(await this.compile(), args, true); + '--max-difficulty', + this.maxDiff + ] + return await this.run(await this.compile(), args, true) } - async compile() { + async compile () { if (!outputProcess) { - await this.run("cargo", [ - "build", - "--release", - "--bin", - "tari_mining_node", - "-Z", - "unstable-options", - "--out-dir", - __dirname + "/../temp/out", - ]); - outputProcess = __dirname + "/../temp/out/tari_mining_node"; + await this.run('cargo', [ + 'build', + '--release', + '--bin', + 'tari_mining_node', + '-Z', + 'unstable-options', + '--out-dir', + __dirname + '/../temp/out' + ]) + outputProcess = __dirname + '/../temp/out/tari_mining_node' } - return outputProcess; + return outputProcess } - stop() { + stop () { return new Promise((resolve) => { if (!this.ps) { - return resolve(); + return resolve() } - this.ps.on("close", (code) => { + this.ps.on('close', (code) => { if (code) { - console.log(`child process exited with code ${code}`); + console.log(`child process exited with code ${code}`) } - resolve(); - }); - this.ps.kill("SIGINT"); - }); + resolve() + }) + this.ps.kill('SIGINT') + }) } } -module.exports = MiningNodeProcess; +module.exports = MiningNodeProcess diff --git a/integration_tests/helpers/transactionBuilder.js b/integration_tests/helpers/transactionBuilder.js index a636809c9b..f6c8030af6 100644 --- a/integration_tests/helpers/transactionBuilder.js +++ b/integration_tests/helpers/transactionBuilder.js @@ -1,111 +1,111 @@ -var tari_crypto = require("tari_crypto"); -var { blake2bInit, blake2bUpdate, blake2bFinal } = require("blakejs"); -const { toLittleEndian, hexSwitchEndianness } = require("../helpers/util"); +const tari_crypto = require('tari_crypto') +const { blake2bInit, blake2bUpdate, blake2bFinal } = require('blakejs') +const { toLittleEndian, hexSwitchEndianness } = require('../helpers/util') class TransactionBuilder { - constructor() { - this.kv = tari_crypto.KeyRing.new(); - this.inputs = []; - this.outputs = []; - this.fee = 100; - this.lockHeight = 0; + constructor () { + this.kv = tari_crypto.KeyRing.new() + this.inputs = [] + this.outputs = [] + this.fee = 100 + this.lockHeight = 0 } - generatePrivateKey(id) { - this.kv.new_key(id); - return this.kv.private_key(id); + generatePrivateKey (id) { + this.kv.new_key(id) + return this.kv.private_key(id) } - buildChallenge(publicNonce, fee, lockHeight) { - var KEY = null; // optional key - var OUTPUT_LENGTH = 32; // bytes - var context = blake2bInit(OUTPUT_LENGTH, KEY); - let buff = Buffer.from(publicNonce, "hex"); - blake2bUpdate(context, buff); - blake2bUpdate(context, toLittleEndian(fee, 64)); - blake2bUpdate(context, toLittleEndian(lockHeight, 64)); - let final = blake2bFinal(context); - return Buffer.from(final).toString("hex"); + buildChallenge (publicNonce, fee, lockHeight) { + const KEY = null // optional key + const OUTPUT_LENGTH = 32 // bytes + const context = blake2bInit(OUTPUT_LENGTH, KEY) + const buff = Buffer.from(publicNonce, 'hex') + blake2bUpdate(context, buff) + blake2bUpdate(context, toLittleEndian(fee, 64)) + blake2bUpdate(context, toLittleEndian(lockHeight, 64)) + const final = blake2bFinal(context) + return Buffer.from(final).toString('hex') } - changeFee(fee) { - this.fee = fee; + changeFee (fee) { + this.fee = fee } - addInput(input) { + addInput (input) { this.inputs.push({ input: input.output, amount: input.amount, - privateKey: input.privateKey, - }); + privateKey: input.privateKey + }) } - addOutput(amount) { - let outputFeatures = { + addOutput (amount) { + const outputFeatures = { flags: 0, - maturity: 0, - }; - let key = Math.floor(Math.random() * 500 + 1); - let privateKey = Buffer.from(toLittleEndian(key, 256)).toString("hex"); - let rangeproofFactory = tari_crypto.RangeProofFactory.new(); - let rangeproof = rangeproofFactory.create_proof(privateKey, BigInt(amount)) - .proof; - let output = { + maturity: 0 + } + const key = Math.floor(Math.random() * 500 + 1) + const privateKey = Buffer.from(toLittleEndian(key, 256)).toString('hex') + const rangeproofFactory = tari_crypto.RangeProofFactory.new() + const rangeproof = rangeproofFactory.create_proof(privateKey, BigInt(amount)) + .proof + const output = { amount: amount, privateKey: privateKey, output: { features: outputFeatures, commitment: Buffer.from( tari_crypto.commit(privateKey, BigInt(amount)).commitment, - "hex" + 'hex' ), - range_proof: Buffer.from(rangeproof, "hex"), - }, - }; - this.outputs.push(output); - return output; + range_proof: Buffer.from(rangeproof, 'hex') + } + } + this.outputs.push(output) + return output } - getSpendableAmount() { - let sum = 0; - this.inputs.forEach((input) => (sum = sum + input.amount)); - return sum - this.fee; + getSpendableAmount () { + let sum = 0 + this.inputs.forEach((input) => (sum = sum + input.amount)) + return sum - this.fee } - build() { - let totalPrivateKey = 0n; + build () { + let totalPrivateKey = 0n this.outputs.forEach( (output) => - (totalPrivateKey += BigInt("0x" + output.privateKey.toString())) - ); + (totalPrivateKey += BigInt('0x' + output.privateKey.toString())) + ) this.inputs.forEach( - (input) => (totalPrivateKey -= BigInt("0x" + input.privateKey.toString())) - ); + (input) => (totalPrivateKey -= BigInt('0x' + input.privateKey.toString())) + ) // Assume low numbers.... - let PrivateKey = totalPrivateKey.toString(16); + let PrivateKey = totalPrivateKey.toString(16) // we need to pad 0's in front while (PrivateKey.length < 64) { - PrivateKey = "0" + PrivateKey; + PrivateKey = '0' + PrivateKey } - let excess = tari_crypto.commit(PrivateKey, BigInt(0)); - let nonce = this.kv.new_key("common_nonce"); - let public_nonce = this.kv.public_key("common_nonce"); - let challenge = this.buildChallenge( + const excess = tari_crypto.commit(PrivateKey, BigInt(0)) + const nonce = this.kv.new_key('common_nonce') + const public_nonce = this.kv.public_key('common_nonce') + const challenge = this.buildChallenge( public_nonce, this.fee, this.lockHeight - ); - let private_nonce = this.kv.private_key("common_nonce"); - let sig = tari_crypto.sign_challenge_with_nonce( + ) + const private_nonce = this.kv.private_key('common_nonce') + const sig = tari_crypto.sign_challenge_with_nonce( PrivateKey, private_nonce, challenge - ); + ) return { - offset: Buffer.from(toLittleEndian(0, 256), "hex"), + offset: Buffer.from(toLittleEndian(0, 256), 'hex'), body: { inputs: this.inputs.map((i) => i.input), outputs: this.outputs.map((o) => o.output), @@ -114,60 +114,60 @@ class TransactionBuilder { features: 0, fee: this.fee, lock_height: this.lockHeight, - excess: Buffer.from(excess.commitment, "hex"), + excess: Buffer.from(excess.commitment, 'hex'), excess_sig: { - public_nonce: Buffer.from(sig.public_nonce, "hex"), - signature: Buffer.from(sig.signature, "hex"), - }, - }, - ], - }, - }; + public_nonce: Buffer.from(sig.public_nonce, 'hex'), + signature: Buffer.from(sig.signature, 'hex') + } + } + ] + } + } } - generateCoinbase(value, privateKey, fee, lockHeight) { - let coinbase = tari_crypto.commit(privateKey, BigInt(value + fee)); - let rangeproofFactory = tari_crypto.RangeProofFactory.new(); - let rangeproof = rangeproofFactory.create_proof( + generateCoinbase (value, privateKey, fee, lockHeight) { + const coinbase = tari_crypto.commit(privateKey, BigInt(value + fee)) + const rangeproofFactory = tari_crypto.RangeProofFactory.new() + const rangeproof = rangeproofFactory.create_proof( privateKey, BigInt(value + fee) - ).proof; - let excess = tari_crypto.commit(privateKey, BigInt(0)); - this.kv.new_key("nonce"); - let public_nonce = this.kv.public_key("nonce"); - let challenge = this.buildChallenge(public_nonce, 0, lockHeight); - let private_nonce = this.kv.private_key("nonce"); - let sig = tari_crypto.sign_challenge_with_nonce( + ).proof + const excess = tari_crypto.commit(privateKey, BigInt(0)) + this.kv.new_key('nonce') + const public_nonce = this.kv.public_key('nonce') + const challenge = this.buildChallenge(public_nonce, 0, lockHeight) + const private_nonce = this.kv.private_key('nonce') + const sig = tari_crypto.sign_challenge_with_nonce( privateKey, private_nonce, challenge - ); - let outputFeatures = { + ) + const outputFeatures = { flags: 1, - maturity: lockHeight, - }; + maturity: lockHeight + } return { outputs: [ { features: outputFeatures, - commitment: Buffer.from(coinbase.commitment, "hex"), - range_proof: Buffer.from(rangeproof, "hex"), - }, + commitment: Buffer.from(coinbase.commitment, 'hex'), + range_proof: Buffer.from(rangeproof, 'hex') + } ], kernels: [ { features: 1, fee: 0, lock_height: lockHeight, - excess: Buffer.from(excess.commitment, "hex"), + excess: Buffer.from(excess.commitment, 'hex'), excess_sig: { - public_nonce: Buffer.from(sig.public_nonce, "hex"), - signature: Buffer.from(sig.signature, "hex"), - }, - }, - ], - }; + public_nonce: Buffer.from(sig.public_nonce, 'hex'), + signature: Buffer.from(sig.signature, 'hex') + } + } + ] + } } } -module.exports = TransactionBuilder; +module.exports = TransactionBuilder diff --git a/integration_tests/helpers/util.js b/integration_tests/helpers/util.js index f0591af93e..4999ddb970 100644 --- a/integration_tests/helpers/util.js +++ b/integration_tests/helpers/util.js @@ -1,207 +1,207 @@ -const net = require("net"); -const fs = require("fs"); -const readline = require("readline"); +const net = require('net') +const fs = require('fs') +const readline = require('readline') -const { blake2bInit, blake2bUpdate, blake2bFinal } = require("blakejs"); +const { blake2bInit, blake2bUpdate, blake2bFinal } = require('blakejs') -function getRandomInt(min, max) { - min = Math.ceil(min); - max = Math.floor(max); - return Math.floor(Math.random() * (max - min + 1)) + min; +function getRandomInt (min, max) { + min = Math.ceil(min) + max = Math.floor(max) + return Math.floor(Math.random() * (max - min + 1)) + min } -function sleep(ms) { +function sleep (ms) { return new Promise((resolve) => { - setTimeout(resolve, ms); - }); + setTimeout(resolve, ms) + }) } -function withTimeout(ms, promise, message = "") { +function withTimeout (ms, promise, message = '') { const timeout = new Promise((_resolve, reject) => { setTimeout( () => reject(new Error(message || `Timed out after ${ms}ms`)), ms - ); - }); - return Promise.race([timeout, promise]); + ) + }) + return Promise.race([timeout, promise]) } -async function waitFor( +async function waitFor ( asyncTestFn, toBe, maxTime, timeOut = 500, skipLog = 50 ) { - let now = new Date(); + const now = new Date() - let i = 0; + let i = 0 while (new Date() - now < maxTime) { - const value = await asyncTestFn(); + const value = await asyncTestFn() if (value === toBe) { if (i > 1) { - console.log("waiting for process...", timeOut, i, value); + console.log('waiting for process...', timeOut, i, value) } - break; + break } if (i % skipLog === 0 && i > 1) { - console.log("waiting for process...", timeOut, i, value); + console.log('waiting for process...', timeOut, i, value) } - await sleep(timeOut); - i++; + await sleep(timeOut) + i++ } } -function dec2hex(n) { - return n ? [n % 256].concat(dec2hex(~~(n / 256))) : []; +function dec2hex (n) { + return n ? [n % 256].concat(dec2hex(~~(n / 256))) : [] } -function toLittleEndianInner(n) { - let hexar = dec2hex(n); +function toLittleEndianInner (n) { + const hexar = dec2hex(n) return hexar - .map((h) => (h < 16 ? "0" : "") + h.toString(16)) - .concat(Array(4 - hexar.length).fill("00")); + .map((h) => (h < 16 ? '0' : '') + h.toString(16)) + .concat(Array(4 - hexar.length).fill('00')) } -function toLittleEndian(n, numBits) { - let s = toLittleEndianInner(n); +function toLittleEndian (n, numBits) { + const s = toLittleEndianInner(n) for (let i = s.length; i < numBits / 8; i++) { - s.push("00"); + s.push('00') } - let arr = Buffer.from(s.join(""), "hex"); + const arr = Buffer.from(s.join(''), 'hex') - return arr; + return arr } -function hexSwitchEndianness(val) { - let res = ""; +function hexSwitchEndianness (val) { + let res = '' for (let i = val.length - 2; i > 0; i -= 2) { - res += val[i] + val[i + 1]; + res += val[i] + val[i + 1] } - return res; + return res } // Thanks to https://stackoverflow.com/questions/29860354/in-nodejs-how-do-i-check-if-a-port-is-listening-or-in-use -let portInUse = function (port, callback) { - let server = net.createServer(function (socket) { - socket.write("Echo server\r\n"); - socket.pipe(socket); - }); - - server.listen(port, "127.0.0.1"); - server.on("error", function (e) { - callback(true); - }); - server.on("listening", function (e) { - server.close(); - callback(false); - }); -}; - -let index = 0; -let getFreePort = async function (from, to) { - function testPort(port) { +const portInUse = function (port, callback) { + const server = net.createServer(function (socket) { + socket.write('Echo server\r\n') + socket.pipe(socket) + }) + + server.listen(port, '127.0.0.1') + server.on('error', function (e) { + callback(true) + }) + server.on('listening', function (e) { + server.close() + callback(false) + }) +} + +let index = 0 +const getFreePort = async function (from, to) { + function testPort (port) { return new Promise((r) => { portInUse(port, (v) => { if (v) { - r(false); + r(false) } - r(true); - }); - }); + r(true) + }) + }) } - let port = from + index; + let port = from + index if (port > to) { - index = from; - port = from; + index = from + port = from } while (port < to) { // let port = getRandomInt(from, to); // await sleep(100); - port++; - index++; - let notInUse = await testPort(port); + port++ + index++ + const notInUse = await testPort(port) // console.log("Port not in use:", notInUse); if (notInUse) { - return port; + return port } } -}; +} // WIP this doesn't hash properly const getTransactionOutputHash = function (output) { - let KEY = null; // optional key - let OUTPUT_LENGTH = 32; // bytes - let context = blake2bInit(OUTPUT_LENGTH, KEY); - let flags = Buffer.alloc(1); - flags[0] = output.features.flags; - let buffer = Buffer.concat([ + const KEY = null // optional key + const OUTPUT_LENGTH = 32 // bytes + const context = blake2bInit(OUTPUT_LENGTH, KEY) + const flags = Buffer.alloc(1) + flags[0] = output.features.flags + const buffer = Buffer.concat([ flags, - toLittleEndian(parseInt(output.features.maturity), 64), - ]); - blake2bUpdate(context, buffer); - blake2bUpdate(context, output.commitment); - let final = blake2bFinal(context); - return Buffer.from(final); -}; - -function consoleLogTransactionDetails(txnDetails, txId) { - let found = txnDetails[0]; - let status = txnDetails[1]; + toLittleEndian(parseInt(output.features.maturity), 64) + ]) + blake2bUpdate(context, buffer) + blake2bUpdate(context, output.commitment) + const final = blake2bFinal(context) + return Buffer.from(final) +} + +function consoleLogTransactionDetails (txnDetails, txId) { + const found = txnDetails[0] + const status = txnDetails[1] if (found) { console.log( - " Transaction " + - pad("'" + status.transactions[0]["tx_id"] + "'", 24) + - " has status " + - pad("'" + status.transactions[0]["status"] + "'", 40) + - " and " + + ' Transaction ' + + pad("'" + status.transactions[0].tx_id + "'", 24) + + ' has status ' + + pad("'" + status.transactions[0].status + "'", 40) + + ' and ' + pad( - "is_cancelled(" + status.transactions[0]["is_cancelled"] + ")", + 'is_cancelled(' + status.transactions[0].is_cancelled + ')', 21 ) + - " and " + - pad("is_valid(" + status.transactions[0]["valid"] + ")", 16) - ); + ' and ' + + pad('is_valid(' + status.transactions[0].valid + ')', 16) + ) } else { - console.log(" Transaction '" + txId + "' " + status); + console.log(" Transaction '" + txId + "' " + status) } } -function consoleLogBalance(balance) { +function consoleLogBalance (balance) { console.log( - " Available " + - pad(balance["available_balance"], 16) + - " uT, Pending incoming " + - pad(balance["pending_incoming_balance"], 16) + - " uT, Pending outgoing " + - pad(balance["pending_outgoing_balance"], 16) + - " uT" - ); + ' Available ' + + pad(balance.available_balance, 16) + + ' uT, Pending incoming ' + + pad(balance.pending_incoming_balance, 16) + + ' uT, Pending outgoing ' + + pad(balance.pending_outgoing_balance, 16) + + ' uT' + ) } -function consoleLogCoinbaseDetails(txnDetails) { +function consoleLogCoinbaseDetails (txnDetails) { console.log( - " Transaction " + - pad("'" + txnDetails["tx_id"] + "'", 24) + - " has status " + - pad("'" + txnDetails["status"] + "'", 40) + - " and " + - pad("is_cancelled(" + txnDetails["is_cancelled"] + ")", 21) + - " and " + - pad("is_valid(" + txnDetails["valid"] + ")", 16) - ); -} - -function pad(str, length, padLeft = true) { - let padding = Array(length).join(" "); - if (typeof str === "undefined") return padding; + ' Transaction ' + + pad("'" + txnDetails.tx_id + "'", 24) + + ' has status ' + + pad("'" + txnDetails.status + "'", 40) + + ' and ' + + pad('is_cancelled(' + txnDetails.is_cancelled + ')', 21) + + ' and ' + + pad('is_valid(' + txnDetails.valid + ')', 16) + ) +} + +function pad (str, length, padLeft = true) { + const padding = Array(length).join(' ') + if (typeof str === 'undefined') return padding if (padLeft) { - return (padding + str).slice(-padding.length); + return (padding + str).slice(-padding.length) } else { - return (str + padding).substring(" ", padding.length); + return (str + padding).substring(' ', padding.length) } } @@ -217,5 +217,5 @@ module.exports = { consoleLogTransactionDetails, consoleLogBalance, consoleLogCoinbaseDetails, - withTimeout, -}; + withTimeout +} diff --git a/integration_tests/helpers/walletClient.js b/integration_tests/helpers/walletClient.js index fd465dd18a..8a4990a239 100644 --- a/integration_tests/helpers/walletClient.js +++ b/integration_tests/helpers/walletClient.js @@ -1,275 +1,275 @@ -const { Client } = require("wallet-grpc-client"); -const { sleep } = require("./util"); +const { Client } = require('wallet-grpc-client') +const { sleep } = require('./util') -function transactionStatus() { +function transactionStatus () { return [ - "TRANSACTION_STATUS_IMPORTED", - "TRANSACTION_STATUS_COINBASE", - "TRANSACTION_STATUS_PENDING", - "TRANSACTION_STATUS_COMPLETED", - "TRANSACTION_STATUS_BROADCAST", - "TRANSACTION_STATUS_MINED_UNCONFIRMED", - "TRANSACTION_STATUS_MINED_CONFIRMED", - ]; + 'TRANSACTION_STATUS_IMPORTED', + 'TRANSACTION_STATUS_COINBASE', + 'TRANSACTION_STATUS_PENDING', + 'TRANSACTION_STATUS_COMPLETED', + 'TRANSACTION_STATUS_BROADCAST', + 'TRANSACTION_STATUS_MINED_UNCONFIRMED', + 'TRANSACTION_STATUS_MINED_CONFIRMED' + ] } class WalletClient { - constructor(walletAddress, name) { - this.client = Client.connect(walletAddress); - this.name = name; + constructor (walletAddress, name) { + this.client = Client.connect(walletAddress) + this.name = name } - async getVersion() { - return await this.client.getVersion(); + async getVersion () { + return await this.client.getVersion() } - async getBalance() { - return await this.client.getBalance(); + async getBalance () { + return await this.client.getBalance() } - async getCompletedTransactions() { - let data = await this.client.getCompletedTransactions(); - let transactions = []; - let myDate = new Date(); - for (var i = 0; i < data.length; i++) { + async getCompletedTransactions () { + const data = await this.client.getCompletedTransactions() + const transactions = [] + const myDate = new Date() + for (let i = 0; i < data.length; i++) { transactions.push({ - tx_id: data[i].transaction["tx_id"], - source_pk: data[i].transaction["source_pk"].toString("hex"), - dest_pk: data[i].transaction["dest_pk"].toString("hex"), - status: data[i].transaction["status"], - direction: data[i].transaction["direction"], - amount: data[i].transaction["amount"], - fee: data[i].transaction["fee"], - is_cancelled: data[i].transaction["is_cancelled"], - excess_sig: data[i].transaction["excess_sig"].toString("hex"), + tx_id: data[i].transaction.tx_id, + source_pk: data[i].transaction.source_pk.toString('hex'), + dest_pk: data[i].transaction.dest_pk.toString('hex'), + status: data[i].transaction.status, + direction: data[i].transaction.direction, + amount: data[i].transaction.amount, + fee: data[i].transaction.fee, + is_cancelled: data[i].transaction.is_cancelled, + excess_sig: data[i].transaction.excess_sig.toString('hex'), timestamp: new Date( - Number(data[i].transaction["timestamp"]["seconds"]) * 1000 + Number(data[i].transaction.timestamp.seconds) * 1000 ), - message: data[i].transaction["message"], - valid: data[i].transaction["valid"], - }); + message: data[i].transaction.message, + valid: data[i].transaction.valid + }) } - return transactions; + return transactions } - async getAllCoinbaseTransactions() { - let data = await this.getCompletedTransactions(); - let transactions = []; - for (var i = 0; i < data.length; i++) { + async getAllCoinbaseTransactions () { + const data = await this.getCompletedTransactions() + const transactions = [] + for (let i = 0; i < data.length; i++) { if ( - data[i]["message"].includes("Coinbase Transaction for Block ") && - data[i]["fee"] == 0 + data[i].message.includes('Coinbase Transaction for Block ') && + data[i].fee == 0 ) { - transactions.push(data[i]); + transactions.push(data[i]) } } - return transactions; + return transactions } - async getAllSpendableCoinbaseTransactions() { - let data = await this.getAllCoinbaseTransactions(); - let transactions = []; - for (var i = 0; i < data.length; i++) { + async getAllSpendableCoinbaseTransactions () { + const data = await this.getAllCoinbaseTransactions() + const transactions = [] + for (let i = 0; i < data.length; i++) { if ( - transactionStatus().indexOf(data[i]["status"]) == 6 && - data[i]["valid"] == true + transactionStatus().indexOf(data[i].status) == 6 && + data[i].valid == true ) { - transactions.push(data[i]); + transactions.push(data[i]) } } - return transactions; + return transactions } - async areCoinbasesConfirmedAtLeast(number) { - let data = await this.getAllSpendableCoinbaseTransactions(); + async areCoinbasesConfirmedAtLeast (number) { + const data = await this.getAllSpendableCoinbaseTransactions() if (data.length >= number) { - return true; + return true } else { - return false; + return false } } - async getAllNormalTransactions() { - let data = this.getCompletedTransactions(); - let transactions = []; - for (var i = 0; i < data.length; i++) { + async getAllNormalTransactions () { + const data = this.getCompletedTransactions() + const transactions = [] + for (let i = 0; i < data.length; i++) { if ( !( - data[i]["message"].includes("Coinbase Transaction for Block ") && - data[i]["fee"] == 0 + data[i].message.includes('Coinbase Transaction for Block ') && + data[i].fee == 0 ) ) { - transactions.push(data[i]); + transactions.push(data[i]) } } - return transactions; + return transactions } - async transfer(args) { - return await this.client.transfer(args); + async transfer (args) { + return await this.client.transfer(args) } - async getTransactionInfo(args) { - return await this.client.getTransactionInfo(args); + async getTransactionInfo (args) { + return await this.client.getTransactionInfo(args) } - async identify(args) { - let info = await this.client.identify(args); + async identify (args) { + const info = await this.client.identify(args) return { - public_key: info["public_key"].toString("utf8"), - public_address: info["public_address"], - node_id: info["node_id"].toString("utf8"), - }; + public_key: info.public_key.toString('utf8'), + public_address: info.public_address, + node_id: info.node_id.toString('utf8') + } } - async isTransactionRegistered(tx_id) { + async isTransactionRegistered (tx_id) { try { await this.getTransactionInfo({ - transaction_ids: [tx_id.toString()], - }); - return true; + transaction_ids: [tx_id.toString()] + }) + return true } catch (err) { // Any error here must be treated as if the required status was not achieved - return false; + return false } } - async isBalanceAtLeast(amount) { + async isBalanceAtLeast (amount) { try { - let balance = await this.getBalance(); - if (balance["available_balance"] >= amount) { - return true; + const balance = await this.getBalance() + if (balance.available_balance >= amount) { + return true } else { - return false; + return false } } catch (err) { // Any error here must be treated as if the required status was not achieved - return false; + return false } } - async isTransactionAtLeastPending(tx_id) { + async isTransactionAtLeastPending (tx_id) { try { - let txnDetails = await this.getTransactionInfo({ - transaction_ids: [tx_id.toString()], - }); + const txnDetails = await this.getTransactionInfo({ + transaction_ids: [tx_id.toString()] + }) if ( - transactionStatus().indexOf(txnDetails.transactions[0]["status"]) >= 2 + transactionStatus().indexOf(txnDetails.transactions[0].status) >= 2 ) { - return true; + return true } else { - return false; + return false } } catch (err) { // Any error here must be treated as if the required status was not achieved - return false; + return false } } - async isTransactionAtLeastCompleted(tx_id) { + async isTransactionAtLeastCompleted (tx_id) { try { - let txnDetails = await this.getTransactionInfo({ - transaction_ids: [tx_id.toString()], - }); + const txnDetails = await this.getTransactionInfo({ + transaction_ids: [tx_id.toString()] + }) if ( - transactionStatus().indexOf(txnDetails.transactions[0]["status"]) >= 3 + transactionStatus().indexOf(txnDetails.transactions[0].status) >= 3 ) { - return true; + return true } else { - return false; + return false } } catch (err) { // Any error here must be treated as if the required status was not achieved - return false; + return false } } - async isTransactionAtLeastBroadcast(tx_id) { + async isTransactionAtLeastBroadcast (tx_id) { try { - let txnDetails = await this.getTransactionInfo({ - transaction_ids: [tx_id.toString()], - }); + const txnDetails = await this.getTransactionInfo({ + transaction_ids: [tx_id.toString()] + }) if ( - transactionStatus().indexOf(txnDetails.transactions[0]["status"]) >= 4 + transactionStatus().indexOf(txnDetails.transactions[0].status) >= 4 ) { - return true; + return true } else { - return false; + return false } } catch (err) { // Any error here must be treated as if the required status was not achieved - return false; + return false } } - async isTransactionAtLeastMinedUnconfirmed(tx_id) { + async isTransactionAtLeastMinedUnconfirmed (tx_id) { try { - let txnDetails = await this.getTransactionInfo({ - transaction_ids: [tx_id.toString()], - }); + const txnDetails = await this.getTransactionInfo({ + transaction_ids: [tx_id.toString()] + }) if ( - transactionStatus().indexOf(txnDetails.transactions[0]["status"]) >= 5 + transactionStatus().indexOf(txnDetails.transactions[0].status) >= 5 ) { - return true; + return true } else { - return false; + return false } } catch (err) { // Any error here must be treated as if the required status was not achieved - return false; + return false } } - async isTransactionMinedUnconfirmed(tx_id) { + async isTransactionMinedUnconfirmed (tx_id) { try { - let txnDetails = await this.getTransactionInfo({ - transaction_ids: [tx_id.toString()], - }); + const txnDetails = await this.getTransactionInfo({ + transaction_ids: [tx_id.toString()] + }) if ( - transactionStatus().indexOf(txnDetails.transactions[0]["status"]) == 5 + transactionStatus().indexOf(txnDetails.transactions[0].status) == 5 ) { - return true; + return true } else { - return false; + return false } } catch (err) { // Any error here must be treated as if the required status was not achieved - return false; + return false } } - async isTransactionMinedConfirmed(tx_id) { + async isTransactionMinedConfirmed (tx_id) { try { - let txnDetails = await this.getTransactionInfo({ - transaction_ids: [tx_id.toString()], - }); + const txnDetails = await this.getTransactionInfo({ + transaction_ids: [tx_id.toString()] + }) if ( - transactionStatus().indexOf(txnDetails.transactions[0]["status"]) == 6 + transactionStatus().indexOf(txnDetails.transactions[0].status) == 6 ) { - return true; + return true } else { - return false; + return false } } catch (err) { // Any error here must be treated as if the required status was not achieved - return false; + return false } } - async getTransactionDetails(tx_id) { + async getTransactionDetails (tx_id) { try { - let txnDetails = await this.getTransactionInfo({ - transaction_ids: [tx_id.toString()], - }); - return [true, txnDetails]; + const txnDetails = await this.getTransactionInfo({ + transaction_ids: [tx_id.toString()] + }) + return [true, txnDetails] } catch (err) { - return [false, err]; + return [false, err] } } - async coin_split(args) { - return await this.client.coinSplit(args); + async coin_split (args) { + return await this.client.coinSplit(args) } } -module.exports = WalletClient; +module.exports = WalletClient diff --git a/integration_tests/helpers/walletProcess.js b/integration_tests/helpers/walletProcess.js index 1ff4714c0b..6b4f5ece12 100644 --- a/integration_tests/helpers/walletProcess.js +++ b/integration_tests/helpers/walletProcess.js @@ -1,168 +1,168 @@ -const { getFreePort } = require("./util"); -const dateFormat = require("dateformat"); -const fs = require("fs"); -const path = require("path"); -const { spawn} = require("child_process"); -const { expect } = require("chai"); -const { createEnv } = require("./config"); -const WalletClient = require("./walletClient"); +const { getFreePort } = require('./util') +const dateFormat = require('dateformat') +const fs = require('fs') +const path = require('path') +const { spawn } = require('child_process') +const { expect } = require('chai') +const { createEnv } = require('./config') +const WalletClient = require('./walletClient') -let outputProcess; +let outputProcess class WalletProcess { - constructor(name, options, logFilePath, seedWords) { - this.name = name; - this.options = options; - this.logFilePath = logFilePath ? path.resolve(logFilePath) : logFilePath; - this.recoverWallet = !!seedWords; - this.seedWords = seedWords; + constructor (name, options, logFilePath, seedWords) { + this.name = name + this.options = options + this.logFilePath = logFilePath ? path.resolve(logFilePath) : logFilePath + this.recoverWallet = !!seedWords + this.seedWords = seedWords } - async init() { - this.port = await getFreePort(19000, 25000); - this.name = `Wallet${this.port}-${this.name}`; - this.grpcPort = await getFreePort(19000, 25000); + async init () { + this.port = await getFreePort(19000, 25000) + this.name = `Wallet${this.port}-${this.name}` + this.grpcPort = await getFreePort(19000, 25000) this.baseDir = `./temp/base_nodes/${dateFormat( new Date(), - "yyyymmddHHMM" - )}/${this.name}`; - this.seedWordsFile = path.resolve(this.baseDir + "/config/seed_words.log"); + 'yyyymmddHHMM' + )}/${this.name}` + this.seedWordsFile = path.resolve(this.baseDir + '/config/seed_words.log') } - getGrpcAddress() { - return "127.0.0.1:" + this.grpcPort; + getGrpcAddress () { + return '127.0.0.1:' + this.grpcPort } - getClient() { - return new WalletClient(this.getGrpcAddress(), this.name); + getClient () { + return new WalletClient(this.getGrpcAddress(), this.name) } - getSeedWords() { + getSeedWords () { try { - return fs.readFileSync(this.seedWordsFile, "utf8"); + return fs.readFileSync(this.seedWordsFile, 'utf8') } catch (err) { - console.error("\n", this.name, ": Seed words file not found!\n", err); + console.error('\n', this.name, ': Seed words file not found!\n', err) } } - setPeerSeeds(addresses) { - this.peerSeeds = addresses.join(","); + setPeerSeeds (addresses) { + this.peerSeeds = addresses.join(',') } - run(cmd, args, saveFile) { + run (cmd, args, saveFile) { return new Promise((resolve, reject) => { if (!fs.existsSync(this.baseDir)) { - fs.mkdirSync(this.baseDir, { recursive: true }); - fs.mkdirSync(this.baseDir + "/log", { recursive: true }); + fs.mkdirSync(this.baseDir, { recursive: true }) + fs.mkdirSync(this.baseDir + '/log', { recursive: true }) } - let envs = createEnv( + const envs = createEnv( this.name, true, - "cwalletid.json", - "127.0.0.1", + 'cwalletid.json', + '127.0.0.1', this.grpcPort, this.port, - "127.0.0.1", - "8080", - "8081", - "127.0.0.1:8084", + '127.0.0.1', + '8080', + '8081', + '127.0.0.1:8084', this.options, this.peerSeeds - ); + ) if (saveFile) { - fs.appendFileSync(`${this.baseDir}/.env`, JSON.stringify(envs)); + fs.appendFileSync(`${this.baseDir}/.env`, JSON.stringify(envs)) } const ps = spawn(cmd, args, { cwd: this.baseDir, // shell: true, - env: {...process.env, ...envs}, - }); + env: { ...process.env, ...envs } + }) - ps.stdout.on("data", (data) => { - //console.log(`stdout: ${data}`); - fs.appendFileSync(`${this.baseDir}/log/stdout.log`, data.toString()); + ps.stdout.on('data', (data) => { + // console.log(`stdout: ${data}`); + fs.appendFileSync(`${this.baseDir}/log/stdout.log`, data.toString()) if (data.toString().match(/Starting grpc server/)) { - resolve(ps); + resolve(ps) } - }); + }) - ps.stderr.on("data", (data) => { - console.error(`stderr: ${data}`); - fs.appendFileSync(`${this.baseDir}/log/stderr.log`, data.toString()); - }); + ps.stderr.on('data', (data) => { + console.error(`stderr: ${data}`) + fs.appendFileSync(`${this.baseDir}/log/stderr.log`, data.toString()) + }) - ps.on("close", (code) => { - let ps = this.ps; - this.ps = null; + ps.on('close', (code) => { + const ps = this.ps + this.ps = null if (code) { - console.log(`child process exited with code ${code}`); - reject(`child process exited with code ${code}`); + console.log(`child process exited with code ${code}`) + reject(`child process exited with code ${code}`) } else { - resolve(ps); + resolve(ps) } - }); + }) - expect(ps.error).to.be.an("undefined"); - this.ps = ps; - }); + expect(ps.error).to.be.an('undefined') + this.ps = ps + }) } - async startNew() { - await this.init(); - let args; + async startNew () { + await this.init() + let args args = [ - "--base-path", - ".", - "--init", - "--create_id", - "--password", - "kensentme", - "--seed-words-file-name", + '--base-path', + '.', + '--init', + '--create_id', + '--password', + 'kensentme', + '--seed-words-file-name', this.seedWordsFile, - "--daemon", - ]; + '--daemon' + ] if (this.recoverWallet) { - args.push("--recover", "--seed-words", this.seedWords); + args.push('--recover', '--seed-words', this.seedWords) } if (this.logFilePath) { - args.push("--log-config", this.logFilePath); + args.push('--log-config', this.logFilePath) } - return await this.run(await this.compile(), args, true); + return await this.run(await this.compile(), args, true) } - async compile() { + async compile () { if (!outputProcess) { - await this.run("cargo", [ - "build", - "--release", - "--bin", - "tari_console_wallet", - "-Z", - "unstable-options", - "--out-dir", - __dirname + "/../temp/out", - ]); - outputProcess = __dirname + "/../temp/out/tari_console_wallet"; + await this.run('cargo', [ + 'build', + '--release', + '--bin', + 'tari_console_wallet', + '-Z', + 'unstable-options', + '--out-dir', + __dirname + '/../temp/out' + ]) + outputProcess = __dirname + '/../temp/out/tari_console_wallet' } - return outputProcess; + return outputProcess } - stop() { + stop () { return new Promise((resolve) => { if (!this.ps) { - return resolve(); + return resolve() } - this.ps.on("close", (code) => { + this.ps.on('close', (code) => { if (code) { - console.log(`child process exited with code ${code}`); + console.log(`child process exited with code ${code}`) } - resolve(); - }); - this.ps.kill("SIGINT"); - }); + resolve() + }) + this.ps.kill('SIGINT') + }) } } -module.exports = WalletProcess; +module.exports = WalletProcess diff --git a/integration_tests/package-lock.json b/integration_tests/package-lock.json index 5ed7baaa45..adb1f3a328 100644 --- a/integration_tests/package-lock.json +++ b/integration_tests/package-lock.json @@ -4,6 +4,45 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", + "dev": true + }, + "@babel/highlight": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", + "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.0", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, "@babel/runtime-corejs3": { "version": "7.13.7", "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.13.7.tgz", @@ -14,6 +53,46 @@ "regenerator-runtime": "^0.13.4" } }, + "@eslint/eslintrc": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", + "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } + } + }, "@grpc/grpc-js": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.2.8.tgz", @@ -97,6 +176,12 @@ "@types/node": "*" } }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, "@types/long": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", @@ -121,6 +206,18 @@ "event-target-shim": "^5.0.0" } }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true + }, "agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -129,6 +226,39 @@ "debug": "4" } }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, "any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -151,6 +281,39 @@ "readable-stream": "^2.0.6" } }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-includes": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", + "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.5" + } + }, + "array.prototype.flat": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", + "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + } + }, "arrify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", @@ -189,6 +352,12 @@ "repeat-string": "^1.6.1" } }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, "axios": { "version": "0.21.1", "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", @@ -280,6 +449,22 @@ } } }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, "camelcase": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", @@ -300,6 +485,57 @@ "type-detect": "^4.0.5" } }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", @@ -459,6 +695,12 @@ "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, "core-js-pure": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.9.0.tgz", @@ -471,6 +713,17 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, "cucumber": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cucumber/-/cucumber-6.0.5.tgz", @@ -702,6 +955,21 @@ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -720,6 +988,15 @@ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "duration": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/duration/-/duration-0.2.2.tgz", @@ -738,6 +1015,30 @@ "safe-buffer": "^5.0.1" } }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, "error-stack-parser": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.6.tgz", @@ -747,6 +1048,41 @@ "stackframe": "^1.1.1" } }, + "es-abstract": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", + "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.2", + "is-string": "^1.0.5", + "object-inspect": "^1.9.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.0" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, "es5-ext": { "version": "0.10.53", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", @@ -785,6 +1121,318 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, + "eslint": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.25.0.tgz", + "integrity": "sha512-TVpSovpvCNpLURIScDRB6g5CYu/ZFq9GfX2hLNIV4dSBKxIWojeDODvYl3t0k0VtMxYeR8OXPCFE5+oHMlGfhw==", + "dev": true, + "requires": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.21", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.4", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + } + } + }, + "eslint-config-standard": { + "version": "16.0.2", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.2.tgz", + "integrity": "sha512-fx3f1rJDsl9bY7qzyX8SAtP8GBSk6MfXFaTfaGgk12aAYW4gJSyRm7dM790L6cbXv63fvjY4XeSzXnb4WM+SKw==", + "dev": true + }, + "eslint-import-resolver-node": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-module-utils": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", + "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-es": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", + "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", + "dev": true, + "requires": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + } + }, + "eslint-plugin-import": { + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", + "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "array.prototype.flat": "^1.2.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.4", + "eslint-module-utils": "^2.6.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.1", + "read-pkg-up": "^2.0.0", + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-node": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", + "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", + "dev": true, + "requires": { + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "dependencies": { + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + } + } + }, + "eslint-plugin-promise": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.3.1.tgz", + "integrity": "sha512-bY2sGqyptzFBDLh/GMbAxfdJC+b0f23ME63FOE4+Jao0oZ3E1LEwFtWJX/1pGMJLiTtrSSern2CRM/g+dfc0eQ==", + "dev": true + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, "event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", @@ -818,6 +1466,24 @@ "integrity": "sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=", "dev": true }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, "fast-text-encoding": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", @@ -832,6 +1498,15 @@ "escape-string-regexp": "^1.0.5" } }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, "file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -846,6 +1521,31 @@ "traverse-chain": "~0.1.0" } }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", + "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", + "dev": true + }, "follow-redirects": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.2.tgz", @@ -894,6 +1594,12 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", @@ -974,6 +1680,17 @@ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -988,6 +1705,32 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.8.0.tgz", + "integrity": "sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + }, + "dependencies": { + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, "google-auth-library": { "version": "6.1.6", "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.1.6.tgz", @@ -1070,6 +1813,24 @@ "function-bind": "^1.1.1" } }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -1081,6 +1842,12 @@ "resolved": "https://registry.npmjs.org/hex64/-/hex64-0.4.0.tgz", "integrity": "sha1-rRB4rIHVfXLeYjKxADvE9vsCh8A=" }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, "https-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", @@ -1104,6 +1871,12 @@ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, "ignore-walk": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", @@ -1113,6 +1886,22 @@ "minimatch": "^3.0.4" } }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, "indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", @@ -1147,6 +1936,33 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-bigint": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", + "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", + "dev": true + }, + "is-boolean-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", + "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } + }, + "is-callable": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "dev": true + }, "is-core-module": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", @@ -1156,12 +1972,51 @@ "has": "^1.0.3" } }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, "is-generator": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-generator/-/is-generator-1.0.3.tgz", "integrity": "sha1-wUwhBX7TbjKNuANHlmxpP4hjifM=", "dev": true }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true + }, + "is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "dev": true + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -1170,11 +2025,36 @@ "isobject": "^3.0.1" } }, + "is-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", + "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.1" + } + }, "is-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, "is-wsl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", @@ -1187,6 +2067,12 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", @@ -1198,12 +2084,49 @@ "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", "dev": true }, - "json-bigint": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", - "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "requires": { + "bignumber.js": "^9.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, "requires": { - "bignumber.js": "^9.0.0" + "minimist": "^1.2.0" } }, "jsonfile": { @@ -1258,6 +2181,38 @@ "invert-kv": "^1.0.0" } }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -1275,12 +2230,30 @@ "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", "dev": true }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true + }, "lodash.toarray": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=", "dev": true }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, "long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", @@ -1367,6 +2340,12 @@ "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", "dev": true }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, "needle": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz", @@ -1464,6 +2443,26 @@ "osenv": "^0.1.4" } }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, "npm-bundled": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", @@ -1514,6 +2513,42 @@ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, + "object-inspect": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.2.tgz", + "integrity": "sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.values": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", + "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2", + "has": "^1.0.3" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1532,6 +2567,20 @@ "is-wsl": "^1.1.0" } }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, "optjs": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", @@ -1569,6 +2618,30 @@ "os-tmpdir": "^1.0.0" } }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, "pad-right": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/pad-right/-/pad-right-0.2.2.tgz", @@ -1578,24 +2651,84 @@ "repeat-string": "^1.5.2" } }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, "pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, "prettier": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", @@ -1634,6 +2767,12 @@ "long": "^4.0.0" } }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -1646,6 +2785,27 @@ "strip-json-comments": "~2.0.1" } }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -1675,12 +2835,24 @@ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", "dev": true }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true + }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, "resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", @@ -1691,6 +2863,21 @@ "path-parse": "^1.0.6" } }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1750,12 +2937,102 @@ "kind-of": "^6.0.2" } }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", + "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, "stack-chain": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/stack-chain/-/stack-chain-2.0.0.tgz", @@ -1812,6 +3089,37 @@ "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", "dev": true }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -1829,12 +3137,36 @@ } } }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, "synchronized-promise": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/synchronized-promise/-/synchronized-promise-0.3.1.tgz", @@ -1843,6 +3175,41 @@ "deasync": "^0.1.15" } }, + "table": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.6.0.tgz", + "integrity": "sha512-iZMtp5tUvcnAdtHpZTWLPF0M7AgiQsURR2DwmxnJwSy8I3+cY+ozzVvYha3BOLG2TB+L0CqjIz+91htuj6yCXg==", + "dev": true, + "requires": { + "ajv": "^8.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.2.0.tgz", + "integrity": "sha512-WSNGFuyWd//XO8n/m/EaOlNLtO0yL8EXT/74LqT4khdhpZjP7lkj/kT5uwRmGitKEVp/Oj7ZUHeGfPtgHhQ5CA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } + } + }, "tar": { "version": "4.4.13", "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", @@ -1871,6 +3238,12 @@ "resolved": "https://registry.npmjs.org/tari_crypto/-/tari_crypto-0.8.0.tgz", "integrity": "sha512-s5HGopz81fppphP83nG8FL0MzhIy2h0chkmef2P88YUS7d9AmsTpAuqZBkNG2PIfxoWSqOSXtfOU66vZXG9d1Q==" }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, "thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -1922,12 +3295,33 @@ "integrity": "sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE=", "dev": true }, + "tsconfig-paths": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", + "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, "type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", "dev": true }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -1940,6 +3334,18 @@ "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", "dev": true }, + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + } + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -1952,6 +3358,15 @@ "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", "dev": true }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, "util-arity": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/util-arity/-/util-arity-1.1.0.tgz", @@ -1970,6 +3385,22 @@ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "dev": true }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -1990,6 +3421,28 @@ "grpc-promise": "^1.4.0" } }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", @@ -2038,6 +3491,12 @@ "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", "dev": true }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", diff --git a/integration_tests/package.json b/integration_tests/package.json index 46fff6b261..50320a9b33 100644 --- a/integration_tests/package.json +++ b/integration_tests/package.json @@ -19,6 +19,11 @@ "cucumber": "^6.0.5", "cucumber-html-reporter": "^5.3.0", "cucumber-pretty": "^6.0.0", + "eslint": "^7.25.0", + "eslint-config-standard": "^16.0.2", + "eslint-plugin-import": "^2.22.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^4.3.1", "grpc": "^1.24.3", "grpc-promise": "^1.4.0", "prettier": "^2.2.1" From 00e8a59a123d2745aa1050e292195de31e7d0027 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Fri, 7 May 2021 13:55:23 +0200 Subject: [PATCH 2/2] [tests] eslint config and husky pre-commit hook - update eslint config to play nicely with prettier - fix lint issues - add husky to run pre-commit hook - add pre-commit hook to run prettier and lint check if files in integration_tests have been staged for commit Tested on macOS and windows --- .circleci/config.yml | 2 +- integration_tests/.eslintrc.json | 34 +- integration_tests/.husky/.gitignore | 1 + integration_tests/.husky/pre-commit | 13 + integration_tests/.prettierrc | 3 + integration_tests/cucumber.js | 6 +- integration_tests/features/support/steps.js | 1930 ++++++++--------- integration_tests/features/support/world.js | 262 ++- integration_tests/generate_report.js | 14 +- integration_tests/helpers/baseNodeClient.js | 294 +-- integration_tests/helpers/baseNodeProcess.js | 206 +- integration_tests/helpers/config.js | 149 +- .../helpers/mergeMiningProxyClient.js | 84 +- .../helpers/mergeMiningProxyProcess.js | 163 +- .../helpers/miningNodeProcess.js | 167 +- .../helpers/transactionBuilder.js | 183 +- integration_tests/helpers/util.js | 225 +- integration_tests/helpers/walletClient.js | 246 +-- integration_tests/helpers/walletProcess.js | 198 +- integration_tests/package-lock.json | 544 +---- integration_tests/package.json | 14 +- 21 files changed, 2215 insertions(+), 2523 deletions(-) create mode 100644 integration_tests/.husky/.gitignore create mode 100755 integration_tests/.husky/pre-commit create mode 100644 integration_tests/.prettierrc diff --git a/.circleci/config.yml b/.circleci/config.yml index 9eaacd05f9..d409554d71 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -94,7 +94,7 @@ commands: command: cd integration_tests && npm run check-fmt - run: name: Check eslint - command: cd integration_tests && npx eslint . + command: cd integration_tests && npm run lint - run: name: Pre-build base node command: cargo build --release --bin tari_base_node diff --git a/integration_tests/.eslintrc.json b/integration_tests/.eslintrc.json index 36f559cdf3..b5a271328d 100644 --- a/integration_tests/.eslintrc.json +++ b/integration_tests/.eslintrc.json @@ -1,15 +1,25 @@ { - "env": { - "browser": true, - "commonjs": true, - "es2021": true - }, - "extends": [ - "standard" + "extends": ["eslint:recommended", "plugin:prettier/recommended"], + "plugins": ["prettier"], + "env": { + "browser": true, + "commonjs": true, + "node": true, + "es2021": true + }, + "rules": { + "no-unused-vars": [ + "error", + { + "argsIgnorePattern": "^_" + } ], - "parserOptions": { - "ecmaVersion": 12 - }, - "rules": { - } + "prettier/prettier": [ + "error", + { + "doubleQuote": true, + "endOfLine": "auto" + } + ] + } } diff --git a/integration_tests/.husky/.gitignore b/integration_tests/.husky/.gitignore new file mode 100644 index 0000000000..31354ec138 --- /dev/null +++ b/integration_tests/.husky/.gitignore @@ -0,0 +1 @@ +_ diff --git a/integration_tests/.husky/pre-commit b/integration_tests/.husky/pre-commit new file mode 100755 index 0000000000..c9aef10c88 --- /dev/null +++ b/integration_tests/.husky/pre-commit @@ -0,0 +1,13 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +# run prettier and lint check before commit if any files in integration_tests have been staged +CHECK=$(git diff --name-only --staged | grep -i integration_tests || true) + +if [ -z "${CHECK}" ]; then + exit 0 +else + echo "Files staged for commit in integration_tests/" + echo "Running pre-commit hook" + cd integration_tests && npm run check-fmt && npm run lint +fi diff --git a/integration_tests/.prettierrc b/integration_tests/.prettierrc new file mode 100644 index 0000000000..168d9d2a0c --- /dev/null +++ b/integration_tests/.prettierrc @@ -0,0 +1,3 @@ +{ + "endOfLine": "auto" +} diff --git a/integration_tests/cucumber.js b/integration_tests/cucumber.js index 2ae23c74a3..988c7217a3 100644 --- a/integration_tests/cucumber.js +++ b/integration_tests/cucumber.js @@ -1,4 +1,4 @@ module.exports = { - default: '', - critical: '--format @cucumber/pretty-formatter --tags @critical' -} + default: "", + critical: "--format @cucumber/pretty-formatter --tags @critical", +}; diff --git a/integration_tests/features/support/steps.js b/integration_tests/features/support/steps.js index 5f6d848b38..86a309f8f1 100644 --- a/integration_tests/features/support/steps.js +++ b/integration_tests/features/support/steps.js @@ -1,218 +1,217 @@ // features/support/steps.js -const assert = require('assert') -const { Given, When, Then } = require('cucumber') -const MergeMiningProxyProcess = require('../../helpers/mergeMiningProxyProcess') -const MiningNodeProcess = require('../../helpers/miningNodeProcess') -const WalletProcess = require('../../helpers/walletProcess') -const expect = require('chai').expect +const assert = require("assert"); +const { Given, When, Then } = require("cucumber"); +const MergeMiningProxyProcess = require("../../helpers/mergeMiningProxyProcess"); +const MiningNodeProcess = require("../../helpers/miningNodeProcess"); +const WalletProcess = require("../../helpers/walletProcess"); +const expect = require("chai").expect; const { waitFor, getTransactionOutputHash, sleep, consoleLogBalance, consoleLogCoinbaseDetails, - withTimeout -} = require('../../helpers/util') -const TransactionBuilder = require('../../helpers/transactionBuilder') -let lastResult + withTimeout, +} = require("../../helpers/util"); +const TransactionBuilder = require("../../helpers/transactionBuilder"); +let lastResult; Given(/I have a seed node (.*)/, { timeout: 20 * 1000 }, async function (name) { - return await this.createSeedNode(name) -}) + return await this.createSeedNode(name); +}); -Given('I have {int} seed nodes', { timeout: 20 * 1000 }, async function (n) { - const promises = [] +Given("I have {int} seed nodes", { timeout: 20 * 1000 }, async function (n) { + const promises = []; for (let i = 0; i < n; i++) { - promises.push(this.createSeedNode(`SeedNode${i}`)) + promises.push(this.createSeedNode(`SeedNode${i}`)); } - await Promise.all(promises) -}) + await Promise.all(promises); +}); Given( /I have a base node (.*) connected to all seed nodes/, { timeout: 20 * 1000 }, async function (name) { - await this.createAndAddNode(name, this.seedAddresses()) + await this.createAndAddNode(name, this.seedAddresses()); } -) +); Given( /I have a base node (.*) connected to seed (.*)/, { timeout: 20 * 1000 }, async function (name, seedNode) { - await this.createAndAddNode(name, this.seeds[seedNode].peerAddress()) + await this.createAndAddNode(name, this.seeds[seedNode].peerAddress()); } -) +); Given( /I have a base node (.*) connected to nodes (.*)/, { timeout: 20 * 1000 }, async function (name, nodes) { - const addresses = [] - nodes = nodes.split(',') + const addresses = []; + nodes = nodes.split(","); for (let i = 0; i < nodes.length; i++) { - addresses.push(this.nodes[nodes[i]].peerAddress()) + addresses.push(this.nodes[nodes[i]].peerAddress()); } - await this.createAndAddNode(name, addresses) + await this.createAndAddNode(name, addresses); } -) - +); Given( /I have a base node (.*) connected to node (.*)/, { timeout: 20 * 1000 }, async function (name, node) { - await this.createAndAddNode(name, this.nodes[node].peerAddress()) + await this.createAndAddNode(name, this.nodes[node].peerAddress()); } -) +); Given( /I have a base node (\S+)$/, { timeout: 20 * 1000 }, async function (name) { - await this.createAndAddNode(name) + await this.createAndAddNode(name); } -) +); Given( /I have a SHA3 miner (.*) connected to seed node (.*)/, { timeout: 40 * 1000 }, async function (name, seed) { // add the base_node - await this.createAndAddNode(name, this.seeds[seed].peerAddress(), this) - const node = this.getNode(name) + await this.createAndAddNode(name, this.seeds[seed].peerAddress(), this); + const node = this.getNode(name); // Add the wallet connected to the above base node - await this.createAndAddWallet(name, node.peerAddress(), this) + await this.createAndAddWallet(name, node.peerAddress(), this); // Now lets add a standalone miner to both - const wallet = this.getWallet(name) + const wallet = this.getWallet(name); const miningNode = new MiningNodeProcess( name, node.getGrpcAddress(), wallet.getGrpcAddress() - ) - this.addMiningNode(name, miningNode) + ); + this.addMiningNode(name, miningNode); } -) +); Given( /I have a SHA3 miner (.*) connected to node (.*)/, { timeout: 40 * 1000 }, async function (name, basenode) { // add the base_node - await this.createAndAddNode(name, this.nodes[basenode].peerAddress(), this) - const node = this.getNode(name) + await this.createAndAddNode(name, this.nodes[basenode].peerAddress(), this); + const node = this.getNode(name); // Add the wallet connected to the above base node - await this.createAndAddWallet(name, node.peerAddress(), this) + await this.createAndAddWallet(name, node.peerAddress(), this); // Now lets add a standalone miner to both - const wallet = this.getWallet(name) + const wallet = this.getWallet(name); const miningNode = new MiningNodeProcess( name, node.getGrpcAddress(), wallet.getGrpcAddress() - ) - this.addMiningNode(name, miningNode) + ); + this.addMiningNode(name, miningNode); } -) +); Given( /I have a SHA3 miner (.*) connected to all seed nodes/, { timeout: 40 * 1000 }, async function (name) { // add the base_node - await this.createAndAddNode(name, this.seedAddresses(), this) - const node = this.getNode(name) + await this.createAndAddNode(name, this.seedAddresses(), this); + const node = this.getNode(name); // Add the wallet connected to the above base node - await this.createAndAddWallet(name, node.peerAddress(), this) + await this.createAndAddWallet(name, node.peerAddress(), this); // Now lets add a standalone miner to both - const wallet = this.getWallet(name) + const wallet = this.getWallet(name); const miningNode = new MiningNodeProcess( name, node.getGrpcAddress(), wallet.getGrpcAddress() - ) - this.addMiningNode(name, miningNode) + ); + this.addMiningNode(name, miningNode); } -) +); Given( /I connect node (.*) to node (.*) and wait (.*) seconds/, { timeout: 1200 * 1000 }, async function (nodeNameA, nodeNameB, waitSeconds) { - expect(waitSeconds < 1190).to.equal(true) + expect(waitSeconds < 1190).to.equal(true); console.log( - 'Connecting', + "Connecting", nodeNameA, - 'to', + "to", nodeNameB, - ', waiting for', + ", waiting for", waitSeconds, - 'seconds' - ) - const nodeA = this.getNode(nodeNameA) - const nodeB = this.getNode(nodeNameB) - nodeA.setPeerSeeds([nodeB.peerAddress()]) - await this.stopNode(nodeNameA) - await this.startNode(nodeNameA) + "seconds" + ); + const nodeA = this.getNode(nodeNameA); + const nodeB = this.getNode(nodeNameB); + nodeA.setPeerSeeds([nodeB.peerAddress()]); + await this.stopNode(nodeNameA); + await this.startNode(nodeNameA); } -) +); Given( /I have a pruned node (.*) connected to node (.*) with pruning horizon set to (.*)/, { timeout: 20 * 1000 }, async function (name, node, horizon) { - const miner = this.createNode(name, { horizon }) - miner.setPeerSeeds([this.nodes[node].peerAddress()]) - await miner.startNew() - this.addNode(name, miner) - await sleep(1000) + const miner = this.createNode(name, { horizon }); + miner.setPeerSeeds([this.nodes[node].peerAddress()]); + await miner.startNew(); + this.addNode(name, miner); + await sleep(1000); } -) +); Given( /I have a lagging delayed node (.*) connected to node (.*) with blocks_behind_before_considered_lagging (\d+)/, { timeout: 20 * 1000 }, async function (name, node, delay) { const miner = this.createNode(name, { - blocks_behind_before_considered_lagging: delay - }) - miner.setPeerSeeds([this.nodes[node].peerAddress()]) - await miner.startNew() - this.addNode(name, miner) - await sleep(1000) + blocks_behind_before_considered_lagging: delay, + }); + miner.setPeerSeeds([this.nodes[node].peerAddress()]); + await miner.startNew(); + this.addNode(name, miner); + await sleep(1000); } -) +); Given( /I have a base node (.*) unconnected/, { timeout: 20 * 1000 }, async function (name) { - const node = this.createNode(name) - await node.startNew() - this.addNode(name, node) + const node = this.createNode(name); + await node.startNew(); + this.addNode(name, node); } -) +); Given( - 'I have {int} base nodes connected to all seed nodes', + "I have {int} base nodes connected to all seed nodes", { timeout: 190 * 1000 }, async function (n) { - const promises = [] + const promises = []; for (let i = 0; i < n; i++) { - const miner = this.createNode(`BaseNode${i}`) - miner.setPeerSeeds([this.seedAddresses()]) + const miner = this.createNode(`BaseNode${i}`); + miner.setPeerSeeds([this.seedAddresses()]); promises.push( miner.startNew().then(() => this.addNode(`BaseNode${i}`, miner)) - ) + ); } - await Promise.all(promises) + await Promise.all(promises); } -) +); Given( /I have stress-test wallet (.*) connected to the seed node (.*) with broadcast monitoring timeout (.*)/, @@ -222,12 +221,12 @@ Given( walletName, { broadcastMonitoringTimeout: timeout }, this.logFilePathWallet - ) - wallet.setPeerSeeds([this.seeds[seedName].peerAddress()]) - await wallet.startNew() - this.addWallet(walletName, wallet) + ); + wallet.setPeerSeeds([this.seeds[seedName].peerAddress()]); + await wallet.startNew(); + this.addWallet(walletName, wallet); } -) +); Given( /I have stress-test wallet (.*) connected to all the seed nodes with broadcast monitoring timeout (.*)/, @@ -237,38 +236,42 @@ Given( name, { broadcastMonitoringTimeout: timeout }, this.logFilePathWallet - ) - wallet.setPeerSeeds([this.seedAddresses()]) - await wallet.startNew() - this.addWallet(name, wallet) + ); + wallet.setPeerSeeds([this.seedAddresses()]); + await wallet.startNew(); + this.addWallet(name, wallet); } -) +); Given( /I have wallet (.*) connected to seed node (.*)/, { timeout: 20 * 1000 }, async function (walletName, seedName) { - await this.createAndAddWallet(walletName, this.seeds[seedName].peerAddress()) + await this.createAndAddWallet( + walletName, + this.seeds[seedName].peerAddress() + ); } -) +); Given( /I have wallet (.*) connected to base node (.*)/, { timeout: 20 * 1000 }, async function (walletName, nodeName) { - await this.createAndAddWallet(walletName, this.nodes[nodeName].peerAddress()) + await this.createAndAddWallet( + walletName, + this.nodes[nodeName].peerAddress() + ); } -) +); Given( /I have wallet (.*) connected to all seed nodes/, { timeout: 20 * 1000 }, async function (name) { - await this.createAndAddWallet(name, this.seedAddresses()) + await this.createAndAddWallet(name, this.seedAddresses()); } -) - - +); Given( /I have non-default wallet (.*) connected to all seed nodes using (.*)/, @@ -279,544 +282,544 @@ Given( name, { routingMechanism: mechanism }, this.logFilePathWallet - ) - console.log(wallet.name, wallet.options) - wallet.setPeerSeeds([this.seedAddresses()]) - await wallet.startNew() - this.addWallet(name, wallet) + ); + console.log(wallet.name, wallet.options); + wallet.setPeerSeeds([this.seedAddresses()]); + await wallet.startNew(); + this.addWallet(name, wallet); } -) +); Given( /I have (.*) non-default wallets connected to all seed nodes using (.*)/, { timeout: 190 * 1000 }, async function (n, mechanism) { // mechanism: DirectOnly, StoreAndForwardOnly, DirectAndStoreAndForward - const promises = [] + const promises = []; for (let i = 0; i < n; i++) { if (i < 10) { const wallet = new WalletProcess( - 'Wallet_0' + String(i), + "Wallet_0" + String(i), { routingMechanism: mechanism }, this.logFilePathWallet - ) - console.log(wallet.name, wallet.options) - wallet.setPeerSeeds([this.seedAddresses()]) + ); + console.log(wallet.name, wallet.options); + wallet.setPeerSeeds([this.seedAddresses()]); promises.push( wallet .startNew() - .then(() => this.addWallet('Wallet_0' + String(i), wallet)) - ) + .then(() => this.addWallet("Wallet_0" + String(i), wallet)) + ); } else { const wallet = new WalletProcess( - 'Wallet_0' + String(i), + "Wallet_0" + String(i), { routingMechanism: mechanism }, this.logFilePathWallet - ) - console.log(wallet.name, wallet.options) - wallet.setPeerSeeds([this.seedAddresses()]) + ); + console.log(wallet.name, wallet.options); + wallet.setPeerSeeds([this.seedAddresses()]); promises.push( wallet .startNew() - .then(() => this.addWallet('Wallet_' + String(i), wallet)) - ) + .then(() => this.addWallet("Wallet_" + String(i), wallet)) + ); } } - await Promise.all(promises) + await Promise.all(promises); } -) +); Given( /I recover wallet (.*) into wallet (.*) connected to all seed nodes/, { timeout: 120 * 1000 }, async function (walletNameA, walletNameB) { - const seedWords = this.getWallet(walletNameA).getSeedWords() + const seedWords = this.getWallet(walletNameA).getSeedWords(); console.log( - 'Recover ' + + "Recover " + walletNameA + - ' into ' + + " into " + walletNameB + - ', seed words:\n ' + + ", seed words:\n " + seedWords - ) + ); const walletB = new WalletProcess( walletNameB, {}, this.logFilePathWallet, seedWords - ) - walletB.setPeerSeeds([this.seedAddresses()]) - walletB.startNew() // Do not 'await' here - this.addWallet(walletNameB, walletB) + ); + walletB.setPeerSeeds([this.seedAddresses()]); + walletB.startNew(); // Do not 'await' here + this.addWallet(walletNameB, walletB); } -) +); Given( /I have a merge mining proxy (.*) connected to (.*) and (.*) with default config/, { timeout: 20 * 1000 }, async function (mmProxy, node, wallet) { - const baseNode = this.getNode(node) - const walletNode = this.getWallet(wallet) + const baseNode = this.getNode(node); + const walletNode = this.getWallet(wallet); const proxy = new MergeMiningProxyProcess( mmProxy, baseNode.getGrpcAddress(), walletNode.getGrpcAddress(), this.logFilePathProxy, true - ) - await proxy.startNew() - this.addProxy(mmProxy, proxy) + ); + await proxy.startNew(); + this.addProxy(mmProxy, proxy); } -) +); Given( /I have a merge mining proxy (.*) connected to (.*) and (.*) with origin submission disabled/, { timeout: 20 * 1000 }, async function (mmProxy, node, wallet) { - const baseNode = this.getNode(node) - const walletNode = this.getWallet(wallet) + const baseNode = this.getNode(node); + const walletNode = this.getWallet(wallet); const proxy = new MergeMiningProxyProcess( mmProxy, baseNode.getGrpcAddress(), walletNode.getGrpcAddress(), this.logFilePathProxy, false - ) - await proxy.startNew() - this.addProxy(mmProxy, proxy) + ); + await proxy.startNew(); + this.addProxy(mmProxy, proxy); } -) +); Given( /I have a merge mining proxy (.*) connected to (.*) and (.*) with origin submission enabled/, { timeout: 20 * 1000 }, async function (mmProxy, node, wallet) { - const baseNode = this.getNode(node) - const walletNode = this.getWallet(wallet) + const baseNode = this.getNode(node); + const walletNode = this.getWallet(wallet); const proxy = new MergeMiningProxyProcess( mmProxy, baseNode.getGrpcAddress(), walletNode.getGrpcAddress(), this.logFilePathProxy, true - ) - await proxy.startNew() - this.addProxy(mmProxy, proxy) + ); + await proxy.startNew(); + this.addProxy(mmProxy, proxy); } -) +); Given( /I have mining node (.*) connected to base node (.*) and wallet (.*)/, async function (miner, node, wallet) { - const baseNode = this.getNode(node) - const walletNode = await this.getOrCreateWallet(wallet) + const baseNode = this.getNode(node); + const walletNode = await this.getOrCreateWallet(wallet); const miningNode = new MiningNodeProcess( miner, baseNode.getGrpcAddress(), walletNode.getGrpcAddress(), true - ) - this.addMiningNode(miner, miningNode) + ); + this.addMiningNode(miner, miningNode); } -) +); Given( /I have mine-before-tip mining node (.*) connected to base node (.*) and wallet (.*)/, function (miner, node, wallet) { - const baseNode = this.getNode(node) - const walletNode = this.getWallet(wallet) + const baseNode = this.getNode(node); + const walletNode = this.getWallet(wallet); const miningNode = new MiningNodeProcess( miner, baseNode.getGrpcAddress(), walletNode.getGrpcAddress(), false - ) - this.addMiningNode(miner, miningNode) + ); + this.addMiningNode(miner, miningNode); } -) +); When(/I ask for a block height from proxy (.*)/, async function (mmProxy) { - lastResult = 'NaN' - const proxy = this.getProxy(mmProxy) - const proxyClient = proxy.createClient() - const height = await proxyClient.getHeight() - lastResult = height -}) + lastResult = "NaN"; + const proxy = this.getProxy(mmProxy); + const proxyClient = proxy.createClient(); + const height = await proxyClient.getHeight(); + lastResult = height; +}); -Then('Proxy response height is valid', function () { - assert(Number.isInteger(lastResult), true) -}) +Then("Proxy response height is valid", function () { + assert(Number.isInteger(lastResult), true); +}); When(/I ask for a block template from proxy (.*)/, async function (mmProxy) { - lastResult = {} - const proxy = this.getProxy(mmProxy) - const proxyClient = proxy.createClient() - const template = await proxyClient.getBlockTemplate() - lastResult = template -}) - -Then('Proxy response block template is valid', function () { - assert(typeof lastResult === 'object' && lastResult !== null, true) - assert(typeof lastResult._aux !== 'undefined', true) - assert(lastResult.status, 'OK') -}) + lastResult = {}; + const proxy = this.getProxy(mmProxy); + const proxyClient = proxy.createClient(); + const template = await proxyClient.getBlockTemplate(); + lastResult = template; +}); + +Then("Proxy response block template is valid", function () { + assert(typeof lastResult === "object" && lastResult !== null, true); + assert(typeof lastResult._aux !== "undefined", true); + assert(lastResult.status, "OK"); +}); When(/I submit a block through proxy (.*)/, async function (mmProxy) { - const blockTemplateBlob = lastResult.blocktemplate_blob - const proxy = this.getProxy(mmProxy) - const proxyClient = proxy.createClient() - const result = await proxyClient.submitBlock(blockTemplateBlob) - lastResult = result -}) + const blockTemplateBlob = lastResult.blocktemplate_blob; + const proxy = this.getProxy(mmProxy); + const proxyClient = proxy.createClient(); + const result = await proxyClient.submitBlock(blockTemplateBlob); + lastResult = result; +}); Then( - 'Proxy response block submission is valid with submitting to origin', + "Proxy response block submission is valid with submitting to origin", function () { assert( - typeof lastResult.result === 'object' && lastResult.result !== null, + typeof lastResult.result === "object" && lastResult.result !== null, true - ) - assert(typeof lastResult.result._aux !== 'undefined', true) - assert(lastResult.result.status, 'OK') + ); + assert(typeof lastResult.result._aux !== "undefined", true); + assert(lastResult.result.status, "OK"); } -) +); Then( - 'Proxy response block submission is valid without submitting to origin', + "Proxy response block submission is valid without submitting to origin", function () { - assert(lastResult.result !== null, true) - assert(lastResult.status, 'OK') + assert(lastResult.result !== null, true); + assert(lastResult.status, "OK"); } -) +); When( /I ask for the last block header from proxy (.*)/, async function (mmProxy) { - const proxy = this.getProxy(mmProxy) - const proxyClient = proxy.createClient() - const result = await proxyClient.getLastBlockHeader() - lastResult = result + const proxy = this.getProxy(mmProxy); + const proxyClient = proxy.createClient(); + const result = await proxyClient.getLastBlockHeader(); + lastResult = result; } -) +); -Then('Proxy response for last block header is valid', function () { - assert(typeof lastResult === 'object' && lastResult !== null, true) - assert(typeof lastResult.result._aux !== 'undefined', true) - assert(lastResult.result.status, 'OK') - lastResult = lastResult.result.block_header.hash -}) +Then("Proxy response for last block header is valid", function () { + assert(typeof lastResult === "object" && lastResult !== null, true); + assert(typeof lastResult.result._aux !== "undefined", true); + assert(lastResult.result.status, "OK"); + lastResult = lastResult.result.block_header.hash; +}); When( /I ask for a block header by hash using last block header from proxy (.*)/, async function (mmProxy) { - const proxy = this.getProxy(mmProxy) - const proxyClient = proxy.createClient() - const result = await proxyClient.getBlockHeaderByHash(lastResult) - lastResult = result + const proxy = this.getProxy(mmProxy); + const proxyClient = proxy.createClient(); + const result = await proxyClient.getBlockHeaderByHash(lastResult); + lastResult = result; } -) +); -Then('Proxy response for block header by hash is valid', function () { - assert(typeof lastResult === 'object' && lastResult !== null, true) - assert(lastResult.result.status, 'OK') -}) +Then("Proxy response for block header by hash is valid", function () { + assert(typeof lastResult === "object" && lastResult !== null, true); + assert(lastResult.result.status, "OK"); +}); When(/I start (.*)/, { timeout: 20 * 1000 }, async function (name) { - await this.startNode(name) -}) + await this.startNode(name); +}); When(/I stop (.*)/, async function (name) { - await this.stopNode(name) -}) + await this.stopNode(name); +}); Then( /node (.*) is at height (\d+)/, { timeout: 120 * 1000 }, async function (name, height) { - const client = this.getClient(name) - await waitFor(async () => client.getTipHeight(), height, 115 * 1000) - expect(await client.getTipHeight()).to.equal(height) + const client = this.getClient(name); + await waitFor(async () => client.getTipHeight(), height, 115 * 1000); + expect(await client.getTipHeight()).to.equal(height); } -) +); Then( /node (.*) is at the same height as node (.*)/, { timeout: 120 * 1000 }, async function (nodeA, nodeB) { - expectedHeight = parseInt(await this.getClient(nodeB).getTipHeight()) + const expectedHeight = parseInt(await this.getClient(nodeB).getTipHeight()); await waitFor( async () => this.getClient(nodeA).getTipHeight(), expectedHeight, 115 * 1000 - ) - currentHeight = await this.getClient(nodeA).getTipHeight() + ); + const currentHeight = await this.getClient(nodeA).getTipHeight(); console.log( `Node ${nodeA} is at tip: ${currentHeight} (should be`, expectedHeight, - ')' - ) - expect(currentHeight).to.equal(expectedHeight) + ")" + ); + expect(currentHeight).to.equal(expectedHeight); } -) +); Then( - 'all nodes are on the same chain at height {int}', + "all nodes are on the same chain at height {int}", { timeout: 1200 * 1000 }, async function (height) { - let tipHash = null + let tipHash = null; await this.forEachClientAsync(async (client, name) => { - await waitFor(async () => client.getTipHeight(), height, 115 * 1000) - const currTip = await client.getTipHeader() - expect(currTip.height).to.equal(height) + await waitFor(async () => client.getTipHeight(), height, 115 * 1000); + const currTip = await client.getTipHeader(); + expect(currTip.height).to.equal(height); if (!tipHash) { - tipHash = currTip.hash.toString('hex') - console.log(`Node ${name} is at tip: ${tipHash}`) + tipHash = currTip.hash.toString("hex"); + console.log(`Node ${name} is at tip: ${tipHash}`); } else { - const currTipHash = currTip.hash.toString('hex') + const currTipHash = currTip.hash.toString("hex"); console.log( `Node ${name} is at tip: ${currTipHash} (should be ${tipHash})` - ) - expect(currTipHash).to.equal(tipHash) + ); + expect(currTipHash).to.equal(tipHash); } - }) + }); } -) +); Then( - 'all nodes are at height {int}', + "all nodes are at height {int}", { timeout: 1200 * 1000 }, async function (height) { await this.forEachClientAsync(async (client, name) => { - await waitFor(async () => client.getTipHeight(), height, 115 * 1000) - const currTip = await client.getTipHeight() - console.log(`Node ${name} is at tip: ${currTip} (should be ${height})`) - expect(currTip).to.equal(height) - }) + await waitFor(async () => client.getTipHeight(), height, 115 * 1000); + const currTip = await client.getTipHeight(); + console.log(`Node ${name} is at tip: ${currTip} (should be ${height})`); + expect(currTip).to.equal(height); + }); } -) +); Then( - 'all nodes are at current tip height', + "all nodes are at current tip height", { timeout: 1200 * 1000 }, async function () { - const height = parseInt(this.tipHeight) - console.log('Wait for all nodes to reach height of', height) + const height = parseInt(this.tipHeight); + console.log("Wait for all nodes to reach height of", height); await this.forEachClientAsync(async (client, name) => { - await waitFor(async () => client.getTipHeight(), height, 1200 * 1000) - const currTip = await client.getTipHeight() - console.log(`Node ${name} is at tip: ${currTip} (expected ${height})`) - expect(currTip).to.equal(height) - }) + await waitFor(async () => client.getTipHeight(), height, 1200 * 1000); + const currTip = await client.getTipHeight(); + console.log(`Node ${name} is at tip: ${currTip} (expected ${height})`); + expect(currTip).to.equal(height); + }); } -) +); Then( /all nodes are at the same height as node (.*)/, { timeout: 1200 * 1000 }, async function (nodeB) { - expectedHeight = parseInt(await this.getClient(nodeB).getTipHeight()) - console.log('Wait for all nodes to reach height of', expectedHeight) + const expectedHeight = parseInt(await this.getClient(nodeB).getTipHeight()); + console.log("Wait for all nodes to reach height of", expectedHeight); await this.forEachClientAsync(async (client, name) => { await waitFor( async () => client.getTipHeight(), expectedHeight, 1200 * 1000 - ) - const currTip = await client.getTipHeight() + ); + const currTip = await client.getTipHeight(); console.log( `Node ${name} is at tip: ${currTip} (should be`, expectedHeight, - ')' - ) - expect(currTip).to.equal(expectedHeight) - }) + ")" + ); + expect(currTip).to.equal(expectedHeight); + }); } -) +); Then( /meddling with block template data from node (.*) for wallet (.*) is not allowed/, async function (baseNodeName, walletName) { - const baseNodeClient = this.getClient(baseNodeName) - const walletClient = this.getWallet(walletName).getClient() + const baseNodeClient = this.getClient(baseNodeName); + const walletClient = this.getWallet(walletName).getClient(); // No meddling with data // - Current tip - const currHeight = await baseNodeClient.getTipHeight() + const currHeight = await baseNodeClient.getTipHeight(); // - New block - let newBlock = await baseNodeClient.mineBlockBeforeSubmit(walletClient, 0) + let newBlock = await baseNodeClient.mineBlockBeforeSubmit(walletClient, 0); // console.log("\nNew block:\n"); // console.dir(newBlock, { depth: null }); // - Submit block to base node - let response = await baseNodeClient.submitMinedBlock(newBlock) + await baseNodeClient.submitMinedBlock(newBlock); // - Verify new height - expect(await baseNodeClient.getTipHeight()).to.equal(currHeight + 1) + expect(await baseNodeClient.getTipHeight()).to.equal(currHeight + 1); // Meddle with data - kernel_mmr_size // - New block - newBlock = await baseNodeClient.mineBlockBeforeSubmit(walletClient, 0) + newBlock = await baseNodeClient.mineBlockBeforeSubmit(walletClient, 0); // - Change kernel_mmr_size newBlock.block.header.kernel_mmr_size = - parseInt(newBlock.block.header.kernel_mmr_size) + 1 + parseInt(newBlock.block.header.kernel_mmr_size) + 1; // - Try to submit illegal block to base node try { - response = await baseNodeClient.submitMinedBlock(newBlock) - expect('Meddling with MMR size for Kernel not detected!').to.equal('') + await baseNodeClient.submitMinedBlock(newBlock); + expect("Meddling with MMR size for Kernel not detected!").to.equal(""); } catch (err) { console.log( - '\nMeddle with kernel_mmr_size - error details (as expected):\n', + "\nMeddle with kernel_mmr_size - error details (as expected):\n", err.details - ) + ); expect( err.details.includes( - 'Block validation error: MMR size for Kernel does not match.' + "Block validation error: MMR size for Kernel does not match." ) - ).to.equal(true) + ).to.equal(true); } // Meddle with data - output_mmr_size // - New block - newBlock = await baseNodeClient.mineBlockBeforeSubmit(walletClient, 0) + newBlock = await baseNodeClient.mineBlockBeforeSubmit(walletClient, 0); // - Change output_mmr_size newBlock.block.header.output_mmr_size = - parseInt(newBlock.block.header.output_mmr_size) + 1 + parseInt(newBlock.block.header.output_mmr_size) + 1; // - Try to submit illegal block to base node try { - response = await baseNodeClient.submitMinedBlock(newBlock) - expect('Meddling with MMR size for UTXO not detected!').to.equal('') + await baseNodeClient.submitMinedBlock(newBlock); + expect("Meddling with MMR size for UTXO not detected!").to.equal(""); } catch (err) { console.log( - 'Meddle with output_mmr_size - error details (as expected):\n', + "Meddle with output_mmr_size - error details (as expected):\n", err.details - ) + ); expect( err.details.includes( - 'Block validation error: MMR size for UTXO does not match.' + "Block validation error: MMR size for UTXO does not match." ) - ).to.equal(true) + ).to.equal(true); } } -) +); When( /I create a transaction (.*) spending (.*) to (.*)/, function (txnName, inputs, output) { - const txInputs = inputs.split(',').map((input) => this.outputs[input]) - const txn = new TransactionBuilder() - txInputs.forEach((txIn) => txn.addInput(txIn)) - const txOutput = txn.addOutput(txn.getSpendableAmount()) - this.addOutput(output, txOutput) - this.transactions[txnName] = txn.build() + const txInputs = inputs.split(",").map((input) => this.outputs[input]); + const txn = new TransactionBuilder(); + txInputs.forEach((txIn) => txn.addInput(txIn)); + const txOutput = txn.addOutput(txn.getSpendableAmount()); + this.addOutput(output, txOutput); + this.transactions[txnName] = txn.build(); } -) +); When( /I create a custom fee transaction (.*) spending (.*) to (.*) with fee (\d+)/, function (txnName, inputs, output, fee) { - const txInputs = inputs.split(',').map((input) => this.outputs[input]) - const txn = new TransactionBuilder() - txn.changeFee(fee) - txInputs.forEach((txIn) => txn.addInput(txIn)) - const txOutput = txn.addOutput(txn.getSpendableAmount()) - this.addOutput(output, txOutput) - this.transactions[txnName] = txn.build() + const txInputs = inputs.split(",").map((input) => this.outputs[input]); + const txn = new TransactionBuilder(); + txn.changeFee(fee); + txInputs.forEach((txIn) => txn.addInput(txIn)); + const txOutput = txn.addOutput(txn.getSpendableAmount()); + this.addOutput(output, txOutput); + this.transactions[txnName] = txn.build(); } -) +); When(/I submit transaction (.*) to (.*)/, async function (txn, node) { this.lastResult = await this.getClient(node).submitTransaction( this.transactions[txn] - ) - expect(this.lastResult.result).to.equal('ACCEPTED') -}) + ); + expect(this.lastResult.result).to.equal("ACCEPTED"); +}); When(/I submit locked transaction (.*) to (.*)/, async function (txn, node) { this.lastResult = await this.getClient(node).submitTransaction( this.transactions[txn] - ) - expect(this.lastResult.result).to.equal('REJECTED') -}) + ); + expect(this.lastResult.result).to.equal("REJECTED"); +}); When(/I spend outputs (.*) via (.*)/, async function (inputs, node) { - const txInputs = inputs.split(',').map((input) => this.outputs[input]) - console.log(txInputs) - const txn = new TransactionBuilder() - txInputs.forEach((txIn) => txn.addInput(txIn)) - console.log(txn.getSpendableAmount()) - const output = txn.addOutput(txn.getSpendableAmount()) - console.log(output) - this.lastResult = await this.getClient(node).submitTransaction(txn.build()) - expect(this.lastResult.result).to.equal('ACCEPTED') -}) + const txInputs = inputs.split(",").map((input) => this.outputs[input]); + console.log(txInputs); + const txn = new TransactionBuilder(); + txInputs.forEach((txIn) => txn.addInput(txIn)); + console.log(txn.getSpendableAmount()); + const output = txn.addOutput(txn.getSpendableAmount()); + console.log(output); + this.lastResult = await this.getClient(node).submitTransaction(txn.build()); + expect(this.lastResult.result).to.equal("ACCEPTED"); +}); Then(/(.*) has (.*) in (.*) state/, async function (node, txn, pool) { - const client = this.getClient(node) - const sig = this.transactions[txn].body.kernels[0].excess_sig + const client = this.getClient(node); + const sig = this.transactions[txn].body.kernels[0].excess_sig; await waitFor( async () => client.transactionStateResult(sig), pool, 1200 * 1000 - ) + ); this.lastResult = await this.getClient(node).transactionState( this.transactions[txn].body.kernels[0].excess_sig - ) - console.log(`Node ${node} response is: ${this.lastResult.result}`) - expect(this.lastResult.result).to.equal(pool) -}) + ); + console.log(`Node ${node} response is: ${this.lastResult.result}`); + expect(this.lastResult.result).to.equal(pool); +}); Then( /(.*) is in the (.*) of all nodes/, { timeout: 1200 * 1000 }, async function (txn, pool) { - const sig = this.transactions[txn].body.kernels[0].excess_sig + const sig = this.transactions[txn].body.kernels[0].excess_sig; await this.forEachClientAsync(async (client, name) => { await waitFor( async () => client.transactionStateResult(sig), pool, 1200 * 1000 - ) - this.lastResult = await client.transactionState(sig) - console.log(`Node ${name} response is: ${this.lastResult.result}`) - expect(this.lastResult.result).to.equal(pool) - }) + ); + this.lastResult = await client.transactionState(sig); + console.log(`Node ${name} response is: ${this.lastResult.result}`); + expect(this.lastResult.result).to.equal(pool); + }); } -) +); -Then(/(.*) is in the mempool/, function (txn) { - expect(this.lastResult.result).to.equal('ACCEPTED') -}) +Then(/(.*) is in the mempool/, function (_txn) { + expect(this.lastResult.result).to.equal("ACCEPTED"); +}); -Then(/(.*) should not be in the mempool/, function (txn) { - expect(this.lastResult.result).to.equal('REJECTED') -}) +Then(/(.*) should not be in the mempool/, function (_txn) { + expect(this.lastResult.result).to.equal("REJECTED"); +}); When(/I save the tip on (.*) as (.*)/, async function (node, name) { - const client = this.getClient(node) - const header = await client.getTipHeader() - this.headers[name] = header -}) + const client = this.getClient(node); + const header = await client.getTipHeader(); + this.headers[name] = header; +}); Then(/node (.*) is at tip (.*)/, async function (node, name) { - const client = this.getClient(node) - const header = await client.getTipHeader() + const client = this.getClient(node); + const header = await client.getTipHeader(); // console.log("headers:", this.headers); - const existingHeader = this.headers[name] - expect(existingHeader).to.not.be.null - expect(existingHeader.hash.toString('hex')).to.equal( - header.hash.toString('hex') - ) -}) + const existingHeader = this.headers[name]; + expect(existingHeader).to.not.be.null; + expect(existingHeader.hash.toString("hex")).to.equal( + header.hash.toString("hex") + ); +}); When( /I mine a block on (.*) with coinbase (.*)/, { timeout: 600 * 1000 }, async function (name, coinbaseName) { await this.mineBlock(name, 0, (candidate) => { - this.addOutput(coinbaseName, candidate.originalTemplate.coinbase) - return candidate - }) - this.tipHeight += 1 + this.addOutput(coinbaseName, candidate.originalTemplate.coinbase); + return candidate; + }); + this.tipHeight += 1; } -) +); When( /I mine (\d+) custom weight blocks on (.*) with weight (\d+)/, @@ -824,72 +827,72 @@ When( async function (numBlocks, name, weight) { for (let i = 0; i < numBlocks; i++) { // If a block cannot be mined quickly enough (or the process has frozen), timeout. - await withTimeout(60 * 1000, this.mineBlock(name, parseInt(weight))) + await withTimeout(60 * 1000, this.mineBlock(name, parseInt(weight))); } - this.tipHeight += parseInt(numBlocks) + this.tipHeight += parseInt(numBlocks); } -) +); When( /mining node (.*) mines (\d+) blocks with min difficulty (\d+) and max difficulty (\d+)/, { timeout: 600 * 1000 }, async function (miner, numBlocks, min, max) { - const miningNode = this.getMiningNode(miner) - await miningNode.init(numBlocks, min, max, miningNode.mineOnTipOnly) - await miningNode.startNew() + const miningNode = this.getMiningNode(miner); + await miningNode.init(numBlocks, min, max, miningNode.mineOnTipOnly); + await miningNode.startNew(); } -) +); When( /mining node (.*) mines (\d+) blocks$/, { timeout: 600 * 1000 }, async function (miner, numBlocks) { - const miningNode = this.getMiningNode(miner) - await miningNode.init(numBlocks, 1, 100000) - await miningNode.startNew() + const miningNode = this.getMiningNode(miner); + await miningNode.init(numBlocks, 1, 100000); + await miningNode.startNew(); } -) +); When( /I update the parent of block (.*) to be an orphan/, - async function (block) { + async function (_block) { // TODO } -) +); When( /I mine (\d+) blocks on (.*)/, { timeout: -1 }, async function (numBlocks, name) { for (let i = 0; i < numBlocks; i++) { - await withTimeout(60 * 1000, this.mineBlock(name, 0)) + await withTimeout(60 * 1000, this.mineBlock(name, 0)); } - this.tipHeight += parseInt(numBlocks) + this.tipHeight += parseInt(numBlocks); } -) +); When( /I mine (\d+) blocks using wallet (.*) on (.*)/, { timeout: 600 * 1000 }, async function (numBlocks, walletName, nodeName) { - const nodeClient = this.getClient(nodeName) - const walletClient = this.getWallet(walletName).getClient() + const nodeClient = this.getClient(nodeName); + const walletClient = this.getWallet(walletName).getClient(); for (let i = 0; i < numBlocks; i++) { - await nodeClient.mineBlock(walletClient) + await nodeClient.mineBlock(walletClient); } } -) +); When( /I merge mine (.*) blocks via (.*)/, { timeout: 600 * 1000 }, async function (numBlocks, mmProxy) { for (let i = 0; i < numBlocks; i++) { - await this.mergeMineBlock(mmProxy, 0) + await this.mergeMineBlock(mmProxy, 0); } - this.tipHeight += parseInt(numBlocks) + this.tipHeight += parseInt(numBlocks); } -) +); When( /I mine but don't submit a block (.*) on (.*)/, @@ -898,99 +901,99 @@ When( nodeName, null, (block) => { - this.saveBlock(blockName, block) - return false + this.saveBlock(blockName, block); + return false; }, 0 - ) + ); } -) +); When(/I submit block (.*) to (.*)/, async function (blockName, nodeName) { - await this.submitBlock(blockName, nodeName) -}) + await this.submitBlock(blockName, nodeName); +}); When( /I mine a block on (.*) based on height (\d+)/, async function (node, atHeight) { - const client = this.getClient(node) - const template = client.getPreviousBlockTemplate(atHeight) - const candidate = await client.getMinedCandidateBlock(0, template) + const client = this.getClient(node); + const template = client.getPreviousBlockTemplate(atHeight); + const candidate = await client.getMinedCandidateBlock(0, template); await client.submitBlock( candidate.template, (block) => { - return block + return block; }, (error) => { // Expect an error - console.log(error) - return false + console.log(error); + return false; } - ) + ); } -) +); When( /I mine a block on (.*) at height (\d+) with an invalid MMR/, async function (node, atHeight) { - const client = this.getClient(node) - const template = client.getPreviousBlockTemplate(atHeight) - const candidate = await client.getMinedCandidateBlock(0, template) + const client = this.getClient(node); + const template = client.getPreviousBlockTemplate(atHeight); + const candidate = await client.getMinedCandidateBlock(0, template); await client .submitBlock(candidate.template, (block) => { // console.log("Candidate:", block); - block.block.header.output_mr[0] = 1 + block.block.header.output_mr[0] = 1; // block.block.header.height = atHeight + 1; // block.block.header.prev_hash = candidate.header.hash; - return block + return block; }) .catch((err) => { - console.log('Received expected error. This is fine actually:', err) - }) + console.log("Received expected error. This is fine actually:", err); + }); } -) +); Then( /the UTXO (.*) has been mined according to (.*)/, async function (outputName, nodeName) { - const client = this.getClient(nodeName) - const hash = getTransactionOutputHash(this.outputs[outputName].output) - const lastResult = await client.fetchMatchingUtxos([hash]) - expect(lastResult[0].output.commitment.toString('hex')).to.equal( - this.outputs[outputName].output.commitment.toString('hex') - ) + const client = this.getClient(nodeName); + const hash = getTransactionOutputHash(this.outputs[outputName].output); + const lastResult = await client.fetchMatchingUtxos([hash]); + expect(lastResult[0].output.commitment.toString("hex")).to.equal( + this.outputs[outputName].output.commitment.toString("hex") + ); } -) +); -Then('I receive an error containing {string}', function (string) { +Then("I receive an error containing {string}", function (_string) { // TODO -}) +}); Then(/(.*) should have (\d+) peers/, async function (nodeName, peerCount) { - await sleep(500) - const client = this.getClient(nodeName) - const peers = await client.getPeers() + await sleep(500); + const client = this.getClient(nodeName); + const peers = await client.getPeers(); // we add a non existing node when the node starts before adding any actual peers. So the count should always be 1 higher - expect(peers.length).to.equal(peerCount + 1) -}) + expect(peers.length).to.equal(peerCount + 1); +}); -When('I print the world', function () { - console.log(this) -}) +When("I print the world", function () { + console.log(this); +}); When( /I wait for wallet (.*) to have at least (.*) uT/, { timeout: 250 * 1000 }, async function (wallet, amount) { - const walletClient = this.getWallet(wallet).getClient() - console.log('\n') + const walletClient = this.getWallet(wallet).getClient(); + console.log("\n"); console.log( - 'Waiting for ' + wallet + ' balance to be at least ' + amount + ' uT' - ) - const balance = await walletClient.getBalance() - consoleLogBalance(balance) + "Waiting for " + wallet + " balance to be at least " + amount + " uT" + ); + const balance = await walletClient.getBalance(); + consoleLogBalance(balance); if (parseInt(balance.available_balance) < parseInt(amount)) { await waitFor( async () => walletClient.isBalanceAtLeast(amount), @@ -998,58 +1001,56 @@ When( 240 * 1000, 5 * 1000, 5 - ) + ); if (!walletClient.isBalanceAtLeast(amount)) { - console.log('Balance not adequate!') + console.log("Balance not adequate!"); } - consoleLogBalance(await walletClient.getBalance()) + consoleLogBalance(await walletClient.getBalance()); } } -) +); Then( /wallet (.*) and wallet (.*) have the same balance/, { timeout: 60 * 1000 }, async function (walletNameA, walletNameB) { - const walletClientA = this.getWallet(walletNameA).getClient() - const balanceA = await walletClientA.getBalance() - console.log('\n') - console.log(walletNameA, 'balance:') - consoleLogBalance(balanceA) - const walletClientB = this.getWallet(walletNameB).getClient() + const walletClientA = this.getWallet(walletNameA).getClient(); + const balanceA = await walletClientA.getBalance(); + console.log("\n"); + console.log(walletNameA, "balance:"); + consoleLogBalance(balanceA); + const walletClientB = this.getWallet(walletNameB).getClient(); await waitFor( async () => walletClientB.isBalanceAtLeast(balanceA.available_balance), true, 55 * 1000, 5 * 1000, 5 - ) - const balanceB = await walletClientB.getBalance() - console.log(walletNameB, 'balance:') - consoleLogBalance(balanceB) - expect(balanceA.available_balance).to.equal( - balanceB.available_balance - ) - } -) - -async function send_tari (sourceWallet, destWallet, tariAmount, feePerGram) { - const sourceWalletClient = sourceWallet.getClient() - const destInfo = await destWallet.getClient().identify() + ); + const balanceB = await walletClientB.getBalance(); + console.log(walletNameB, "balance:"); + consoleLogBalance(balanceB); + expect(balanceA.available_balance).to.equal(balanceB.available_balance); + } +); + +async function send_tari(sourceWallet, destWallet, tariAmount, feePerGram) { + const sourceWalletClient = sourceWallet.getClient(); + const destInfo = await destWallet.getClient().identify(); console.log( sourceWallet.name + - ' sending ' + + " sending " + tariAmount + - 'uT to ' + + "uT to " + destWallet.name + - ' `' + + " `" + destInfo.public_key + - '`' - ) - let success = false - let retries = 1 - const retries_limit = 25 - let lastResult + "`" + ); + let success = false; + let retries = 1; + const retries_limit = 25; + let lastResult; while (!success && retries <= retries_limit) { lastResult = await sourceWalletClient.transfer({ recipients: [ @@ -1057,146 +1058,146 @@ async function send_tari (sourceWallet, destWallet, tariAmount, feePerGram) { address: destInfo.public_key, amount: tariAmount, fee_per_gram: feePerGram, - message: 'msg' - } - ] - }) - success = lastResult.results[0].is_success + message: "msg", + }, + ], + }); + success = lastResult.results[0].is_success; if (!success) { - const wait_seconds = 5 + const wait_seconds = 5; console.log( - ' ' + + " " + lastResult.results[0].failure_message + - ', trying again after ' + + ", trying again after " + wait_seconds + - 's (' + + "s (" + retries + - ' of ' + + " of " + retries_limit + - ')' - ) - await sleep(wait_seconds * 1000) - retries++ + ")" + ); + await sleep(wait_seconds * 1000); + retries++; } } - return lastResult + return lastResult; } When( /I send (.*) uT from wallet (.*) to wallet (.*) at fee (.*)/, { timeout: 25 * 5 * 1000 }, async function (tariAmount, source, dest, feePerGram) { - const sourceInfo = await this.getWallet(source).getClient().identify() - const destInfo = await this.getWallet(dest).getClient().identify() + const sourceInfo = await this.getWallet(source).getClient().identify(); + const destInfo = await this.getWallet(dest).getClient().identify(); this.lastResult = await send_tari( this.getWallet(source), this.getWallet(dest), tariAmount, feePerGram - ) - expect(this.lastResult.results[0].is_success).to.equal(true) + ); + expect(this.lastResult.results[0].is_success).to.equal(true); this.addTransaction( sourceInfo.public_key, this.lastResult.results[0].transaction_id - ) + ); this.addTransaction( destInfo.public_key, this.lastResult.results[0].transaction_id - ) + ); console.log( " Transaction '" + this.lastResult.results[0].transaction_id + "' is_success(" + this.lastResult.results[0].is_success + - ')' - ) + ")" + ); } -) +); When( /I multi-send (.*) transactions of (.*) uT from wallet (.*) to wallet (.*) at fee (.*)/, { timeout: 25 * 5 * 1000 }, async function (number, tariAmount, source, dest, fee) { - console.log('\n') - const sourceInfo = await this.getWallet(source).getClient().identify() - const destInfo = await this.getWallet(dest).getClient().identify() + console.log("\n"); + const sourceInfo = await this.getWallet(source).getClient().identify(); + const destInfo = await this.getWallet(dest).getClient().identify(); for (let i = 0; i < number; i++) { this.lastResult = await send_tari( this.getWallet(source), this.getWallet(dest), tariAmount, fee - ) - expect(this.lastResult.results[0].is_success).to.equal(true) + ); + expect(this.lastResult.results[0].is_success).to.equal(true); this.addTransaction( sourceInfo.public_key, this.lastResult.results[0].transaction_id - ) + ); this.addTransaction( destInfo.public_key, this.lastResult.results[0].transaction_id - ) + ); // console.log(" Transaction '" + this.lastResult.results[0]["transaction_id"] + "' is_success(" + // this.lastResult.results[0]["is_success"] + ")"); } } -) +); When( /I multi-send (.*) uT from wallet (.*) to all wallets at fee (.*)/, { timeout: 25 * 5 * 1000 }, async function (tariAmount, source, fee) { - const sourceWalletClient = this.getWallet(source).getClient() - const sourceInfo = await sourceWalletClient.identify() + const sourceWalletClient = this.getWallet(source).getClient(); + const sourceInfo = await sourceWalletClient.identify(); for (const wallet in this.wallets) { if (this.getWallet(source).name === this.getWallet(wallet).name) { - continue + continue; } - const destInfo = await this.getWallet(wallet).getClient().identify() + const destInfo = await this.getWallet(wallet).getClient().identify(); this.lastResult = await send_tari( this.getWallet(source), this.getWallet(wallet), tariAmount, fee - ) - expect(this.lastResult.results[0].is_success).to.equal(true) + ); + expect(this.lastResult.results[0].is_success).to.equal(true); this.addTransaction( sourceInfo.public_key, this.lastResult.results[0].transaction_id - ) + ); this.addTransaction( destInfo.public_key, this.lastResult.results[0].transaction_id - ) + ); // console.log(" Transaction '" + this.lastResult.results[0]["transaction_id"] + "' is_success(" + // this.lastResult.results[0]["is_success"] + ")"); } } -) +); When( /I transfer (.*) uT from (.*) to (.*) and (.*) at fee (.*)/, { timeout: 25 * 5 * 1000 }, async function (tariAmount, source, dest1, dest2, feePerGram) { - const sourceClient = this.getWallet(source).getClient() - const destClient1 = this.getWallet(dest1).getClient() - const destClient2 = this.getWallet(dest2).getClient() + const sourceClient = this.getWallet(source).getClient(); + const destClient1 = this.getWallet(dest1).getClient(); + const destClient2 = this.getWallet(dest2).getClient(); - const sourceInfo = await sourceClient.identify() - const dest1Info = await destClient1.identify() - const dest2Info = await destClient2.identify() + const sourceInfo = await sourceClient.identify(); + const dest1Info = await destClient1.identify(); + const dest2Info = await destClient2.identify(); console.log( - 'Starting transfer of', + "Starting transfer of", tariAmount, - 'to', + "to", dest1, - 'and to', + "and to", dest2 - ) - let success = false - let retries = 1 - const retries_limit = 25 + ); + let success = false; + let retries = 1; + const retries_limit = 25; while (!success && retries <= retries_limit) { lastResult = await sourceClient.transfer({ recipients: [ @@ -1204,149 +1205,148 @@ When( address: dest1Info.public_key, amount: tariAmount, fee_per_gram: feePerGram, - message: 'msg' + message: "msg", }, { address: dest2Info.public_key, amount: tariAmount, fee_per_gram: feePerGram, - message: 'msg' - } - ] - }) + message: "msg", + }, + ], + }); success = - lastResult.results[0].is_success && - lastResult.results[1].is_success + lastResult.results[0].is_success && lastResult.results[1].is_success; if (!success) { - const wait_seconds = 5 + const wait_seconds = 5; console.log( - ' ' + + " " + lastResult.results[0].failure_message + - ', trying again after ' + + ", trying again after " + wait_seconds + - 's (' + + "s (" + retries + - ' of ' + + " of " + retries_limit + - ')' - ) - await sleep(wait_seconds * 1000) - retries++ + ")" + ); + await sleep(wait_seconds * 1000); + retries++; } } if (success) { this.addTransaction( sourceInfo.public_key, lastResult.results[0].transaction_id - ) + ); this.addTransaction( sourceInfo.public_key, lastResult.results[1].transaction_id - ) + ); this.addTransaction( dest1Info.public_key, lastResult.results[0].transaction_id - ) + ); this.addTransaction( dest2Info.public_key, lastResult.results[1].transaction_id - ) + ); } - expect(success).to.equal(true) + expect(success).to.equal(true); } -) +); When( /I transfer (.*) uT to self from wallet (.*) at fee (.*)/, { timeout: 25 * 5 * 1000 }, async function (tariAmount, source, feePerGram) { - const sourceInfo = await this.getWallet(source).getClient().identify() + const sourceInfo = await this.getWallet(source).getClient().identify(); this.lastResult = await send_tari( this.getWallet(source), this.getWallet(source), tariAmount, feePerGram - ) - expect(this.lastResult.results[0].is_success).to.equal(true) + ); + expect(this.lastResult.results[0].is_success).to.equal(true); this.addTransaction( sourceInfo.public_key, this.lastResult.results[0].transaction_id - ) + ); console.log( " Transaction '" + this.lastResult.results[0].transaction_id + "' is_success(" + this.lastResult.results[0].is_success + - ')' - ) + ")" + ); } -) +); When( /I transfer (.*) uT from (.*) to ([A-Za-z0-9,]+) at fee (.*)/, async function (amount, source, dests, feePerGram) { - const wallet = this.getWallet(source) - const client = wallet.getClient() + const wallet = this.getWallet(source); + const client = wallet.getClient(); const destWallets = dests - .split(',') - .map((dest) => this.getWallet(dest).getClient()) + .split(",") + .map((dest) => this.getWallet(dest).getClient()); - console.log('Starting Transfer of', amount, 'to') + console.log("Starting Transfer of", amount, "to"); const recipients = destWallets.map((w) => ({ address: w.public_key, amount: amount, fee_per_gram: feePerGram, - message: 'msg' - })) - const output = await client.transfer({ recipients }) - console.log('output', output) - lastResult = output + message: "msg", + })); + const output = await client.transfer({ recipients }); + console.log("output", output); + lastResult = output; } -) +); When(/I wait (.*) seconds/, { timeout: 600 * 1000 }, async function (int) { - console.log('Waiting for', int, 'seconds') - await sleep(int * 1000) - console.log('Waiting finished') -}) + console.log("Waiting for", int, "seconds"); + await sleep(int * 1000); + console.log("Waiting finished"); +}); Then( /Batch transfer of (.*) transactions was a success from (.*) to ([A-Za-z0-9,]+)/, async function (txCount, walletListStr) { - const clients = walletListStr.split(',').map((s) => { - const wallet = this.getWallet(s) - return wallet.getClient() - }) - - const resultObj = lastResult.results - console.log(resultObj) + const clients = walletListStr.split(",").map((s) => { + const wallet = this.getWallet(s); + return wallet.getClient(); + }); + + const resultObj = lastResult.results; + console.log(resultObj); + let successCount = 0; for (let i = 0; i < txCount; i++) { - let successCount = 0 - const obj = resultObj[i] + const obj = resultObj[i]; if (!obj.is_success) { - console.log(obj.transaction_id, 'failed') - assert(obj.is_success, true) + console.log(obj.transaction_id, "failed"); + assert(obj.is_success, true); } else { console.log( - 'Transaction', + "Transaction", obj.transaction_id, - 'passed from original request succeeded' - ) + "passed from original request succeeded" + ); const req = { - transaction_ids: [obj.transaction_id.toString()] - } - console.log(req) + transaction_ids: [obj.transaction_id.toString()], + }; + console.log(req); for (const client of clients) { try { - const tx = await client.getTransactionInfo(req) - successCount++ - console.log(tx) + const tx = await client.getTransactionInfo(req); + successCount++; + console.log(tx); } catch (err) { console.log( obj.transaction_id.toString(), - 'not found in :', + "not found in :", await client.identify() - ) + ); } } } @@ -1354,11 +1354,11 @@ Then( console.log( `Number of successful transactions is ${successCount} of ${txCount}` - ) - assert(successCount === txCount) - console.log('All transactions found') + ); + assert(successCount === txCount); + console.log("All transactions found"); } -) +); Then( /wallet (.*) detects all transactions are at least Pending/, @@ -1366,50 +1366,50 @@ Then( async function (walletName) { // Note: This initial step can take a long time if network conditions are not favourable // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed - const wallet = this.getWallet(walletName) - const walletClient = wallet.getClient() - const walletInfo = await walletClient.identify() + const wallet = this.getWallet(walletName); + const walletClient = wallet.getClient(); + const walletInfo = await walletClient.identify(); - const txIds = this.transactionsMap.get(walletInfo.public_key) + const txIds = this.transactionsMap.get(walletInfo.public_key); if (txIds === undefined) { - console.log('\nNo transactions for ' + walletName + '!') - expect(false).to.equal(true) + console.log("\nNo transactions for " + walletName + "!"); + expect(false).to.equal(true); } console.log( - '\nDetecting', + "\nDetecting", txIds.length, - 'transactions as at least Pending: ', + "transactions as at least Pending: ", walletName, txIds - ) - for (i = 0; i < txIds.length; i++) { + ); + for (let i = 0; i < txIds.length; i++) { console.log( - '(' + + "(" + (i + 1) + - '/' + + "/" + txIds.length + - ') - ' + + ") - " + wallet.name + - ': Waiting for TxId:' + + ": Waiting for TxId:" + txIds[i] + - ' to register at least Pending in the wallet ...' - ) + " to register at least Pending in the wallet ..." + ); await waitFor( async () => wallet.getClient().isTransactionAtLeastPending(txIds[i]), true, 3700 * 1000, 5 * 1000, 5 - ) + ); const transactionPending = await wallet .getClient() - .isTransactionAtLeastPending(txIds[i]) + .isTransactionAtLeastPending(txIds[i]); // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); // consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(transactionPending).to.equal(true) + expect(transactionPending).to.equal(true); } } -) +); Then( /all wallets detect all transactions are at least Pending/, @@ -1418,102 +1418,102 @@ Then( // Note: This initial step to register pending can take a long time if network conditions are not favourable // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed for (const walletName in this.wallets) { - const wallet = this.getWallet(walletName) - const walletClient = wallet.getClient() - const walletInfo = await walletClient.identify() + const wallet = this.getWallet(walletName); + const walletClient = wallet.getClient(); + const walletInfo = await walletClient.identify(); - const txIds = this.transactionsMap.get(walletInfo.public_key) + const txIds = this.transactionsMap.get(walletInfo.public_key); if (txIds === undefined) { - console.log('\nNo transactions for ' + walletName + '!') - expect(false).to.equal(true) + console.log("\nNo transactions for " + walletName + "!"); + expect(false).to.equal(true); } console.log( - '\nDetecting', + "\nDetecting", txIds.length, - 'transactions as at least Pending: ', + "transactions as at least Pending: ", walletName, txIds - ) - for (i = 0; i < txIds.length; i++) { + ); + for (let i = 0; i < txIds.length; i++) { console.log( - '(' + + "(" + (i + 1) + - '/' + + "/" + txIds.length + - ') - ' + + ") - " + wallet.name + - ': Waiting for TxId:' + + ": Waiting for TxId:" + txIds[i] + - ' to register at least Pending in the wallet ...' - ) + " to register at least Pending in the wallet ..." + ); await waitFor( async () => wallet.getClient().isTransactionAtLeastPending(txIds[i]), true, 3700 * 1000, 5 * 1000, 5 - ) + ); const transactionPending = await wallet .getClient() - .isTransactionAtLeastPending(txIds[i]) + .isTransactionAtLeastPending(txIds[i]); // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); // consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(transactionPending).to.equal(true) + expect(transactionPending).to.equal(true); } } } -) +); Then( /wallet (.*) detects all transactions are at least Completed/, { timeout: 1200 * 1000 }, async function (walletName) { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed - const wallet = this.getWallet(walletName) - const walletClient = wallet.getClient() - const walletInfo = await walletClient.identify() + const wallet = this.getWallet(walletName); + const walletClient = wallet.getClient(); + const walletInfo = await walletClient.identify(); - const txIds = this.transactionsMap.get(walletInfo.public_key) + const txIds = this.transactionsMap.get(walletInfo.public_key); if (txIds === undefined) { - console.log('\nNo transactions for ' + walletName + '!') - expect(false).to.equal(true) + console.log("\nNo transactions for " + walletName + "!"); + expect(false).to.equal(true); } console.log( - '\nDetecting', + "\nDetecting", txIds.length, - 'transactions as at least Completed: ', + "transactions as at least Completed: ", walletName, txIds - ) - for (i = 0; i < txIds.length; i++) { + ); + for (let i = 0; i < txIds.length; i++) { // Get details console.log( - '(' + + "(" + (i + 1) + - '/' + + "/" + txIds.length + - ') - ' + + ") - " + wallet.name + - ': Waiting for TxId:' + + ": Waiting for TxId:" + txIds[i] + - ' to register at least Completed in the wallet ...' - ) + " to register at least Completed in the wallet ..." + ); await waitFor( async () => wallet.getClient().isTransactionAtLeastCompleted(txIds[i]), true, 600 * 1000, 5 * 1000, 5 - ) + ); const transactionCompleted = await wallet .getClient() - .isTransactionAtLeastCompleted(txIds[i]) + .isTransactionAtLeastCompleted(txIds[i]); // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); // consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(transactionCompleted).to.equal(true) + expect(transactionCompleted).to.equal(true); } } -) +); Then( /all wallets detect all transactions are at least Completed/, @@ -1521,35 +1521,35 @@ Then( async function () { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed for (const walletName in this.wallets) { - const wallet = this.getWallet(walletName) - const walletClient = wallet.getClient() - const walletInfo = await walletClient.identify() + const wallet = this.getWallet(walletName); + const walletClient = wallet.getClient(); + const walletInfo = await walletClient.identify(); - const txIds = this.transactionsMap.get(walletInfo.public_key) + const txIds = this.transactionsMap.get(walletInfo.public_key); if (txIds === undefined) { - console.log('\nNo transactions for ' + walletName + '!') - expect(false).to.equal(true) + console.log("\nNo transactions for " + walletName + "!"); + expect(false).to.equal(true); } console.log( - '\nDetecting', + "\nDetecting", txIds.length, - 'transactions as at least Completed: ', + "transactions as at least Completed: ", walletName, txIds - ) - for (i = 0; i < txIds.length; i++) { + ); + for (let i = 0; i < txIds.length; i++) { // Get details console.log( - '(' + + "(" + (i + 1) + - '/' + + "/" + txIds.length + - ') - ' + + ") - " + wallet.name + - ': Waiting for TxId:' + + ": Waiting for TxId:" + txIds[i] + - ' to register at least Completed in the wallet ...' - ) + " to register at least Completed in the wallet ..." + ); await waitFor( async () => wallet.getClient().isTransactionAtLeastCompleted(txIds[i]), @@ -1557,68 +1557,68 @@ Then( 1100 * 1000, 5 * 1000, 5 - ) + ); const transactionCompleted = await wallet .getClient() - .isTransactionAtLeastCompleted(txIds[i]) + .isTransactionAtLeastCompleted(txIds[i]); // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); // consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(transactionCompleted).to.equal(true) + expect(transactionCompleted).to.equal(true); } } } -) +); Then( /wallet (.*) detects all transactions are at least Broadcast/, { timeout: 1200 * 1000 }, async function (walletName) { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed - const wallet = this.getWallet(walletName) - const walletClient = wallet.getClient() - const walletInfo = await walletClient.identify() + const wallet = this.getWallet(walletName); + const walletClient = wallet.getClient(); + const walletInfo = await walletClient.identify(); - const txIds = this.transactionsMap.get(walletInfo.public_key) + const txIds = this.transactionsMap.get(walletInfo.public_key); if (txIds === undefined) { - console.log('\nNo transactions for ' + walletName + '!') - expect(false).to.equal(true) + console.log("\nNo transactions for " + walletName + "!"); + expect(false).to.equal(true); } console.log( - '\nDetecting', + "\nDetecting", txIds.length, - 'transactions as at least Broadcast: ', + "transactions as at least Broadcast: ", walletName, txIds - ) - for (i = 0; i < txIds.length; i++) { + ); + for (let i = 0; i < txIds.length; i++) { // Get details console.log( - '(' + + "(" + (i + 1) + - '/' + + "/" + txIds.length + - ') - ' + + ") - " + wallet.name + - ': Waiting for TxId:' + + ": Waiting for TxId:" + txIds[i] + - ' to register at least Broadcast in the wallet ...' - ) + " to register at least Broadcast in the wallet ..." + ); await waitFor( async () => wallet.getClient().isTransactionAtLeastBroadcast(txIds[i]), true, 600 * 1000, 5 * 1000, 5 - ) + ); const transactionBroadcasted = await wallet .getClient() - .isTransactionAtLeastBroadcast(txIds[i]) + .isTransactionAtLeastBroadcast(txIds[i]); // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); // consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(transactionBroadcasted).to.equal(true) + expect(transactionBroadcasted).to.equal(true); } } -) +); Then( /all wallets detect all transactions are at least Broadcast/, @@ -1626,35 +1626,35 @@ Then( async function () { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed for (const walletName in this.wallets) { - const wallet = this.getWallet(walletName) - const walletClient = wallet.getClient() - const walletInfo = await walletClient.identify() + const wallet = this.getWallet(walletName); + const walletClient = wallet.getClient(); + const walletInfo = await walletClient.identify(); - const txIds = this.transactionsMap.get(walletInfo.public_key) + const txIds = this.transactionsMap.get(walletInfo.public_key); if (txIds === undefined) { - console.log('\nNo transactions for ' + walletName + '!') - expect(false).to.equal(true) + console.log("\nNo transactions for " + walletName + "!"); + expect(false).to.equal(true); } console.log( - '\nDetecting', + "\nDetecting", txIds.length, - 'transactions as at least Broadcast: ', + "transactions as at least Broadcast: ", walletName, txIds - ) - for (i = 0; i < txIds.length; i++) { + ); + for (let i = 0; i < txIds.length; i++) { // Get details console.log( - '(' + + "(" + (i + 1) + - '/' + + "/" + txIds.length + - ') - ' + + ") - " + wallet.name + - ': Waiting for TxId:' + + ": Waiting for TxId:" + txIds[i] + - ' to register at least Broadcast in the wallet ...' - ) + " to register at least Broadcast in the wallet ..." + ); await waitFor( async () => wallet.getClient().isTransactionAtLeastBroadcast(txIds[i]), @@ -1662,51 +1662,51 @@ Then( 1100 * 1000, 5 * 1000, 5 - ) + ); const transactionBroadcasted = await wallet .getClient() - .isTransactionAtLeastBroadcast(txIds[i]) + .isTransactionAtLeastBroadcast(txIds[i]); // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); // consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(transactionBroadcasted).to.equal(true) + expect(transactionBroadcasted).to.equal(true); } } } -) +); Then( /wallet (.*) detects all transactions are at least Mined_Unconfirmed/, { timeout: 1200 * 1000 }, async function (walletName) { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed - const wallet = this.getWallet(walletName) - const walletClient = wallet.getClient() - const walletInfo = await walletClient.identify() + const wallet = this.getWallet(walletName); + const walletClient = wallet.getClient(); + const walletInfo = await walletClient.identify(); - const txIds = this.transactionsMap.get(walletInfo.public_key) + const txIds = this.transactionsMap.get(walletInfo.public_key); if (txIds === undefined) { - console.log('\nNo transactions for ' + walletName + '!') - expect(false).to.equal(true) + console.log("\nNo transactions for " + walletName + "!"); + expect(false).to.equal(true); } console.log( - '\nDetecting', + "\nDetecting", txIds.length, - 'transactions as at least Mined_Unconfirmed: ', + "transactions as at least Mined_Unconfirmed: ", walletName, txIds - ) - for (i = 0; i < txIds.length; i++) { + ); + for (let i = 0; i < txIds.length; i++) { console.log( - '(' + + "(" + (i + 1) + - '/' + + "/" + txIds.length + - ') - ' + + ") - " + wallet.name + - ': Waiting for TxId:' + + ": Waiting for TxId:" + txIds[i] + - ' to be detected as Mined_Unconfirmed in the wallet ...' - ) + " to be detected as Mined_Unconfirmed in the wallet ..." + ); await waitFor( async () => wallet.getClient().isTransactionAtLeastMinedUnconfirmed(txIds[i]), @@ -1714,16 +1714,16 @@ Then( 600 * 1000, 5 * 1000, 5 - ) + ); const isTransactionAtLeastMinedUnconfirmed = await wallet .getClient() - .isTransactionAtLeastMinedUnconfirmed(txIds[i]) + .isTransactionAtLeastMinedUnconfirmed(txIds[i]); // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); // consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(isTransactionAtLeastMinedUnconfirmed).to.equal(true) + expect(isTransactionAtLeastMinedUnconfirmed).to.equal(true); } } -) +); Then( /all wallets detect all transactions are at least Mined_Unconfirmed/, @@ -1731,33 +1731,33 @@ Then( async function () { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed for (const walletName in this.wallets) { - const wallet = this.getWallet(walletName) - const walletClient = wallet.getClient() - const walletInfo = await walletClient.identify() + const wallet = this.getWallet(walletName); + const walletClient = wallet.getClient(); + const walletInfo = await walletClient.identify(); - const txIds = this.transactionsMap.get(walletInfo.public_key) + const txIds = this.transactionsMap.get(walletInfo.public_key); if (txIds === undefined) { - console.log('\nNo transactions for ' + walletName + '!') - expect(false).to.equal(true) + console.log("\nNo transactions for " + walletName + "!"); + expect(false).to.equal(true); } console.log( - '\nDetecting', + "\nDetecting", txIds.length, - 'transactions as at least Mined_Unconfirmed: ', + "transactions as at least Mined_Unconfirmed: ", walletName, txIds - ) - for (i = 0; i < txIds.length; i++) { + ); + for (let i = 0; i < txIds.length; i++) { console.log( - '(' + + "(" + (i + 1) + - '/' + + "/" + txIds.length + - ') - ' + + ") - " + wallet.name + - ': Waiting for TxId:', - txIds[i] + ' to be detected as Mined_Unconfirmed in the wallet ...' - ) + ": Waiting for TxId:", + txIds[i] + " to be detected as Mined_Unconfirmed in the wallet ..." + ); await waitFor( async () => wallet.getClient().isTransactionAtLeastMinedUnconfirmed(txIds[i]), @@ -1765,67 +1765,67 @@ Then( 1100 * 1000, 5 * 1000, 5 - ) + ); const isTransactionAtLeastMinedUnconfirmed = await wallet .getClient() - .isTransactionAtLeastMinedUnconfirmed(txIds[i]) + .isTransactionAtLeastMinedUnconfirmed(txIds[i]); // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); // consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(isTransactionAtLeastMinedUnconfirmed).to.equal(true) + expect(isTransactionAtLeastMinedUnconfirmed).to.equal(true); } } } -) +); Then( /wallet (.*) detects all transactions as Mined_Unconfirmed/, { timeout: 1200 * 1000 }, async function (walletName) { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed - const wallet = this.getWallet(walletName) - const walletClient = wallet.getClient() - const walletInfo = await walletClient.identify() + const wallet = this.getWallet(walletName); + const walletClient = wallet.getClient(); + const walletInfo = await walletClient.identify(); - const txIds = this.transactionsMap.get(walletInfo.public_key) + const txIds = this.transactionsMap.get(walletInfo.public_key); if (txIds === undefined) { - console.log('\nNo transactions for ' + walletName + '!') - expect(false).to.equal(true) + console.log("\nNo transactions for " + walletName + "!"); + expect(false).to.equal(true); } console.log( - '\nDetecting', + "\nDetecting", txIds.length, - 'transactions as Mined_Unconfirmed: ', + "transactions as Mined_Unconfirmed: ", walletName, txIds - ) - for (i = 0; i < txIds.length; i++) { + ); + for (let i = 0; i < txIds.length; i++) { console.log( - '(' + + "(" + (i + 1) + - '/' + + "/" + txIds.length + - ') - ' + + ") - " + wallet.name + - ': Waiting for TxId:' + + ": Waiting for TxId:" + txIds[i] + - ' to be detected as Mined_Unconfirmed in the wallet ...' - ) + " to be detected as Mined_Unconfirmed in the wallet ..." + ); await waitFor( async () => wallet.getClient().isTransactionMinedUnconfirmed(txIds[i]), true, 600 * 1000, 5 * 1000, 5 - ) + ); const isTransactionMinedUnconfirmed = await wallet .getClient() - .isTransactionMinedUnconfirmed(txIds[i]) + .isTransactionMinedUnconfirmed(txIds[i]); // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); // consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(isTransactionMinedUnconfirmed).to.equal(true) + expect(isTransactionMinedUnconfirmed).to.equal(true); } } -) +); Then( /all wallets detect all transactions as Mined_Unconfirmed/, @@ -1833,34 +1833,34 @@ Then( async function () { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed for (const walletName in this.wallets) { - const wallet = this.getWallet(walletName) - const walletClient = wallet.getClient() - const walletInfo = await walletClient.identify() + const wallet = this.getWallet(walletName); + const walletClient = wallet.getClient(); + const walletInfo = await walletClient.identify(); - const txIds = this.transactionsMap.get(walletInfo.public_key) + const txIds = this.transactionsMap.get(walletInfo.public_key); if (txIds === undefined) { - console.log('\nNo transactions for ' + walletName + '!') - expect(false).to.equal(true) + console.log("\nNo transactions for " + walletName + "!"); + expect(false).to.equal(true); } console.log( - '\nDetecting', + "\nDetecting", txIds.length, - 'transactions as Mined_Unconfirmed: ', + "transactions as Mined_Unconfirmed: ", walletName, txIds - ) - for (i = 0; i < txIds.length; i++) { + ); + for (let i = 0; i < txIds.length; i++) { console.log( - '(' + + "(" + (i + 1) + - '/' + + "/" + txIds.length + - ') - ' + + ") - " + wallet.name + - ': Waiting for TxId:' + + ": Waiting for TxId:" + txIds[i] + - ' to be detected as Mined_Unconfirmed in the wallet ...' - ) + " to be detected as Mined_Unconfirmed in the wallet ..." + ); await waitFor( async () => wallet.getClient().isTransactionMinedUnconfirmed(txIds[i]), @@ -1868,182 +1868,182 @@ Then( 1100 * 1000, 5 * 1000, 5 - ) + ); const isTransactionMinedUnconfirmed = await wallet .getClient() - .isTransactionMinedUnconfirmed(txIds[i]) + .isTransactionMinedUnconfirmed(txIds[i]); // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); // consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(isTransactionMinedUnconfirmed).to.equal(true) + expect(isTransactionMinedUnconfirmed).to.equal(true); } } } -) +); Then( /wallet (.*) detects all transactions as Mined_Confirmed/, { timeout: 1200 * 1000 }, async function (walletName) { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed - const wallet = this.getWallet(walletName) - const walletClient = wallet.getClient() - const walletInfo = await walletClient.identify() + const wallet = this.getWallet(walletName); + const walletClient = wallet.getClient(); + const walletInfo = await walletClient.identify(); - const txIds = this.transactionsMap.get(walletInfo.public_key) + const txIds = this.transactionsMap.get(walletInfo.public_key); if (txIds === undefined) { - console.log('\nNo transactions for ' + walletName + '!') - expect(false).to.equal(true) + console.log("\nNo transactions for " + walletName + "!"); + expect(false).to.equal(true); } console.log( - '\nDetecting', + "\nDetecting", txIds.length, - 'transactions as Mined_Confirmed: ', + "transactions as Mined_Confirmed: ", walletName, txIds - ) - for (i = 0; i < txIds.length; i++) { + ); + for (let i = 0; i < txIds.length; i++) { console.log( - '(' + + "(" + (i + 1) + - '/' + + "/" + txIds.length + - ') - ' + + ") - " + wallet.name + - ': Waiting for TxId:' + + ": Waiting for TxId:" + txIds[i] + - ' to be detected as Mined_Confirmed in the wallet ...' - ) + " to be detected as Mined_Confirmed in the wallet ..." + ); await waitFor( async () => wallet.getClient().isTransactionMinedConfirmed(txIds[i]), true, 600 * 1000, 5 * 1000, 5 - ) + ); const isTransactionMinedConfirmed = await wallet .getClient() - .isTransactionMinedConfirmed(txIds[i]) + .isTransactionMinedConfirmed(txIds[i]); // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); // consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(isTransactionMinedConfirmed).to.equal(true) + expect(isTransactionMinedConfirmed).to.equal(true); } } -) +); Then( /while mining via (.*) all transactions in wallet (.*) are found to be Mined_Confirmed/, { timeout: 1200 * 1000 }, async function (nodeName, walletName) { - const wallet = this.getWallet(walletName) - const walletClient = wallet.getClient() - const walletInfo = await walletClient.identify() - const nodeClient = this.getClient(nodeName) + const wallet = this.getWallet(walletName); + const walletClient = wallet.getClient(); + const walletInfo = await walletClient.identify(); + const nodeClient = this.getClient(nodeName); - const txIds = this.transactionsMap.get(walletInfo.public_key) + const txIds = this.transactionsMap.get(walletInfo.public_key); if (txIds === undefined) { - console.log('\nNo transactions for ' + walletName + '!') - expect(false).to.equal(true) + console.log("\nNo transactions for " + walletName + "!"); + expect(false).to.equal(true); } console.log( - '\nDetecting', + "\nDetecting", txIds.length, - 'transactions as Mined_Confirmed: ', + "transactions as Mined_Confirmed: ", walletName, txIds - ) - for (i = 0; i < txIds.length; i++) { + ); + for (let i = 0; i < txIds.length; i++) { console.log( - '(' + + "(" + (i + 1) + - '/' + + "/" + txIds.length + - ') - ' + + ") - " + wallet.name + - ': Waiting for TxId:' + + ": Waiting for TxId:" + txIds[i] + - ' to be detected as Mined_Confirmed in the wallet ...' - ) + " to be detected as Mined_Confirmed in the wallet ..." + ); await waitFor( async () => { if (await walletClient.isTransactionMinedConfirmed(txIds[i])) { - return true + return true; } else { - await nodeClient.mineBlock(walletClient) - this.tipHeight += 1 - return false + await nodeClient.mineBlock(walletClient); + this.tipHeight += 1; + return false; } }, true, 600 * 1000, 5 * 1000, 5 - ) + ); const isTransactionMinedConfirmed = await wallet .getClient() - .isTransactionMinedConfirmed(txIds[i]) + .isTransactionMinedConfirmed(txIds[i]); // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); // consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(isTransactionMinedConfirmed).to.equal(true) + expect(isTransactionMinedConfirmed).to.equal(true); } } -) +); Then( /while merge mining via (.*) all transactions in wallet (.*) are found to be Mined_Confirmed/, { timeout: 3600 * 1000 }, async function (mmProxy, walletName) { - const wallet = this.getWallet(walletName) - const walletClient = wallet.getClient() - const walletInfo = await walletClient.identify() + const wallet = this.getWallet(walletName); + const walletClient = wallet.getClient(); + const walletInfo = await walletClient.identify(); - const txIds = this.transactionsMap.get(walletInfo.public_key) + const txIds = this.transactionsMap.get(walletInfo.public_key); if (txIds === undefined) { - console.log('\nNo transactions for ' + walletName + '!') - expect(false).to.equal(true) + console.log("\nNo transactions for " + walletName + "!"); + expect(false).to.equal(true); } console.log( - '\nDetecting', + "\nDetecting", txIds.length, - 'transactions as Mined_Confirmed: ', + "transactions as Mined_Confirmed: ", walletName, txIds - ) - for (i = 0; i < txIds.length; i++) { + ); + for (let i = 0; i < txIds.length; i++) { console.log( - '(' + + "(" + (i + 1) + - '/' + + "/" + txIds.length + - ') - ' + + ") - " + wallet.name + - ': Waiting for TxId:' + + ": Waiting for TxId:" + txIds[i] + - ' to be detected as Mined_Confirmed in the wallet ...' - ) + " to be detected as Mined_Confirmed in the wallet ..." + ); await waitFor( async () => { if (await walletClient.isTransactionMinedConfirmed(txIds[i])) { - return true + return true; } else { - await this.mergeMineBlock(mmProxy) - this.tipHeight += 1 - return false + await this.mergeMineBlock(mmProxy); + this.tipHeight += 1; + return false; } }, true, 600 * 1000, 5 * 1000, 5 - ) + ); const isTransactionMinedConfirmed = await wallet .getClient() - .isTransactionMinedConfirmed(txIds[i]) + .isTransactionMinedConfirmed(txIds[i]); // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); // consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(isTransactionMinedConfirmed).to.equal(true) + expect(isTransactionMinedConfirmed).to.equal(true); } } -) +); Then( /all wallets detect all transactions as Mined_Confirmed/, @@ -2051,238 +2051,238 @@ Then( async function () { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed for (const walletName in this.wallets) { - const wallet = this.getWallet(walletName) - const walletClient = wallet.getClient() - const walletInfo = await walletClient.identify() + const wallet = this.getWallet(walletName); + const walletClient = wallet.getClient(); + const walletInfo = await walletClient.identify(); - const txIds = this.transactionsMap.get(walletInfo.public_key) + const txIds = this.transactionsMap.get(walletInfo.public_key); if (txIds === undefined) { - console.log('\nNo transactions for ' + walletName + '!') - expect(false).to.equal(true) + console.log("\nNo transactions for " + walletName + "!"); + expect(false).to.equal(true); } console.log( - '\nDetecting', + "\nDetecting", txIds.length, - 'transactions as Mined_Confirmed: ', + "transactions as Mined_Confirmed: ", walletName, txIds - ) - for (i = 0; i < txIds.length; i++) { + ); + for (let i = 0; i < txIds.length; i++) { console.log( - '(' + + "(" + (i + 1) + - '/' + + "/" + txIds.length + - ') - ' + + ") - " + wallet.name + - ': Waiting for TxId:' + + ": Waiting for TxId:" + txIds[i] + - ' to be detected as Mined_Confirmed in the wallet ...' - ) + " to be detected as Mined_Confirmed in the wallet ..." + ); await waitFor( async () => wallet.getClient().isTransactionMinedConfirmed(txIds[i]), true, 1100 * 1000, 5 * 1000, 5 - ) + ); const isTransactionMinedConfirmed = await wallet .getClient() - .isTransactionMinedConfirmed(txIds[i]) + .isTransactionMinedConfirmed(txIds[i]); // let txnDetails = await wallet.getClient().getTransactionDetails(txIds[i]); // consoleLogTransactionDetails(txnDetails, txIds[i]); - expect(isTransactionMinedConfirmed).to.equal(true) + expect(isTransactionMinedConfirmed).to.equal(true); } } } -) +); When( /I list all coinbase transactions for wallet (.*)/, { timeout: 20 * 1000 }, async function (walletName) { - const wallet = this.getWallet(walletName) - const walletClient = wallet.getClient() - console.log('\nListing all coinbase transactions: ', walletName) - const transactions = await walletClient.getAllCoinbaseTransactions() + const wallet = this.getWallet(walletName); + const walletClient = wallet.getClient(); + console.log("\nListing all coinbase transactions: ", walletName); + const transactions = await walletClient.getAllCoinbaseTransactions(); if (transactions.length > 0) { - for (i = 0; i < transactions.length; i++) { - consoleLogCoinbaseDetails(transactions[i]) + for (let i = 0; i < transactions.length; i++) { + consoleLogCoinbaseDetails(transactions[i]); } } else { - console.log(' No coinbase transactions found!') + console.log(" No coinbase transactions found!"); } } -) +); Then( /wallet (.*) has (.*) coinbase transactions/, { timeout: 20 * 1000 }, async function (walletName, count) { - const walletClient = this.getWallet(walletName).getClient() - const transactions = await walletClient.getAllCoinbaseTransactions() - expect(transactions.length).to.equal(Number(count)) - this.resultStack.push([walletName, transactions.length]) + const walletClient = this.getWallet(walletName).getClient(); + const transactions = await walletClient.getAllCoinbaseTransactions(); + expect(transactions.length).to.equal(Number(count)); + this.resultStack.push([walletName, transactions.length]); } -) +); Then( /wallet (.*) detects at least (.*) coinbase transactions as Mined_Confirmed/, { timeout: 605 * 1000 }, async function (walletName, count) { - const walletClient = this.getWallet(walletName).getClient() + const walletClient = this.getWallet(walletName).getClient(); await waitFor( async () => walletClient.areCoinbasesConfirmedAtLeast(count), true, 600 * 1000, 5 * 1000, 5 - ) - const transactions = await walletClient.getAllSpendableCoinbaseTransactions() - expect(transactions.length >= count).to.equal(true) + ); + const transactions = await walletClient.getAllSpendableCoinbaseTransactions(); + expect(transactions.length >= count).to.equal(true); } -) +); Then( /the number of coinbase transactions for wallet (.*) and wallet (.*) are (.*) less/, { timeout: 20 * 1000 }, async function (walletNameA, walletNameB, count) { - const walletClientA = this.getWallet(walletNameA).getClient() - const transactionsA = await walletClientA.getAllCoinbaseTransactions() - const walletClientB = this.getWallet(walletNameB).getClient() - const transactionsB = await walletClientB.getAllCoinbaseTransactions() + const walletClientA = this.getWallet(walletNameA).getClient(); + const transactionsA = await walletClientA.getAllCoinbaseTransactions(); + const walletClientB = this.getWallet(walletNameB).getClient(); + const transactionsB = await walletClientB.getAllCoinbaseTransactions(); if (this.resultStack.length >= 2) { - const walletStats = [this.resultStack.pop(), this.resultStack.pop()] + const walletStats = [this.resultStack.pop(), this.resultStack.pop()]; console.log( - '\nCoinbase comparison: Expect this (current + deficit)', + "\nCoinbase comparison: Expect this (current + deficit)", transactionsA.length, transactionsB.length, Number(count), - 'to equal this (previous)', + "to equal this (previous)", walletStats[0][1], walletStats[1][1] - ) + ); expect( transactionsA.length + transactionsB.length + Number(count) - ).to.equal(walletStats[0][1] + walletStats[1][1]) + ).to.equal(walletStats[0][1] + walletStats[1][1]); } else { expect( - '\nCoinbase comparison: Not enough results saved on the stack!' - ).to.equal('') + "\nCoinbase comparison: Not enough results saved on the stack!" + ).to.equal(""); } } -) +); When(/I request the difficulties of a node (.*)/, async function (node) { - const client = this.getClient(node) - const difficulties = await client.getNetworkDifficulties(2, 0, 2) - this.lastResult = difficulties -}) + const client = this.getClient(node); + const difficulties = await client.getNetworkDifficulties(2, 0, 2); + this.lastResult = difficulties; +}); -Then('difficulties are available', function () { - assert(this.lastResult.length, 3) +Then("difficulties are available", function () { + assert(this.lastResult.length, 3); // check genesis block, chain in reverse height order - assert(this.lastResult[2].difficulty, '1') - assert(this.lastResult[2].estimated_hash_rate, '0') - assert(this.lastResult[2].height, '1') - assert(this.lastResult[2].pow_algo, '0') -}) + assert(this.lastResult[2].difficulty, "1"); + assert(this.lastResult[2].estimated_hash_rate, "0"); + assert(this.lastResult[2].height, "1"); + assert(this.lastResult[2].pow_algo, "0"); +}); When( /I coin split tari in wallet (.*) to produce (.*) UTXOs of (.*) uT each with fee_per_gram (.*) uT/, { timeout: 4800 * 1000 }, async function (walletName, splitNum, splitValue, feePerGram) { - console.log('\n') - const numberOfSplits = Math.ceil(splitNum / 499) - let splitsLeft = splitNum + console.log("\n"); + const numberOfSplits = Math.ceil(splitNum / 499); + let splitsLeft = splitNum; - const wallet = this.getWallet(walletName) - const walletClient = wallet.getClient() - const walletInfo = await walletClient.identify() + const wallet = this.getWallet(walletName); + const walletClient = wallet.getClient(); + const walletInfo = await walletClient.identify(); console.log( - 'Performing', + "Performing", numberOfSplits, - 'coin splits to produce', + "coin splits to produce", splitNum, - 'outputs of', + "outputs of", splitValue, - 'uT' - ) + "uT" + ); for (let i = 0; i < numberOfSplits; i++) { - const splits = Math.min(499, splitsLeft) - splitsLeft -= splits + const splits = Math.min(499, splitsLeft); + splitsLeft -= splits; const result = await walletClient.coin_split({ amount_per_split: splitValue, split_count: splits, fee_per_gram: feePerGram, - message: 'Cucumber coinsplit', - lockheight: 0 - }) + message: "Cucumber coinsplit", + lockheight: 0, + }); console.log( - 'Coin split', + "Coin split", i + 1, - '/', + "/", numberOfSplits, - ' completed with TxId: ', + " completed with TxId: ", result - ) - this.addTransaction(walletInfo.public_key, result.tx_id) - this.lastResult = result + ); + this.addTransaction(walletInfo.public_key, result.tx_id); + this.lastResult = result; } } -) +); When( /I send (.*) transactions of (.*) uT each from wallet (.*) to wallet (.*) at fee_per_gram (.*)/, { timeout: 10800 * 1000 }, async function (numTransactions, amount, sourceWallet, dest, feePerGram) { - console.log('\n') - const sourceWalletClient = this.getWallet(sourceWallet).getClient() - const sourceInfo = await sourceWalletClient.identify() - const destInfo = await this.getWallet(dest).getClient().identify() + console.log("\n"); + const sourceWalletClient = this.getWallet(sourceWallet).getClient(); + const sourceInfo = await sourceWalletClient.identify(); + const destInfo = await this.getWallet(dest).getClient().identify(); console.log( - 'Sending', + "Sending", numTransactions, - 'transactions from', + "transactions from", sourceWallet, - 'to', + "to", dest - ) + ); - let batch = 1 - for (i = 0; i < numTransactions; i++) { + let batch = 1; + for (let i = 0; i < numTransactions; i++) { const message = - 'Transaction from ' + sourceWallet + ' to ' + dest + ' ' + i + "Transaction from " + sourceWallet + " to " + dest + " " + i; const result = await sourceWalletClient.transfer({ recipients: [ { address: destInfo.public_key, amount: amount, fee_per_gram: feePerGram, - message: message - } - ] - }) - expect(result.results[0].is_success).to.equal(true) + message: message, + }, + ], + }); + expect(result.results[0].is_success).to.equal(true); this.addTransaction( sourceInfo.public_key, result.results[0].transaction_id - ) + ); this.addTransaction( destInfo.public_key, result.results[0].transaction_id - ) + ); if (i / 10 >= batch) { - batch++ - console.log(i, '/', numTransactions, ' transactions sent') + batch++; + console.log(i, "/", numTransactions, " transactions sent"); } - await sleep(50) + await sleep(50); } - console.log(numTransactions, ' transactions successfully sent.') + console.log(numTransactions, " transactions successfully sent."); } -) +); diff --git a/integration_tests/features/support/world.js b/integration_tests/features/support/world.js index 2f233320f0..2a444a7a3b 100644 --- a/integration_tests/features/support/world.js +++ b/integration_tests/features/support/world.js @@ -1,235 +1,233 @@ -const { setWorldConstructor, After, BeforeAll } = require('cucumber') +const { setWorldConstructor, After, BeforeAll } = require("cucumber"); -const BaseNodeProcess = require('../../helpers/baseNodeProcess') -const MergeMiningProxyProcess = require('../../helpers/mergeMiningProxyProcess') -const WalletProcess = require('../../helpers/walletProcess') -const MiningNodeProcess = require('../../helpers/miningNodeProcess') +const BaseNodeProcess = require("../../helpers/baseNodeProcess"); +const MergeMiningProxyProcess = require("../../helpers/mergeMiningProxyProcess"); +const WalletProcess = require("../../helpers/walletProcess"); +const MiningNodeProcess = require("../../helpers/miningNodeProcess"); class CustomWorld { - constructor ({ attach, log, parameters }) { + constructor({ parameters }) { // this.variable = 0; - this.seeds = {} - this.nodes = {} - this.proxies = {} - this.miners = {} - this.wallets = {} - this.clients = {} - this.headers = {} - this.outputs = {} - this.testrun = `run${Date.now()}` - this.lastResult = null - this.blocks = {} - this.transactions = {} - this.peers = {} - this.transactionsMap = new Map() - this.resultStack = [] - this.tipHeight = 0 + this.seeds = {}; + this.nodes = {}; + this.proxies = {}; + this.miners = {}; + this.wallets = {}; + this.clients = {}; + this.headers = {}; + this.outputs = {}; + this.testrun = `run${Date.now()}`; + this.lastResult = null; + this.blocks = {}; + this.transactions = {}; + this.peers = {}; + this.transactionsMap = new Map(); + this.resultStack = []; + this.tipHeight = 0; this.logFilePathBaseNode = - parameters.logFilePathBaseNode || './log4rs/base_node.yml' - this.logFilePathProxy = parameters.logFilePathProxy || './log4rs/proxy.yml' + parameters.logFilePathBaseNode || "./log4rs/base_node.yml"; + this.logFilePathProxy = parameters.logFilePathProxy || "./log4rs/proxy.yml"; this.logFilePathWallet = - parameters.logFilePathWallet || './log4rs/wallet.yml' + parameters.logFilePathWallet || "./log4rs/wallet.yml"; } - async createSeedNode (name) { + async createSeedNode(name) { const proc = new BaseNodeProcess( `seed-${name}`, null, this.logFilePathBaseNode - ) - await proc.startNew() - this.seeds[name] = proc - this.clients[name] = proc.createGrpcClient() + ); + await proc.startNew(); + this.seeds[name] = proc; + this.clients[name] = proc.createGrpcClient(); } - seedAddresses () { - const res = [] + seedAddresses() { + const res = []; for (const property in this.seeds) { - res.push(this.seeds[property].peerAddress()) + res.push(this.seeds[property].peerAddress()); } - return res + return res; } /// Create but don't add the node - createNode (name, options) { - return new BaseNodeProcess(name, options, this.logFilePathBaseNode) + createNode(name, options) { + return new BaseNodeProcess(name, options, this.logFilePathBaseNode); } - - async createAndAddNode (name, addresses) { - const node = this.createNode(name) + async createAndAddNode(name, addresses) { + const node = this.createNode(name); if (Array.isArray(addresses)) { - node.setPeerSeeds(addresses) + node.setPeerSeeds(addresses); } else { - node.setPeerSeeds([addresses]) + node.setPeerSeeds([addresses]); } - await node.startNew() - this.addNode(name, node) + await node.startNew(); + this.addNode(name, node); } - - addNode (name, process) { - this.nodes[name] = process - this.clients[name] = process.createGrpcClient() + addNode(name, process) { + this.nodes[name] = process; + this.clients[name] = process.createGrpcClient(); } - addMiningNode (name, process) { - this.miners[name] = process + addMiningNode(name, process) { + this.miners[name] = process; } - addProxy (name, process) { - this.proxies[name] = process + addProxy(name, process) { + this.proxies[name] = process; } - async createAndAddWallet (name, nodeAddresses) { - const wallet = new WalletProcess(name, {}, this.logFilePathWallet) - wallet.setPeerSeeds([nodeAddresses]) - await wallet.startNew() - this.addWallet(name, wallet) + async createAndAddWallet(name, nodeAddresses) { + const wallet = new WalletProcess(name, {}, this.logFilePathWallet); + wallet.setPeerSeeds([nodeAddresses]); + await wallet.startNew(); + this.addWallet(name, wallet); } - addWallet (name, process) { - this.wallets[name] = process + addWallet(name, process) { + this.wallets[name] = process; } - addOutput (name, output) { - this.outputs[name] = output + addOutput(name, output) { + this.outputs[name] = output; } - async mineBlock (name, weight, beforeSubmit, onError) { + async mineBlock(name, weight, beforeSubmit, onError) { await this.clients[name].mineBlockWithoutWallet( beforeSubmit, weight, onError - ) + ); } - async mergeMineBlock (name, weight) { - const client = this.proxies[name].createClient() - await client.mineBlock(weight) + async mergeMineBlock(name, weight) { + const client = this.proxies[name].createClient(); + await client.mineBlock(weight); } - saveBlock (name, block) { - this.blocks[name] = block + saveBlock(name, block) { + this.blocks[name] = block; } - async submitBlock (blockName, nodeName) { - const result = await this.clients[nodeName] + async submitBlock(blockName, nodeName) { + await this.clients[nodeName] .submitBlock(this.blocks[blockName].block) .catch((err) => { - console.log('submit block erro', err) - }) + console.log("submit block erro", err); + }); // console.log(result); } - getClient (name) { - return this.clients[name] + getClient(name) { + return this.clients[name]; } - getNode (name) { - return this.nodes[name] || this.seeds[name] + getNode(name) { + return this.nodes[name] || this.seeds[name]; } - getMiningNode (name) { - return this.miners[name] + getMiningNode(name) { + return this.miners[name]; } - getWallet (name) { - return this.wallets[name] + getWallet(name) { + return this.wallets[name]; } async getOrCreateWallet(name) { - const wallet = this.getWallet(name) + const wallet = this.getWallet(name); if (wallet) { - return wallet + return wallet; } - await this.createAndAddWallet(name, this.seedAddresses()) - return this.getWallet(name) + await this.createAndAddWallet(name, this.seedAddresses()); + return this.getWallet(name); } - getProxy (name) { - return this.proxies[name] + getProxy(name) { + return this.proxies[name]; } - async forEachClientAsync (f) { - const promises = [] + async forEachClientAsync(f) { + const promises = []; for (const property in this.seeds) { - promises.push(f(this.getClient(property), property)) + promises.push(f(this.getClient(property), property)); } for (const property in this.nodes) { - promises.push(f(this.getClient(property), property)) + promises.push(f(this.getClient(property), property)); } - await Promise.all(promises) + await Promise.all(promises); } - async stopNode (name) { - const node = this.seeds[name] || this.nodes[name] - await node.stop() + async stopNode(name) { + const node = this.seeds[name] || this.nodes[name]; + await node.stop(); } - async startNode (name) { - const node = this.seeds[name] || this.nodes[name] - await node.start() + async startNode(name) { + const node = this.seeds[name] || this.nodes[name]; + await node.start(); } - addTransaction (pubKey, txId) { + addTransaction(pubKey, txId) { if (!this.transactionsMap.has(pubKey)) { - this.transactionsMap.set(pubKey, []) + this.transactionsMap.set(pubKey, []); } - this.transactionsMap.get(pubKey).push(txId) + this.transactionsMap.get(pubKey).push(txId); } } -setWorldConstructor(CustomWorld) +setWorldConstructor(CustomWorld); BeforeAll({ timeout: 1200000 }, async function () { - const baseNode = new BaseNodeProcess('compile') - console.log('Compiling base node...') - await baseNode.startNew() - await baseNode.stop() + const baseNode = new BaseNodeProcess("compile"); + console.log("Compiling base node..."); + await baseNode.startNew(); + await baseNode.stop(); const mmProxy = new MergeMiningProxyProcess( - 'compile', - '127.0.0.1:9999', - '127.0.0.1:9998' - ) - console.log('Compiling mmproxy...') - await mmProxy.startNew() - await mmProxy.stop() - - const wallet = new WalletProcess('compile') - console.log('Compiling wallet...') - await wallet.startNew() - await wallet.stop() + "compile", + "127.0.0.1:9999", + "127.0.0.1:9998" + ); + console.log("Compiling mmproxy..."); + await mmProxy.startNew(); + await mmProxy.stop(); + + const wallet = new WalletProcess("compile"); + console.log("Compiling wallet..."); + await wallet.startNew(); + await wallet.stop(); const miningNode = new MiningNodeProcess( - 'compile', - '127.0.0.1:9999', - '127.0.0.1:9998' - ) - console.log('Compiling mining node...') - await miningNode.init(1, 1, 1, true) - await miningNode.compile() + "compile", + "127.0.0.1:9999", + "127.0.0.1:9998" + ); + console.log("Compiling mining node..."); + await miningNode.init(1, 1, 1, true); + await miningNode.compile(); - console.log('Finished compilation.') -}) + console.log("Finished compilation."); +}); After(async function () { - console.log('Stopping nodes') + console.log("Stopping nodes"); for (const key in this.seeds) { - await this.stopNode(key) + await this.stopNode(key); } for (const key in this.nodes) { - await this.stopNode(key) + await this.stopNode(key); } for (const key in this.proxies) { - await this.proxies[key].stop() + await this.proxies[key].stop(); } for (const key in this.wallets) { - await this.wallets[key].stop() + await this.wallets[key].stop(); } for (const key in this.miners) { - await this.miners[key].stop() + await this.miners[key].stop(); } -}) +}); diff --git a/integration_tests/generate_report.js b/integration_tests/generate_report.js index 8c4215323a..9d19857efb 100644 --- a/integration_tests/generate_report.js +++ b/integration_tests/generate_report.js @@ -1,12 +1,12 @@ -const reporter = require('cucumber-html-reporter') +const reporter = require("cucumber-html-reporter"); const options = { - theme: 'bootstrap', - jsonFile: 'temp/output.json', - output: 'temp/reports/cucumber_report.html', + theme: "bootstrap", + jsonFile: "temp/output.json", + output: "temp/reports/cucumber_report.html", reportSuiteAsScenarios: true, scenarioTimestamp: true, - launchReport: true + launchReport: true, // metadata: { // "App Version":"0.3.2", // "Test Environment": "STAGING", @@ -15,6 +15,6 @@ const options = { // "Parallel": "Scenarios", // "Executed": "Remote" // } -} +}; -reporter.generate(options) +reporter.generate(options); diff --git a/integration_tests/helpers/baseNodeClient.js b/integration_tests/helpers/baseNodeClient.js index 1920bf439d..712531f781 100644 --- a/integration_tests/helpers/baseNodeClient.js +++ b/integration_tests/helpers/baseNodeClient.js @@ -1,263 +1,265 @@ -const expect = require('chai').expect -const grpc = require('grpc') -const protoLoader = require('@grpc/proto-loader') -const grpc_promise = require('grpc-promise') -const TransactionBuilder = require('./transactionBuilder') -const { SHA3 } = require('sha3') -const { toLittleEndian } = require('./util') -const cloneDeep = require('clone-deep') +const expect = require("chai").expect; +const grpc = require("grpc"); +const protoLoader = require("@grpc/proto-loader"); +const grpc_promise = require("grpc-promise"); +const TransactionBuilder = require("./transactionBuilder"); +const { SHA3 } = require("sha3"); +const { toLittleEndian } = require("./util"); +const cloneDeep = require("clone-deep"); class BaseNodeClient { - constructor (clientOrPort) { - if (typeof clientOrPort === 'number') { - this.client = this.createGrpcClient(clientOrPort) + constructor(clientOrPort) { + if (typeof clientOrPort === "number") { + this.client = this.createGrpcClient(clientOrPort); } else { - this.client = clientOrPort + this.client = clientOrPort; } - this.blockTemplates = {} + this.blockTemplates = {}; } - createGrpcClient (port) { + createGrpcClient(port) { const PROTO_PATH = - __dirname + '/../../applications/tari_app_grpc/proto/base_node.proto' + __dirname + "/../../applications/tari_app_grpc/proto/base_node.proto"; const packageDefinition = protoLoader.loadSync(PROTO_PATH, { keepCase: true, longs: String, enums: String, defaults: true, - oneofs: true - }) - const protoDescriptor = grpc.loadPackageDefinition(packageDefinition) - const tari = protoDescriptor.tari.rpc + oneofs: true, + }); + const protoDescriptor = grpc.loadPackageDefinition(packageDefinition); + const tari = protoDescriptor.tari.rpc; const client = new tari.BaseNode( - '127.0.0.1:' + port, + "127.0.0.1:" + port, grpc.credentials.createInsecure() - ) - grpc_promise.promisifyAll(client) - return client + ); + grpc_promise.promisifyAll(client); + return client; } - getHeaderAt (height) { + getHeaderAt(height) { return this.client .listHeaders() .sendMessage({ from_height: height, num_headers: 1 }) .then((header) => { - console.log('Header:', header) - return header - }) + console.log("Header:", header); + return header; + }); } - getNetworkDifficulties (tip, start, end) { + getNetworkDifficulties(tip, start, end) { return this.client .getNetworkDifficulty() - .sendMessage({ from_tip: tip, start_height: start, end_height: end }) + .sendMessage({ from_tip: tip, start_height: start, end_height: end }); } - getPeers () { + getPeers() { return this.client .getPeers() .sendMessage({}) .then((peers) => { - console.log('Got ', peers.length, ' peers:') - return peers - }) + console.log("Got ", peers.length, " peers:"); + return peers; + }); } - getTipHeader () { + getTipHeader() { return this.client .listHeaders() .sendMessage({ from_height: 0, num_headers: 1 }) .then((headers) => { - const header = headers[0] + const header = headers[0]; return Object.assign(header, { - height: +header.height - }) - }) + height: +header.height, + }); + }); } - getTipHeight () { + getTipHeight() { return this.client .getTipInfo() .sendMessage({}) - .then((tip) => parseInt(tip.metadata.height_of_longest_chain)) + .then((tip) => parseInt(tip.metadata.height_of_longest_chain)); } - getPreviousBlockTemplate (height) { - return cloneDeep(this.blockTemplates['height' + height]) + getPreviousBlockTemplate(height) { + return cloneDeep(this.blockTemplates["height" + height]); } - getBlockTemplate (weight) { + getBlockTemplate(weight) { return this.client .getNewBlockTemplate() .sendMessage({ algo: { pow_algo: 2 }, max_weight: weight }) .then((template) => { const res = { minerData: template.miner_data, - block: template.new_block_template - } + block: template.new_block_template, + }; this.blockTemplates[ - 'height' + template.new_block_template.header.height - ] = cloneDeep(res) - return res - }) + "height" + template.new_block_template.header.height + ] = cloneDeep(res); + return res; + }); } - submitBlockWithCoinbase (template, coinbase) { - const cb = coinbase - template.body.outputs = template.body.outputs.concat(cb.outputs) - template.body.kernels = template.body.kernels.concat(cb.kernels) + submitBlockWithCoinbase(template, coinbase) { + const cb = coinbase; + template.body.outputs = template.body.outputs.concat(cb.outputs); + template.body.kernels = template.body.kernels.concat(cb.kernels); return this.client .getNewBlock() .sendMessage(template) .then((b) => { - return this.client.submitBlock().sendMessage(b.block) - }) + return this.client.submitBlock().sendMessage(b.block); + }); } - submitTemplate (template, beforeSubmit) { + submitTemplate(template, beforeSubmit) { return this.client .getNewBlock() .sendMessage(template.template) .then((b) => { // console.log("Sha3 diff", this.getSha3Difficulty(b.block.header)); if (beforeSubmit) { - b = beforeSubmit({ block: b, originalTemplate: template }) + b = beforeSubmit({ block: b, originalTemplate: template }); if (!b) { - return Promise.resolve() + return Promise.resolve(); } - b = b.block + b = b.block; } - return this.client.submitBlock().sendMessage(b.block) - }) + return this.client.submitBlock().sendMessage(b.block); + }); } - submitBlock (b) { - return this.client.submitBlock().sendMessage(b.block) + submitBlock(b) { + return this.client.submitBlock().sendMessage(b.block); } - submitTransaction (txn) { + submitTransaction(txn) { return this.client .submitTransaction() .sendMessage({ transaction: txn }) .then((res) => { - return res - }) + return res; + }); } - transactionState (txn) { + transactionState(txn) { return this.client .transactionState() .sendMessage({ excess_sig: txn }) .then((res) => { - return res - }) + return res; + }); } - transactionStateResult (txn) { + transactionStateResult(txn) { return this.client .transactionState() .sendMessage({ excess_sig: txn }) .then((res) => { - return res.result - }) + return res.result; + }); } - fetchMatchingUtxos (hashes) { + fetchMatchingUtxos(hashes) { return this.client .fetchMatchingUtxos() .sendMessage({ hashes: hashes }) .then((result) => { - return result - }) + return result; + }); } - async mineBlockBeforeSubmit (walletClient, weight) { + async mineBlockBeforeSubmit(walletClient, weight) { // Empty template from base node const emptyTemplate = await this.client .getNewBlockTemplate() - .sendMessage({ algo: { pow_algo: 2 }, max_weight: weight }) + .sendMessage({ algo: { pow_algo: 2 }, max_weight: weight }); // Coinbase from wallet const coinbase = await walletClient.client.inner.getCoinbase().sendMessage({ reward: emptyTemplate.miner_data.reward, fee: emptyTemplate.miner_data.total_fees, - height: emptyTemplate.new_block_template.header.height - }) + height: emptyTemplate.new_block_template.header.height, + }); // New block from base node including coinbase - const block = emptyTemplate.new_block_template + const block = emptyTemplate.new_block_template; block.body.outputs = block.body.outputs.concat( coinbase.transaction.body.outputs - ) + ); block.body.kernels = block.body.kernels.concat( coinbase.transaction.body.kernels - ) - const newBlock = await this.client.getNewBlock().sendMessage(block) - return newBlock + ); + const newBlock = await this.client.getNewBlock().sendMessage(block); + return newBlock; } - async submitMinedBlock (newBlock) { - const response = await this.client.submitBlock().sendMessage(newBlock.block) - return response + async submitMinedBlock(newBlock) { + const response = await this.client + .submitBlock() + .sendMessage(newBlock.block); + return response; } - mineBlock (walletClient, weight) { + mineBlock(walletClient, weight) { if (!walletClient) { - return this.mineBlockWithoutWallet(weight) + return this.mineBlockWithoutWallet(weight); } - let currHeight - let block + let currHeight; + let block; return this.client .getTipInfo() .sendMessage({}) .then((tip) => { - currHeight = parseInt(tip.metadata.height_of_longest_chain) + currHeight = parseInt(tip.metadata.height_of_longest_chain); return this.client .getNewBlockTemplate() - .sendMessage({ algo: { pow_algo: 2 }, max_weight: weight }) + .sendMessage({ algo: { pow_algo: 2 }, max_weight: weight }); }) .then((template) => { - block = template.new_block_template - const height = block.header.height + block = template.new_block_template; + const height = block.header.height; return walletClient.client.inner.getCoinbase().sendMessage({ reward: template.miner_data.reward, fee: template.miner_data.total_fees, - height: height - }) + height: height, + }); }) .then((coinbase) => { - const cb = coinbase.transaction - block.body.outputs = block.body.outputs.concat(cb.body.outputs) - block.body.kernels = block.body.kernels.concat(cb.body.kernels) - return this.client.getNewBlock().sendMessage(block) + const cb = coinbase.transaction; + block.body.outputs = block.body.outputs.concat(cb.body.outputs); + block.body.kernels = block.body.kernels.concat(cb.body.kernels); + return this.client.getNewBlock().sendMessage(block); }) .then((b) => { - return this.client.submitBlock().sendMessage(b.block) + return this.client.submitBlock().sendMessage(b.block); }) - .then((empty) => { - return this.client.getTipInfo().sendMessage({}) + .then(() => { + return this.client.getTipInfo().sendMessage({}); }) .then((tipInfo) => { expect(tipInfo.metadata.height_of_longest_chain).to.equal( - currHeight + 1 + '' - ) - }) + currHeight + 1 + "" + ); + }); } - async getMinedCandidateBlock (weight, existingBlockTemplate) { - const builder = new TransactionBuilder() + async getMinedCandidateBlock(weight, existingBlockTemplate) { + const builder = new TransactionBuilder(); const blockTemplate = - existingBlockTemplate || (await this.getBlockTemplate(weight)) + existingBlockTemplate || (await this.getBlockTemplate(weight)); const privateKey = Buffer.from( toLittleEndian(blockTemplate.block.header.height, 256) - ).toString('hex') + ).toString("hex"); const cb = builder.generateCoinbase( parseInt(blockTemplate.minerData.reward), privateKey, parseInt(blockTemplate.minerData.total_fees), parseInt(blockTemplate.block.header.height) + 2 - ) - const template = blockTemplate.block - template.body.outputs = template.body.outputs.concat(cb.outputs) - template.body.kernels = template.body.kernels.concat(cb.kernels) + ); + const template = blockTemplate.block; + template.body.outputs = template.body.outputs.concat(cb.outputs); + template.body.kernels = template.body.kernels.concat(cb.kernels); return { template: template, coinbase: { @@ -265,58 +267,58 @@ class BaseNodeClient { privateKey: privateKey, amount: parseInt(blockTemplate.minerData.reward) + - parseInt(blockTemplate.minerData.total_fees) - } - } + parseInt(blockTemplate.minerData.total_fees), + }, + }; } - async mineBlockWithoutWallet (beforeSubmit, weight, onError) { - const template = await this.getMinedCandidateBlock(weight) + async mineBlockWithoutWallet(beforeSubmit, weight, onError) { + const template = await this.getMinedCandidateBlock(weight); return this.submitTemplate(template, beforeSubmit).then( async () => { // let tip = await this.getTipHeight(); // console.log("Node is at tip:", tip); }, (err) => { - console.log('err submitting block:', err) + console.log("err submitting block:", err); if (onError) { if (!onError(err)) { - throw err + throw err; } // handled } else { - throw err + throw err; } } - ) + ); } - getSha3Difficulty (header) { - const hash = new SHA3(256) - hash.update(toLittleEndian(header.version, 16)) - hash.update(toLittleEndian(parseInt(header.height), 64)) - hash.update(header.prev_hash) - const timestamp = parseInt(header.timestamp.seconds) - hash.update(toLittleEndian(timestamp, 64)) - hash.update(header.output_mr) - hash.update(header.range_proof_mr) - hash.update(header.kernel_mr) - hash.update(header.total_kernel_offset) - hash.update(toLittleEndian(parseInt(header.nonce), 64)) - hash.update(toLittleEndian(header.pow.pow_algo)) + getSha3Difficulty(header) { + const hash = new SHA3(256); + hash.update(toLittleEndian(header.version, 16)); + hash.update(toLittleEndian(parseInt(header.height), 64)); + hash.update(header.prev_hash); + const timestamp = parseInt(header.timestamp.seconds); + hash.update(toLittleEndian(timestamp, 64)); + hash.update(header.output_mr); + hash.update(header.range_proof_mr); + hash.update(header.kernel_mr); + hash.update(header.total_kernel_offset); + hash.update(toLittleEndian(parseInt(header.nonce), 64)); + hash.update(toLittleEndian(header.pow.pow_algo)); hash.update( toLittleEndian(parseInt(header.pow.accumulated_monero_difficulty), 64) - ) + ); hash.update( toLittleEndian(parseInt(header.pow.accumulated_blake_difficulty), 64) - ) - hash.update(header.pow.pow_data) - const first_round = hash.digest() - const hash2 = new SHA3(256) - hash2.update(first_round) - const res = hash2.digest('hex') - return res + ); + hash.update(header.pow.pow_data); + const first_round = hash.digest(); + const hash2 = new SHA3(256); + hash2.update(first_round); + const res = hash2.digest("hex"); + return res; } } -module.exports = BaseNodeClient +module.exports = BaseNodeClient; diff --git a/integration_tests/helpers/baseNodeProcess.js b/integration_tests/helpers/baseNodeProcess.js index ad13fcd473..e6967e72de 100644 --- a/integration_tests/helpers/baseNodeProcess.js +++ b/integration_tests/helpers/baseNodeProcess.js @@ -1,184 +1,184 @@ -const { spawn } = require('child_process') -const { expect } = require('chai') -const fs = require('fs') -const path = require('path') -const BaseNodeClient = require('./baseNodeClient') -const { getFreePort } = require('./util') -const dateFormat = require('dateformat') -const { createEnv } = require('./config') - -let outputProcess +const { spawn } = require("child_process"); +const { expect } = require("chai"); +const fs = require("fs"); +const path = require("path"); +const BaseNodeClient = require("./baseNodeClient"); +const { getFreePort } = require("./util"); +const dateFormat = require("dateformat"); +const { createEnv } = require("./config"); + +let outputProcess; class BaseNodeProcess { - constructor (name, options, logFilePath, nodeFile) { - this.name = name - this.logFilePath = logFilePath ? path.resolve(logFilePath) : logFilePath - this.nodeFile = nodeFile - this.options = options + constructor(name, options, logFilePath, nodeFile) { + this.name = name; + this.logFilePath = logFilePath ? path.resolve(logFilePath) : logFilePath; + this.nodeFile = nodeFile; + this.options = options; } - async init () { - this.port = await getFreePort(19000, 25000) - this.grpcPort = await getFreePort(19000, 25000) - this.name = `Basenode${this.port}-${this.name}` - this.nodeFile = this.nodeFile || 'nodeid.json' + async init() { + this.port = await getFreePort(19000, 25000); + this.grpcPort = await getFreePort(19000, 25000); + this.name = `Basenode${this.port}-${this.name}`; + this.nodeFile = this.nodeFile || "nodeid.json"; this.baseDir = `./temp/base_nodes/${dateFormat( new Date(), - 'yyyymmddHHMM' - )}/${this.name}` - const args = ['--base-path', '.', '--init', '--create-id'] + "yyyymmddHHMM" + )}/${this.name}`; + const args = ["--base-path", ".", "--init", "--create-id"]; if (this.logFilePath) { - args.push('--log-config', this.logFilePath) + args.push("--log-config", this.logFilePath); } - await this.run(await this.compile(), args) + await this.run(await this.compile(), args); // console.log("Port:", this.port); // console.log("GRPC:", this.grpcPort); // console.log(`Starting node ${this.name}...`); } - async compile () { + async compile() { if (!outputProcess) { - await this.run('cargo', [ - 'build', - '--release', - '--bin', - 'tari_base_node', - '-Z', - 'unstable-options', - '--out-dir', - __dirname + '/../temp/out' - ]) - outputProcess = __dirname + '/../temp/out/tari_base_node' + await this.run("cargo", [ + "build", + "--release", + "--bin", + "tari_base_node", + "-Z", + "unstable-options", + "--out-dir", + __dirname + "/../temp/out", + ]); + outputProcess = __dirname + "/../temp/out/tari_base_node"; } - return outputProcess + return outputProcess; } - ensureNodeInfo () { - while (true) { - if (fs.existsSync(this.baseDir + '/' + this.nodeFile)) { - break + ensureNodeInfo() { + for (;;) { + if (fs.existsSync(this.baseDir + "/" + this.nodeFile)) { + break; } } this.nodeInfo = JSON.parse( - fs.readFileSync(this.baseDir + '/' + this.nodeFile, 'utf8') - ) + fs.readFileSync(this.baseDir + "/" + this.nodeFile, "utf8") + ); } - peerAddress () { - this.ensureNodeInfo() - const addr = this.nodeInfo.public_key + '::' + this.nodeInfo.public_address + peerAddress() { + this.ensureNodeInfo(); + const addr = this.nodeInfo.public_key + "::" + this.nodeInfo.public_address; // console.log("Peer:", addr); - return addr + return addr; } - setPeerSeeds (addresses) { - this.peerSeeds = addresses.join(',') + setPeerSeeds(addresses) { + this.peerSeeds = addresses.join(","); } - getGrpcAddress () { - const address = '127.0.0.1:' + this.grpcPort + getGrpcAddress() { + const address = "127.0.0.1:" + this.grpcPort; // console.log("Base Node GRPC Address:",address); - return address + return address; } - run (cmd, args, saveFile) { + run(cmd, args) { return new Promise((resolve, reject) => { if (!fs.existsSync(this.baseDir)) { - fs.mkdirSync(this.baseDir, { recursive: true }) - fs.mkdirSync(this.baseDir + '/log', { recursive: true }) + fs.mkdirSync(this.baseDir, { recursive: true }); + fs.mkdirSync(this.baseDir + "/log", { recursive: true }); } const envs = createEnv( this.name, false, this.nodeFile, - '127.0.0.1', - '8082', - '8081', - '127.0.0.1', + "127.0.0.1", + "8082", + "8081", + "127.0.0.1", this.grpcPort, this.port, - '127.0.0.1:8080', + "127.0.0.1:8080", this.options, this.peerSeeds - ) + ); const ps = spawn(cmd, args, { cwd: this.baseDir, // shell: true, - env: { ...process.env, ...envs } - }) + env: { ...process.env, ...envs }, + }); - ps.stdout.on('data', (data) => { + ps.stdout.on("data", (data) => { // console.log(`stdout: ${data}`); - fs.appendFileSync(`${this.baseDir}/log/stdout.log`, data.toString()) + fs.appendFileSync(`${this.baseDir}/log/stdout.log`, data.toString()); if ( data .toString() .match(/Copyright 2019-2020. The Tari Development Community/) ) { - resolve(ps) + resolve(ps); } - }) + }); - ps.stderr.on('data', (data) => { - console.error(`stderr: ${data}`) - fs.appendFileSync(`${this.baseDir}/log/stderr.log`, data.toString()) - }) + ps.stderr.on("data", (data) => { + console.error(`stderr: ${data}`); + fs.appendFileSync(`${this.baseDir}/log/stderr.log`, data.toString()); + }); - ps.on('close', (code) => { - const ps = this.ps - this.ps = null + ps.on("close", (code) => { + const ps = this.ps; + this.ps = null; if (code) { - console.log(`child process exited with code ${code}`) - reject(`child process exited with code ${code}`) + console.log(`child process exited with code ${code}`); + reject(`child process exited with code ${code}`); } else { - resolve(ps) + resolve(ps); } - }) + }); - expect(ps.error).to.be.an('undefined') - this.ps = ps - }) + expect(ps.error).to.be.an("undefined"); + this.ps = ps; + }); } - async startNew () { - await this.init() - return await this.start() + async startNew() { + await this.init(); + return await this.start(); } - async startAndConnect () { - await this.startNew() - return this.createGrpcClient() + async startAndConnect() { + await this.startNew(); + return this.createGrpcClient(); } - async start () { - const args = ['--base-path', '.'] + async start() { + const args = ["--base-path", "."]; if (this.logFilePath) { - args.push('--log-config', this.logFilePath) + args.push("--log-config", this.logFilePath); } - return await this.run(await this.compile(), args) + return await this.run(await this.compile(), args); } - stop () { + stop() { return new Promise((resolve) => { if (!this.ps) { - return resolve() + return resolve(); } - this.ps.on('close', (code) => { + this.ps.on("close", (code) => { if (code) { - console.log(`child process exited with code ${code}`) + console.log(`child process exited with code ${code}`); } - resolve() - }) - this.ps.kill('SIGINT') - }) + resolve(); + }); + this.ps.kill("SIGINT"); + }); } - createGrpcClient () { - return new BaseNodeClient(this.grpcPort) + createGrpcClient() { + return new BaseNodeClient(this.grpcPort); } } -module.exports = BaseNodeProcess +module.exports = BaseNodeProcess; diff --git a/integration_tests/helpers/config.js b/integration_tests/helpers/config.js index 2cfdb7b914..9711dc837a 100644 --- a/integration_tests/helpers/config.js +++ b/integration_tests/helpers/config.js @@ -1,71 +1,71 @@ - -function mapEnvs (options) { - const res = {} +function mapEnvs(options) { + const res = {}; if (options.blocks_behind_before_considered_lagging) { res.TARI_BASE_NODE__LOCALNET__BLOCKS_BEHIND_BEFORE_CONSIDERED_LAGGING = - options.blocks_behind_before_considered_lagging + options.blocks_behind_before_considered_lagging; } if (options.pruningHorizon) { // In the config toml file: `base_node.network.pruning_horizon` with `network = localnet` - res.TARI_BASE_NODE__LOCALNET__PRUNING_HORIZON = options.pruningHorizon + res.TARI_BASE_NODE__LOCALNET__PRUNING_HORIZON = options.pruningHorizon; } - if ('num_confirmations' in options) { - res.TARI_WALLET__TRANSACTION_NUM_CONFIRMATIONS_REQUIRED = options.num_confirmations + if ("num_confirmations" in options) { + res.TARI_WALLET__TRANSACTION_NUM_CONFIRMATIONS_REQUIRED = + options.num_confirmations; } if (options.routingMechanism) { // In the config toml file: `wallet.transaction_routing_mechanism` - res.TARI_WALLET__TRANSACTION_ROUTING_MECHANISM = options.routingMechanism + res.TARI_WALLET__TRANSACTION_ROUTING_MECHANISM = options.routingMechanism; } if (options.broadcastMonitoringTimeout) { res.TARI_WALLET__TRANSACTION_BROADCAST_MONITORING_TIMEOUT = - options.broadcastMonitoringTimeout + options.broadcastMonitoringTimeout; } else { - res.TARI_WALLET__TRANSACTION_BROADCAST_MONITORING_TIMEOUT = 3 + res.TARI_WALLET__TRANSACTION_BROADCAST_MONITORING_TIMEOUT = 3; } - if ('mineOnTipOnly' in options) { - res.TARI_MINING_NODE__MINE_ON_TIP_ONLY = options.mineOnTipOnly + if ("mineOnTipOnly" in options) { + res.TARI_MINING_NODE__MINE_ON_TIP_ONLY = options.mineOnTipOnly; } if (options.network) { - res.TARI_BASE_NODE__NETWORK = options.network + res.TARI_BASE_NODE__NETWORK = options.network; } if (options.transport) { - res.TARI_BASE_NODE__LOCALNET__TRANSPORT = options.transport - res.TARI_BASE_NODE__STIBBONS__TRANSPORT = options.transport + res.TARI_BASE_NODE__LOCALNET__TRANSPORT = options.transport; + res.TARI_BASE_NODE__STIBBONS__TRANSPORT = options.transport; } - return res + return res; } -function baseEnvs (peerSeeds = []) { +function baseEnvs(peerSeeds = []) { const envs = { RUST_BACKTRACE: 1, - TARI_BASE_NODE__NETWORK: 'localnet', - TARI_BASE_NODE__LOCALNET__DATA_DIR: 'localnet', - TARI_BASE_NODE__LOCALNET__DB_TYPE: 'lmdb', - TARI_BASE_NODE__LOCALNET__ORPHAN_STORAGE_CAPACITY: '10', - TARI_BASE_NODE__LOCALNET__PRUNING_HORIZON: '0', - TARI_BASE_NODE__LOCALNET__PRUNED_MODE_CLEANUP_INTERVAL: '10000', - TARI_BASE_NODE__LOCALNET__CORE_THREADS: '10', - TARI_BASE_NODE__LOCALNET__MAX_THREADS: '512', - TARI_BASE_NODE__LOCALNET__IDENTITY_FILE: 'none.json', - TARI_BASE_NODE__LOCALNET__BASE_NODE_TOR_IDENTITY_FILE: 'torid.json', - TARI_BASE_NODE__LOCALNET__WALLET_IDENTITY_FILE: 'walletid.json', - TARI_BASE_NODE__LOCALNET__CONSOLE_WALLET_IDENTITY_FILE: 'cwalletid.json', - TARI_BASE_NODE__LOCALNET__WALLET_TOR_IDENTITY_FILE: 'wallettorid.json', - TARI_BASE_NODE__LOCALNET__CONSOLE_WALLET_TOR_IDENTITY_FILE: 'none.json', + TARI_BASE_NODE__NETWORK: "localnet", + TARI_BASE_NODE__LOCALNET__DATA_DIR: "localnet", + TARI_BASE_NODE__LOCALNET__DB_TYPE: "lmdb", + TARI_BASE_NODE__LOCALNET__ORPHAN_STORAGE_CAPACITY: "10", + TARI_BASE_NODE__LOCALNET__PRUNING_HORIZON: "0", + TARI_BASE_NODE__LOCALNET__PRUNED_MODE_CLEANUP_INTERVAL: "10000", + TARI_BASE_NODE__LOCALNET__CORE_THREADS: "10", + TARI_BASE_NODE__LOCALNET__MAX_THREADS: "512", + TARI_BASE_NODE__LOCALNET__IDENTITY_FILE: "none.json", + TARI_BASE_NODE__LOCALNET__BASE_NODE_TOR_IDENTITY_FILE: "torid.json", + TARI_BASE_NODE__LOCALNET__WALLET_IDENTITY_FILE: "walletid.json", + TARI_BASE_NODE__LOCALNET__CONSOLE_WALLET_IDENTITY_FILE: "cwalletid.json", + TARI_BASE_NODE__LOCALNET__WALLET_TOR_IDENTITY_FILE: "wallettorid.json", + TARI_BASE_NODE__LOCALNET__CONSOLE_WALLET_TOR_IDENTITY_FILE: "none.json", TARI_BASE_NODE__LOCALNET__ALLOW_TEST_ADDRESSES: true, TARI_BASE_NODE__LOCALNET__GRPC_ENABLED: true, TARI_BASE_NODE__LOCALNET__ENABLE_WALLET: false, - TARI_BASE_NODE__LOCALNET__DNS_SEEDS_NAME_SERVER: '1.1.1.1:53', - TARI_BASE_NODE__LOCALNET__DNS_SEEDS_USE_DNSSEC: 'true', - TARI_BASE_NODE__LOCALNET__BLOCK_SYNC_STRATEGY: 'ViaBestChainMetadata', - TARI_BASE_NODE__LOCALNET__NUM_MINING_THREADS: '1', - TARI_BASE_NODE__LOCALNET__ORPHAN_DB_CLEAN_OUT_THRESHOLD: '0', - TARI_BASE_NODE__LOCALNET__MAX_RANDOMX_VMS: '1', - TARI_BASE_NODE__LOCALNET__AUTO_PING_INTERVAL: '15', - TARI_BASE_NODE__LOCALNET__FLOOD_BAN_MAX_MSG_COUNT: '100000', + TARI_BASE_NODE__LOCALNET__DNS_SEEDS_NAME_SERVER: "1.1.1.1:53", + TARI_BASE_NODE__LOCALNET__DNS_SEEDS_USE_DNSSEC: "true", + TARI_BASE_NODE__LOCALNET__BLOCK_SYNC_STRATEGY: "ViaBestChainMetadata", + TARI_BASE_NODE__LOCALNET__NUM_MINING_THREADS: "1", + TARI_BASE_NODE__LOCALNET__ORPHAN_DB_CLEAN_OUT_THRESHOLD: "0", + TARI_BASE_NODE__LOCALNET__MAX_RANDOMX_VMS: "1", + TARI_BASE_NODE__LOCALNET__AUTO_PING_INTERVAL: "15", + TARI_BASE_NODE__LOCALNET__FLOOD_BAN_MAX_MSG_COUNT: "100000", TARI_MERGE_MINING_PROXY__LOCALNET__MONEROD_URL: - 'http://18.133.55.120:38081', + "http://18.133.55.120:38081", TARI_MERGE_MINING_PROXY__LOCALNET__MONEROD_USE_AUTH: false, TARI_MERGE_MINING_PROXY__LOCALNET__MONEROD_USERNAME: '""', TARI_MERGE_MINING_PROXY__LOCALNET__MONEROD_PASSWORD: '""', @@ -73,53 +73,62 @@ function baseEnvs (peerSeeds = []) { TARI_BASE_NODE__LOCALNET__DB_RESIZE_THRESHOLD_MB: 10, TARI_BASE_NODE__LOCALNET__DB_GROW_SIZE_MB: 20, TARI_MERGE_MINING_PROXY__LOCALNET__WAIT_FOR_INITIAL_SYNC_AT_STARTUP: false, - TARI_MINING_NODE__MINE_ON_TIP_ONLY: true - } + TARI_MINING_NODE__MINE_ON_TIP_ONLY: true, + }; if (peerSeeds.length != 0) { - envs.TARI_BASE_NODE__LOCALNET__PEER_SEEDS = peerSeeds + envs.TARI_BASE_NODE__LOCALNET__PEER_SEEDS = peerSeeds; } else { // Nowheresville envs.TARI_BASE_NODE__LOCALNET__PEER_SEEDS = [ - '5cfcf17f41b01980eb4fa03cec5ea12edbd3783496a2b5dabf99e4bf6410f460::/ip4/10.0.0.50/tcp/1' - ] + "5cfcf17f41b01980eb4fa03cec5ea12edbd3783496a2b5dabf99e4bf6410f460::/ip4/10.0.0.50/tcp/1", + ]; } - return envs + return envs; } -function createEnv ( - name = 'config_identity', +function createEnv( + _name = "config_identity", isWallet = false, - nodeFile = 'newnodeid.json', - walletGrpcAddress = '127.0.0.1', - walletGrpcPort = '8082', - walletPort = '8083', - baseNodeGrpcAddress = '127.0.0.1', - baseNodeGrpcPort = '8080', - baseNodePort = '8081', - proxyFullAddress = '127.0.0.1:8084', + nodeFile = "newnodeid.json", + walletGrpcAddress = "127.0.0.1", + walletGrpcPort = "8082", + walletPort = "8083", + baseNodeGrpcAddress = "127.0.0.1", + baseNodeGrpcPort = "8080", + baseNodePort = "8081", + proxyFullAddress = "127.0.0.1:8084", options, peerSeeds = [], - txnSendingMechanism = 'DirectAndStoreAndForward' + _txnSendingMechanism = "DirectAndStoreAndForward" ) { - const envs = baseEnvs(peerSeeds) - const network = (options && options.network) ? options.network.toUpperCase() : 'LOCALNET' + const envs = baseEnvs(peerSeeds); + const network = + options && options.network ? options.network.toUpperCase() : "LOCALNET"; - const configEnvs = {} + const configEnvs = {}; - configEnvs[`TARI_BASE_NODE__${network}__GRPC_BASE_NODE_ADDRESS`] = `${baseNodeGrpcAddress}:${baseNodeGrpcPort}` - configEnvs[`TARI_BASE_NODE__${network}__GRPC_CONSOLE_WALLET_ADDRESS`] = `${walletGrpcAddress}:${walletGrpcPort}` - configEnvs[`TARI_BASE_NODE__${network}__BASE_NODE_IDENTITY_FILE`] = `${nodeFile}` + configEnvs[ + `TARI_BASE_NODE__${network}__GRPC_BASE_NODE_ADDRESS` + ] = `${baseNodeGrpcAddress}:${baseNodeGrpcPort}`; + configEnvs[ + `TARI_BASE_NODE__${network}__GRPC_CONSOLE_WALLET_ADDRESS` + ] = `${walletGrpcAddress}:${walletGrpcPort}`; + configEnvs[ + `TARI_BASE_NODE__${network}__BASE_NODE_IDENTITY_FILE` + ] = `${nodeFile}`; configEnvs[`TARI_BASE_NODE__${network}__TCP_LISTENER_ADDRESS`] = - '/ip4/127.0.0.1/tcp/' + (isWallet ? `${walletPort}` : `${baseNodePort}`) + "/ip4/127.0.0.1/tcp/" + (isWallet ? `${walletPort}` : `${baseNodePort}`); configEnvs[`TARI_BASE_NODE__${network}__PUBLIC_ADDRESS`] = - '/ip4/127.0.0.1/tcp/' + (isWallet ? `${walletPort}` : `${baseNodePort}`) - configEnvs[`TARI_MERGE_MINING_PROXY__${network}__PROXY_HOST_ADDRESS`] = `${proxyFullAddress}` - configEnvs[`TARI_BASE_NODE__${network}__TRANSPORT`] = 'tcp' + "/ip4/127.0.0.1/tcp/" + (isWallet ? `${walletPort}` : `${baseNodePort}`); + configEnvs[ + `TARI_MERGE_MINING_PROXY__${network}__PROXY_HOST_ADDRESS` + ] = `${proxyFullAddress}`; + configEnvs[`TARI_BASE_NODE__${network}__TRANSPORT`] = "tcp"; - return { ...envs, ...configEnvs, ...mapEnvs(options || {}) } + return { ...envs, ...configEnvs, ...mapEnvs(options || {}) }; } module.exports = { - createEnv -} + createEnv, +}; diff --git a/integration_tests/helpers/mergeMiningProxyClient.js b/integration_tests/helpers/mergeMiningProxyClient.js index 7af6f63068..5170f880e3 100644 --- a/integration_tests/helpers/mergeMiningProxyClient.js +++ b/integration_tests/helpers/mergeMiningProxyClient.js @@ -1,70 +1,70 @@ -const axios = require('axios') +const axios = require("axios"); class MergeMiningProxyClient { - constructor (address) { - this.address = address + constructor(address) { + this.address = address; } - async getHeight () { - const res = await axios.get(`${this.address}/get_height`) - return res.data.height + async getHeight() { + const res = await axios.get(`${this.address}/get_height`); + return res.data.height; } - async getBlockTemplate () { + async getBlockTemplate() { const res = await axios.post(`${this.address}/json_rpc`, { - jsonrpc: '2.0', - id: '0', - method: 'getblocktemplate', + jsonrpc: "2.0", + id: "0", + method: "getblocktemplate", params: { wallet_address: - '55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt', - reserve_size: 60 - } - }) + "55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt", + reserve_size: 60, + }, + }); // console.log(res.data); // console.log("Blocktemplate:",res.data.result.blocktemplate_blob); - return res.data.result + return res.data.result; } - async submitBlock (block) { + async submitBlock(block) { const res = await axios.post(`${this.address}/json_rpc`, { - jsonrpc: '2.0', - id: '0', - method: 'submit_block', - params: [block] - }) - return res.data + jsonrpc: "2.0", + id: "0", + method: "submit_block", + params: [block], + }); + return res.data; } - async getLastBlockHeader () { + async getLastBlockHeader() { const res = await axios.post(`${this.address}/json_rpc`, { - jsonrpc: '2.0', - id: '0', - method: 'get_last_block_header' - }) - return res.data + jsonrpc: "2.0", + id: "0", + method: "get_last_block_header", + }); + return res.data; } - async getBlockHeaderByHash (hash) { + async getBlockHeaderByHash(hash) { const res = await axios.post(`${this.address}/json_rpc`, { - jsonrpc: '2.0', - id: '0', - method: 'get_block_header_by_hash', + jsonrpc: "2.0", + id: "0", + method: "get_block_header_by_hash", params: { - hash: hash - } - }) - return res.data + hash: hash, + }, + }); + return res.data; } - async mineBlock () { + async mineBlock() { // Mines a block in the same way that xmrig would - const template = await this.getBlockTemplate() - const height = await this.getHeight() - const block = template.blocktemplate_blob + const template = await this.getBlockTemplate(); + // const height = await this.getHeight(); + const block = template.blocktemplate_blob; // Need to insert a nonce into the template as xmrig would for it to be a valid block. - const result = await this.submitBlock(block) + await this.submitBlock(block); } } -module.exports = MergeMiningProxyClient +module.exports = MergeMiningProxyClient; diff --git a/integration_tests/helpers/mergeMiningProxyProcess.js b/integration_tests/helpers/mergeMiningProxyProcess.js index 9c3c95d666..13565252bb 100644 --- a/integration_tests/helpers/mergeMiningProxyProcess.js +++ b/integration_tests/helpers/mergeMiningProxyProcess.js @@ -1,54 +1,53 @@ -const { getFreePort } = require('./util') -const dateFormat = require('dateformat') -const fs = require('fs') -const path = require('path') -const { spawnSync, spawn, execSync } = require('child_process') -const { expect } = require('chai') -const MergeMiningProxyClient = require('./mergeMiningProxyClient') -const { createEnv } = require('./config') -const { setWorldConstructor } = require('cucumber') +const { getFreePort } = require("./util"); +const dateFormat = require("dateformat"); +const fs = require("fs"); +const path = require("path"); +const { spawn } = require("child_process"); +const { expect } = require("chai"); +const MergeMiningProxyClient = require("./mergeMiningProxyClient"); +const { createEnv } = require("./config"); -let outputProcess +let outputProcess; class MergeMiningProxyProcess { - constructor ( + constructor( name, baseNodeAddress, walletAddress, logFilePath, submitOrigin = true ) { - this.name = name - this.nodeAddress = baseNodeAddress.split(':')[0] - this.nodeGrpcPort = baseNodeAddress.split(':')[1] - this.walletAddress = walletAddress.split(':')[0] - this.walletGrpcPort = walletAddress.split(':')[1] - this.submitOrigin = submitOrigin - this.logFilePath = logFilePath ? path.resolve(logFilePath) : logFilePath + this.name = name; + this.nodeAddress = baseNodeAddress.split(":")[0]; + this.nodeGrpcPort = baseNodeAddress.split(":")[1]; + this.walletAddress = walletAddress.split(":")[0]; + this.walletGrpcPort = walletAddress.split(":")[1]; + this.submitOrigin = submitOrigin; + this.logFilePath = logFilePath ? path.resolve(logFilePath) : logFilePath; } - async init () { - this.port = await getFreePort(19000, 25000) - this.name = `MMProxy${this.port}-${this.name}` + async init() { + this.port = await getFreePort(19000, 25000); + this.name = `MMProxy${this.port}-${this.name}`; this.baseDir = `./temp/base_nodes/${dateFormat( new Date(), - 'yyyymmddHHMM' - )}/${this.name}` + "yyyymmddHHMM" + )}/${this.name}`; // console.log("MergeMiningProxyProcess init - assign server GRPC:", this.grpcPort); } - run (cmd, args, saveFile) { + run(cmd, args) { return new Promise((resolve, reject) => { if (!fs.existsSync(this.baseDir)) { - fs.mkdirSync(this.baseDir, { recursive: true }) - fs.mkdirSync(this.baseDir + '/log', { recursive: true }) + fs.mkdirSync(this.baseDir, { recursive: true }); + fs.mkdirSync(this.baseDir + "/log", { recursive: true }); } - const proxyAddress = '127.0.0.1:' + this.port + const proxyAddress = "127.0.0.1:" + this.port; const envs = createEnv( this.name, false, - 'nodeid.json', + "nodeid.json", this.walletAddress, this.walletGrpcPort, this.port, @@ -58,93 +57,93 @@ class MergeMiningProxyProcess { proxyAddress, [], [] - ) + ); const extraEnvs = { TARI_MERGE_MINING_PROXY__LOCALNET__PROXY_SUBMIT_TO_ORIGIN: this - .submitOrigin - } - const completeEnvs = { ...envs, ...extraEnvs } + .submitOrigin, + }; + const completeEnvs = { ...envs, ...extraEnvs }; const ps = spawn(cmd, args, { cwd: this.baseDir, // shell: true, - env: { ...process.env, ...completeEnvs } - }) + env: { ...process.env, ...completeEnvs }, + }); - ps.stdout.on('data', (data) => { + ps.stdout.on("data", (data) => { // console.log(`stdout: ${data}`); - fs.appendFileSync(`${this.baseDir}/log/stdout.log`, data.toString()) + fs.appendFileSync(`${this.baseDir}/log/stdout.log`, data.toString()); if (data.toString().match(/Listening on/)) { - resolve(ps) + resolve(ps); } - }) + }); - ps.stderr.on('data', (data) => { - console.error(`stderr: ${data}`) - fs.appendFileSync(`${this.baseDir}/log/stderr.log`, data.toString()) - }) + ps.stderr.on("data", (data) => { + console.error(`stderr: ${data}`); + fs.appendFileSync(`${this.baseDir}/log/stderr.log`, data.toString()); + }); - ps.on('close', (code) => { - const ps = this.ps - this.ps = null + ps.on("close", (code) => { + const ps = this.ps; + this.ps = null; if (code) { - console.log(`child process exited with code ${code}`) - reject(`child process exited with code ${code}`) + console.log(`child process exited with code ${code}`); + reject(`child process exited with code ${code}`); } else { - resolve(ps) + resolve(ps); } - }) + }); - expect(ps.error).to.be.an('undefined') - this.ps = ps - }) + expect(ps.error).to.be.an("undefined"); + this.ps = ps; + }); } - async startNew () { - await this.init() - const args = ['--base-path', '.', '--init'] + async startNew() { + await this.init(); + const args = ["--base-path", ".", "--init"]; if (this.logFilePath) { - args.push('--log-config', this.logFilePath) + args.push("--log-config", this.logFilePath); } - return await this.run(await this.compile(), args, true) + return await this.run(await this.compile(), args, true); } - async compile () { + async compile() { if (!outputProcess) { - await this.run('cargo', [ - 'build', - '--release', - '--bin', - 'tari_merge_mining_proxy', - '-Z', - 'unstable-options', - '--out-dir', - __dirname + '/../temp/out' - ]) - outputProcess = __dirname + '/../temp/out/tari_merge_mining_proxy' + await this.run("cargo", [ + "build", + "--release", + "--bin", + "tari_merge_mining_proxy", + "-Z", + "unstable-options", + "--out-dir", + __dirname + "/../temp/out", + ]); + outputProcess = __dirname + "/../temp/out/tari_merge_mining_proxy"; } - return outputProcess + return outputProcess; } - stop () { + stop() { return new Promise((resolve) => { if (!this.ps) { - return resolve() + return resolve(); } - this.ps.on('close', (code) => { + this.ps.on("close", (code) => { if (code) { - console.log(`child process exited with code ${code}`) + console.log(`child process exited with code ${code}`); } - resolve() - }) - this.ps.kill('SIGINT') - }) + resolve(); + }); + this.ps.kill("SIGINT"); + }); } - createClient () { - const address = 'http://127.0.0.1:' + this.port + createClient() { + const address = "http://127.0.0.1:" + this.port; // console.log("MergeMiningProxyProcess createClient - client address:", address); - return new MergeMiningProxyClient(address) + return new MergeMiningProxyClient(address); } } -module.exports = MergeMiningProxyProcess +module.exports = MergeMiningProxyProcess; diff --git a/integration_tests/helpers/miningNodeProcess.js b/integration_tests/helpers/miningNodeProcess.js index 38d595fc08..3084e37a48 100644 --- a/integration_tests/helpers/miningNodeProcess.js +++ b/integration_tests/helpers/miningNodeProcess.js @@ -1,139 +1,138 @@ -const { getFreePort } = require('./util') -const dateFormat = require('dateformat') -const fs = require('fs') -const { spawnSync, spawn, execSync } = require('child_process') -const { expect } = require('chai') -const { createEnv } = require('./config') +const dateFormat = require("dateformat"); +const fs = require("fs"); +const { spawn } = require("child_process"); +const { expect } = require("chai"); +const { createEnv } = require("./config"); -let outputProcess +let outputProcess; class MiningNodeProcess { - constructor (name, baseNodeAddress, walletAddress, mineOnTipOnly = true) { - this.name = `MiningNode-${name}` - this.maxBlocks = 1 - this.minDiff = 0 - this.maxDiff = 100000 - this.nodeAddress = baseNodeAddress.split(':')[0] - this.nodeGrpcPort = baseNodeAddress.split(':')[1] - this.walletAddress = walletAddress.split(':')[0] - this.walletGrpcPort = walletAddress.split(':')[1] - this.mineOnTipOnly = mineOnTipOnly + constructor(name, baseNodeAddress, walletAddress, mineOnTipOnly = true) { + this.name = `MiningNode-${name}`; + this.maxBlocks = 1; + this.minDiff = 0; + this.maxDiff = 100000; + this.nodeAddress = baseNodeAddress.split(":")[0]; + this.nodeGrpcPort = baseNodeAddress.split(":")[1]; + this.walletAddress = walletAddress.split(":")[0]; + this.walletGrpcPort = walletAddress.split(":")[1]; + this.mineOnTipOnly = mineOnTipOnly; } - async init (maxBlocks, minDiff, maxDiff, mineOnTipOnly) { - this.maxBlocks = maxBlocks || this.maxBlocks - this.minDiff = minDiff || this.minDiff - this.maxDiff = maxDiff || this.maxDiff + async init(maxBlocks, minDiff, maxDiff, mineOnTipOnly) { + this.maxBlocks = maxBlocks || this.maxBlocks; + this.minDiff = minDiff || this.minDiff; + this.maxDiff = maxDiff || this.maxDiff; this.baseDir = `./temp/base_nodes/${dateFormat( new Date(), - 'yyyymmddHHMM' - )}/${this.name}` - this.mineOnTipOnly = mineOnTipOnly || this.mineOnTipOnly + "yyyymmddHHMM" + )}/${this.name}`; + this.mineOnTipOnly = mineOnTipOnly || this.mineOnTipOnly; } - run (cmd, args, saveFile) { + run(cmd, args) { return new Promise((resolve, reject) => { if (!fs.existsSync(this.baseDir)) { - fs.mkdirSync(this.baseDir, { recursive: true }) - fs.mkdirSync(this.baseDir + '/log', { recursive: true }) + fs.mkdirSync(this.baseDir, { recursive: true }); + fs.mkdirSync(this.baseDir + "/log", { recursive: true }); } const envs = createEnv( this.name, false, - 'nodeid.json', + "nodeid.json", this.walletAddress, this.walletGrpcPort, - '8080', + "8080", this.nodeAddress, this.nodeGrpcPort, this.baseNodePort, - '127.0.0.1:8084', + "127.0.0.1:8084", { mineOnTipOnly: this.mineOnTipOnly }, [] - ) + ); const ps = spawn(cmd, args, { cwd: this.baseDir, // shell: true, - env: { ...process.env, ...envs } - }) + env: { ...process.env, ...envs }, + }); - ps.stdout.on('data', (data) => { + ps.stdout.on("data", (data) => { // console.log(`stdout: ${data}`); - fs.appendFileSync(`${this.baseDir}/log/stdout.log`, data.toString()) + fs.appendFileSync(`${this.baseDir}/log/stdout.log`, data.toString()); // resolve(ps); - }) + }); - ps.stderr.on('data', (data) => { - console.error(`stderr: ${data}`) - fs.appendFileSync(`${this.baseDir}/log/stderr.log`, data.toString()) - }) + ps.stderr.on("data", (data) => { + console.error(`stderr: ${data}`); + fs.appendFileSync(`${this.baseDir}/log/stderr.log`, data.toString()); + }); - ps.on('close', (code) => { - const ps = this.ps - this.ps = null + ps.on("close", (code) => { + const ps = this.ps; + this.ps = null; if (code) { - console.log(`child process exited with code ${code}`) - reject(`child process exited with code ${code}`) + console.log(`child process exited with code ${code}`); + reject(`child process exited with code ${code}`); } else { - resolve(ps) + resolve(ps); } - }) + }); - expect(ps.error).to.be.an('undefined') - this.ps = ps - }) + expect(ps.error).to.be.an("undefined"); + this.ps = ps; + }); } - async startNew () { - await this.init() + async startNew() { + await this.init(); const args = [ - '--base-path', - '.', - '--init', - '--daemon', - '--max-blocks', + "--base-path", + ".", + "--init", + "--daemon", + "--max-blocks", this.maxBlocks, - '--min-difficulty', + "--min-difficulty", this.minDiff, - '--max-difficulty', - this.maxDiff - ] - return await this.run(await this.compile(), args, true) + "--max-difficulty", + this.maxDiff, + ]; + return await this.run(await this.compile(), args, true); } - async compile () { + async compile() { if (!outputProcess) { - await this.run('cargo', [ - 'build', - '--release', - '--bin', - 'tari_mining_node', - '-Z', - 'unstable-options', - '--out-dir', - __dirname + '/../temp/out' - ]) - outputProcess = __dirname + '/../temp/out/tari_mining_node' + await this.run("cargo", [ + "build", + "--release", + "--bin", + "tari_mining_node", + "-Z", + "unstable-options", + "--out-dir", + __dirname + "/../temp/out", + ]); + outputProcess = __dirname + "/../temp/out/tari_mining_node"; } - return outputProcess + return outputProcess; } - stop () { + stop() { return new Promise((resolve) => { if (!this.ps) { - return resolve() + return resolve(); } - this.ps.on('close', (code) => { + this.ps.on("close", (code) => { if (code) { - console.log(`child process exited with code ${code}`) + console.log(`child process exited with code ${code}`); } - resolve() - }) - this.ps.kill('SIGINT') - }) + resolve(); + }); + this.ps.kill("SIGINT"); + }); } } -module.exports = MiningNodeProcess +module.exports = MiningNodeProcess; diff --git a/integration_tests/helpers/transactionBuilder.js b/integration_tests/helpers/transactionBuilder.js index f6c8030af6..cb2b4babce 100644 --- a/integration_tests/helpers/transactionBuilder.js +++ b/integration_tests/helpers/transactionBuilder.js @@ -1,55 +1,57 @@ -const tari_crypto = require('tari_crypto') -const { blake2bInit, blake2bUpdate, blake2bFinal } = require('blakejs') -const { toLittleEndian, hexSwitchEndianness } = require('../helpers/util') +const tari_crypto = require("tari_crypto"); +const { blake2bInit, blake2bUpdate, blake2bFinal } = require("blakejs"); +const { toLittleEndian } = require("../helpers/util"); class TransactionBuilder { - constructor () { - this.kv = tari_crypto.KeyRing.new() - this.inputs = [] - this.outputs = [] - this.fee = 100 - this.lockHeight = 0 + constructor() { + this.kv = tari_crypto.KeyRing.new(); + this.inputs = []; + this.outputs = []; + this.fee = 100; + this.lockHeight = 0; } - generatePrivateKey (id) { - this.kv.new_key(id) - return this.kv.private_key(id) + generatePrivateKey(id) { + this.kv.new_key(id); + return this.kv.private_key(id); } - buildChallenge (publicNonce, fee, lockHeight) { - const KEY = null // optional key - const OUTPUT_LENGTH = 32 // bytes - const context = blake2bInit(OUTPUT_LENGTH, KEY) - const buff = Buffer.from(publicNonce, 'hex') - blake2bUpdate(context, buff) - blake2bUpdate(context, toLittleEndian(fee, 64)) - blake2bUpdate(context, toLittleEndian(lockHeight, 64)) - const final = blake2bFinal(context) - return Buffer.from(final).toString('hex') + buildChallenge(publicNonce, fee, lockHeight) { + const KEY = null; // optional key + const OUTPUT_LENGTH = 32; // bytes + const context = blake2bInit(OUTPUT_LENGTH, KEY); + const buff = Buffer.from(publicNonce, "hex"); + blake2bUpdate(context, buff); + blake2bUpdate(context, toLittleEndian(fee, 64)); + blake2bUpdate(context, toLittleEndian(lockHeight, 64)); + const final = blake2bFinal(context); + return Buffer.from(final).toString("hex"); } - changeFee (fee) { - this.fee = fee + changeFee(fee) { + this.fee = fee; } - addInput (input) { + addInput(input) { this.inputs.push({ input: input.output, amount: input.amount, - privateKey: input.privateKey - }) + privateKey: input.privateKey, + }); } - addOutput (amount) { + addOutput(amount) { const outputFeatures = { flags: 0, - maturity: 0 - } - const key = Math.floor(Math.random() * 500 + 1) - const privateKey = Buffer.from(toLittleEndian(key, 256)).toString('hex') - const rangeproofFactory = tari_crypto.RangeProofFactory.new() - const rangeproof = rangeproofFactory.create_proof(privateKey, BigInt(amount)) - .proof + maturity: 0, + }; + const key = Math.floor(Math.random() * 500 + 1); + const privateKey = Buffer.from(toLittleEndian(key, 256)).toString("hex"); + const rangeproofFactory = tari_crypto.RangeProofFactory.new(); + const rangeproof = rangeproofFactory.create_proof( + privateKey, + BigInt(amount) + ).proof; const output = { amount: amount, privateKey: privateKey, @@ -57,55 +59,54 @@ class TransactionBuilder { features: outputFeatures, commitment: Buffer.from( tari_crypto.commit(privateKey, BigInt(amount)).commitment, - 'hex' + "hex" ), - range_proof: Buffer.from(rangeproof, 'hex') - } - } - this.outputs.push(output) - return output + range_proof: Buffer.from(rangeproof, "hex"), + }, + }; + this.outputs.push(output); + return output; } - getSpendableAmount () { - let sum = 0 - this.inputs.forEach((input) => (sum = sum + input.amount)) - return sum - this.fee + getSpendableAmount() { + let sum = 0; + this.inputs.forEach((input) => (sum = sum + input.amount)); + return sum - this.fee; } - build () { - let totalPrivateKey = 0n + build() { + let totalPrivateKey = 0n; this.outputs.forEach( (output) => - (totalPrivateKey += BigInt('0x' + output.privateKey.toString())) - ) + (totalPrivateKey += BigInt("0x" + output.privateKey.toString())) + ); this.inputs.forEach( - (input) => (totalPrivateKey -= BigInt('0x' + input.privateKey.toString())) - ) + (input) => (totalPrivateKey -= BigInt("0x" + input.privateKey.toString())) + ); // Assume low numbers.... - let PrivateKey = totalPrivateKey.toString(16) + let PrivateKey = totalPrivateKey.toString(16); // we need to pad 0's in front while (PrivateKey.length < 64) { - PrivateKey = '0' + PrivateKey + PrivateKey = "0" + PrivateKey; } - const excess = tari_crypto.commit(PrivateKey, BigInt(0)) - const nonce = this.kv.new_key('common_nonce') - const public_nonce = this.kv.public_key('common_nonce') + const excess = tari_crypto.commit(PrivateKey, BigInt(0)); + const public_nonce = this.kv.public_key("common_nonce"); const challenge = this.buildChallenge( public_nonce, this.fee, this.lockHeight - ) - const private_nonce = this.kv.private_key('common_nonce') + ); + const private_nonce = this.kv.private_key("common_nonce"); const sig = tari_crypto.sign_challenge_with_nonce( PrivateKey, private_nonce, challenge - ) + ); return { - offset: Buffer.from(toLittleEndian(0, 256), 'hex'), + offset: Buffer.from(toLittleEndian(0, 256), "hex"), body: { inputs: this.inputs.map((i) => i.input), outputs: this.outputs.map((o) => o.output), @@ -114,60 +115,60 @@ class TransactionBuilder { features: 0, fee: this.fee, lock_height: this.lockHeight, - excess: Buffer.from(excess.commitment, 'hex'), + excess: Buffer.from(excess.commitment, "hex"), excess_sig: { - public_nonce: Buffer.from(sig.public_nonce, 'hex'), - signature: Buffer.from(sig.signature, 'hex') - } - } - ] - } - } + public_nonce: Buffer.from(sig.public_nonce, "hex"), + signature: Buffer.from(sig.signature, "hex"), + }, + }, + ], + }, + }; } - generateCoinbase (value, privateKey, fee, lockHeight) { - const coinbase = tari_crypto.commit(privateKey, BigInt(value + fee)) - const rangeproofFactory = tari_crypto.RangeProofFactory.new() + generateCoinbase(value, privateKey, fee, lockHeight) { + const coinbase = tari_crypto.commit(privateKey, BigInt(value + fee)); + const rangeproofFactory = tari_crypto.RangeProofFactory.new(); const rangeproof = rangeproofFactory.create_proof( privateKey, BigInt(value + fee) - ).proof - const excess = tari_crypto.commit(privateKey, BigInt(0)) - this.kv.new_key('nonce') - const public_nonce = this.kv.public_key('nonce') - const challenge = this.buildChallenge(public_nonce, 0, lockHeight) - const private_nonce = this.kv.private_key('nonce') + ).proof; + const excess = tari_crypto.commit(privateKey, BigInt(0)); + this.kv.new_key("nonce"); + const public_nonce = this.kv.public_key("nonce"); + const challenge = this.buildChallenge(public_nonce, 0, lockHeight); + const private_nonce = this.kv.private_key("nonce"); const sig = tari_crypto.sign_challenge_with_nonce( privateKey, private_nonce, challenge - ) + ); const outputFeatures = { flags: 1, - maturity: lockHeight - } + maturity: lockHeight, + }; return { outputs: [ { features: outputFeatures, - commitment: Buffer.from(coinbase.commitment, 'hex'), - range_proof: Buffer.from(rangeproof, 'hex') - } + commitment: Buffer.from(coinbase.commitment, "hex"), + range_proof: Buffer.from(rangeproof, "hex"), + }, ], kernels: [ { features: 1, fee: 0, lock_height: lockHeight, - excess: Buffer.from(excess.commitment, 'hex'), + excess: Buffer.from(excess.commitment, "hex"), excess_sig: { - public_nonce: Buffer.from(sig.public_nonce, 'hex'), - signature: Buffer.from(sig.signature, 'hex') - } - } - ] - } + public_nonce: Buffer.from(sig.public_nonce, "hex"), + signature: Buffer.from(sig.signature, "hex"), + }, + }, + ], + }; } } -module.exports = TransactionBuilder +module.exports = TransactionBuilder; diff --git a/integration_tests/helpers/util.js b/integration_tests/helpers/util.js index 4999ddb970..4ffc30c2ae 100644 --- a/integration_tests/helpers/util.js +++ b/integration_tests/helpers/util.js @@ -1,207 +1,202 @@ -const net = require('net') -const fs = require('fs') -const readline = require('readline') +const net = require("net"); -const { blake2bInit, blake2bUpdate, blake2bFinal } = require('blakejs') +const { blake2bInit, blake2bUpdate, blake2bFinal } = require("blakejs"); -function getRandomInt (min, max) { - min = Math.ceil(min) - max = Math.floor(max) - return Math.floor(Math.random() * (max - min + 1)) + min +function getRandomInt(min, max) { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min + 1)) + min; } -function sleep (ms) { +function sleep(ms) { return new Promise((resolve) => { - setTimeout(resolve, ms) - }) + setTimeout(resolve, ms); + }); } -function withTimeout (ms, promise, message = '') { +function withTimeout(ms, promise, message = "") { const timeout = new Promise((_resolve, reject) => { setTimeout( () => reject(new Error(message || `Timed out after ${ms}ms`)), ms - ) - }) - return Promise.race([timeout, promise]) + ); + }); + return Promise.race([timeout, promise]); } -async function waitFor ( +async function waitFor( asyncTestFn, toBe, maxTime, timeOut = 500, skipLog = 50 ) { - const now = new Date() + const now = new Date(); - let i = 0 + let i = 0; while (new Date() - now < maxTime) { - const value = await asyncTestFn() + const value = await asyncTestFn(); if (value === toBe) { if (i > 1) { - console.log('waiting for process...', timeOut, i, value) + console.log("waiting for process...", timeOut, i, value); } - break + break; } if (i % skipLog === 0 && i > 1) { - console.log('waiting for process...', timeOut, i, value) + console.log("waiting for process...", timeOut, i, value); } - await sleep(timeOut) - i++ + await sleep(timeOut); + i++; } } -function dec2hex (n) { - return n ? [n % 256].concat(dec2hex(~~(n / 256))) : [] +function dec2hex(n) { + return n ? [n % 256].concat(dec2hex(~~(n / 256))) : []; } -function toLittleEndianInner (n) { - const hexar = dec2hex(n) +function toLittleEndianInner(n) { + const hexar = dec2hex(n); return hexar - .map((h) => (h < 16 ? '0' : '') + h.toString(16)) - .concat(Array(4 - hexar.length).fill('00')) + .map((h) => (h < 16 ? "0" : "") + h.toString(16)) + .concat(Array(4 - hexar.length).fill("00")); } -function toLittleEndian (n, numBits) { - const s = toLittleEndianInner(n) +function toLittleEndian(n, numBits) { + const s = toLittleEndianInner(n); for (let i = s.length; i < numBits / 8; i++) { - s.push('00') + s.push("00"); } - const arr = Buffer.from(s.join(''), 'hex') + const arr = Buffer.from(s.join(""), "hex"); - return arr + return arr; } -function hexSwitchEndianness (val) { - let res = '' +function hexSwitchEndianness(val) { + let res = ""; for (let i = val.length - 2; i > 0; i -= 2) { - res += val[i] + val[i + 1] + res += val[i] + val[i + 1]; } - return res + return res; } // Thanks to https://stackoverflow.com/questions/29860354/in-nodejs-how-do-i-check-if-a-port-is-listening-or-in-use const portInUse = function (port, callback) { const server = net.createServer(function (socket) { - socket.write('Echo server\r\n') - socket.pipe(socket) - }) - - server.listen(port, '127.0.0.1') - server.on('error', function (e) { - callback(true) - }) - server.on('listening', function (e) { - server.close() - callback(false) - }) -} - -let index = 0 + socket.write("Echo server\r\n"); + socket.pipe(socket); + }); + + server.listen(port, "127.0.0.1"); + server.on("error", function () { + callback(true); + }); + server.on("listening", function () { + server.close(); + callback(false); + }); +}; + +let index = 0; const getFreePort = async function (from, to) { - function testPort (port) { + function testPort(port) { return new Promise((r) => { portInUse(port, (v) => { if (v) { - r(false) + r(false); } - r(true) - }) - }) + r(true); + }); + }); } - let port = from + index + let port = from + index; if (port > to) { - index = from - port = from + index = from; + port = from; } while (port < to) { // let port = getRandomInt(from, to); // await sleep(100); - port++ - index++ - const notInUse = await testPort(port) + port++; + index++; + const notInUse = await testPort(port); // console.log("Port not in use:", notInUse); if (notInUse) { - return port + return port; } } -} +}; // WIP this doesn't hash properly const getTransactionOutputHash = function (output) { - const KEY = null // optional key - const OUTPUT_LENGTH = 32 // bytes - const context = blake2bInit(OUTPUT_LENGTH, KEY) - const flags = Buffer.alloc(1) - flags[0] = output.features.flags + const KEY = null; // optional key + const OUTPUT_LENGTH = 32; // bytes + const context = blake2bInit(OUTPUT_LENGTH, KEY); + const flags = Buffer.alloc(1); + flags[0] = output.features.flags; const buffer = Buffer.concat([ flags, - toLittleEndian(parseInt(output.features.maturity), 64) - ]) - blake2bUpdate(context, buffer) - blake2bUpdate(context, output.commitment) - const final = blake2bFinal(context) - return Buffer.from(final) -} - -function consoleLogTransactionDetails (txnDetails, txId) { - const found = txnDetails[0] - const status = txnDetails[1] + toLittleEndian(parseInt(output.features.maturity), 64), + ]); + blake2bUpdate(context, buffer); + blake2bUpdate(context, output.commitment); + const final = blake2bFinal(context); + return Buffer.from(final); +}; + +function consoleLogTransactionDetails(txnDetails, txId) { + const found = txnDetails[0]; + const status = txnDetails[1]; if (found) { console.log( - ' Transaction ' + + " Transaction " + pad("'" + status.transactions[0].tx_id + "'", 24) + - ' has status ' + + " has status " + pad("'" + status.transactions[0].status + "'", 40) + - ' and ' + - pad( - 'is_cancelled(' + status.transactions[0].is_cancelled + ')', - 21 - ) + - ' and ' + - pad('is_valid(' + status.transactions[0].valid + ')', 16) - ) + " and " + + pad("is_cancelled(" + status.transactions[0].is_cancelled + ")", 21) + + " and " + + pad("is_valid(" + status.transactions[0].valid + ")", 16) + ); } else { - console.log(" Transaction '" + txId + "' " + status) + console.log(" Transaction '" + txId + "' " + status); } } -function consoleLogBalance (balance) { +function consoleLogBalance(balance) { console.log( - ' Available ' + + " Available " + pad(balance.available_balance, 16) + - ' uT, Pending incoming ' + + " uT, Pending incoming " + pad(balance.pending_incoming_balance, 16) + - ' uT, Pending outgoing ' + + " uT, Pending outgoing " + pad(balance.pending_outgoing_balance, 16) + - ' uT' - ) + " uT" + ); } -function consoleLogCoinbaseDetails (txnDetails) { +function consoleLogCoinbaseDetails(txnDetails) { console.log( - ' Transaction ' + + " Transaction " + pad("'" + txnDetails.tx_id + "'", 24) + - ' has status ' + + " has status " + pad("'" + txnDetails.status + "'", 40) + - ' and ' + - pad('is_cancelled(' + txnDetails.is_cancelled + ')', 21) + - ' and ' + - pad('is_valid(' + txnDetails.valid + ')', 16) - ) + " and " + + pad("is_cancelled(" + txnDetails.is_cancelled + ")", 21) + + " and " + + pad("is_valid(" + txnDetails.valid + ")", 16) + ); } -function pad (str, length, padLeft = true) { - const padding = Array(length).join(' ') - if (typeof str === 'undefined') return padding +function pad(str, length, padLeft = true) { + const padding = Array(length).join(" "); + if (typeof str === "undefined") return padding; if (padLeft) { - return (padding + str).slice(-padding.length) + return (padding + str).slice(-padding.length); } else { - return (str + padding).substring(' ', padding.length) + return (str + padding).substring(" ", padding.length); } } @@ -217,5 +212,5 @@ module.exports = { consoleLogTransactionDetails, consoleLogBalance, consoleLogCoinbaseDetails, - withTimeout -} + withTimeout, +}; diff --git a/integration_tests/helpers/walletClient.js b/integration_tests/helpers/walletClient.js index 8a4990a239..78ee7b2bbe 100644 --- a/integration_tests/helpers/walletClient.js +++ b/integration_tests/helpers/walletClient.js @@ -1,275 +1,261 @@ -const { Client } = require('wallet-grpc-client') -const { sleep } = require('./util') +const { Client } = require("wallet-grpc-client"); -function transactionStatus () { +function transactionStatus() { return [ - 'TRANSACTION_STATUS_IMPORTED', - 'TRANSACTION_STATUS_COINBASE', - 'TRANSACTION_STATUS_PENDING', - 'TRANSACTION_STATUS_COMPLETED', - 'TRANSACTION_STATUS_BROADCAST', - 'TRANSACTION_STATUS_MINED_UNCONFIRMED', - 'TRANSACTION_STATUS_MINED_CONFIRMED' - ] + "TRANSACTION_STATUS_IMPORTED", + "TRANSACTION_STATUS_COINBASE", + "TRANSACTION_STATUS_PENDING", + "TRANSACTION_STATUS_COMPLETED", + "TRANSACTION_STATUS_BROADCAST", + "TRANSACTION_STATUS_MINED_UNCONFIRMED", + "TRANSACTION_STATUS_MINED_CONFIRMED", + ]; } class WalletClient { - constructor (walletAddress, name) { - this.client = Client.connect(walletAddress) - this.name = name + constructor(walletAddress, name) { + this.client = Client.connect(walletAddress); + this.name = name; } - async getVersion () { - return await this.client.getVersion() + async getVersion() { + return await this.client.getVersion(); } - async getBalance () { - return await this.client.getBalance() + async getBalance() { + return await this.client.getBalance(); } - async getCompletedTransactions () { - const data = await this.client.getCompletedTransactions() - const transactions = [] - const myDate = new Date() + async getCompletedTransactions() { + const data = await this.client.getCompletedTransactions(); + const transactions = []; for (let i = 0; i < data.length; i++) { transactions.push({ tx_id: data[i].transaction.tx_id, - source_pk: data[i].transaction.source_pk.toString('hex'), - dest_pk: data[i].transaction.dest_pk.toString('hex'), + source_pk: data[i].transaction.source_pk.toString("hex"), + dest_pk: data[i].transaction.dest_pk.toString("hex"), status: data[i].transaction.status, direction: data[i].transaction.direction, amount: data[i].transaction.amount, fee: data[i].transaction.fee, is_cancelled: data[i].transaction.is_cancelled, - excess_sig: data[i].transaction.excess_sig.toString('hex'), + excess_sig: data[i].transaction.excess_sig.toString("hex"), timestamp: new Date( Number(data[i].transaction.timestamp.seconds) * 1000 ), message: data[i].transaction.message, - valid: data[i].transaction.valid - }) + valid: data[i].transaction.valid, + }); } - return transactions + return transactions; } - async getAllCoinbaseTransactions () { - const data = await this.getCompletedTransactions() - const transactions = [] + async getAllCoinbaseTransactions() { + const data = await this.getCompletedTransactions(); + const transactions = []; for (let i = 0; i < data.length; i++) { if ( - data[i].message.includes('Coinbase Transaction for Block ') && + data[i].message.includes("Coinbase Transaction for Block ") && data[i].fee == 0 ) { - transactions.push(data[i]) + transactions.push(data[i]); } } - return transactions + return transactions; } - async getAllSpendableCoinbaseTransactions () { - const data = await this.getAllCoinbaseTransactions() - const transactions = [] + async getAllSpendableCoinbaseTransactions() { + const data = await this.getAllCoinbaseTransactions(); + const transactions = []; for (let i = 0; i < data.length; i++) { if ( transactionStatus().indexOf(data[i].status) == 6 && data[i].valid == true ) { - transactions.push(data[i]) + transactions.push(data[i]); } } - return transactions + return transactions; } - async areCoinbasesConfirmedAtLeast (number) { - const data = await this.getAllSpendableCoinbaseTransactions() + async areCoinbasesConfirmedAtLeast(number) { + const data = await this.getAllSpendableCoinbaseTransactions(); if (data.length >= number) { - return true + return true; } else { - return false + return false; } } - async getAllNormalTransactions () { - const data = this.getCompletedTransactions() - const transactions = [] + async getAllNormalTransactions() { + const data = this.getCompletedTransactions(); + const transactions = []; for (let i = 0; i < data.length; i++) { if ( !( - data[i].message.includes('Coinbase Transaction for Block ') && + data[i].message.includes("Coinbase Transaction for Block ") && data[i].fee == 0 ) ) { - transactions.push(data[i]) + transactions.push(data[i]); } } - return transactions + return transactions; } - async transfer (args) { - return await this.client.transfer(args) + async transfer(args) { + return await this.client.transfer(args); } - async getTransactionInfo (args) { - return await this.client.getTransactionInfo(args) + async getTransactionInfo(args) { + return await this.client.getTransactionInfo(args); } - async identify (args) { - const info = await this.client.identify(args) + async identify(args) { + const info = await this.client.identify(args); return { - public_key: info.public_key.toString('utf8'), + public_key: info.public_key.toString("utf8"), public_address: info.public_address, - node_id: info.node_id.toString('utf8') - } + node_id: info.node_id.toString("utf8"), + }; } - async isTransactionRegistered (tx_id) { + async isTransactionRegistered(tx_id) { try { await this.getTransactionInfo({ - transaction_ids: [tx_id.toString()] - }) - return true + transaction_ids: [tx_id.toString()], + }); + return true; } catch (err) { // Any error here must be treated as if the required status was not achieved - return false + return false; } } - async isBalanceAtLeast (amount) { + async isBalanceAtLeast(amount) { try { - const balance = await this.getBalance() + const balance = await this.getBalance(); if (balance.available_balance >= amount) { - return true + return true; } else { - return false + return false; } } catch (err) { // Any error here must be treated as if the required status was not achieved - return false + return false; } } - async isTransactionAtLeastPending (tx_id) { + async isTransactionAtLeastPending(tx_id) { try { const txnDetails = await this.getTransactionInfo({ - transaction_ids: [tx_id.toString()] - }) - if ( - transactionStatus().indexOf(txnDetails.transactions[0].status) >= 2 - ) { - return true + transaction_ids: [tx_id.toString()], + }); + if (transactionStatus().indexOf(txnDetails.transactions[0].status) >= 2) { + return true; } else { - return false + return false; } } catch (err) { // Any error here must be treated as if the required status was not achieved - return false + return false; } } - async isTransactionAtLeastCompleted (tx_id) { + async isTransactionAtLeastCompleted(tx_id) { try { const txnDetails = await this.getTransactionInfo({ - transaction_ids: [tx_id.toString()] - }) - if ( - transactionStatus().indexOf(txnDetails.transactions[0].status) >= 3 - ) { - return true + transaction_ids: [tx_id.toString()], + }); + if (transactionStatus().indexOf(txnDetails.transactions[0].status) >= 3) { + return true; } else { - return false + return false; } } catch (err) { // Any error here must be treated as if the required status was not achieved - return false + return false; } } - async isTransactionAtLeastBroadcast (tx_id) { + async isTransactionAtLeastBroadcast(tx_id) { try { const txnDetails = await this.getTransactionInfo({ - transaction_ids: [tx_id.toString()] - }) - if ( - transactionStatus().indexOf(txnDetails.transactions[0].status) >= 4 - ) { - return true + transaction_ids: [tx_id.toString()], + }); + if (transactionStatus().indexOf(txnDetails.transactions[0].status) >= 4) { + return true; } else { - return false + return false; } } catch (err) { // Any error here must be treated as if the required status was not achieved - return false + return false; } } - async isTransactionAtLeastMinedUnconfirmed (tx_id) { + async isTransactionAtLeastMinedUnconfirmed(tx_id) { try { const txnDetails = await this.getTransactionInfo({ - transaction_ids: [tx_id.toString()] - }) - if ( - transactionStatus().indexOf(txnDetails.transactions[0].status) >= 5 - ) { - return true + transaction_ids: [tx_id.toString()], + }); + if (transactionStatus().indexOf(txnDetails.transactions[0].status) >= 5) { + return true; } else { - return false + return false; } } catch (err) { // Any error here must be treated as if the required status was not achieved - return false + return false; } } - async isTransactionMinedUnconfirmed (tx_id) { + async isTransactionMinedUnconfirmed(tx_id) { try { const txnDetails = await this.getTransactionInfo({ - transaction_ids: [tx_id.toString()] - }) - if ( - transactionStatus().indexOf(txnDetails.transactions[0].status) == 5 - ) { - return true + transaction_ids: [tx_id.toString()], + }); + if (transactionStatus().indexOf(txnDetails.transactions[0].status) == 5) { + return true; } else { - return false + return false; } } catch (err) { // Any error here must be treated as if the required status was not achieved - return false + return false; } } - async isTransactionMinedConfirmed (tx_id) { + async isTransactionMinedConfirmed(tx_id) { try { const txnDetails = await this.getTransactionInfo({ - transaction_ids: [tx_id.toString()] - }) - if ( - transactionStatus().indexOf(txnDetails.transactions[0].status) == 6 - ) { - return true + transaction_ids: [tx_id.toString()], + }); + if (transactionStatus().indexOf(txnDetails.transactions[0].status) == 6) { + return true; } else { - return false + return false; } } catch (err) { // Any error here must be treated as if the required status was not achieved - return false + return false; } } - async getTransactionDetails (tx_id) { + async getTransactionDetails(tx_id) { try { const txnDetails = await this.getTransactionInfo({ - transaction_ids: [tx_id.toString()] - }) - return [true, txnDetails] + transaction_ids: [tx_id.toString()], + }); + return [true, txnDetails]; } catch (err) { - return [false, err] + return [false, err]; } } - async coin_split (args) { - return await this.client.coinSplit(args) + async coin_split(args) { + return await this.client.coinSplit(args); } } -module.exports = WalletClient +module.exports = WalletClient; diff --git a/integration_tests/helpers/walletProcess.js b/integration_tests/helpers/walletProcess.js index 6b4f5ece12..0dffdda4b5 100644 --- a/integration_tests/helpers/walletProcess.js +++ b/integration_tests/helpers/walletProcess.js @@ -1,168 +1,168 @@ -const { getFreePort } = require('./util') -const dateFormat = require('dateformat') -const fs = require('fs') -const path = require('path') -const { spawn } = require('child_process') -const { expect } = require('chai') -const { createEnv } = require('./config') -const WalletClient = require('./walletClient') +const { getFreePort } = require("./util"); +const dateFormat = require("dateformat"); +const fs = require("fs"); +const path = require("path"); +const { spawn } = require("child_process"); +const { expect } = require("chai"); +const { createEnv } = require("./config"); +const WalletClient = require("./walletClient"); -let outputProcess +let outputProcess; class WalletProcess { - constructor (name, options, logFilePath, seedWords) { - this.name = name - this.options = options - this.logFilePath = logFilePath ? path.resolve(logFilePath) : logFilePath - this.recoverWallet = !!seedWords - this.seedWords = seedWords + constructor(name, options, logFilePath, seedWords) { + this.name = name; + this.options = options; + this.logFilePath = logFilePath ? path.resolve(logFilePath) : logFilePath; + this.recoverWallet = !!seedWords; + this.seedWords = seedWords; } - async init () { - this.port = await getFreePort(19000, 25000) - this.name = `Wallet${this.port}-${this.name}` - this.grpcPort = await getFreePort(19000, 25000) + async init() { + this.port = await getFreePort(19000, 25000); + this.name = `Wallet${this.port}-${this.name}`; + this.grpcPort = await getFreePort(19000, 25000); this.baseDir = `./temp/base_nodes/${dateFormat( new Date(), - 'yyyymmddHHMM' - )}/${this.name}` - this.seedWordsFile = path.resolve(this.baseDir + '/config/seed_words.log') + "yyyymmddHHMM" + )}/${this.name}`; + this.seedWordsFile = path.resolve(this.baseDir + "/config/seed_words.log"); } - getGrpcAddress () { - return '127.0.0.1:' + this.grpcPort + getGrpcAddress() { + return "127.0.0.1:" + this.grpcPort; } - getClient () { - return new WalletClient(this.getGrpcAddress(), this.name) + getClient() { + return new WalletClient(this.getGrpcAddress(), this.name); } - getSeedWords () { + getSeedWords() { try { - return fs.readFileSync(this.seedWordsFile, 'utf8') + return fs.readFileSync(this.seedWordsFile, "utf8"); } catch (err) { - console.error('\n', this.name, ': Seed words file not found!\n', err) + console.error("\n", this.name, ": Seed words file not found!\n", err); } } - setPeerSeeds (addresses) { - this.peerSeeds = addresses.join(',') + setPeerSeeds(addresses) { + this.peerSeeds = addresses.join(","); } - run (cmd, args, saveFile) { + run(cmd, args, saveFile) { return new Promise((resolve, reject) => { if (!fs.existsSync(this.baseDir)) { - fs.mkdirSync(this.baseDir, { recursive: true }) - fs.mkdirSync(this.baseDir + '/log', { recursive: true }) + fs.mkdirSync(this.baseDir, { recursive: true }); + fs.mkdirSync(this.baseDir + "/log", { recursive: true }); } const envs = createEnv( this.name, true, - 'cwalletid.json', - '127.0.0.1', + "cwalletid.json", + "127.0.0.1", this.grpcPort, this.port, - '127.0.0.1', - '8080', - '8081', - '127.0.0.1:8084', + "127.0.0.1", + "8080", + "8081", + "127.0.0.1:8084", this.options, this.peerSeeds - ) + ); if (saveFile) { - fs.appendFileSync(`${this.baseDir}/.env`, JSON.stringify(envs)) + fs.appendFileSync(`${this.baseDir}/.env`, JSON.stringify(envs)); } const ps = spawn(cmd, args, { cwd: this.baseDir, // shell: true, - env: { ...process.env, ...envs } - }) + env: { ...process.env, ...envs }, + }); - ps.stdout.on('data', (data) => { + ps.stdout.on("data", (data) => { // console.log(`stdout: ${data}`); - fs.appendFileSync(`${this.baseDir}/log/stdout.log`, data.toString()) + fs.appendFileSync(`${this.baseDir}/log/stdout.log`, data.toString()); if (data.toString().match(/Starting grpc server/)) { - resolve(ps) + resolve(ps); } - }) + }); - ps.stderr.on('data', (data) => { - console.error(`stderr: ${data}`) - fs.appendFileSync(`${this.baseDir}/log/stderr.log`, data.toString()) - }) + ps.stderr.on("data", (data) => { + console.error(`stderr: ${data}`); + fs.appendFileSync(`${this.baseDir}/log/stderr.log`, data.toString()); + }); - ps.on('close', (code) => { - const ps = this.ps - this.ps = null + ps.on("close", (code) => { + const ps = this.ps; + this.ps = null; if (code) { - console.log(`child process exited with code ${code}`) - reject(`child process exited with code ${code}`) + console.log(`child process exited with code ${code}`); + reject(`child process exited with code ${code}`); } else { - resolve(ps) + resolve(ps); } - }) + }); - expect(ps.error).to.be.an('undefined') - this.ps = ps - }) + expect(ps.error).to.be.an("undefined"); + this.ps = ps; + }); } - async startNew () { - await this.init() - let args + async startNew() { + await this.init(); + let args; args = [ - '--base-path', - '.', - '--init', - '--create_id', - '--password', - 'kensentme', - '--seed-words-file-name', + "--base-path", + ".", + "--init", + "--create_id", + "--password", + "kensentme", + "--seed-words-file-name", this.seedWordsFile, - '--daemon' - ] + "--daemon", + ]; if (this.recoverWallet) { - args.push('--recover', '--seed-words', this.seedWords) + args.push("--recover", "--seed-words", this.seedWords); } if (this.logFilePath) { - args.push('--log-config', this.logFilePath) + args.push("--log-config", this.logFilePath); } - return await this.run(await this.compile(), args, true) + return await this.run(await this.compile(), args, true); } - async compile () { + async compile() { if (!outputProcess) { - await this.run('cargo', [ - 'build', - '--release', - '--bin', - 'tari_console_wallet', - '-Z', - 'unstable-options', - '--out-dir', - __dirname + '/../temp/out' - ]) - outputProcess = __dirname + '/../temp/out/tari_console_wallet' + await this.run("cargo", [ + "build", + "--release", + "--bin", + "tari_console_wallet", + "-Z", + "unstable-options", + "--out-dir", + __dirname + "/../temp/out", + ]); + outputProcess = __dirname + "/../temp/out/tari_console_wallet"; } - return outputProcess + return outputProcess; } - stop () { + stop() { return new Promise((resolve) => { if (!this.ps) { - return resolve() + return resolve(); } - this.ps.on('close', (code) => { + this.ps.on("close", (code) => { if (code) { - console.log(`child process exited with code ${code}`) + console.log(`child process exited with code ${code}`); } - resolve() - }) - this.ps.kill('SIGINT') - }) + resolve(); + }); + this.ps.kill("SIGINT"); + }); } } -module.exports = WalletProcess +module.exports = WalletProcess; diff --git a/integration_tests/package-lock.json b/integration_tests/package-lock.json index adb1f3a328..b42ca2300d 100644 --- a/integration_tests/package-lock.json +++ b/integration_tests/package-lock.json @@ -176,12 +176,6 @@ "@types/node": "*" } }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true - }, "@types/long": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", @@ -290,30 +284,6 @@ "sprintf-js": "~1.0.2" } }, - "array-includes": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", - "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.5" - } - }, - "array.prototype.flat": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", - "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - } - }, "arrify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", @@ -432,6 +402,12 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, "bytebuffer": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", @@ -449,16 +425,6 @@ } } }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -961,15 +927,6 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -1030,15 +987,6 @@ "ansi-colors": "^4.1.1" } }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, "error-stack-parser": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.6.tgz", @@ -1048,41 +996,6 @@ "stackframe": "^1.1.1" } }, - "es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, "es5-ext": { "version": "0.10.53", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", @@ -1183,6 +1096,12 @@ } } }, + "eslint-config-prettier": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", + "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", + "dev": true + }, "eslint-config-standard": { "version": "16.0.2", "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.2.tgz", @@ -1190,13 +1109,14 @@ "dev": true }, "eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz", + "integrity": "sha1-Wt2BBujJKNssuiMrzZ76hG49oWw=", "dev": true, "requires": { - "debug": "^2.6.9", - "resolve": "^1.13.1" + "debug": "^2.2.0", + "object-assign": "^4.0.1", + "resolve": "^1.1.6" }, "dependencies": { "debug": { @@ -1254,24 +1174,21 @@ } }, "eslint-plugin-import": { - "version": "2.22.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", - "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.2.0.tgz", + "integrity": "sha1-crowb60wXWfEgWNIpGmaQimsi04=", "dev": true, "requires": { - "array-includes": "^3.1.1", - "array.prototype.flat": "^1.2.3", + "builtin-modules": "^1.1.1", "contains-path": "^0.1.0", - "debug": "^2.6.9", + "debug": "^2.2.0", "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.0", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.1", - "read-pkg-up": "^2.0.0", - "resolve": "^1.17.0", - "tsconfig-paths": "^3.9.0" + "eslint-import-resolver-node": "^0.2.0", + "eslint-module-utils": "^2.0.0", + "has": "^1.0.1", + "lodash.cond": "^4.3.0", + "minimatch": "^3.0.3", + "pkg-up": "^1.0.0" }, "dependencies": { "debug": { @@ -1323,6 +1240,15 @@ } } }, + "eslint-plugin-prettier": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.0.tgz", + "integrity": "sha512-UDK6rJT6INSfcOo545jiaOwB701uAIt2/dR7WnFQoGCVl1/EMqdANBmwUaqqQ45aXprsTGzSa39LI1PyuRBxxw==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, "eslint-plugin-promise": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.3.1.tgz", @@ -1472,6 +1398,12 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -1680,17 +1612,6 @@ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -1813,24 +1734,12 @@ "function-bind": "^1.1.1" } }, - "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true - }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -1842,12 +1751,6 @@ "resolved": "https://registry.npmjs.org/hex64/-/hex64-0.4.0.tgz", "integrity": "sha1-rRB4rIHVfXLeYjKxADvE9vsCh8A=" }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, "https-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", @@ -1857,6 +1760,12 @@ "debug": "4" } }, + "husky": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/husky/-/husky-6.0.0.tgz", + "integrity": "sha512-SQS2gDTB7tBN486QSoKPKQItZw97BMOd+Kdb6ghfpBc0yXyzrddI0oDV5MkDAbuB4X2mO3/nj60TRMcYxwzZeQ==", + "dev": true + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1936,33 +1845,6 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-bigint": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", - "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", - "dev": true - }, - "is-boolean-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", - "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", - "dev": true, - "requires": { - "call-bind": "^1.0.0" - } - }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", - "dev": true - }, "is-core-module": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", @@ -1972,12 +1854,6 @@ "has": "^1.0.3" } }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true - }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2005,18 +1881,6 @@ "is-extglob": "^2.1.1" } }, - "is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "dev": true - }, - "is-number-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", - "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", - "dev": true - }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -2025,36 +1889,11 @@ "isobject": "^3.0.1" } }, - "is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" - } - }, "is-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" }, - "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, "is-wsl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", @@ -2120,15 +1959,6 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, "jsonfile": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-5.0.0.tgz", @@ -2191,18 +2021,6 @@ "type-check": "~0.4.0" } }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } - }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", @@ -2236,6 +2054,12 @@ "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", "dev": true }, + "lodash.cond": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz", + "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=", + "dev": true + }, "lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", @@ -2443,26 +2267,6 @@ "osenv": "^0.1.4" } }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, "npm-bundled": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", @@ -2513,42 +2317,6 @@ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, - "object-inspect": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.2.tgz", - "integrity": "sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - }, - "object.values": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", - "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has": "^1.0.3" - } - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -2660,15 +2428,6 @@ "callsites": "^3.0.0" } }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -2693,27 +2452,27 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, "pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", "dev": true }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, "pkg-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", @@ -2723,6 +2482,36 @@ "find-up": "^2.1.0" } }, + "pkg-up": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-1.0.0.tgz", + "integrity": "sha1-Pgj7RhUlxEIWJKM7n35tCvWwWiY=", + "dev": true, + "requires": { + "find-up": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + } + } + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -2735,6 +2524,15 @@ "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", "dev": true }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -2785,27 +2583,6 @@ "strip-json-comments": "~2.0.1" } }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } - }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -2995,38 +2772,6 @@ } } }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", - "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", - "dev": true - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -3100,26 +2845,6 @@ "strip-ansi": "^6.0.0" } }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -3146,12 +2871,6 @@ "ansi-regex": "^5.0.0" } }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -3295,18 +3014,6 @@ "integrity": "sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE=", "dev": true }, - "tsconfig-paths": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", - "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", - "strip-bom": "^3.0.0" - } - }, "type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", @@ -3334,18 +3041,6 @@ "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", "dev": true }, - "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - } - }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -3391,16 +3086,6 @@ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -3430,19 +3115,6 @@ "isexe": "^2.0.0" } }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", diff --git a/integration_tests/package.json b/integration_tests/package.json index 50320a9b33..8b41dc8535 100644 --- a/integration_tests/package.json +++ b/integration_tests/package.json @@ -1,16 +1,17 @@ { "name": "integration_tests", "version": "1.0.0", - "description": "", + "description": "Tari Integration Tests", "repository": "https://github.com/tari-project/tari", "scripts": { "test": "cucumber-js", "fmt": "prettier -w .", "check-fmt": "prettier -c .", - "fmt-auto": "prettier --end-of-line auto -w .", - "check-fmt-auto": "prettier --end-of-line auto -c ." + "lint": "eslint .", + "lint-fix": "eslint --fix .", + "prepare": "cd .. && husky install integration_tests/.husky" }, - "author": "", + "author": "The Tari Project", "license": "ISC", "devDependencies": { "@grpc/proto-loader": "^0.5.5", @@ -20,12 +21,15 @@ "cucumber-html-reporter": "^5.3.0", "cucumber-pretty": "^6.0.0", "eslint": "^7.25.0", + "eslint-config-prettier": "^8.3.0", "eslint-config-standard": "^16.0.2", - "eslint-plugin-import": "^2.22.1", + "eslint-plugin-import": "^2.2.0", "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^3.4.0", "eslint-plugin-promise": "^4.3.1", "grpc": "^1.24.3", "grpc-promise": "^1.4.0", + "husky": "^6.0.0", "prettier": "^2.2.1" }, "dependencies": {