From 9b5827752eaa3965b61f31789cb030e464b6a252 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Thu, 31 Oct 2019 14:37:54 -0700 Subject: [PATCH] feat(full-node): moved full node routes to their own subdir --- package.json | 1 - src/app.js | 10 +- src/routes/v3/{ => full-node}/blockchain.js | 4 +- src/routes/v3/{ => full-node}/control.js | 4 +- src/routes/v3/{ => full-node}/mining.js | 4 +- src/routes/v3/{ => full-node}/network.js | 0 .../v3/{ => full-node}/rawtransactions.js | 4 +- test/v2/address.js | 1373 ----------------- test/v2/block.js | 610 -------- test/v2/blockchain.js | 1148 -------------- test/v2/control.js | 140 -- test/v2/e2e/address.js | 60 - test/v2/helpers/panda.js | 29 - test/v2/integration/README.md | 7 - test/v2/integration/rate-limits.js | 94 -- test/v2/integration/raw-transactions.js | 191 --- test/v2/mining.js | 176 --- test/v2/mocks/address-mock.js | 160 -- test/v2/mocks/block-mock.js | 42 - test/v2/mocks/blockchain-mock.js | 271 ---- test/v2/mocks/control-mock.js | 27 - test/v2/mocks/express-mocks.js | 88 -- test/v2/mocks/mining-mocks.js | 22 - test/v2/mocks/raw-transactions-mocks.js | 157 -- test/v2/mocks/slp-mocks.js | 327 ---- test/v2/mocks/slpjs-mocks.js | 71 - test/v2/mocks/transaction-mocks.js | 74 - test/v2/mocks/util-mocks.js | 18 - test/v2/rate-limits.js | 166 -- test/v2/raw-transactions.js | 807 ---------- test/v2/slp.js | 971 ------------ test/v2/transaction.js | 333 ---- test/v2/util.js | 300 ---- test/v3/blockchain.js | 2 +- test/v3/control.js | 2 +- test/v3/mining.js | 2 +- test/v3/rate-limits.js | 2 +- test/v3/raw-transactions.js | 2 +- 38 files changed, 18 insertions(+), 7681 deletions(-) rename src/routes/v3/{ => full-node}/blockchain.js (99%) rename src/routes/v3/{ => full-node}/control.js (96%) rename src/routes/v3/{ => full-node}/mining.js (97%) rename src/routes/v3/{ => full-node}/network.js (100%) rename src/routes/v3/{ => full-node}/rawtransactions.js (99%) delete mode 100644 test/v2/address.js delete mode 100644 test/v2/block.js delete mode 100644 test/v2/blockchain.js delete mode 100644 test/v2/control.js delete mode 100644 test/v2/e2e/address.js delete mode 100644 test/v2/helpers/panda.js delete mode 100644 test/v2/integration/README.md delete mode 100644 test/v2/integration/rate-limits.js delete mode 100644 test/v2/integration/raw-transactions.js delete mode 100644 test/v2/mining.js delete mode 100644 test/v2/mocks/address-mock.js delete mode 100644 test/v2/mocks/block-mock.js delete mode 100644 test/v2/mocks/blockchain-mock.js delete mode 100644 test/v2/mocks/control-mock.js delete mode 100644 test/v2/mocks/express-mocks.js delete mode 100644 test/v2/mocks/mining-mocks.js delete mode 100644 test/v2/mocks/raw-transactions-mocks.js delete mode 100644 test/v2/mocks/slp-mocks.js delete mode 100644 test/v2/mocks/slpjs-mocks.js delete mode 100644 test/v2/mocks/transaction-mocks.js delete mode 100644 test/v2/mocks/util-mocks.js delete mode 100644 test/v2/rate-limits.js delete mode 100644 test/v2/raw-transactions.js delete mode 100644 test/v2/slp.js delete mode 100644 test/v2/transaction.js delete mode 100644 test/v2/util.js diff --git a/package.json b/package.json index 36617f3..cd1070c 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,6 @@ "start": "node ./src/app.js", "dev": "nodemon ./dist/app.js", "test": "npm run test-v3", - "test-v2": "export NETWORK=testnet && nyc --reporter=text mocha --timeout 25000 test/v2/", "test-v3": "export NETWORK=mainnet && nyc --reporter=text mocha --timeout 25000 test/v3/", "test:integration": "mocha test/v3/integration", "coverage": "nyc report --reporter=text-lcov | coveralls", diff --git a/src/app.js b/src/app.js index f9114df..99a8a29 100644 --- a/src/app.js +++ b/src/app.js @@ -22,11 +22,11 @@ const jwtAuth = require("./middleware/jwt-auth") // v3 const healthCheckV3 = require("./routes/v3/health-check") -const blockchainV3 = require("./routes/v3/blockchain") -const controlV3 = require("./routes/v3/control") -const miningV3 = require("./routes/v3/mining") -const networkV3 = require("./routes/v3/network") -const rawtransactionsV3 = require("./routes/v3/rawtransactions") +const blockchainV3 = require("./routes/v3/full-node/blockchain") +const controlV3 = require("./routes/v3/full-node/control") +const miningV3 = require("./routes/v3/full-node/mining") +const networkV3 = require("./routes/v3/full-node/network") +const rawtransactionsV3 = require("./routes/v3/full-node/rawtransactions") const utilV3 = require("./routes/v3/util") const slpV3 = require("./routes/v3/slp") const xpubV3 = require("./routes/v3/xpub") diff --git a/src/routes/v3/blockchain.js b/src/routes/v3/full-node/blockchain.js similarity index 99% rename from src/routes/v3/blockchain.js rename to src/routes/v3/full-node/blockchain.js index 092e8bf..8e2403b 100644 --- a/src/routes/v3/blockchain.js +++ b/src/routes/v3/full-node/blockchain.js @@ -9,8 +9,8 @@ const express = require("express") const router = express.Router() const axios = require("axios") -const routeUtils = require("./route-utils") -const wlogger = require("../../util/winston-logging") +const routeUtils = require("../route-utils") +const wlogger = require("../../../util/winston-logging") // Used to convert error messages to strings, to safely pass to users. const util = require("util") diff --git a/src/routes/v3/control.js b/src/routes/v3/full-node/control.js similarity index 96% rename from src/routes/v3/control.js rename to src/routes/v3/full-node/control.js index 6a3f6ee..e2e6374 100644 --- a/src/routes/v3/control.js +++ b/src/routes/v3/full-node/control.js @@ -4,8 +4,8 @@ const express = require("express") const router = express.Router() const axios = require("axios") -const routeUtils = require("./route-utils") -const wlogger = require("../../util/winston-logging") +const routeUtils = require("../route-utils") +const wlogger = require("../../../util/winston-logging") // Used for processing error messages before sending them to the user. const util = require("util") diff --git a/src/routes/v3/mining.js b/src/routes/v3/full-node/mining.js similarity index 97% rename from src/routes/v3/mining.js rename to src/routes/v3/full-node/mining.js index 60f48d6..daa6c10 100644 --- a/src/routes/v3/mining.js +++ b/src/routes/v3/full-node/mining.js @@ -4,8 +4,8 @@ const express = require("express") const router = express.Router() const axios = require("axios") -const routeUtils = require("./route-utils") -const wlogger = require("../../util/winston-logging") +const routeUtils = require("../route-utils") +const wlogger = require("../../../util/winston-logging") // Used to convert error messages to strings, to safely pass to users. const util = require("util") diff --git a/src/routes/v3/network.js b/src/routes/v3/full-node/network.js similarity index 100% rename from src/routes/v3/network.js rename to src/routes/v3/full-node/network.js diff --git a/src/routes/v3/rawtransactions.js b/src/routes/v3/full-node/rawtransactions.js similarity index 99% rename from src/routes/v3/rawtransactions.js rename to src/routes/v3/full-node/rawtransactions.js index d72beb9..7ae5998 100644 --- a/src/routes/v3/rawtransactions.js +++ b/src/routes/v3/full-node/rawtransactions.js @@ -4,8 +4,8 @@ const express = require("express") const router = express.Router() const axios = require("axios") -const routeUtils = require("./route-utils") -const wlogger = require("../../util/winston-logging") +const routeUtils = require("../route-utils") +const wlogger = require("../../../util/winston-logging") // Used to convert error messages to strings, to safely pass to users. const util = require("util") diff --git a/test/v2/address.js b/test/v2/address.js deleted file mode 100644 index 070c5d9..0000000 --- a/test/v2/address.js +++ /dev/null @@ -1,1373 +0,0 @@ -/* - TESTS FOR THE ADDRESS.JS LIBRARY - - This test file uses the environment variable TEST to switch between unit - and integration tests. By default, TEST is set to 'unit'. Set this variable - to 'integration' to run the tests against BCH mainnet. - - To-Do: - -/details/:address - --Verify to/from query options work correctly. - -GET /unconfirmed/:address & POST /unconfirmed - --Should initiate a transfer of BCH to verify unconfirmed TX. - ---This would be more of an e2e test. -*/ - -"use strict" - -const chai = require("chai") -const assert = chai.assert -const addressRoute = require("../../src/routes/v2/address") -const nock = require("nock") // HTTP mocking - -let originalUrl // Used during transition from integration to unit tests. - -// Mocking data. -const { mockReq, mockRes } = require("./mocks/express-mocks") -const mockData = require("./mocks/address-mock") - -// Used for debugging. -const util = require("util") -util.inspect.defaultOptions = { depth: 1 } - -describe("#AddressRouter", () => { - let req, res - - before(() => { - originalUrl = process.env.BITCOINCOM_BASEURL - - // Set default environment variables for unit tests. - if (!process.env.TEST) process.env.TEST = "unit" - if (process.env.TEST === "unit") - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - // console.log(`Testing type is: ${process.env.TEST}`) - }) - - // Setup the mocks before each test. - beforeEach(() => { - // Mock the req and res objects used by Express routes. - req = mockReq - res = mockRes - - // Explicitly reset the parmas and body. - req.params = {} - req.body = {} - req.query = {} - - // Activate nock if it's inactive. - if (!nock.isActive()) nock.activate() - }) - - afterEach(() => { - // Clean up HTTP mocks. - nock.cleanAll() // clear interceptor list. - nock.restore() - }) - - after(() => { - process.env.BITCOINCOM_BASEURL = originalUrl - }) - - describe("#root", () => { - // root route handler. - const root = addressRoute.testableComponents.root - - it("should respond to GET for base route", async () => { - const result = root(req, res) - - assert.equal(result.status, "address", "Returns static string") - }) - }) - - describe("#AddressDetailsBulk", () => { - // details route handler. - const detailsBulk = addressRoute.testableComponents.detailsBulk - - it("should throw an error for an empty body", async () => { - req.body = {} - - const result = await detailsBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "addresses needs to be an array", - "Proper error message" - ) - }) - - it("should error on non-array single address", async () => { - req.body = { - address: `qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - } - - const result = await detailsBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "addresses needs to be an array", - "Proper error message" - ) - }) - - it("should throw an error for an invalid address", async () => { - req.body = { - addresses: [`02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - } - - const result = await detailsBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "Invalid BCH address", - "Proper error message" - ) - }) - - it("should throw 400 error if addresses array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.addresses = testArray - - const result = await detailsBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should detect a network mismatch", async () => { - req.body = { - addresses: [`bitcoincash:qqqvv56zepke5k0xeaehlmjtmkv9ly2uzgkxpajdx3`] - } - - const result = await detailsBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid network", "Proper error message") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.body = { - addresses: [`bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`] - } - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - const result = await detailsBulk(req, res) - //console.log(`network issue result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.isAbove(res.statusCode, 499, "HTTP status code 500 expected.") - //assert.include(result.error, "ENOTFOUND", "Error message expected") - assert.include( - result.error, - "Network error: Could not communicate", - "Error message expected" - ) - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should default to page 0", async () => { - req.body = { - addresses: [`bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/addr/mgps7qxk2Z5ma4mXsviznnet8wx4VvMPFz?from=0&to=1000`) - .reply(200, mockData.mockAddressDetails) - } - - // Call the details API. - const result = await detailsBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Assert current page defaults to 0 - assert.equal(result[0].currentPage, 0) - }) - - it("should process the requested page", async () => { - req.body = { - addresses: [`bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`], - page: 5 - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/addr/mgps7qxk2Z5ma4mXsviznnet8wx4VvMPFz?from=5000&to=6000`) - .reply(200, mockData.mockAddressDetails) - } - - // Call the details API. - const result = await detailsBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Assert current page is same as requested - assert.equal(result[0].currentPage, 5) - }) - - it("should calculate the total number of pages", async () => { - req.body = { - addresses: [`bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/addr/mgps7qxk2Z5ma4mXsviznnet8wx4VvMPFz?from=0&to=1000`) - .reply(200, mockData.mockAddressDetails) - } - - // Call the details API. - const result = await detailsBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(result[0].pagesTotal, 1) - }) - - it("should get details for a single address", async () => { - req.body = { - addresses: [`bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/addr/mgps7qxk2Z5ma4mXsviznnet8wx4VvMPFz?from=0&to=1000`) - .reply(200, mockData.mockAddressDetails) - } - - // Call the details API. - const result = await detailsBulk(req, res) - // console.log(`result: ${util.inspect(result)}`) - - // Assert that required fields exist in the returned object. - assert.equal(result.length, 1, "Array with one entry") - assert.hasAllKeys(result[0], [ - "balance", - "balanceSat", - "totalReceived", - "totalReceivedSat", - "totalSent", - "totalSentSat", - "unconfirmedBalance", - "unconfirmedBalanceSat", - "unconfirmedTxApperances", - "txApperances", - "transactions", - "legacyAddress", - "cashAddress", - "currentPage", - "pagesTotal" - ]) - }) - - it("should get details for multiple addresses", async () => { - req.body = { - addresses: [ - `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`, - `bchtest:qzknfggae0av6yvxk77gmyq7syc67yux6sk80haqyr` - ] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/addr/mgps7qxk2Z5ma4mXsviznnet8wx4VvMPFz?from=0&to=1000`) - .reply(200, mockData.mockAddressDetails) - - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/addr/mwJnEzXzKkveF2q5Af9jxi9j1zrtWAnPU8?from=0&to=1000`) - .reply(200, mockData.mockAddressDetails) - } - - // Call the details API. - const result = await detailsBulk(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.equal(result.length, 2, "2 outputs for 2 inputs") - }) - }) - - describe("#AddressDetailsSingle", () => { - // details route handler. - const detailsSingle = addressRoute.testableComponents.detailsSingle - - it("should throw 400 if address is empty", async () => { - const result = await detailsSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "address can not be empty") - }) - - it("should error on an array", async () => { - req.params.address = [`qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - - const result = await detailsSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "address can not be an array", - "Proper error message" - ) - }) - - it("should throw an error for an invalid address", async () => { - req.params.address = `02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - - const result = await detailsSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "Invalid BCH address", - "Proper error message" - ) - }) - - it("should detect a network mismatch", async () => { - req.params.address = `bitcoincash:qqqvv56zepke5k0xeaehlmjtmkv9ly2uzgkxpajdx3` - - const result = await detailsSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid network", "Proper error message") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.params.address = `qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - const result = await detailsSingle(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should default to page 0", async () => { - req.params.address = `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4` - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/addr/mgps7qxk2Z5ma4mXsviznnet8wx4VvMPFz?from=0&to=1000`) - .reply(200, mockData.mockAddressDetails) - } - - // Call the details API. - const result = await detailsSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Assert current page defaults to 0 - assert.equal(result.currentPage, 0) - }) - - it("should process the requested page", async () => { - req.params.address = `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4` - req.query.page = 5 - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/addr/mgps7qxk2Z5ma4mXsviznnet8wx4VvMPFz?from=5000&to=6000`) - .reply(200, mockData.mockAddressDetails) - } - - // Call the details API. - const result = await detailsSingle(req, res) - - // Assert current page is same as requested - assert.equal(result.currentPage, 5) - }) - - it("should calculate the total number of pages", async () => { - req.params.address = `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4` - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/addr/mgps7qxk2Z5ma4mXsviznnet8wx4VvMPFz?from=0&to=1000`) - .reply(200, mockData.mockAddressDetails) - } - - // Call the details API. - const result = await detailsSingle(req, res) - - assert.equal(result.pagesTotal, 1) - }) - - it("should get details for a single address", async () => { - req.params.address = `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4` - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/addr/mgps7qxk2Z5ma4mXsviznnet8wx4VvMPFz?from=0&to=1000`) - .reply(200, mockData.mockAddressDetails) - } - - // Call the details API. - const result = await detailsSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Assert that required fields exist in the returned object. - assert.hasAllKeys(result, [ - "balance", - "balanceSat", - "totalReceived", - "totalReceivedSat", - "totalSent", - "totalSentSat", - "unconfirmedBalance", - "unconfirmedBalanceSat", - "unconfirmedTxApperances", - "txApperances", - "transactions", - "legacyAddress", - "cashAddress", - "currentPage", - "pagesTotal" - ]) - }) - }) - - describe("#AddressUtxoBulk", () => { - // utxo route handler. - const utxoBulk = addressRoute.testableComponents.utxoBulk - - it("should throw an error for an empty body", async () => { - req.body = {} - - const result = await utxoBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "addresses needs to be an array", - "Proper error message" - ) - }) - - it("should error on non-array single address", async () => { - req.body = { - address: `qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - } - - const result = await utxoBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "addresses needs to be an array", - "Proper error message" - ) - }) - - it("should throw an error for an invalid address", async () => { - req.body = { - addresses: [`02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - } - - const result = await utxoBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "Invalid BCH address", - "Proper error message" - ) - }) - - it("should detect a network mismatch", async () => { - req.body = { - addresses: [`bitcoincash:qqqvv56zepke5k0xeaehlmjtmkv9ly2uzgkxpajdx3`] - } - - const result = await utxoBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid network", "Proper error message") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.body = { - addresses: [`qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - } - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api" - - const result = await utxoBulk(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should get utxos for a single address", async () => { - req.body = { - addresses: [`bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/addr/mgps7qxk2Z5ma4mXsviznnet8wx4VvMPFz/utxo`) - .reply(200, mockData.mockUtxoDetails) - } - - // Call the details API. - const result = await utxoBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result, "result should be an array") - - // Each element should have these primary properties. - assert.hasAllKeys(result[0], [ - "utxos", - "legacyAddress", - "cashAddress", - "scriptPubKey" - ]) - - // Validate the UTXO data structure. - assert.hasAnyKeys(result[0].utxos[0], [ - "txid", - "vout", - "amount", - "satoshis", - "height", - "confirmations" - ]) - }) - - it("should get utxos for mulitple addresses", async () => { - req.body = { - addresses: [ - `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`, - `bchtest:qzknfggae0av6yvxk77gmyq7syc67yux6sk80haqyr` - ] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/addr/mgps7qxk2Z5ma4mXsviznnet8wx4VvMPFz/utxo`) - .reply(200, mockData.mockUtxoDetails) - - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/addr/mwJnEzXzKkveF2q5Af9jxi9j1zrtWAnPU8/utxo`) - .reply(200, mockData.mockUtxoDetails) - } - - // Call the details API. - const result = await utxoBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.equal(result.length, 2, "2 outputs for 2 inputs") - }) - - it("should throw 400 error if addresses array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.addresses = testArray - - const result = await utxoBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - }) - - describe("#AddressUtxoSingle", () => { - // details route handler. - const utxoSingle = addressRoute.testableComponents.utxoSingle - - it("should throw 400 if address is empty", async () => { - const result = await utxoSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "address can not be empty") - }) - - it("should error on an array", async () => { - req.params.address = [`qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - - const result = await utxoSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "address can not be an array", - "Proper error message" - ) - }) - - it("should throw an error for an invalid address", async () => { - req.params.address = `02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - - const result = await utxoSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "Invalid BCH address", - "Proper error message" - ) - }) - - it("should detect a network mismatch", async () => { - req.params.address = `bitcoincash:qqqvv56zepke5k0xeaehlmjtmkv9ly2uzgkxpajdx3` - - const result = await utxoSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid network", "Proper error message") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.params.address = `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4` - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - const result = await utxoSingle(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should get details for a single address", async () => { - req.params.address = `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4` - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/addr/mgps7qxk2Z5ma4mXsviznnet8wx4VvMPFz/utxo`) - .reply(200, mockData.mockUtxoDetails) - } - - // Call the details API. - const result = await utxoSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Each element should have these primary properties. - assert.hasAllKeys(result, [ - "utxos", - "legacyAddress", - "cashAddress", - "scriptPubKey" - ]) - - // Validate the UTXO data structure. - assert.hasAnyKeys(result.utxos[0], [ - "txid", - "vout", - "amount", - "satoshis", - "height", - "confirmations" - ]) - }) - }) - - describe("#AddressUnconfirmedBulk", () => { - // unconfirmed route handler. - const unconfirmedBulk = addressRoute.testableComponents.unconfirmedBulk - - it("should throw an error for an empty body", async () => { - req.body = {} - - const result = await unconfirmedBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "addresses needs to be an array", - "Proper error message" - ) - }) - - it("should error on non-array single address", async () => { - req.body = { - address: `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4` - } - - const result = await unconfirmedBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "addresses needs to be an array", - "Proper error message" - ) - }) - - it("should throw 400 error if addresses array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.addresses = testArray - - const result = await unconfirmedBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should throw an error for an invalid address", async () => { - req.body = { - addresses: [`02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - } - - const result = await unconfirmedBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "Invalid BCH address", - "Proper error message" - ) - }) - - it("should detect a network mismatch", async () => { - req.body = { - addresses: [`bitcoincash:qqqvv56zepke5k0xeaehlmjtmkv9ly2uzgkxpajdx3`] - } - - const result = await unconfirmedBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid network", "Proper error message") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.body = { - addresses: [`qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - } - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api" - - const result = await unconfirmedBulk(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should get unconfirmed data for a single address", async () => { - req.body = { - addresses: [`bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/addr/mgps7qxk2Z5ma4mXsviznnet8wx4VvMPFz/utxo`) - .reply(200, mockData.mockUtxoDetails) - } - - // Call the details API. - const result = await unconfirmedBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - //console.log(`result[0].utxos: ${util.inspect(result[0].utxos)}`) - - assert.isArray(result, "result should be an array") - - // Dev note: Unconfirmed TXs are hard to test in an integration test because - // the nature of an unconfirmed transation is transient. It quickly becomes - // confirmed and thus should not show up. - }) - - it("should get unconfirmed data for an array of addresses", async () => { - req.body = { - addresses: [ - `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`, - `bchtest:qzknfggae0av6yvxk77gmyq7syc67yux6sk80haqyr` - ] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/addr/mgps7qxk2Z5ma4mXsviznnet8wx4VvMPFz/utxo`) - .reply(200, mockData.mockUtxoDetails) - - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/addr/mwJnEzXzKkveF2q5Af9jxi9j1zrtWAnPU8/utxo`) - .reply(200, mockData.mockUtxoDetails) - } - - // Call the details API. - const result = await unconfirmedBulk(req, res) - - assert.isArray(result) - }) - }) - - describe("#AddressUnconfirmedSingle", () => { - // details route handler. - const unconfirmedSingle = addressRoute.testableComponents.unconfirmedSingle - - it("should throw 400 if address is empty", async () => { - const result = await unconfirmedSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "address can not be empty") - }) - - it("should error on an array", async () => { - req.params.address = [`qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - - const result = await unconfirmedSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "address can not be an array", - "Proper error message" - ) - }) - - it("should throw an error for an invalid address", async () => { - req.params.address = `02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - - const result = await unconfirmedSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "Invalid BCH address", - "Proper error message" - ) - }) - - it("should detect a network mismatch", async () => { - req.params.address = `bitcoincash:qqqvv56zepke5k0xeaehlmjtmkv9ly2uzgkxpajdx3` - - const result = await unconfirmedSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid network", "Proper error message") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.params.address = `qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - const result = await unconfirmedSingle(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should get details for a single address", async () => { - req.params.address = `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4` - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/addr/mgps7qxk2Z5ma4mXsviznnet8wx4VvMPFz/utxo`) - .reply(200, mockData.mockUtxoDetails) - } - - // Call the details API. - const result = await unconfirmedSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Each element should have these primary properties. - assert.hasAllKeys(result, [ - "utxos", - "legacyAddress", - "cashAddress", - "scriptPubKey" - ]) - - assert.isArray(result.utxos) - }) - }) - - describe("#AddressTransactionsBulk", () => { - // unconfirmed route handler. - const transactionsBulk = addressRoute.testableComponents.transactionsBulk - - it("should throw an error for an empty body", async () => { - req.body = {} - - const result = await transactionsBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "addresses needs to be an array", - "Proper error message" - ) - }) - - it("should error on non-array single address", async () => { - req.body = { - address: `qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - } - - const result = await transactionsBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "addresses needs to be an array", - "Proper error message" - ) - }) - - it("should throw 400 error if addresses array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.addresses = testArray - - const result = await transactionsBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should throw an error for an invalid address", async () => { - req.body = { - addresses: [`02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - } - - const result = await transactionsBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "Invalid BCH address", - "Proper error message" - ) - }) - - it("should detect a network mismatch", async () => { - req.body = { - addresses: [`bitcoincash:qqqvv56zepke5k0xeaehlmjtmkv9ly2uzgkxpajdx3`] - } - - const result = await transactionsBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid network", "Proper error message") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.body = { - addresses: [`qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - } - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api" - - const result = await transactionsBulk(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should default to page 0", async () => { - req.body = { - addresses: [`bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get( - `/txs/?address=bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4&pageNum=0` - ) - .reply(200, mockData.mockTransactions) - } - - // Call the endpoint - const result = await transactionsBulk(req, res) - - // Assert current page defaults to 0 - assert.equal(result[0].currentPage, 0) - }) - - it("should process the requested page", async () => { - req.body = { - addresses: [`bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`], - page: 5 - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get( - `/txs/?address=bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4&pageNum=5` - ) - .reply(200, mockData.mockTransactions) - } - - // Call the endpoint - const result = await transactionsBulk(req, res) - - // Assert current page is same as requested - assert.equal(result[0].currentPage, 5) - }) - - it("should get transactions for a single address", async () => { - req.body = { - addresses: [`bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get( - `/txs/?address=bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4&pageNum=0` - ) - .reply(200, mockData.mockTransactions) - } - - // Call the details API. - const result = await transactionsBulk(req, res) - - assert.isArray(result, "result should be an array") - - assert.exists(result[0].pagesTotal) - assert.exists(result[0].currentPage) - assert.exists(result[0].txs) - assert.isArray(result[0].txs) - assert.exists(result[0].legacyAddress) - assert.exists(result[0].cashAddress) - }) - - it("should get transactions for an array of addresses", async () => { - req.body = { - addresses: [ - `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`, - `bchtest:qzknfggae0av6yvxk77gmyq7syc67yux6sk80haqyr` - ] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get( - `/txs/?address=bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4&pageNum=0` - ) - .reply(200, mockData.mockTransactions) - - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get( - `/txs/?address=bchtest:qzknfggae0av6yvxk77gmyq7syc67yux6sk80haqyr&pageNum=0` - ) - .reply(200, mockData.mockTransactions) - } - - // Call the details API. - const result = await transactionsBulk(req, res) - - assert.isArray(result, "result should be an array") - - assert.equal(result.length, 2, "Array should have 2 elements") - }) - }) - - describe("#AddressTransactionsSingle", () => { - // details route handler. - const transactionsSingle = - addressRoute.testableComponents.transactionsSingle - - it("should throw 400 if address is empty", async () => { - const result = await transactionsSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "address can not be empty") - }) - - it("should error on an array", async () => { - req.params.address = [`qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - - const result = await transactionsSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "address can not be an array", - "Proper error message" - ) - }) - - it("should throw an error for an invalid address", async () => { - req.params.address = `02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - - const result = await transactionsSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "Invalid BCH address", - "Proper error message" - ) - }) - - it("should detect a network mismatch", async () => { - req.params.address = `bitcoincash:qqqvv56zepke5k0xeaehlmjtmkv9ly2uzgkxpajdx3` - - const result = await transactionsSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid network", "Proper error message") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.params.address = `qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - const result = await transactionsSingle(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should default to page 0", async () => { - req.params.address = `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4` - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get( - `/txs/?address=bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4&pageNum=0` - ) - .reply(200, mockData.mockTransactions) - } - - // Call the endpoint - const result = await transactionsSingle(req, res) - - // Assert current page defaults to 0 - assert.equal(result.currentPage, 0) - }) - - it("should process the requested page", async () => { - req.params.address = `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4` - req.query.page = 5 - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get( - `/txs/?address=bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4&pageNum=5` - ) - .reply(200, mockData.mockTransactions) - } - - // Call the endpoint - const result = await transactionsSingle(req, res) - - // Assert current page is same as requested - assert.equal(result.currentPage, 5) - }) - - it("should get details for a single address", async () => { - req.params.address = `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4` - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get( - `/txs/?address=bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4&pageNum=0` - ) - .reply(200, mockData.mockTransactions) - } - - // Call the details API. - const result = await transactionsSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Assert that required fields exist in the returned object. - assert.exists(result.pagesTotal) - assert.exists(result.currentPage) - assert.exists(result.txs) - assert.isArray(result.txs) - assert.exists(result.legacyAddress) - assert.exists(result.cashAddress) - }) - }) - - describe("#AddressFromXPubSingle", () => { - // details route handler. - const fromXPubSingle = addressRoute.testableComponents.fromXPubSingle - - it("should throw 400 if xpub is empty", async () => { - const result = await fromXPubSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "xpub can not be empty") - }) - - it("should error on an array", async () => { - req.params.xpub = [ - `tpubDHTK2jqg73w3GwoiHfAMbMYML1HN8FhrUxD9rFgbSgHXdwwrY6pAFqKDfUHhqw7vreaZty5hPGjb1S7ZPQeMmu6TFHAKfY9tJpYbvaGjPRM` - ] - - const result = await fromXPubSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "xpub can not be an array", - "Proper error message" - ) - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.params.xpub = `tpubDHTK2jqg73w3GwoiHfAMbMYML1HN8FhrUxD9rFgbSgHXdwwrY6pAFqKDfUHhqw7vreaZty5hPGjb1S7ZPQeMmu6TFHAKfY9tJpYbvaGjPRM` - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - const result = await fromXPubSingle(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should create an address from xpub", async () => { - req.params.xpub = `tpubDHTK2jqg73w3GwoiHfAMbMYML1HN8FhrUxD9rFgbSgHXdwwrY6pAFqKDfUHhqw7vreaZty5hPGjb1S7ZPQeMmu6TFHAKfY9tJpYbvaGjPRM` - - // Mock the Insight URL for unit tests. - // TODO add unit test - // if (process.env.TEST === "unit") { - // nock(`${process.env.BITCOINCOM_BASEURL}`) - // .get( - // `/txs/?address=bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4&pageNum=0` - // ) - // .reply(200, mockData.mockTransactions) - // } - - // Call the details API. - const result = await fromXPubSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Assert that required fields exist in the returned object. - assert.exists(result.legacyAddress) - assert.exists(result.cashAddress) - }) - }) -}) diff --git a/test/v2/block.js b/test/v2/block.js deleted file mode 100644 index 3817e62..0000000 --- a/test/v2/block.js +++ /dev/null @@ -1,610 +0,0 @@ -"use strict" - -const blockRoute = require("../../src/routes/v2/block") -const chai = require("chai") -const assert = chai.assert -const nock = require("nock") // HTTP mocking - -let originalEnvVars // Used during transition from integration to unit tests. - -// Mocking data. -const { mockReq, mockRes } = require("./mocks/express-mocks") -const mockData = require("./mocks/block-mock") - -// Used for debugging. -const util = require("util") -util.inspect.defaultOptions = { depth: 1 } - -describe("#Block", () => { - let req, res - - before(() => { - // Save existing environment variables. - originalEnvVars = { - BITCOINCOM_BASEURL: process.env.BITCOINCOM_BASEURL, - RPC_BASEURL: process.env.RPC_BASEURL, - RPC_USERNAME: process.env.RPC_USERNAME, - RPC_PASSWORD: process.env.RPC_PASSWORD - } - - // Set default environment variables for unit tests. - if (!process.env.TEST) process.env.TEST = "unit" - if (process.env.TEST === "unit") { - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - process.env.RPC_BASEURL = "http://fakeurl/api" - process.env.RPC_USERNAME = "fakeusername" - process.env.RPC_PASSWORD = "fakepassword" - } - }) - - // Setup the mocks before each test. - beforeEach(() => { - // Mock the req and res objects used by Express routes. - req = mockReq - res = mockRes - - // Explicitly reset the parmas and body. - req.params = {} - req.body = {} - - // Activate nock if it's inactive. - if (!nock.isActive()) nock.activate() - }) - - afterEach(() => { - // Clean up HTTP mocks. - nock.cleanAll() // clear interceptor list. - nock.restore() - }) - - after(() => { - // Restore any pre-existing environment variables. - process.env.BITCOINCOM_BASEURL = originalEnvVars.BITCOINCOM_BASEURL - process.env.RPC_BASEURL = originalEnvVars.RPC_BASEURL - process.env.RPC_USERNAME = originalEnvVars.RPC_USERNAME - process.env.RPC_PASSWORD = originalEnvVars.RPC_PASSWORD - }) - - describe("#root", () => { - // root route handler. - const root = blockRoute.testableComponents.root - - it("should respond to GET for base route", async () => { - const result = root(req, res) - - assert.equal(result.status, "block", "Returns static string") - }) - }) - - describe("#detailsByHashSingle", () => { - const detailsByHash = blockRoute.testableComponents.detailsByHashSingle - - it("should throw an error for an empty hash", async () => { - req.params.hash = "" - - const result = await detailsByHash(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "hash must not be empty", - "Proper error message" - ) - }) - - it("should throw 50X when network issues", async () => { - // Save the existing RPC URL. - const savedUrl = process.env.BITCOINCOM_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - req.params.hash = "abc123" - const result = await detailsByHash(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.isAbove(res.statusCode, 499, "HTTP status code 50X expected.") - //assert.include(result.error, "ENOTFOUND", "Error message expected") - }) - - it("should throw an error for invalid hash", async () => { - req.params.hash = "abc123" - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/block/${req.params.hash}`) - .reply(404, "Not found") - } - - const result = await detailsByHash(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.include(result.error, "Not found", "Proper error message") - }) - - it("should GET /detailsByHash/:hash", async () => { - req.params.hash = - "00000000000000645dec6503d3f5eafb0d2537a7a28f181d721dec7c44154c79" - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/block/${req.params.hash}`) - .reply(200, mockData.mockBlockDetails) - } - - const result = await detailsByHash(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAnyKeys(result, [ - "hash", - "size", - "height", - "version", - "merkleroot", - "tx", - "time", - "nonce", - "bits", - "difficulty", - "chainwork", - "confirmations", - "previousblockhash", - "nextblockhash", - "reward", - "isMainChain", - "poolInfo" - ]) - assert.isArray(result.tx) - }) - }) - - describe("#detailsByHashBulk", () => { - // details route handler. - const detailsByHashBulk = blockRoute.testableComponents.detailsByHashBulk - - it("should throw an error for an empty body", async () => { - req.body = {} - - const result = await detailsByHashBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "hashes needs to be an array", - "Proper error message" - ) - }) - - it("should error on non-array single address", async () => { - req.body = { - hashes: - "00000000000000645dec6503d3f5eafb0d2537a7a28f181d721dec7c44154c79" - } - - const result = await detailsByHashBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "hashes needs to be an array", - "Proper error message" - ) - }) - - it("should throw 400 error if addresses array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.hashes = testArray - - const result = await detailsByHashBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should throw an error for an invalid hash", async () => { - req.body = { - hashes: [`abc123`] - } - - const result = await detailsByHashBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid hash", "Proper error message") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.body = { - hashes: [ - "00000000000000645dec6503d3f5eafb0d2537a7a28f181d721dec7c44154c79" - ] - } - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - const result = await detailsByHashBulk(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should get details for a single hash", async () => { - req.body = { - hashes: [ - "00000000000000645dec6503d3f5eafb0d2537a7a28f181d721dec7c44154c79" - ] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/block/${req.body.hashes[0]}`) - .reply(200, mockData.mockBlockDetails) - } - - // Call the details API. - const result = await detailsByHashBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Assert that required fields exist in the returned object. - assert.equal(result.length, 1, "Array with one entry") - assert.hasAllKeys(result[0], [ - "bits", - "chainwork", - "confirmations", - "difficulty", - "hash", - "height", - "isMainChain", - "merkleroot", - "nextblockhash", - "nonce", - "poolInfo", - "previousblockhash", - "reward", - "size", - "time", - "tx", - "version" - ]) - }) - - it("should get details for multiple hashes", async () => { - req.body = { - hashes: [ - `00000000000000645dec6503d3f5eafb0d2537a7a28f181d721dec7c44154c79`, - `00000000c2b2c19cf499f57d5b0f724c6df753330d7acc7d4a8ebe412d427bd0` - ] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/block/${req.body.hashes[0]}`) - .reply(200, mockData.mockBlockDetails) - - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/block/${req.body.hashes[1]}`) - .reply(200, mockData.mockBlockDetails) - } - - // Call the details API. - const result = await detailsByHashBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.equal(result.length, 2, "2 outputs for 2 inputs") - }) - - it("should throw an error if hash not found", async () => { - req.body = { - hashes: [ - `00000000000000645dec6503d3f5eafb0d2537a7a28f181d721dec7c44abcdef` - ] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/block/${req.body.hashes[0]}`) - //.reply(404, { error: { message: "Not Found" } }) - .reply(404, "Not found") - } - - const result = await detailsByHashBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(res.statusCode, 404, "HTTP status code 404 expected.") - assert.include(result.error, "Not found", "Proper error message") - }) - }) - - describe("Block Details By Height", () => { - // block route handler. - const detailsByHeight = blockRoute.testableComponents.detailsByHeightSingle - - it("should throw an error for an empty height", async () => { - req.params.height = "" - - const result = await detailsByHeight(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "height must not be empty", - "Proper error message" - ) - }) - - it("should throw 500 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl = process.env.BITCOINCOM_BASEURL - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - process.env.RPC_BASEURL = "http://fakeurl/api/" - - req.params.height = "abc123" - const result = await detailsByHeight(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - process.env.RPC_BASEURL = savedUrl2 - - assert.isAbove( - res.statusCode, - 499, - "HTTP status code 500 or great expected." - ) - //assert.include(result.error, "ENOTFOUND", "Error message expected") - }) - - it("should throw an error for invalid height", async () => { - req.params.height = "abc123" - - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(500, { - error: { - code: -1, - message: "JSON value is not an integer as expected" - } - }) - } - - const result = await detailsByHeight(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "JSON value is not an integer as expected", - "Proper error message" - ) - }) - - it("should GET /detailsByHeight/:height", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockBlockHash }) - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get( - `/block/00000000000000645dec6503d3f5eafb0d2537a7a28f181d721dec7c44154c79` - ) - .reply(200, mockData.mockBlockDetails) - } - - req.params.height = 500000 - - const result = await detailsByHeight(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAnyKeys(result, [ - "hash", - "size", - "height", - "version", - "merkleroot", - "tx", - "time", - "nonce", - "bits", - "difficulty", - "chainwork", - "confirmations", - "previousblockhash", - "nextblockhash", - "reward", - "isMainChain", - "poolInfo" - ]) - assert.isArray(result.tx) - }) - }) - - describe("#detailsByHeightBulk", () => { - // details route handler. - const detailsByHeightBulk = - blockRoute.testableComponents.detailsByHeightBulk - - it("should throw an error for an empty body", async () => { - req.body = {} - - const result = await detailsByHeightBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "heights needs to be an array", - "Proper error message" - ) - }) - - it("should error on non-array single height", async () => { - req.body = { - heights: 500000 - } - - const result = await detailsByHeightBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "heights needs to be an array", - "Proper error message" - ) - }) - - it("should throw 400 error if addresses array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.heights = testArray - - const result = await detailsByHeightBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should throw error for an invalid height", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(500, { - error: { - code: -1, - message: "JSON value is not an integer as expected" - } - }) - } - - req.body.heights = [`abc123`] - - const result = await detailsByHeightBulk(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.body.heights = [`500000`] - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - const result = await detailsByHeightBulk(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should get details for a single height", async () => { - req.body.heights = [`500000`] - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockBlockHash }) - - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/block/${mockData.mockBlockHash}`) - .reply(200, mockData.mockBlockDetails) - } - - // Call the details API. - const result = await detailsByHeightBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Assert that required fields exist in the returned object. - assert.equal(result.length, 1, "Array with one entry") - assert.hasAllKeys(result[0], [ - "bits", - "chainwork", - "confirmations", - "difficulty", - "hash", - "height", - "isMainChain", - "merkleroot", - "nextblockhash", - "nonce", - "poolInfo", - "previousblockhash", - "reward", - "size", - "time", - "tx", - "version" - ]) - }) - - it("should get details for multiple block heights", async () => { - req.body = { - heights: [`500000`, `500001`] - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .times(2) - .reply(200, { result: mockData.mockBlockHash }) - - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/block/${mockData.mockBlockHash}`) - .times(2) - .reply(200, mockData.mockBlockDetails) - } - - // Call the details API. - const result = await detailsByHeightBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.equal(result.length, 2, "2 outputs for 2 inputs") - }) - }) -}) diff --git a/test/v2/blockchain.js b/test/v2/blockchain.js deleted file mode 100644 index a2b4458..0000000 --- a/test/v2/blockchain.js +++ /dev/null @@ -1,1148 +0,0 @@ -/* - TODO: - -getRawMempool - --Add tests for 'verbose' input values - -getMempoolEntry & getMempoolEntryBulk - --Needs e2e test to create unconfirmed tx, for real-world test. -*/ - -"use strict" - -const chai = require("chai") -const assert = chai.assert -const nock = require("nock") // HTTP mocking -const blockchainRoute = require("../../src/routes/v2/blockchain") - -const util = require("util") -util.inspect.defaultOptions = { depth: 1 } - -if (!process.env.TEST) process.env.TEST = "unit" - -// Mocking data. -const { mockReq, mockRes } = require("./mocks/express-mocks") -const mockData = require("./mocks/blockchain-mock") - -let originalEnvVars // Used during transition from integration to unit tests. - -describe("#BlockchainRouter", () => { - let req, res - - // local node will be started in regtest mode on the port 48332 - //before(panda.runLocalNode) - - before(() => { - // Save existing environment variables. - originalEnvVars = { - BITCOINCOM_BASEURL: process.env.BITCOINCOM_BASEURL, - RPC_BASEURL: process.env.RPC_BASEURL, - RPC_USERNAME: process.env.RPC_USERNAME, - RPC_PASSWORD: process.env.RPC_PASSWORD - } - - // Set default environment variables for unit tests. - if (process.env.TEST === "unit") { - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - process.env.RPC_BASEURL = "http://fakeurl/api" - process.env.RPC_USERNAME = "fakeusername" - process.env.RPC_PASSWORD = "fakepassword" - } - }) - - // Setup the mocks before each test. - beforeEach(() => { - // Mock the req and res objects used by Express routes. - req = mockReq - res = mockRes - - // Explicitly reset the parmas and body. - req.params = {} - req.body = {} - - // Activate nock if it's inactive. - if (!nock.isActive()) nock.activate() - }) - - afterEach(() => { - // Clean up HTTP mocks. - nock.cleanAll() // clear interceptor list. - nock.restore() - }) - - after(() => { - // otherwise the panda will run forever - //process.exit() - - // Restore any pre-existing environment variables. - process.env.BITCOINCOM_BASEURL = originalEnvVars.BITCOINCOM_BASEURL - process.env.RPC_BASEURL = originalEnvVars.RPC_BASEURL - process.env.RPC_USERNAME = originalEnvVars.RPC_USERNAME - process.env.RPC_PASSWORD = originalEnvVars.RPC_PASSWORD - }) - - describe("#root", () => { - // root route handler. - const root = blockchainRoute.testableComponents.root - - it("should respond to GET for base route", async () => { - const result = root(req, res) - - assert.equal(result.status, "blockchain", "Returns static string") - }) - }) - - describe("getBestBlockHash()", () => { - // block route handler. - const getBestBlockHash = blockchainRoute.testableComponents.getBestBlockHash - - it("should throw 503 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" - - const result = await getBestBlockHash(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.RPC_BASEURL = savedUrl2 - - assert.equal(res.statusCode, 503, "HTTP status code 503 expected.") - assert.include( - result.error, - "Could not communicate with full node", - "Error message expected" - ) - }) - - it("should GET /getBestBlockHash", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockBlockHash }) - } - - const result = await getBestBlockHash(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isString(result) - assert.equal(result.length, 64, "Hash string is fixed length") - }) - }) - - describe("getBlockchainInfo()", () => { - // block route handler. - const getBlockchainInfo = - blockchainRoute.testableComponents.getBlockchainInfo - - it("should throw 503 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" - - const result = await getBlockchainInfo(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.RPC_BASEURL = savedUrl2 - - assert.equal(res.statusCode, 503, "HTTP status code 503 expected.") - assert.include( - result.error, - "Could not communicate with full node", - "Error message expected" - ) - }) - - it("should GET /getBlockchainInfo", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockBlockchainInfo }) - } - - const result = await getBlockchainInfo(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAnyKeys(result, [ - "chain", - "blocks", - "headers", - "bestblockhash", - "difficulty", - "mediantime", - "verificationprogress", - "chainwork", - "pruned", - "softforks", - "bip9_softforks" - ]) - }) - }) - - describe("getBlockCount()", () => { - // block route handler. - const getBlockCount = blockchainRoute.testableComponents.getBlockCount - - it("should throw 503 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" - - const result = await getBlockCount(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.RPC_BASEURL = savedUrl2 - - assert.equal(res.statusCode, 503, "HTTP status code 503 expected.") - assert.include( - result.error, - "Could not communicate with full node", - "Error message expected" - ) - }) - - it("should GET /getBlockCount", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: 126769 }) - } - - const result = await getBlockCount(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isNumber(result) - }) - }) - - describe("getBlockHeaderSingle()", async () => { - const getBlockHeader = - blockchainRoute.testableComponents.getBlockHeaderSingle - - it("should throw 400 error if hash is missing", async () => { - const result = await getBlockHeader(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "hash can not be empty") - }) - - it("should throw 503 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" - - req.params.hash = - "00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900" - - const result = await getBlockHeader(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.RPC_BASEURL = savedUrl2 - - assert.equal(res.statusCode, 503, "HTTP status code 503 expected.") - assert.include( - result.error, - "Network error: Could not communicate with full node", - "Error message expected" - ) - }) - - it("should GET block header", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { - result: - "0000ff7f7d217c9b7845ea8b50d620c59a1bf7c276566406e9b7bc7e463e0000000000006d70322c0b697c1c81d2744f87f09f1e9780ba5d30338952e2cdc64e60456f8423bb0a5ceafa091a3e843526" - }) - } - - req.params.hash = - "00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900" - - const result = await getBlockHeader(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isString(result) - assert.equal( - result, - "0000ff7f7d217c9b7845ea8b50d620c59a1bf7c276566406e9b7bc7e463e0000000000006d70322c0b697c1c81d2744f87f09f1e9780ba5d30338952e2cdc64e60456f8423bb0a5ceafa091a3e843526" - ) - }) - - it("should GET verbose block header", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockBlockHeader }) - } - - req.query.verbose = true - req.params.hash = - "00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900" - - const result = await getBlockHeader(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, [ - "hash", - "confirmations", - "height", - "version", - "versionHex", - "merkleroot", - "time", - "mediantime", - "nonce", - "bits", - "difficulty", - "chainwork", - "previousblockhash", - "nextblockhash" - ]) - }) - }) - - describe("#getBlockHeaderBulk", () => { - // route handler. - const getBlockHeaderBulk = - blockchainRoute.testableComponents.getBlockHeaderBulk - - it("should throw an error for an empty body", async () => { - req.body = {} - - const result = await getBlockHeaderBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "hashes needs to be an array", - "Proper error message" - ) - }) - - it("should error on non-array single hash", async () => { - req.body.hashes = - "00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900" - - const result = await getBlockHeaderBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "hashes needs to be an array", - "Proper error message" - ) - }) - - it("should throw 400 error if addresses array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.hashes = testArray - - const result = await getBlockHeaderBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should throw a 400 error for an invalid hash", async () => { - req.body.hashes = ["badHash"] - - await getBlockHeaderBulk(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.body.hashes = [ - "00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900" - ] - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - const result = await getBlockHeaderBulk(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should get concise block header for a single hash", async () => { - req.body.hashes = [ - "00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900" - ] - - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockBlockHeaderConcise }) - } - - // Call the details API. - const result = await getBlockHeaderBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Assert that required fields exist in the returned object. - assert.isArray(result) - assert.equal( - result[0], - "0000ff7f7d217c9b7845ea8b50d620c59a1bf7c276566406e9b7bc7e463e0000000000006d70322c0b697c1c81d2744f87f09f1e9780ba5d30338952e2cdc64e60456f8423bb0a5ceafa091a3e843526" - ) - }) - - it("should get verbose block header for a single hash", async () => { - req.body = { - hashes: [ - "00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900" - ], - verbose: true - } - - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockBlockHeader }) - } - - // Call the details API. - const result = await getBlockHeaderBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Assert that required fields exist in the returned object. - assert.isArray(result) - assert.hasAllKeys(result[0], [ - "hash", - "confirmations", - "height", - "version", - "versionHex", - "merkleroot", - "time", - "mediantime", - "nonce", - "bits", - "difficulty", - "chainwork", - "previousblockhash", - "nextblockhash" - ]) - }) - - it("should get details for multiple block heights", async () => { - req.body.hashes = [ - "00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900", - "00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900" - ] - - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .times(2) - .reply(200, { result: mockData.mockBlockHeaderConcise }) - } - - // Call the details API. - const result = await getBlockHeaderBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.equal(result.length, 2, "2 outputs for 2 inputs") - }) - }) - - describe("getChainTips()", () => { - // block route handler. - const getChainTips = blockchainRoute.testableComponents.getChainTips - - it("should throw 503 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" - - const result = await getChainTips(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.RPC_BASEURL = savedUrl2 - - assert.equal(res.statusCode, 503, "HTTP status code 503 expected.") - assert.include( - result.error, - "Could not communicate with full node", - "Error message expected" - ) - }) - - it("should GET /getChainTips", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockChainTips }) - } - - const result = await getChainTips(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAnyKeys(result[0], ["height", "hash", "branchlen", "status"]) - }) - }) - - describe("getDifficulty()", () => { - // block route handler. - const getDifficulty = blockchainRoute.testableComponents.getDifficulty - - it("should throw 503 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" - - const result = await getDifficulty(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.RPC_BASEURL = savedUrl2 - - assert.equal(res.statusCode, 503, "HTTP status code 503 expected.") - assert.include( - result.error, - "Could not communicate with full node", - "Error message expected" - ) - }) - - it("should GET /getDifficulty", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: 4049809.205246544 }) - } - - const result = await getDifficulty(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isNumber(result) - }) - }) - - describe("getMempoolInfo()", () => { - // block route handler. - const getMempoolInfo = blockchainRoute.testableComponents.getMempoolInfo - - it("should throw 503 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" - - const result = await getMempoolInfo(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.RPC_BASEURL = savedUrl2 - - assert.equal(res.statusCode, 503, "HTTP status code 503 expected.") - assert.include( - result.error, - "Could not communicate with full node", - "Error message expected" - ) - }) - - it("should GET /getMempoolInfo", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockMempoolInfo }) - } - - const result = await getMempoolInfo(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAnyKeys(result, [ - "result", - "bytes", - "usage", - "maxmempool", - "mempoolminfree" - ]) - }) - }) - - describe("getRawMempool()", () => { - // block route handler. - const getRawMempool = blockchainRoute.testableComponents.getRawMempool - - it("should throw 503 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" - - const result = await getRawMempool(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.RPC_BASEURL = savedUrl2 - - assert.equal(res.statusCode, 503, "HTTP status code 503 expected.") - assert.include( - result.error, - "Could not communicate with full node", - "Error message expected" - ) - }) - - it("should GET /getMempoolInfo", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockRawMempool }) - } - - const result = await getRawMempool(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - // Not sure what other assertions should be made here. - }) - }) - - describe("getMempoolEntry()", () => { - // block route handler. - const getMempoolEntry = - blockchainRoute.testableComponents.getMempoolEntrySingle - - it("should throw 400 if txid is empty", async () => { - const result = await getMempoolEntry(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "txid can not be empty") - }) - - it("should throw 503 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" - - req.params.txid = `d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde` - - const result = await getMempoolEntry(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.RPC_BASEURL = savedUrl2 - - assert.equal(res.statusCode, 503, "HTTP status code 503 expected.") - assert.include( - result.error, - "Could not communicate with full node", - "Error message expected" - ) - }) - - it("should GET /getMempoolEntry", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: { error: "Transaction not in mempool" } }) - } - - req.params.txid = `d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde` - - const result = await getMempoolEntry(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.isString(result.error) - assert.equal(result.error, "Transaction not in mempool") - }) - }) - - describe("#getMempoolEntryBulk", () => { - // route handler. - const getMempoolEntryBulk = - blockchainRoute.testableComponents.getMempoolEntryBulk - - it("should throw an error for an empty body", async () => { - req.body = {} - - const result = await getMempoolEntryBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "txids needs to be an array", - "Proper error message" - ) - }) - - it("should error on non-array single txid", async () => { - req.body.txids = `d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde` - - const result = await getMempoolEntryBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "txids needs to be an array", - "Proper error message" - ) - }) - - it("should throw 400 error if addresses array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.txids = testArray - - const result = await getMempoolEntryBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - // Only execute on integration tests. - if (process.env.TEST !== "unit") { - // Dev-note: This test passes because it expects an error. TXIDs do not - // stay in the mempool for long, so it does not work well for a unit or - // integration test. - it("should retrieve single mempool entry", async () => { - req.body.txids = [ - `d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde` - ] - - const result = await getMempoolEntryBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.isString(result.error) - assert.equal(result.error, "Transaction not in mempool") - }) - - // Dev-note: This test passes because it expects an error. TXIDs do not - // stay in the mempool for long, so it does not work well for a unit or - // integration test. - it("should retrieve multiple mempool entries", async () => { - req.body.txids = [ - `d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde`, - `d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde` - ] - - const result = await getMempoolEntryBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.isString(result.error) - assert.equal(result.error, "Transaction not in mempool") - }) - } - }) - - describe("getTxOut()", () => { - // block route handler. - const getTxOut = blockchainRoute.testableComponents.getTxOut - - it("should throw 400 if txid is empty", async () => { - const result = await getTxOut(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "txid can not be empty") - }) - - it("should throw 400 if n is empty", async () => { - req.params.txid = `sometxid` - const result = await getTxOut(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "n can not be empty") - }) - - it("should throw 503 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" - - req.params.txid = `d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde` - req.params.n = 0 - - const result = await getTxOut(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.RPC_BASEURL = savedUrl2 - - assert.equal(res.statusCode, 503, "HTTP status code 503 expected.") - assert.include( - result.error, - "Could not communicate with full node", - "Error message expected" - ) - }) - - // This test can only run for unit tests. See TODO at the top of this file. - it("should GET /getTxOut", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockTxOut }) - } - - req.params.txid = `5747e6462e2c452a5d583fd6a5f82866cd8e4a86826c86d9a1842b7d023e0c0c` - req.params.n = 1 - - const result = await getTxOut(req, res) - //console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.hasAllKeys(result, [ - "bestblock", - "confirmations", - "value", - "scriptPubKey", - "coinbase" - ]) - assert.hasAllKeys(result.scriptPubKey, [ - "asm", - "hex", - "reqSigs", - "type", - "addresses" - ]) - assert.isArray(result.scriptPubKey.addresses) - }) - }) - - describe("getTxOutProof()", () => { - const getTxOutProof = blockchainRoute.testableComponents.getTxOutProofSingle - - it("should throw 400 if txid is empty", async () => { - const result = await getTxOutProof(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "txid can not be empty") - }) - - it("should throw 503 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" - - req.params.txid = `d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde` - - const result = await getTxOutProof(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.RPC_BASEURL = savedUrl2 - - assert.equal(res.statusCode, 503, "HTTP status code 503 expected.") - assert.include( - result.error, - "Could not communicate with full node", - "Error message expected" - ) - }) - - it("should GET /getTxOutProof", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockTxOutProof }) - } - - req.params.txid = `d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde` - - const result = await getTxOutProof(req, res) - //console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.isString(result) - }) - }) - - describe("#getTxOutProofBulk", () => { - // route handler. - const getTxOutProofBulk = - blockchainRoute.testableComponents.getTxOutProofBulk - - it("should throw an error for an empty body", async () => { - req.body = {} - - const result = await getTxOutProofBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "txids needs to be an array", - "Proper error message" - ) - }) - - it("should error on non-array single txid", async () => { - req.body.txids = `d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde` - - const result = await getTxOutProofBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "txids needs to be an array", - "Proper error message" - ) - }) - - it("should throw 400 error if addresses array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.txids = testArray - - const result = await getTxOutProofBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should GET proof for single txid", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockTxOutProof }) - } - - req.body.txids = [ - `d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde` - ] - - const result = await getTxOutProofBulk(req, res) - //console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.isArray(result) - assert.isString(result[0]) - }) - - it("should GET proof for multiple txids", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .times(2) - .reply(200, { result: mockData.mockTxOutProof }) - } - - req.body.txids = [ - `d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde`, - `d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde` - ] - - const result = await getTxOutProofBulk(req, res) - //console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.isArray(result) - assert.equal(result.length, 2, "Correct length of returned array") - }) - }) - - describe("verifyTxOutProof()", () => { - const verifyTxOutProof = - blockchainRoute.testableComponents.verifyTxOutProofSingle - - it("should throw 400 if proof is empty", async () => { - const result = await verifyTxOutProof(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "proof can not be empty") - }) - - it("should throw 503 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" - - req.params.proof = mockData.mockTxOutProof - - const result = await verifyTxOutProof(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.RPC_BASEURL = savedUrl2 - - assert.equal(res.statusCode, 503, "HTTP status code 503 expected.") - assert.include( - result.error, - "Could not communicate with full node", - "Error message expected" - ) - }) - - it("should GET /verifyTxOutProof", async () => { - const expected = - "d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde" - - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: [expected] }) - } - - req.params.proof = mockData.mockTxOutProof - - const result = await verifyTxOutProof(req, res) - //console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.isArray(result) - assert.isString(result[0]) - assert.equal(result[0], expected) - }) - }) - - describe("#verifyTxOutProofBulk", () => { - // route handler. - const verifyTxOutProofBulk = - blockchainRoute.testableComponents.verifyTxOutProofBulk - - it("should throw an error for an empty body", async () => { - req.body = {} - - const result = await verifyTxOutProofBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "proofs needs to be an array", - "Proper error message" - ) - }) - - it("should error on non-array single txid", async () => { - req.body.proofs = mockData.mockTxOutProof - - const result = await verifyTxOutProofBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "proofs needs to be an array", - "Proper error message" - ) - }) - - it("should throw 400 error if addresses array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.proofs = testArray - - const result = await verifyTxOutProofBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should get single proof", async () => { - const expected = - "d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde" - - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: [expected] }) - } - - req.body.proofs = [mockData.mockTxOutProof] - - const result = await verifyTxOutProofBulk(req, res) - //console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.isArray(result) - assert.isString(result[0]) - assert.equal(result[0], expected) - }) - - it("should get multiple proofs", async () => { - const expected = - "d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde" - - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .times(2) - .reply(200, { result: [expected] }) - } - - req.body.proofs = [mockData.mockTxOutProof, mockData.mockTxOutProof] - - const result = await verifyTxOutProofBulk(req, res) - //console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.isArray(result) - assert.isString(result[0]) - assert.equal(result[0], expected) - assert.equal(result.length, 2) - }) - }) -}) diff --git a/test/v2/control.js b/test/v2/control.js deleted file mode 100644 index e5deaa9..0000000 --- a/test/v2/control.js +++ /dev/null @@ -1,140 +0,0 @@ -/* - TESTS FOR THE CONTROL.JS LIBRARY - - This test file uses the environment variable TEST to switch between unit - and integration tests. By default, TEST is set to 'unit'. Set this variable - to 'integration' to run the tests against BCH mainnet. - -*/ - -"use strict" - -const chai = require("chai") -const assert = chai.assert -const controlRoute = require("../../src/routes/v2/control") -const nock = require("nock") // HTTP mocking - -let originalEnvVars // Used during transition from integration to unit tests. - -// Mocking data. -const { mockReq, mockRes } = require("./mocks/express-mocks") -const mockData = require("./mocks/control-mock") - -// Used for debugging. -const util = require("util") -util.inspect.defaultOptions = { depth: 1 } - -describe("#ControlRouter", () => { - let req, res - - before(() => { - // Save existing environment variables. - originalEnvVars = { - BITCOINCOM_BASEURL: process.env.BITCOINCOM_BASEURL, - RPC_BASEURL: process.env.RPC_BASEURL, - RPC_USERNAME: process.env.RPC_USERNAME, - RPC_PASSWORD: process.env.RPC_PASSWORD - } - - // Set default environment variables for unit tests. - if (!process.env.TEST) process.env.TEST = "unit" - if (process.env.TEST === "unit") { - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - process.env.RPC_BASEURL = "http://fakeurl/api" - process.env.RPC_USERNAME = "fakeusername" - process.env.RPC_PASSWORD = "fakepassword" - } - }) - - // Setup the mocks before each test. - beforeEach(() => { - // Mock the req and res objects used by Express routes. - req = mockReq - res = mockRes - - // Explicitly reset the parmas and body. - req.params = {} - req.body = {} - req.query = {} - - // Activate nock if it's inactive. - if (!nock.isActive()) nock.activate() - }) - - afterEach(() => { - // Clean up HTTP mocks. - nock.cleanAll() // clear interceptor list. - nock.restore() - }) - - after(() => { - // Restore any pre-existing environment variables. - process.env.BITCOINCOM_BASEURL = originalEnvVars.BITCOINCOM_BASEURL - process.env.RPC_BASEURL = originalEnvVars.RPC_BASEURL - process.env.RPC_USERNAME = originalEnvVars.RPC_USERNAME - process.env.RPC_PASSWORD = originalEnvVars.RPC_PASSWORD - }) - - describe("#root", async () => { - // root route handler. - const root = controlRoute.testableComponents.root - - it("should respond to GET for base route", async () => { - const result = root(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(result.status, "control", "Returns static string") - }) - }) - - describe("#GetInfo", () => { - const getInfo = controlRoute.testableComponents.getInfo - - it("should throw 500 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" - - const result = await getInfo(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.RPC_BASEURL = savedUrl - - assert.isAbove( - res.statusCode, - 499, - "HTTP status code 500 or greater expected." - ) - //assert.include(result.error, "ENOTFOUND", "Error message expected") - }) - - it("should get info on the full node", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockGetInfo }) - } - - const result = await getInfo(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAnyKeys(result, [ - "version", - "protocolversion", - "blocks", - "timeoffset", - "connections", - "proxy", - "difficulty", - "testnet", - "paytxfee", - "relayfee", - "errors" - ]) - }) - }) -}) diff --git a/test/v2/e2e/address.js b/test/v2/e2e/address.js deleted file mode 100644 index 878ad9e..0000000 --- a/test/v2/e2e/address.js +++ /dev/null @@ -1,60 +0,0 @@ -/* - End-to-end tests for the Address endpoint. - These tests assume that the repo is running locally and pointed at TESTNET -*/ - -"use strict" - -const rp = require("request-promise") - -const rawtransactions = require("../../../dist/routes/v2/address") - -/* - This unconfirmed utxo test needs to be expanded in the future to automatically - create a transaction. For now, that is done manually and the address provided - as a constant. - - 1. Start rest running locally, pointed at TESTNET. - 2. Fund each address with a small amount of tBCH - 3. Run this program with `node address.js` - 4. If successful, it will return the unconfirmed UTXOs. -*/ -const addr1 = "bchtest:qpdcp5pv7qphu5tsjfgwezld9n9aq9ue6swgqpf45c" -const addr2 = "bchtest:qzpvx999fagau0xqmvu3xvll9evapge7u5hcgeknzv" - -async function testSingleUnconfirmed() { - try { - const options = { - method: "GET", - uri: `http://localhost:3000/v2/address/unconfirmed/${addr1}`, - resolveWithFullResponse: true, - json: true - } - - const result = await rp(options) - // console.log(`result.body: ${JSON.stringify(result.body, null, 2)}`) - } catch (err) { - // console.log(`Error: `, err) - } -} -testSingleUnconfirmed() - -async function testDoubleUnconfirmed() { - try { - const options = { - method: "POST", - uri: `http://localhost:3000/v2/address/unconfirmed`, - resolveWithFullResponse: true, - json: true, - body: { - addresses: [addr1, addr2] - } - } - - const result = await rp(options) - // console.log(`result.body: ${JSON.stringify(result.body, null, 2)}`) - } catch (err) { - // console.log(`Error: `, err) - } -} -testDoubleUnconfirmed() diff --git a/test/v2/helpers/panda.js b/test/v2/helpers/panda.js deleted file mode 100644 index 48a7d7f..0000000 --- a/test/v2/helpers/panda.js +++ /dev/null @@ -1,29 +0,0 @@ -"use strict" - -/** - * Read more about panda here: https://panda-suite.github.io/ - */ -const panda = require("pandacash-core") - -const runLocalNode = done => { - const server = panda.server({ - // always the same mnemonic - // mnemonic: "cigar magnet ocean purchase travel damp snack alone theme budget wagon wrong", - seedAccounts: true, - enableLogs: false, - debug: false - }) - - server.listen({ - port: 48332, - walletPort: 48333, - }, (err, pandaCashCore) => { - if (err) return console.error(err) - - done() - }) -} - -module.exports = { - runLocalNode -} diff --git a/test/v2/integration/README.md b/test/v2/integration/README.md deleted file mode 100644 index 3bd22f8..0000000 --- a/test/v2/integration/README.md +++ /dev/null @@ -1,7 +0,0 @@ -This directory contains integration tests. To run them requires that -a local copy of rest.bitcoin.com is running. The tests in this directory are -exactly the same calls that end users would use for their app to interact -directly with rest.bitcoin.com. - -At present, this directory focuses on raw-transations. But more integration tests -will be added. diff --git a/test/v2/integration/rate-limits.js b/test/v2/integration/rate-limits.js deleted file mode 100644 index b61c25e..0000000 --- a/test/v2/integration/rate-limits.js +++ /dev/null @@ -1,94 +0,0 @@ -/* - */ - -"use strict" - -const chai = require("chai") -const assert = chai.assert -const axios = require("axios") - -// Used for debugging. -const util = require("util") -util.inspect.defaultOptions = { depth: 1 } - -const SERVER = `https://rest.btctest.net/v2/` -//const SERVER = `http://localhost:3000/v2/` - -describe("#rate limits", () => { - it("should get control/getInfo() with no auth", async () => { - const options = { - method: "GET", - url: `${SERVER}control/getInfo` - } - - const result = await axios(options) - //console.log(`result.status: ${result.status}`) - //console.log(`result.data: ${util.inspect(result.data)}`) - - assert.equal(result.status, 200) - assert.hasAnyKeys(result.data, ["version"]) - }) - - it("should trigger rate-limit handler if rate limits exceeds 60 request per minute", async () => { - try { - // Actual rate limit is 60 per minute X 4 nodes = 240 rpm. - const options = { - method: "GET", - url: `${SERVER}control/getInfo` - } - - const promises = [] - for (let i = 0; i < 250; i++) { - const promise = axios(options) - promises.push(promise) - } - - await Promise.all(promises) - - assert.equal(true, false, "Unexpected result!") - } catch (err) { - //console.log(`err.response: ${util.inspect(err.response)}`) - - assert.equal(err.response.status, 429) - assert.include(err.response.data.error, "Too many requests") - } - }) - - it("should not trigger rate-limit handler if correct pro-tier password is used", async () => { - try { - const username = "BITBOX" - - // Pro-tier is accessed by using the right password. - const password = "BITBOX" - //const password = "something" - - const combined = `${username}:${password}` - const base64Credential = Buffer.from(combined).toString("base64") - const readyCredential = `Basic ${base64Credential}` - - const options = { - method: "GET", - url: `${SERVER}control/getInfo`, - headers: { Authorization: readyCredential } - } - - const promises = [] - for (let i = 0; i < 250; i++) { - const promise = axios(options) - promises.push(promise) - } - - await Promise.all(promises) - - assert.equal(true, true, "Not throwing an error is a pass!") - } catch (err) { - // console.log(`err.response: ${util.inspect(err.response)}`) - - assert.equal( - true, - false, - "This error handler should not have been triggered. Is the password correct?" - ) - } - }) -}) diff --git a/test/v2/integration/raw-transactions.js b/test/v2/integration/raw-transactions.js deleted file mode 100644 index 7c17347..0000000 --- a/test/v2/integration/raw-transactions.js +++ /dev/null @@ -1,191 +0,0 @@ -/* - These integration tests are intended to be run against a live local copy of - rest.bitcoin.com. They exercise the endpoints in the same way the SDK or - end-user application would. These tests were created to replace the parts - removed from the swagger UI, that otherwise would have excersiced these endpoints. - - TODO: - -/rawtransactions/sendRawTransaction is more appropropriate for an e2e test, - so it is omitted here. -*/ - -"use strict" - -const chai = require("chai") -const assert = chai.assert -const rawtransactions = require("../../../dist/routes/v2/rawtransactions") -const rp = require("request-promise") - -// Used for debugging. -const util = require("util") -util.inspect.defaultOptions = { depth: 1 } - -const mockData = require("../mocks/raw-transactions-mocks") - -describe("#Raw-Transactions", () => { - describe("#root", () => { - it(`should return root`, async () => { - const options = { - method: "GET", - uri: `http://localhost:3000/v2/rawtransactions/`, - resolveWithFullResponse: true, - json: true - } - - const result = await rp(options) - //console.log(`result: ${JSON.stringify(result, null, 0)}`) - - assert.equal(result.body.status, "rawtransactions") - }) - }) - - describe("#whCreateTx", () => { - it(`should return tx hex`, async () => { - const minIn = { - txid: - "f7ed9cf23dee85910f6269c9a101a75fcfd2f3c6fc81f17fad824ff7aaf99ab2", - vout: 1 - } - - const options = { - method: "PUT", - uri: `http://localhost:3000/v2/rawtransactions/create`, - resolveWithFullResponse: true, - json: true, - body: { - //inputs: [mockData.mockWHCreateInput], - inputs: [minIn], - outputs: {} - } - } - - const result = await rp(options) - //console.log(`result.body: ${JSON.stringify(result.body, null, 0)}`) - - assert.equal( - result.body, - "0200000001b29af9aaf74f82ad7ff181fcc6f3d2cf5fa701a1c969620f9185ee3df29cedf70100000000ffffffff0000000000" - ) - }) - }) - - describe("#whOpReturn", () => { - it(`should return tx hex`, async () => { - const options = { - method: "PUT", - uri: `http://localhost:3000/v2/rawtransactions/opreturn`, - resolveWithFullResponse: true, - json: true, - body: { - rawtx: "01000000000000000000", - payload: "00000000000000020000000006dac2c0" - } - } - - const result = await rp(options) - //console.log(`result.body: ${JSON.stringify(result.body, null, 0)}`) - - assert.equal( - result.body, - "0100000000010000000000000000166a140877686300000000000000020000000006dac2c000000000" - ) - }) - }) - - describe("#whReference", () => { - it(`should return tx hex`, async () => { - const options = { - method: "PUT", - uri: `http://localhost:3000/v2/rawtransactions/reference`, - resolveWithFullResponse: true, - json: true, - body: { - rawtx: - "0100000001a7a9402ecd77f3c9f745793c9ec805bfa2e14b89877581c734c774864247e6f50400000000ffffffff03aa0a0000000000001976a9146d18edfe073d53f84dd491dae1379f8fb0dfe5d488ac5c0d0000000000004751210252ce4bdd3ce38b4ebbc5a6e1343608230da508ff12d23d85b58c964204c4cef3210294cc195fc096f87d0f813a337ae7e5f961b1c8a18f1f8604a909b3a5121f065b52aeaa0a0000000000001976a914946cb2e08075bcbaf157e47bcb67eb2b2339d24288ac00000000", - destination: "bitcoincash:qrn60nerx5zug4u4hal06atep3lzhtecvy4pxk75lf", - amount: 0.005 - } - } - - const result = await rp(options) - //console.log(`result.body: ${JSON.stringify(result.body, null, 0)}`) - - assert.isString(result.body) - }) - }) - - describe("#whChangeOutput", () => { - it(`should return tx hex`, async () => { - const options = { - method: "PUT", - uri: `http://localhost:3000/v2/rawtransactions/change`, - resolveWithFullResponse: true, - json: true, - body: { - rawtx: - "0100000001b15ee60431ef57ec682790dec5a3c0d83a0c360633ea8308fbf6d5fc10a779670400000000ffffffff025c0d00000000000047512102f3e471222bb57a7d416c82bf81c627bfcd2bdc47f36e763ae69935bba4601ece21021580b888ff56feb27f17f08802ebed26258c23697d6a462d43fc13b565fda2dd52aeaa0a0000000000001976a914946cb2e08075bcbaf157e47bcb67eb2b2339d24288ac00000000", - destination: "bitcoincash:qrn60nerx5zug4u4hal06atep3lzhtecvy4pxk75lf", - prevtxs: [ - { - txid: - "6779a710fcd5f6fb0883ea3306360c3ad8c0a3c5de902768ec57ef3104e65eb1", - vout: 4, - scriptPubKey: - "76a9147b25205fd98d462880a3e5b0541235831ae959e588ac", - value: 0.00068257 - } - ], - fee: 0.000035 - } - } - - const result = await rp(options) - //console.log(`result.body: ${JSON.stringify(result.body, null, 0)}`) - - assert.isString(result.body) - }) - }) - - describe("#whInput", () => { - it(`should return tx hex`, async () => { - const options = { - method: "PUT", - uri: `http://localhost:3000/v2/rawtransactions/input`, - resolveWithFullResponse: true, - json: true, - body: { - txid: - "b006729017df05eda586df9ad3f8ccfee5be340aadf88155b784d1fc0e8342ee", - n: 0 - } - } - - const result = await rp(options) - //console.log(`result.body: ${JSON.stringify(result.body, null, 0)}`) - - assert.isString(result.body) - }) - }) - - describe("#getRawTransaction", () => { - it(`should return tx hex`, async () => { - const options = { - method: "POST", - uri: `http://localhost:3000/v2/rawtransactions/getRawTransaction`, - resolveWithFullResponse: true, - json: true, - body: { - txids: [ - "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098" - ], - verbose: true - } - } - - const result = await rp(options) - // console.log(`result.body: ${util.inspect(result.body)}`) - - assert.isArray(result.body) - }) - }) -}) diff --git a/test/v2/mining.js b/test/v2/mining.js deleted file mode 100644 index 14e1163..0000000 --- a/test/v2/mining.js +++ /dev/null @@ -1,176 +0,0 @@ -/* - TESTS FOR THE MINING.TS LIBRARY - - This test file uses the environment variable TEST to switch between unit - and integration tests. By default, TEST is set to 'unit'. Set this variable - to 'integration' to run the tests against BCH mainnet. -*/ - -"use strict" - -const chai = require("chai") -const assert = chai.assert -const miningRoute = require("../../src/routes/v2/mining") -const nock = require("nock") // HTTP mocking - -let originalEnvVars // Used during transition from integration to unit tests. - -// Mocking data. -const { mockReq, mockRes } = require("./mocks/express-mocks") -const mockData = require("./mocks/mining-mocks") - -// Used for debugging. -const util = require("util") -util.inspect.defaultOptions = { depth: 1 } - -describe("#Mining", () => { - let req, res - - before(() => { - // Save existing environment variables. - originalEnvVars = { - BITCOINCOM_BASEURL: process.env.BITCOINCOM_BASEURL, - RPC_BASEURL: process.env.RPC_BASEURL, - RPC_USERNAME: process.env.RPC_USERNAME, - RPC_PASSWORD: process.env.RPC_PASSWORD - } - - // Set default environment variables for unit tests. - if (!process.env.TEST) process.env.TEST = "unit" - if (process.env.TEST === "unit") { - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - process.env.RPC_BASEURL = "http://fakeurl/api" - process.env.RPC_USERNAME = "fakeusername" - process.env.RPC_PASSWORD = "fakepassword" - } - }) - - // Setup the mocks before each test. - beforeEach(() => { - // Mock the req and res objects used by Express routes. - req = mockReq - res = mockRes - - // Explicitly reset the parmas and body. - req.params = {} - req.body = {} - req.query = {} - - // Activate nock if it's inactive. - if (!nock.isActive()) nock.activate() - }) - - afterEach(() => { - // Clean up HTTP mocks. - nock.cleanAll() // clear interceptor list. - nock.restore() - }) - - after(() => { - // Restore any pre-existing environment variables. - process.env.BITCOINCOM_BASEURL = originalEnvVars.BITCOINCOM_BASEURL - process.env.RPC_BASEURL = originalEnvVars.RPC_BASEURL - process.env.RPC_USERNAME = originalEnvVars.RPC_USERNAME - process.env.RPC_PASSWORD = originalEnvVars.RPC_PASSWORD - }) - - describe("#root", async () => { - // root route handler. - const root = miningRoute.testableComponents.root - - it("should respond to GET for base route", async () => { - const result = root(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(result.status, "mining", "Returns static string") - }) - }) - - describe("#getMiningInfo", async () => { - const getMiningInfo = miningRoute.testableComponents.getMiningInfo - - it("should throw 503 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" - - const result = await getMiningInfo(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.RPC_BASEURL = savedUrl2 - - assert.isAbove( - res.statusCode, - 499, - "HTTP status code 500 or greater expected." - ) - //assert.include(result.error,"Network error: Could not communicate with full node","Error message expected") - }) - - it("should GET mining information", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockMiningInfo }) - } - - const result = await getMiningInfo(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, [ - "blocks", - "currentblocksize", - "currentblocktx", - "difficulty", - "blockprioritypercentage", - "errors", - "networkhashps", - "pooledtx", - "chain" - ]) - }) - }) - - describe("#getNetworkHashPS", async () => { - const getNetworkHashPS = miningRoute.testableComponents.getNetworkHashPS - - it("should throw 503 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" - - const result = await getNetworkHashPS(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.RPC_BASEURL = savedUrl2 - - assert.isAbove( - res.statusCode, - 499, - "HTTP status code 500 or greater expected." - ) - //assert.include(result.error,"Network error: Could not communicate with full node","Error message expected") - }) - - it("should GET Network Hash per second", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: 517604755.6648782 }) - } - - const result = await getNetworkHashPS(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isNumber(result) - }) - }) -}) diff --git a/test/v2/mocks/address-mock.js b/test/v2/mocks/address-mock.js deleted file mode 100644 index 7d4e3b9..0000000 --- a/test/v2/mocks/address-mock.js +++ /dev/null @@ -1,160 +0,0 @@ -/* - This library contains mocking data for running unit tests on the address route. -*/ - -"use strict" - -const mockAddressDetails = { - addrStr: "1Fg4r9iDrEkCcDmHTy2T79EusNfhyQpu7W", - balance: 0.00126419, - balanceSat: 126419, - totalReceived: 0.02175868, - totalReceivedSat: 2175868, - totalSent: 0.02049449, - totalSentSat: 2049449, - unconfirmedBalance: 0, - unconfirmedBalanceSat: 0, - unconfirmedTxApperances: 0, - txApperances: 3, - transactions: [ - "2dc053f55a666a3d2a08b1c680b704d62a55506d14ad884add87edcc56b9277d", - "544c15ce35c0f2e808d28f29d6587f1ec9276233e29856b7f2938cf0daef0026", - "81039b1d7b855b133f359f9dc65f776bd105650153a941675fedc504228ddbd3" - ], - legacyAddress: "1Fg4r9iDrEkCcDmHTy2T79EusNfhyQpu7W", - cashAddress: "bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c" -} - -const mockUtxoDetails = [ - { - txid: "15f6a584080b04911121fbaca7bfcf3dd64ef2bfa5a01daf31e05a296c3e5e9e", - vout: 286, - amount: 0.00001, - satoshis: 1000, - height: 546083, - confirmations: 3490 - }, - { - txid: "15f6a584080b04911121fbaca7bfcf3dd64ef2bfa5a01daf31e05a296c3e5e9e", - vout: 287, - amount: 0.00001, - satoshis: 1000, - height: 546083, - confirmations: 3490 - }, - { - txid: "15f6a584080b04911121fbaca7bfcf3dd64ef2bfa5a01daf31e05a296c3e5e9e", - vout: 288, - amount: 0.00001, - satoshis: 1000, - height: 546083, - confirmations: 3490 - } -] - -const mockUnconfirmed = [ - { - address: "1EzdL6TBbkNhnB2fYiBaKmcs5fxaoqwdAp", - txid: "000c00a90fb5031da6e02f7625df2f8b35a4c16e6feb9fc72293e67e5ff75786", - vout: 0, - scriptPubKey: "76a914997fabcd94a1e2aaa13a7664362e5e7b96c169a988ac", - amount: 0.00999626, - satoshis: 999626, - confirmations: 0, - ts: 1537989425 - } -] - -const mockTransactions = { - pagesTotal: 1, - txs: [ - { - txid: "000c00a90fb5031da6e02f7625df2f8b35a4c16e6feb9fc72293e67e5ff75786", - version: 2, - locktime: 549565, - vin: [ - { - txid: - "45c891c6d44619fc85716ba1b593aa83ebc1e500fe611b1ab98531ea203a0f21", - vout: 209, - sequence: 4294967294, - n: 0, - scriptSig: { - hex: - "47304402205b136f348bedae61a87c0500979d47ab02c76f0e4aba866b94c4931fccb5d7dc0220757a141660475b0cd4cb8b1f54b1ace95105f5bea775e817b115fb589fe4477541210246daec651c506f353daa7468714399c773df42ac4d663022d0e446a3331ac64a", - asm: - "304402205b136f348bedae61a87c0500979d47ab02c76f0e4aba866b94c4931fccb5d7dc0220757a141660475b0cd4cb8b1f54b1ace95105f5bea775e817b115fb589fe44775[ALL|FORKID] 0246daec651c506f353daa7468714399c773df42ac4d663022d0e446a3331ac64a" - }, - addr: "14TdovsQUL69xL5g3zSzhLpmDb93d9rU9m", - valueSat: 1979534, - value: 0.01979534, - doubleSpentTxID: null - }, - { - txid: - "6e5fa79547112a912adf6082c975dc80e282045193512ea369adb6bac7420674", - vout: 147, - sequence: 4294967294, - n: 1, - scriptSig: { - hex: - "473044022056674ac83a37d54ffec2c6d33cfc2ae2256f821b8bd818e1b6783356b49f3d28022046d3dd147c8fc51f2da5d16996a3cea1d7314e327aa1ae1017418737ed20136a4121038f23af565f68d8455e07e5c33c5cfc5114de2f478f035db23eb02f8ff5fe7f6e", - asm: - "3044022056674ac83a37d54ffec2c6d33cfc2ae2256f821b8bd818e1b6783356b49f3d28022046d3dd147c8fc51f2da5d16996a3cea1d7314e327aa1ae1017418737ed20136a[ALL|FORKID] 038f23af565f68d8455e07e5c33c5cfc5114de2f478f035db23eb02f8ff5fe7f6e" - }, - addr: "1CEtC2fjELvmAzTd6MWuHb1gvuSq8x3Xpb", - valueSat: 10466, - value: 0.00010466, - doubleSpentTxID: null - } - ], - vout: [ - { - value: "0.00999626", - n: 0, - scriptPubKey: { - hex: "76a914997fabcd94a1e2aaa13a7664362e5e7b96c169a988ac", - asm: - "OP_DUP OP_HASH160 997fabcd94a1e2aaa13a7664362e5e7b96c169a9 OP_EQUALVERIFY OP_CHECKSIG", - addresses: ["1EzdL6TBbkNhnB2fYiBaKmcs5fxaoqwdAp"], - type: "pubkeyhash" - }, - spentTxId: null, - spentIndex: null, - spentHeight: null - }, - { - value: "0.00990000", - n: 1, - scriptPubKey: { - hex: "76a914e3335e4d6babe61ea58311293c1c6bfe802801cb88ac", - asm: - "OP_DUP OP_HASH160 e3335e4d6babe61ea58311293c1c6bfe802801cb OP_EQUALVERIFY OP_CHECKSIG", - addresses: ["1MiKvgaQTFCTEZbSDMZgw9ahaB52Cr4ofb"], - type: "pubkeyhash" - }, - spentTxId: null, - spentIndex: null, - spentHeight: null - } - ], - blockhash: - "00000000000000000158b1a2883688873ec5ea076e3b0f576bcdfe1fd277880f", - blockheight: 549601, - confirmations: 5, - time: 1537990026, - blocktime: 1537990026, - valueOut: 0.01989626, - size: 372, - valueIn: 0.0199, - fees: 0.00000374 - } - ] -} - -module.exports = { - mockAddressDetails, - mockUtxoDetails, - mockUnconfirmed, - mockTransactions -} diff --git a/test/v2/mocks/block-mock.js b/test/v2/mocks/block-mock.js deleted file mode 100644 index 069b90d..0000000 --- a/test/v2/mocks/block-mock.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - This library contains mocking data for running unit tests on the address route. -*/ - -"use strict" - -const mockBlockDetails = { - hash: "00000000000000645dec6503d3f5eafb0d2537a7a28f181d721dec7c44154c79", - size: 1319, - height: 1267544, - version: 536870912, - merkleroot: - "c2cd01ec2cf149acc7631385f89ae103d1a2ad212ab810c862d9680a811618ce", - tx: [ - "52bfa89d449fef8070ec33e7a61f5ec8b5417ff62b050cd6a144ebce9557e0fa", - "8988e8742d2523f667c2d1374861919e3a82903e059fec75c10795da2303b93b", - "41def004f22b196d675566a6983ecf97611e72c48375b8ba779983d5ccd369d7", - "8ca8efb06abb94395f8331f87e101504dcf66aee828f2111922f056971fa7502", - "9ab409cbb203be7cf22bd6598d787fcdd5b417d885b72207ecc7253470770649" - ], - time: 1542048973, - nonce: 3936284753, - bits: "1a03c148", - difficulty: 4467892.99177529, - chainwork: "00000000000000000000000000000000000000000000003ee27b503a064045bd", - confirmations: 3, - previousblockhash: - "00000000000001891202cbe18729a02a8763cf04da0ca7aded6e6c7d9b500785", - nextblockhash: - "000000000000039b93b3f3403a0eb21150904b15229d998cf3788fd8bf192cc2", - reward: 0.78125, - isMainChain: true, - poolInfo: {} -} - -const mockBlockHash = - "00000000000000645dec6503d3f5eafb0d2537a7a28f181d721dec7c44154c79" - -module.exports = { - mockBlockDetails, - mockBlockHash -} diff --git a/test/v2/mocks/blockchain-mock.js b/test/v2/mocks/blockchain-mock.js deleted file mode 100644 index 6025583..0000000 --- a/test/v2/mocks/blockchain-mock.js +++ /dev/null @@ -1,271 +0,0 @@ -/* - This library contains mocking data for running unit tests on the address route. -*/ - -"use strict" - -const mockBlockHash = - "00000000000000645dec6503d3f5eafb0d2537a7a28f181d721dec7c44154c79" - -const mockBlockchainInfo = { - chain: "test", - blocks: 1267694, - headers: 1267694, - bestblockhash: - "000000000000013eaf80d1e157e32804c36a58ad0bb26ca59833880c80298780", - difficulty: 4105763.969035785, - mediantime: 1542131305, - verificationprogress: 0.9999968911571566, - chainwork: "00000000000000000000000000000000000000000000003f0443b0b5f02ce255", - pruned: false, - softforks: [ - { id: "bip34", version: 2, reject: { status: true } }, - { id: "bip66", version: 3, reject: { status: true } }, - { id: "bip65", version: 4, reject: { status: true } } - ], - bip9_softforks: { - csv: { - status: "active", - startTime: 1456790400, - timeout: 1493596800, - since: 770112 - } - } -} - -const mockChainTips = [ - { - height: 1267696, - hash: "000000000000035bfc43a642ebbff8cfc1e88b1d564de8b0a6c7e2797eeafb21", - branchlen: 0, - status: "active" - }, - { - height: 1267581, - hash: "000000000001bd12e4124207682563135b21353ca3087bc6b0c409f7f9e1da91", - branchlen: 1, - status: "valid-fork" - }, - { - height: 1267375, - hash: "00000000702036979df70236bcc45dfc72d43d5d0e6834007afa1fa627e49587", - branchlen: 1036, - status: "headers-only" - }, - { - height: 1266979, - hash: "00000000e851abbde2174ccdc5c2508b909f81f23c4b7abeac864eee1a4891c7", - branchlen: 1, - status: "valid-fork" - }, - { - height: 1266973, - hash: "000000007e1324d2900ed70947f89ab8fd4a267e87c9244c333215659a7370d5", - branchlen: 1, - status: "valid-fork" - }, - { - height: 1266967, - hash: "000000000f37f12843d4800f50ec4de44dce0432e4d448242d43ff04a7a2948d", - branchlen: 1, - status: "valid-fork" - }, - { - height: 1266963, - hash: "00000000ae11ec99e88898cbd72567cb4cb79e7fc13243357bef79632769deb4", - branchlen: 1, - status: "valid-fork" - }, - { - height: 1266962, - hash: "000000004f97851259b4460a049e44fa5bd4beadee04a85bf81bd2e90c4f24f9", - branchlen: 1, - status: "valid-fork" - }, - { - height: 1266950, - hash: "00000000d12a0e4a827f73ecaadb563df7e99817294939f2be8e943079dc60b2", - branchlen: 1, - status: "valid-fork" - }, - { - height: 1266944, - hash: "00000000612d16af273217818e8e7ac5014a19f68ed04e1bc897b1be0a9c744f", - branchlen: 1, - status: "valid-fork" - }, - { - height: 1266941, - hash: "0000000000002b91cdb15cacf3368da2c9ffce511d64092193b507dad75f4a27", - branchlen: 1, - status: "valid-fork" - }, - { - height: 1266896, - hash: "000000000002745f67a66617b1f9f65c2dfb4c4b8a9ed9b1320b98d3ca46cbe5", - branchlen: 1, - status: "valid-fork" - }, - { - height: 1266481, - hash: "0000000000036babee3ba7654cddb29a9fe5e85c9fbeb44bb53d5ffb694b9670", - branchlen: 1, - status: "valid-fork" - }, - { - height: 1266452, - hash: "00000000502c3ab1490e0839780a4b441bbe21507c454545941e6adcde73c2ff", - branchlen: 1, - status: "valid-fork" - }, - { - height: 1266336, - hash: "000000001c9a0b7cd9eb2210f69d5a9a3f4546ba3707deb40993d729190582d7", - branchlen: 10, - status: "headers-only" - }, - { - height: 1266097, - hash: "000000000028ac0fbd18afe6f001f70cb7549bd2b3082d754dde88ee236368a2", - branchlen: 1, - status: "valid-fork" - }, - { - height: 1265522, - hash: "00000000000000c6df7a2063030e6ce51399e470cc46e4bf6d67aa3f0feca98d", - branchlen: 1, - status: "valid-fork" - }, - { - height: 1265470, - hash: "0000000000168e6442a595a02340fccf8dc2b0e8912c632d39e1f870685f6d7c", - branchlen: 2, - status: "valid-fork" - }, - { - height: 1265275, - hash: "000000008bc2b37ae6af1b886b52e7e1c1122c12badc4ae6c13df64f789267cf", - branchlen: 11027, - status: "headers-only" - }, - { - height: 1265257, - hash: "00000000005bc3e9973d7273211eab02ae02549c7ebae48764c0bd648d4d7bbe", - branchlen: 114, - status: "valid-fork" - }, - { - height: 1265254, - hash: "0000000000e5b909d3541857315e9ee103b042d9ba661f25cc3e8fb25a96c8ce", - branchlen: 111, - status: "valid-fork" - }, - { - height: 1265245, - hash: "000000000066eb8832f6f990baceb379536f437216e22475a6c1b9133d250cb8", - branchlen: 102, - status: "valid-fork" - }, - { - height: 1264455, - hash: "00000000000001befc1bb17a23208d0b77b2449e37093ce8fbb5e346b19cafcc", - branchlen: 1, - status: "valid-headers" - }, - { - height: 1264373, - hash: "00000000000001ed3747e04fb95054cac0358fb4d8009d1999fc3ea34413e84a", - branchlen: 175, - status: "valid-fork" - }, - { - height: 1263912, - hash: "00000000000004635aecbcb97edcd6f5396483338838cb40da804eb354c68bde", - branchlen: 1, - status: "valid-fork" - }, - { - height: 1262906, - hash: "00000000b31643d92a3e7c38e9755844fc8607e3f1055580a8ff28854e8a8ece", - branchlen: 1, - status: "valid-fork" - }, - { - height: 1255749, - hash: "000000001dde5b015a99137f4cba87871370f4b6fcfbcc8b126547e6c33177da", - branchlen: 129, - status: "headers-only" - }, - { - height: 1188789, - hash: "00000000af942ce4eb60b3213cbcb7c98a7330f1f8f1adb4b6376f5e822e15b2", - branchlen: 92, - status: "headers-only" - } -] - -const mockMempoolInfo = { - size: 87, - bytes: 16816, - usage: 66408, - maxmempool: 300000000, - mempoolminfee: 0 -} - -const mockRawMempool = [ - "db045bc3bd1088fa91f5ebb05c35cb9e2a91a22377f79b465cc6920b9893123c", - "6b3df7febf2b9834f1409155f88b866dd516b36376eae00e2b455df82e290405" -] - -const mockBlockHeaderConcise = - "0000ff7f7d217c9b7845ea8b50d620c59a1bf7c276566406e9b7bc7e463e0000000000006d70322c0b697c1c81d2744f87f09f1e9780ba5d30338952e2cdc64e60456f8423bb0a5ceafa091a3e843526" - -const mockBlockHeader = { - hash: "00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900", - confirmations: 7, - height: 1272859, - version: 2147418112, - versionHex: "7fff0000", - merkleroot: - "846f45604ec6cde2528933305dba80971e9ff0874f74d2811c7c690b2c32706d", - time: 1544207139, - mediantime: 1544202884, - nonce: 641041470, - bits: "1a09faea", - difficulty: 1681035.704111868, - chainwork: "00000000000000000000000000000000000000000000003fc4752e608403be04", - previousblockhash: - "0000000000003e467ebcb7e906645676c2f71b9ac520d6508bea45789b7c217d", - nextblockhash: - "00000000000006899041cdfd6c0b73a97730c362346dde479b77414ad7f25ace" -} - -const mockTxOut = { - bestblock: "00000000003a7f19730dd9f172d7466658a5c8833dd03ed8f4ba36e3d857b5e7", - confirmations: 10, - value: 0.0001, - scriptPubKey: { - asm: - "OP_DUP OP_HASH160 0ee020c07f39526ac5505c54fa1ab98490979b83 OP_EQUALVERIFY OP_CHECKSIG", - hex: "76a9140ee020c07f39526ac5505c54fa1ab98490979b8388ac", - reqSigs: 1, - type: "pubkeyhash", - addresses: ["bchtest:qq8wqgxq0uu4y6k92pw9f7s6hxzfp9umsvtg39pzqf"] - }, - coinbase: false -} - -const mockTxOutProof = - "000000200798039affceb7a381e15dc62443c286efe7cae852393b656807000000000000cf9a7d6c654fd1c4558229a619a550ff749b373fa0f0027eed68b1abf6175d5c07c50f5cffff001d0452403b34000000070d0765da76980d542b5670d27ccda9e717073270f8921ad017deb7ee83fe6c4c22830a48cc8392197f1742a3d81805bd2aa4eb7469f38c74f674429d682cb87efcff1713fd0c388a50f0d11adf05363397ef79d16cdb786d47c941c2cb89f2588f42aced9c05f4203b4440616a9e4266ec47909b9580a643f402b5d4e82cc3cddd73df05a33abf6af3975d973d3033d10c4168a73d58d01f685a96d5a2519cd0de9c77faf3f8725ddf155cbdc8ab8102f173e2d0a0d74767f3bff22f588158d6d5bc71c079c7659cc864819c43877635007650502eb4060fcc9feec3280a41d602ad0a" - -module.exports = { - mockBlockHash, - mockBlockchainInfo, - mockChainTips, - mockMempoolInfo, - mockRawMempool, - mockBlockHeaderConcise, - mockBlockHeader, - mockTxOut, - mockTxOutProof -} diff --git a/test/v2/mocks/control-mock.js b/test/v2/mocks/control-mock.js deleted file mode 100644 index cca9338..0000000 --- a/test/v2/mocks/control-mock.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - This library contains mocking data for running unit tests on the address route. -*/ - -"use strict" - -const mockGetInfo = { - version: 170200, - protocolversion: 70015, - walletversion: 160300, - balance: 0, - blocks: 1266726, - timeoffset: 0, - connections: 8, - proxy: "", - difficulty: 1, - testnet: true, - keypoololdest: 1536331195, - keypoolsize: 2000, - paytxfee: 0, - relayfee: 0.00001, - errors: "Warning: unknown new rules activated (versionbit 28)" -} - -module.exports = { - mockGetInfo -} diff --git a/test/v2/mocks/express-mocks.js b/test/v2/mocks/express-mocks.js deleted file mode 100644 index fcb545f..0000000 --- a/test/v2/mocks/express-mocks.js +++ /dev/null @@ -1,88 +0,0 @@ -/* - Contains mocks of Express req and res objects. -*/ - -"use strict" - -const sinon = require("sinon") - -// Inspect JS Objects. -const util = require("util") -util.inspect.defaultOptions = { - showHidden: true, - colors: true -} - -// mock for res.send() -function fakeSend(arg) { - //console.log(`res.send: ${util.inspect(arg)}`); - mockRes.output = arg - return arg -} - -// mock for res.json() -function fakeJson(arg) { - //console.log(`res.json: ${util.inspect(arg)}`); - mockRes.output = arg - return arg -} - -// mock for res.setStatus(num) -const setStatusCode = arg => { - mockRes.statusCode = arg -} - -const mockReq = { - accepts: sinon.stub().returns({}), - acceptsCharsets: sinon.stub().returns({}), - acceptsEncodings: sinon.stub().returns({}), - acceptsLanguages: sinon.stub().returns({}), - body: {}, - flash: sinon.stub().returns({}), - get: sinon.stub().returns({}), - is: sinon.stub().returns({}), - params: {}, - query: {}, - session: {}, - locals: {}, - headers: {} -} - -const mockRes = { - append: sinon.stub().returns({}), - attachement: sinon.stub().returns({}), - clearCookie: sinon.stub().returns({}), - cookie: sinon.stub().returns({}), - download: sinon.stub().returns({}), - end: sinon.stub().returns({}), - format: {}, - get: sinon.stub().returns({}), - headersSent: sinon.stub().returns({}), - json: sinon.stub().callsFake(fakeJson), - jsonp: sinon.stub().returns({}), - links: sinon.stub().returns({}), - locals: {}, - location: sinon.stub().returns({}), - output: null, // Used for retrieving output data. - redirect: sinon.stub().returns({}), - render: sinon.stub().returns({}), - send: sinon.stub().callsFake(fakeSend), - sendFile: sinon.stub().returns({}), - sendStatus: sinon.stub().returns({}), - set: sinon.stub().returns({}), - status: sinon.stub().callsFake(setStatusCode), - statusCode: null, // Default value before calling stats(); - type: sinon.stub().returns({}), - vary: sinon.stub().returns({}), - write: sinon.stub().returns({}), - setHeader: sinon.stub().returns({}), - format: sinon.stub().returns({}) -} - -const mockNext = sinon.stub().returns() - -module.exports = { - mockReq, - mockRes, - mockNext -} diff --git a/test/v2/mocks/mining-mocks.js b/test/v2/mocks/mining-mocks.js deleted file mode 100644 index 8ef8ada..0000000 --- a/test/v2/mocks/mining-mocks.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - This library contains mocking data for running unit tests on the address route. -*/ - -"use strict" - -const mockMiningInfo = { - blocks: 1270185, - currentblocksize: 0, - currentblocktx: 0, - difficulty: 1, - blockprioritypercentage: 5, - errors: - "Warning: Unknown block versions being mined! It's possible unknown rules are in effect", - networkhashps: 517410290.9365583, - pooledtx: 5, - chain: "test" -} - -module.exports = { - mockMiningInfo -} diff --git a/test/v2/mocks/raw-transactions-mocks.js b/test/v2/mocks/raw-transactions-mocks.js deleted file mode 100644 index 08620a3..0000000 --- a/test/v2/mocks/raw-transactions-mocks.js +++ /dev/null @@ -1,157 +0,0 @@ -/* - This library contains mocking data for running unit tests. -*/ - -"use strict" - -const mockDecodeRawTransaction = { - txid: "a332237d82a2543af1b0e1ae3c8cea1610c290ebcaf084a7e9894a61de0be988", - hash: "a332237d82a2543af1b0e1ae3c8cea1610c290ebcaf084a7e9894a61de0be988", - size: 226, - version: 2, - locktime: 0, - vin: [ - { - txid: "21cced645eab150585ed7ca7c96edebab5793cc0a3b3b286c42fd7d6d798b5b9", - vout: 1, - scriptSig: { - asm: - "3045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd41390[ALL|FORKID] 0360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413d", - hex: - "483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413d" - }, - sequence: 4294967295 - } - ], - vout: [ - { - value: 0.0001, - n: 0, - scriptPubKey: { - asm: - "OP_DUP OP_HASH160 eb4b180def88e3f5625b2d8ae2c098ff7d85f664 OP_EQUALVERIFY OP_CHECKSIG", - hex: "76a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac", - reqSigs: 1, - type: "pubkeyhash", - addresses: [Array] - } - }, - { - value: 0.09989752, - n: 1, - scriptPubKey: { - asm: - "OP_DUP OP_HASH160 eb4b180def88e3f5625b2d8ae2c098ff7d85f664 OP_EQUALVERIFY OP_CHECKSIG", - hex: "76a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac", - reqSigs: 1, - type: "pubkeyhash", - addresses: [Array] - } - } - ] -} - -const mockDecodeScript = { - asm: - "0 0 -57 OP_NOP6 OP_LSHIFT OP_UNKNOWN OP_UNKNOWN OP_UNKNOWN c486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa OP_2OVER OP_NUMEQUALVERIFY OP_OR OP_INVERT OP_UNKNOWN OP_UNKNOWN 2ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab 67c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b [error]", - type: "nonstandard", - p2sh: "bchtest:pzy6dwfy6yf373w0dr05a6flfqksurjhwcl3awhdvm" -} - -const mockRawTransactionConcise = - "02000000014e6b52500110b1c30315b85805fb274f0f4afceffc1589f889b27709e59e987d000000006a473044022052762770baa71c1a0b9544ad0f1ea343d32c22aa87c5f8397b6852f464c15b1e02201f4390745cb470e21e0e3c14229f39fef55ea0643a4c997f99d9f3501eae09b7412103c346eee77a77a8d3e073dacc0532ca7a5b9747bc06d88bf091cac9f4bc8bb792ffffffff02d1778f950a0000001976a91436d2f27bbd826a86db1e93618ce3de89ef33169388ac80969800000000001976a914152ea3cd65f18cb8fa9146c84ea1a97af8f051de88ac00000000" - -const mockRawTransactionVerbose = { - hex: - "02000000014e6b52500110b1c30315b85805fb274f0f4afceffc1589f889b27709e59e987d000000006a473044022052762770baa71c1a0b9544ad0f1ea343d32c22aa87c5f8397b6852f464c15b1e02201f4390745cb470e21e0e3c14229f39fef55ea0643a4c997f99d9f3501eae09b7412103c346eee77a77a8d3e073dacc0532ca7a5b9747bc06d88bf091cac9f4bc8bb792ffffffff02d1778f950a0000001976a91436d2f27bbd826a86db1e93618ce3de89ef33169388ac80969800000000001976a914152ea3cd65f18cb8fa9146c84ea1a97af8f051de88ac00000000", - txid: "bd320377db7026a3dd5c7ec444596c0ee18fc25c4f34ee944adc03e432ce1971", - hash: "bd320377db7026a3dd5c7ec444596c0ee18fc25c4f34ee944adc03e432ce1971", - size: 225, - version: 2, - locktime: 0, - vin: [ - { - txid: "7d989ee50977b289f88915fceffc4a0f4f27fb0558b81503c3b1100150526b4e", - vout: 0, - scriptSig: { - asm: - "3044022052762770baa71c1a0b9544ad0f1ea343d32c22aa87c5f8397b6852f464c15b1e02201f4390745cb470e21e0e3c14229f39fef55ea0643a4c997f99d9f3501eae09b7[ALL|FORKID] 03c346eee77a77a8d3e073dacc0532ca7a5b9747bc06d88bf091cac9f4bc8bb792", - hex: - "473044022052762770baa71c1a0b9544ad0f1ea343d32c22aa87c5f8397b6852f464c15b1e02201f4390745cb470e21e0e3c14229f39fef55ea0643a4c997f99d9f3501eae09b7412103c346eee77a77a8d3e073dacc0532ca7a5b9747bc06d88bf091cac9f4bc8bb792" - }, - sequence: 4294967295 - } - ], - vout: [ - { - value: 454.58880465, - n: 0, - scriptPubKey: { - asm: - "OP_DUP OP_HASH160 36d2f27bbd826a86db1e93618ce3de89ef331693 OP_EQUALVERIFY OP_CHECKSIG", - hex: "76a91436d2f27bbd826a86db1e93618ce3de89ef33169388ac", - reqSigs: 1, - type: "pubkeyhash", - addresses: ["bchtest:qqmd9unmhkpx4pkmr6fkrr8rm6y77vckjvqe8aey35"] - } - }, - { - value: 0.1, - n: 1, - scriptPubKey: { - asm: - "OP_DUP OP_HASH160 152ea3cd65f18cb8fa9146c84ea1a97af8f051de OP_EQUALVERIFY OP_CHECKSIG", - hex: "76a914152ea3cd65f18cb8fa9146c84ea1a97af8f051de88ac", - reqSigs: 1, - type: "pubkeyhash", - addresses: ["bchtest:qq2jag7dvhccew86j9rvsn4p49a03uz3mcpw3d6aca"] - } - } - ], - blockhash: "000000000000026fa244de975ca89ea08008aa566564ce2e8ebb3144361b601b", - confirmations: 125, - time: 1542646373, - blocktime: 1542646373 -} - -const mockWHDecode = { - txid: "f8a9857fe3b8a288b5fcafb1b0fc196731f433add6d962f77acd7c10b970ff89", - fee: "500", - sendingaddress: "bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr", - referenceaddress: "bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr", - ismine: false, - version: 0, - type_int: 0, - type: "Simple Send", - propertyid: 368, - precision: "8", - amount: "10.00000000", - valid: true, - blockhash: "0000000046ba0bcef78caaa4492622176bbc563cf249ab52340a0449bc8e26f6", - blocktime: 1542814183, - positioninblock: 57, - block: 1269008, - confirmations: 2 -} - -const mockWHCreateInput = { - txid: "f7ed9cf23dee85910f6269c9a101a75fcfd2f3c6fc81f17fad824ff7aaf99ab2", - vout: 1, - scriptPubKey: "76a914a4b98b0c118de83e7d39c834445f51dce62425f588ac", - amount: 0.09984138, - satoshis: 9984138, - height: 1269011, - confirmations: 4, - legacyAddress: "mvXwPH74hW2yVTWwDwzsjGoaUAqJvWk7ZJ", - cashAddress: "bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr", - value: 0.09984138 -} - -module.exports = { - mockDecodeRawTransaction, - mockDecodeScript, - mockRawTransactionConcise, - mockRawTransactionVerbose, - mockWHDecode, - mockWHCreateInput -} diff --git a/test/v2/mocks/slp-mocks.js b/test/v2/mocks/slp-mocks.js deleted file mode 100644 index 1d70df0..0000000 --- a/test/v2/mocks/slp-mocks.js +++ /dev/null @@ -1,327 +0,0 @@ -/* - This library contains mocking data for running unit tests. -*/ - -"use strict" - -const mockList = { - t: [ - { - tokenDetails: { - tokenIdHex: - "df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb", - documentUri: "", - documentSha256: "", - symbol: "NAKAMOTO", - name: "NAKAMOTO", - decimals: 8 - }, - tokenStats: { - qty_valid_txns_since_genesis: 241, - qty_valid_token_utxos: 151, - qty_valid_token_addresses: 113, - qty_token_circulating_supply: "20995990", - qty_token_burned: "4010", - qty_token_minted: "21000000", - qty_satoshis_locked_up: 81900 - } - } - ] -} - -const mockSingleToken = { - t: [ - { - tokenDetails: { - decimals: 8, - tokenIdHex: - "650dea14c77f4d749608e36e375450c9ac91deb8b1b53e50cb0de2059a52d19a", - timestamp: "2018-08-26 07:06", - transactionType: "GENESIS", - versionType: 1, - documentUri: "", - documentSha256Hex: null, - symbol: "", - name: "TESTYCOIN", - batonVout: null, - containsBaton: false, - genesisOrMintQuantity: "9999", - sendOutputs: null - }, - tokenStats: { - block_created: 1253802, - block_last_active_send: 1253802, - block_last_active_mint: null, - qty_valid_txns_since_genesis: 2, - qty_valid_token_utxos: 0, - qty_valid_token_addresses: 0, - qty_token_minted: "9999", - qty_token_burned: "9999", - qty_token_circulating_supply: "0", - qty_satoshis_locked_up: 0, - minting_baton_status: "NEVER_CREATED" - } - } - ] -} - -const mockSingleTokenError = { - t: [] -} - -const mockSingleAddress = { - a: [ - { - _id: "5c93ed62a19119333d1595bc", - tokenDetails: { - tokenIdHex: - "6b081fcd1f78b187be1464313dac8ff257251b727a42b613552a4040870aeb29" - }, - address: "slptest:pz0qcslrqn7hr44hsszwl4lw5r6udkg6zqv7sq3kk7", - satoshis_balance: 546, - token_balance: "4616984" - } - ], - t: [ - { - tokenDetails: { - decimals: 8, - tokenIdHex: - "6b081fcd1f78b187be1464313dac8ff257251b727a42b613552a4040870aeb29", - timestamp: "2019-02-25 10:05", - transactionType: "GENESIS", - versionType: 1, - documentUri: "https://developer.bitcoin.com", - documentSha256Hex: "", - symbol: "DEV", - name: "DEVCOIN", - batonVout: 2, - containsBaton: true, - genesisOrMintQuantity: "500000000", - sendOutputs: null - }, - tokenStats: { - block_created: 571272, - block_last_active_send: 574758, - block_last_active_mint: 571272, - qty_valid_txns_since_genesis: 172, - qty_valid_token_utxos: 170, - qty_valid_token_addresses: 170, - qty_token_minted: "1000000000", - qty_token_burned: "4.99999995", - qty_token_circulating_supply: "999999995.00000005", - qty_satoshis_locked_up: 92820, - minting_baton_status: "ALIVE" - } - } - ] -} - -const mockTx = { - txid: "57b3082a2bf269b3d6f40fee7fb9c664e8256a88ca5ee2697c05b9457822d446", - version: 2, - locktime: 0, - vin: [ - { - txid: "61e71554a3dc18158f30d9e8f5c9b6641a789690b32302899f81cbea9fe3bb49", - vout: 2, - sequence: 4294967295, - n: 0, - scriptSig: { - hex: - "4730440220409e79fec552f01203f41d3d621ae3db89c720af261c8268ce5f0453de009f5d022001e7ffefeba7b0716d32ea55cb6ace267b6ee9cbcc8a017bb9c3b6acf7889418412103c87f0ec048a0771bdb60533d45cac88c6974afeb055a65edd663c2f947335585", - asm: - "30440220409e79fec552f01203f41d3d621ae3db89c720af261c8268ce5f0453de009f5d022001e7ffefeba7b0716d32ea55cb6ace267b6ee9cbcc8a017bb9c3b6acf7889418[ALL|FORKID] 03c87f0ec048a0771bdb60533d45cac88c6974afeb055a65edd663c2f947335585" - }, - value: 546, - legacyAddress: "mw22g57T9YA7MZQQu5eBDKj3PKTdt99oDL", - cashAddress: "bchtest:qz4qnxcxwvmacgye8wlakhz0835x0w3vtvaga95c09" - }, - { - txid: "61e71554a3dc18158f30d9e8f5c9b6641a789690b32302899f81cbea9fe3bb49", - vout: 1, - sequence: 4294967295, - n: 1, - scriptSig: { - hex: - "483045022100a743bee56c99bd103be48a78fa4c7342100815d9d2448dbe6e1d338c3a13b241022066728b5279fc22eef5cd019582ff34771e29175835fc98aa3168a1548fd78ac8412103c87f0ec048a0771bdb60533d45cac88c6974afeb055a65edd663c2f947335585", - asm: - "3045022100a743bee56c99bd103be48a78fa4c7342100815d9d2448dbe6e1d338c3a13b241022066728b5279fc22eef5cd019582ff34771e29175835fc98aa3168a1548fd78ac8[ALL|FORKID] 03c87f0ec048a0771bdb60533d45cac88c6974afeb055a65edd663c2f947335585" - }, - value: 546, - legacyAddress: "mw22g57T9YA7MZQQu5eBDKj3PKTdt99oDL", - cashAddress: "bchtest:qz4qnxcxwvmacgye8wlakhz0835x0w3vtvaga95c09" - }, - { - txid: "61e71554a3dc18158f30d9e8f5c9b6641a789690b32302899f81cbea9fe3bb49", - vout: 3, - sequence: 4294967295, - n: 2, - scriptSig: { - hex: - "483045022100821473902eec5f1ce7d43b1ba7f9ec453bfe8b8dfc3de3e0723c883ab109922f02206162960e80618531fab2c16aee260fddd7979bab62471c8686af7de75f8732ec412103c87f0ec048a0771bdb60533d45cac88c6974afeb055a65edd663c2f947335585", - asm: - "3045022100821473902eec5f1ce7d43b1ba7f9ec453bfe8b8dfc3de3e0723c883ab109922f02206162960e80618531fab2c16aee260fddd7979bab62471c8686af7de75f8732ec[ALL|FORKID] 03c87f0ec048a0771bdb60533d45cac88c6974afeb055a65edd663c2f947335585" - }, - value: 9997521, - legacyAddress: "mw22g57T9YA7MZQQu5eBDKj3PKTdt99oDL", - cashAddress: "bchtest:qz4qnxcxwvmacgye8wlakhz0835x0w3vtvaga95c09" - } - ], - vout: [ - { - value: "0.00000000", - n: 0, - scriptPubKey: { - hex: - "6a04534c500001010453454e44207ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796080000000049504f80080000001c71e64280", - asm: - "OP_RETURN 5262419 1 1145980243 7ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796 0000000049504f80 0000001c71e64280" - }, - spentTxId: null, - spentIndex: null, - spentHeight: null - }, - { - value: "0.00000546", - n: 1, - scriptPubKey: { - hex: "76a914396b8e57ad0cb58d30e2992f22047b3c20377aa688ac", - asm: - "OP_DUP OP_HASH160 396b8e57ad0cb58d30e2992f22047b3c20377aa6 OP_EQUALVERIFY OP_CHECKSIG", - addresses: ["mkkZf7T3fU3vHSzNPy51HBmM46ghN1gnN9"], - type: "pubkeyhash" - }, - spentTxId: null, - spentIndex: null, - spentHeight: null - }, - { - value: "0.00000546", - n: 2, - scriptPubKey: { - hex: "76a914aa099b067337dc20993bbfdb5c4f3c6867ba2c5b88ac", - asm: - "OP_DUP OP_HASH160 aa099b067337dc20993bbfdb5c4f3c6867ba2c5b OP_EQUALVERIFY OP_CHECKSIG", - addresses: ["mw22g57T9YA7MZQQu5eBDKj3PKTdt99oDL"], - type: "pubkeyhash" - }, - spentTxId: null, - spentIndex: null, - spentHeight: null - }, - { - value: "0.09996891", - n: 3, - scriptPubKey: { - hex: "76a914aa099b067337dc20993bbfdb5c4f3c6867ba2c5b88ac", - asm: - "OP_DUP OP_HASH160 aa099b067337dc20993bbfdb5c4f3c6867ba2c5b OP_EQUALVERIFY OP_CHECKSIG", - addresses: ["mw22g57T9YA7MZQQu5eBDKj3PKTdt99oDL"], - type: "pubkeyhash" - }, - spentTxId: null, - spentIndex: null, - spentHeight: null - } - ], - blockhash: "000000000000ce978accc64a6bb567acf0c653c202309a0f8e220149bf0c6968", - blockheight: 1287490, - confirmations: 746, - time: 1550855104, - blocktime: 1550855104, - valueOut: 0.09997983, - size: 628, - valueIn: 0.09998613, - fees: 0.0000063, - tokenInfo: { - versionType: 1, - transactionType: "SEND", - tokenIdHex: - "7ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796", - sendOutputs: ["0", "1230000000", "122170000000"] - }, - tokenIsValid: true -} - -const mockConvert = { - slpAddress: "slptest:qz35h5mfa8w2pqma2jq06lp7dnv5fxkp2shlcycvd5", - cashAddress: "bchtest:qz35h5mfa8w2pqma2jq06lp7dnv5fxkp2svtllzmlf", - legacyAddress: "mvQPGnzRT6gMWASZBMg7NcT3vmvsSKSQtf" -} - -const mockTokenDetails = { - tokenIdHex: - "df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb", - documentUri: "", - symbol: "NAKAMOTO", - name: "NAKAMOTO", - decimals: 8, - timestamp: "", - containsBaton: true, - versionType: 1 -} - -const mockTokenStats = { - qty_valid_txns_since_genesis: 241, - qty_valid_token_utxos: 151, - qty_valid_token_addresses: 113, - qty_token_circulating_supply: "20995990", - qty_token_burned: "4010", - qty_token_minted: "21000000", - qty_satoshis_locked_up: 81900 -} - -const mockBalance = { - slpAddress: "simpleledger:qp9d8mn8ypryfvea2mev0ggc3wg6plpn4suuaeuss3", - satoshis_balance: 546, - token_balance: "1000" -} - -const mockTransactions = [ - { - txid: "a302f045be8efa1cd982833a7f187ff4fac8baac36da0c887eb2787d8b45e2af", - tokenDetails: { - valid: true, - detail: { - decimals: null, - tokenIdHex: - "495322b37d6b2eae81f045eda612b95870a0c2b6069c58f70cf8ef4e6a9fd43a", - timestamp: null, - transactionType: "MINT", - versionType: 1, - documentUri: null, - documentSha256Hex: null, - symbol: null, - name: null, - batonVout: 2, - containsBaton: true, - genesisOrMintQuantity: { - $numberDecimal: "1000" - }, - sendOutputs: null - }, - invalidReason: null, - schema_version: 30 - } - } -] - -const mockFoobar = { - c: [], - u: [] -} - -module.exports = { - mockList, - mockSingleToken, - mockConvert, - mockTokenDetails, - mockTokenStats, - mockTx, - mockBalance, - mockTransactions, - mockSingleTokenError, - mockSingleAddress, - mockFoobar -} diff --git a/test/v2/mocks/slpjs-mocks.js b/test/v2/mocks/slpjs-mocks.js deleted file mode 100644 index c130935..0000000 --- a/test/v2/mocks/slpjs-mocks.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - Mocks used for unit tests that interact with slpjs. -*/ - -"use strict" - -const sinon = require("sinon") -const proxyquire = require("proxyquire") -const BigNumber = require("bignumber.js") -const slpMocks = require("./slp-mocks") - -// Mock the BitboxNetwork class. -class BitboxNetwork { - constructor() {} - - async getAllSlpBalancesAndUtxos(address) { - return { - satoshis_available_bch: 9996891, - satoshis_in_slp_baton: 546, - satoshis_in_slp_token: 546, - satoshis_in_invalid_token_dag: 0, - satoshis_in_invalid_baton_dag: 0, - slpTokenBalances: { - "7ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796": new BigNumber( - 123400000000 - ) - }, - slpTokenUtxos: { - "7ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796": [] - }, - slpBatonUtxos: { - "7ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796": [] - }, - nonSlpUtxos: [{}], - invalidTokenUtxos: [], - invalidBatonUtxos: [] - } - } - - async getTokenInformation(txid) { - BigNumber.set({ DECIMAL_PLACES: 8, ROUNDING_MODE: 4 }) - - const obj = { - versionType: 1, - transactionType: 0, - symbol: "SLPSDK", - name: "SLP SDK example using BITBOX", - documentUri: "developer.bitcoin.com", - documentSha256: null, - decimals: 8, - batonVout: 2, - containsBaton: true, - genesisOrMintQuantity: new BigNumber(123400000000) - } - - return obj - } - - async getTransactionDetails(txid) { - return slpMocks.mockTx - } -} - -// Mock the slpjs library. -const slpjs = { - BitboxNetwork, - slp: {}, - validator: {} -} - -module.exports = slpjs diff --git a/test/v2/mocks/transaction-mocks.js b/test/v2/mocks/transaction-mocks.js deleted file mode 100644 index a8d22e2..0000000 --- a/test/v2/mocks/transaction-mocks.js +++ /dev/null @@ -1,74 +0,0 @@ -/* - This library contains mocking data for running unit tests on the address route. -*/ - -"use strict" - -/* -const mockDetails = { - txid: "6f235bd3a689f03c11969cd649ccad592462ca958bc519a30194e7a67b349a40", - version: 2, - locktime: 0, - vin: [Array], - vout: [Array], - blockhash: "00000000e7232ff12462dedf9c11985f5b54202515277c337ccc59812758f28b", - blockheight: 1270188, - confirmations: 2, - time: 1543436253, - blocktime: 1543436253, - valueOut: 450.78867333, - size: 226, - valueIn: 450.78867559, - fees: 0.00000226 -} -*/ - -const mockDetails = { - txid: "6f235bd3a689f03c11969cd649ccad592462ca958bc519a30194e7a67b349a40", - version: 2, - locktime: 0, - vin: [ - { - txid: "273d616d1c48f4b075c497f36ffdc79da5c8d6ed75485808b3599aac504f8525", - vout: 0, - sequence: 4294967295, - n: 0, - scriptSig: [{}], - addr: "bchtest:qqmd9unmhkpx4pkmr6fkrr8rm6y77vckjvqe8aey35", - valueSat: 45078867559, - value: 450.78867559, - doubleSpentTxID: null - } - ], - vout: [ - { - value: "450.68867333", - n: 0, - scriptPubKey: [{}], - spentTxId: null, - spentIndex: null, - spentHeight: null - }, - { - value: "0.10000000", - n: 1, - scriptPubKey: [{}], - spentTxId: null, - spentIndex: null, - spentHeight: null - } - ], - blockhash: "00000000e7232ff12462dedf9c11985f5b54202515277c337ccc59812758f28b", - blockheight: 1270188, - confirmations: 3, - time: 1543436253, - blocktime: 1543436253, - valueOut: 450.78867333, - size: 226, - valueIn: 450.78867559, - fees: 0.00000226 -} - -module.exports = { - mockDetails -} diff --git a/test/v2/mocks/util-mocks.js b/test/v2/mocks/util-mocks.js deleted file mode 100644 index 4118358..0000000 --- a/test/v2/mocks/util-mocks.js +++ /dev/null @@ -1,18 +0,0 @@ -/* - This library contains mocking data for running unit tests on the address route. -*/ - -"use strict" - -const mockAddress = { - isvalid: true, - address: "bchtest:qqqk4y6lsl5da64sg5qc3xezmplyu5kmpyz2ysaa5y", - scriptPubKey: "76a914016a935f87e8deeab04501889b22d87e4e52db0988ac", - ismine: false, - iswatchonly: false, - isscript: false -} - -module.exports = { - mockAddress -} diff --git a/test/v2/rate-limits.js b/test/v2/rate-limits.js deleted file mode 100644 index 030fa64..0000000 --- a/test/v2/rate-limits.js +++ /dev/null @@ -1,166 +0,0 @@ -"use strict" - -const chai = require("chai") -const assert = chai.assert -const nock = require("nock") // HTTP mocking - -// Used for debugging. -const util = require("util") -util.inspect.defaultOptions = { depth: 1 } - -// Mocking data. -const { mockReq, mockRes, mockNext } = require("./mocks/express-mocks") - -// Libraries under test -const rateLimitMiddleware = require("../../src/middleware/route-ratelimit") -const controlRoute = require("../../src/routes/v2/control") - -let req, res, next -let originalEnvVars // Used during transition from integration to unit tests. - -describe("#route-ratelimits", () => { - before(() => { - // Save existing environment variables. - originalEnvVars = { - BITCOINCOM_BASEURL: process.env.BITCOINCOM_BASEURL, - RPC_BASEURL: process.env.RPC_BASEURL, - RPC_USERNAME: process.env.RPC_USERNAME, - RPC_PASSWORD: process.env.RPC_PASSWORD - } - }) - - // Setup the mocks before each test. - beforeEach(() => { - // Mock the req and res objects used by Express routes. - req = mockReq - res = mockRes - next = mockNext - - // Explicitly reset the parmas and body. - req.params = {} - req.body = {} - req.query = {} - }) - - describe("#routeRateLimit", () => { - const routeRateLimit = rateLimitMiddleware.routeRateLimit - const getInfo = controlRoute.testableComponents.getInfo - /* - it("should pass through rate-limit middleware", async () => { - req.baseUrl = "/v2" - req.path = "/control/getInfo" - req.method = "GET" - - await routeRateLimit(req, res, next) - - // next() will be called if rate-limit is not triggered - assert.equal(next.called, true) - }) - - it("should trigger rate-limit handler if rate limits exceeds 60 request per minute", async () => { - req.baseUrl = "/v2" - req.path = "/control/getInfo" - req.method = "GET" - - for (let i = 0; i < 65; i++) { - next.reset() // reset the stubbed next() function. - - await routeRateLimit(req, res, next) - //console.log(`next() called: ${next.called}`) - } - - // Note: next() will be called unless the rate-limit kicks in. - assert.equal( - next.called, - false, - `next should not be called if rate limit was triggered.` - ) - }) - */ - /* - it("should NOT trigger rate-limit handler for pro-tier at 65 RPM", async () => { - // Clear the require cache before running this test. - delete require.cache[ - require.resolve("../../dist/middleware/route-ratelimit") - ] - rateLimitMiddleware = require("../../dist/middleware/route-ratelimit") - routeRateLimit = rateLimitMiddleware.routeRateLimit - - req.baseUrl = "/v2" - req.path = "/control/getInfo" - req.method = "GET" - - req.locals.proLimit = true - - //console.log(`req.locals before test: ${util.inspect(req.locals)}`) - - // Prepare the authorization header - //req.headers.authorization = generateAuthHeader("BITBOX") - - for (let i = 0; i < 65; i++) { - next.reset() // reset the stubbed next() function. - - await routeRateLimit(req, res, next) - //console.log(`next() called: ${next.called}`) - } - - //console.log(`req.locals after test: ${util.inspect(req.locals)}`) - - // Note: next() will be called unless the rate-limit kicks in. - assert.equal( - next.called, - true, - `next should be called if rate limit was not triggered.` - ) - }) - - it("rate-limiting should still kick in at a higher RPM for pro-tier", async () => { - // Clear the require cache before running this test. - delete require.cache[ - require.resolve("../../dist/middleware/route-ratelimit") - ] - rateLimitMiddleware = require("../../dist/middleware/route-ratelimit") - routeRateLimit = rateLimitMiddleware.routeRateLimit - - req.baseUrl = "/v2" - req.path = "/control/getInfo" - req.method = "GET" - - req.locals.proLimit = true - - //console.log(`req.locals before test: ${util.inspect(req.locals)}`) - - // Prepare the authorization header - //req.headers.authorization = generateAuthHeader("BITBOX") - - for (let i = 0; i < 650; i++) { - next.reset() // reset the stubbed next() function. - - await routeRateLimit(req, res, next) - //console.log(`next() called: ${next.called}`) - } - - //console.log(`req.locals after test: ${util.inspect(req.locals)}`) - - // Note: next() will be called unless the rate-limit kicks in. - assert.equal( - next.called, - false, - `next should NOT be called if rate limit was triggered.` - ) - }) - */ - }) -}) - -// Generates a Basic authorization header. -function generateAuthHeader(pass) { - // https://en.wikipedia.org/wiki/Basic_access_authentication - const username = "BITBOX" - const combined = `${username}:${pass}` - - var base64Credential = Buffer.from(combined).toString("base64") - var readyCredential = `Basic ${base64Credential}` - - return readyCredential -} diff --git a/test/v2/raw-transactions.js b/test/v2/raw-transactions.js deleted file mode 100644 index bd20bcc..0000000 --- a/test/v2/raw-transactions.js +++ /dev/null @@ -1,807 +0,0 @@ -/* - TESTS FOR THE RAWTRANSACTIONS.TS LIBRARY - - This test file uses the environment variable TEST to switch between unit - and integration tests. By default, TEST is set to 'unit'. Set this variable - to 'integration' to run the tests against BCH mainnet. - - TODO: - -Create e2e test for sendRawTransaction. - -*/ - -"use strict" - -const chai = require("chai") -const assert = chai.assert -const rawtransactions = require("../../src/routes/v2/rawtransactions") -const nock = require("nock") // HTTP mocking - -let originalEnvVars // Used during transition from integration to unit tests. - -// Mocking data. -//delete require.cache[require.resolve("./mocks/express-mocks")] // Fixes bug -const { mockReq, mockRes, mockNext } = require("./mocks/express-mocks") -const mockData = require("./mocks/raw-transactions-mocks") - -// Used for debugging. -const util = require("util") -util.inspect.defaultOptions = { depth: 5 } - -describe("#Raw-Transactions", () => { - let req, res, next - - before(() => { - // Save existing environment variables. - originalEnvVars = { - BITCOINCOM_BASEURL: process.env.BITCOINCOM_BASEURL, - RPC_BASEURL: process.env.RPC_BASEURL, - RPC_USERNAME: process.env.RPC_USERNAME, - RPC_PASSWORD: process.env.RPC_PASSWORD - } - - // Set default environment variables for unit tests. - if (!process.env.TEST) process.env.TEST = "unit" - if (process.env.TEST === "unit") { - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - process.env.RPC_BASEURL = "http://fakeurl/api" - process.env.RPC_USERNAME = "fakeusername" - process.env.RPC_PASSWORD = "fakepassword" - } - }) - - // Setup the mocks before each test. - beforeEach(() => { - // Mock the req and res objects used by Express routes. - req = mockReq - res = mockRes - next = mockNext - - // Explicitly reset the parmas and body. - req.params = {} - req.body = {} - req.query = {} - req.locals = {} - - // Activate nock if it's inactive. - if (!nock.isActive()) nock.activate() - }) - - afterEach(() => { - // Clean up HTTP mocks. - nock.cleanAll() // clear interceptor list. - nock.restore() - }) - - after(() => { - // Restore any pre-existing environment variables. - process.env.BITCOINCOM_BASEURL = originalEnvVars.BITCOINCOM_BASEURL - process.env.RPC_BASEURL = originalEnvVars.RPC_BASEURL - process.env.RPC_USERNAME = originalEnvVars.RPC_USERNAME - process.env.RPC_PASSWORD = originalEnvVars.RPC_PASSWORD - }) - - describe("#root", async () => { - // root route handler. - const root = rawtransactions.testableComponents.root - - it("should respond to GET for base route", async () => { - const result = root(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(result.status, "rawtransactions", "Returns static string") - }) - }) - - describe("decodeRawTransactionSingle()", () => { - // block route handler. - const decodeRawTransaction = - rawtransactions.testableComponents.decodeRawTransactionSingle - - it("should throw error if hex is missing", async () => { - const result = await decodeRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "hex can not be empty") - }) - - it("should throw 503 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" - - req.params.hex = - "0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000" - - const result = await decodeRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.RPC_BASEURL = savedUrl2 - - assert.isAbove( - res.statusCode, - 499, - "HTTP status code 500 or greater expected." - ) - //assert.include(result.error,"Network error: Could not communicate with full node","Error message expected") - }) - - it("should GET /decodeRawTransaction", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockDecodeRawTransaction }) - } - - req.params.hex = - "0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000" - - const result = await decodeRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAnyKeys(result, [ - "txid", - "hash", - "size", - "version", - "locktime", - "vin", - "vout" - ]) - assert.isArray(result.vin) - assert.isArray(result.vout) - }) - }) - - describe("decodeRawTransactionBulk()", () => { - const decodeRawTransactionBulk = - rawtransactions.testableComponents.decodeRawTransactionBulk - - it("should throw 400 error if hexes array is missing", async () => { - const result = await decodeRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "hexes must be an array") - }) - - it("should throw 400 error if hexes array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.hexes = testArray - - const result = await decodeRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should throw 400 error if hexes is empty", async () => { - req.body.hexes = [""] - - const result = await decodeRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Encountered empty hex") - }) - - it("should error on non-array single hex", async () => { - req.body.hexes = - "0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000" - - const result = await decodeRawTransactionBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "hexes must be an array", - "Proper error message" - ) - }) - - it("should decode an array with a single hex", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockDecodeRawTransaction }) - } - - req.body.hexes = [ - "0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000" - ] - - const result = await decodeRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAnyKeys(result[0], [ - "txid", - "hash", - "size", - "version", - "locktime", - "vin", - "vout" - ]) - assert.isArray(result[0].vin) - assert.isArray(result[0].vout) - }) - - it("should decode an array with multiple hexes", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .times(2) - .reply(200, { result: mockData.mockDecodeRawTransaction }) - } - - req.body.hexes = [ - "0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000", - "0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000" - ] - - const result = await decodeRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAnyKeys(result[0], [ - "txid", - "hash", - "size", - "version", - "locktime", - "vin", - "vout" - ]) - assert.isArray(result[0].vin) - assert.isArray(result[0].vout) - }) - }) - - describe("decodeScriptSingle()", () => { - // block route handler. - const decodeScriptSingle = - rawtransactions.testableComponents.decodeScriptSingle - - it("should throw error if hex is missing", async () => { - const result = await decodeScriptSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "hex can not be empty") - }) - - it("should throw 503 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" - - req.params.hex = - "0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000" - - const result = await decodeScriptSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.RPC_BASEURL = savedUrl2 - - assert.isAbove( - res.statusCode, - 499, - "HTTP status code 500 or greater expected." - ) - //assert.include(result.error,"Network error: Could not communicate with full node","Error message expected") - }) - - it("should GET /decodeScriptSingle", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockDecodeScript }) - } - - req.params.hex = - "0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000" - - const result = await decodeScriptSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["asm", "type", "p2sh"]) - }) - }) - - describe("decodeScriptBulk()", () => { - const decodeScriptBulk = rawtransactions.testableComponents.decodeScriptBulk - - it("should throw 400 error if hexes array is missing", async () => { - const result = await decodeScriptBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "hexes must be an array") - }) - - it("should throw 400 error if hexes array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.hexes = testArray - - const result = await decodeScriptBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should throw 400 error if hexes is empty", async () => { - req.body.hexes = [""] - - const result = await decodeScriptBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Encountered empty hex") - }) - - it("should error on non-array single hex", async () => { - req.body.hexes = - "0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000" - - const result = await decodeScriptBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "hexes must be an array", - "Proper error message" - ) - }) - - it("should decode an array with a single hex", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockDecodeScript }) - } - - req.body.hexes = [ - "4830450221009a51e00ec3524a7389592bc27bea4af5104a59510f5f0cfafa64bbd5c164ca2e02206c2a8bbb47eabdeed52f17d7df668d521600286406930426e3a9415fe10ed592012102e6e1423f7abde8b70bca3e78a7d030e5efabd3eb35c19302542b5fe7879c1a16" - ] - - const result = await decodeScriptBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAllKeys(result[0], ["asm", "type", "p2sh"]) - }) - - it("should decode an array with a multiple hexes", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .times(2) - .reply(200, { result: mockData.mockDecodeScript }) - } - - req.body.hexes = [ - "4830450221009a51e00ec3524a7389592bc27bea4af5104a59510f5f0cfafa64bbd5c164ca2e02206c2a8bbb47eabdeed52f17d7df668d521600286406930426e3a9415fe10ed592012102e6e1423f7abde8b70bca3e78a7d030e5efabd3eb35c19302542b5fe7879c1a16", - "4830450221009a51e00ec3524a7389592bc27bea4af5104a59510f5f0cfafa64bbd5c164ca2e02206c2a8bbb47eabdeed52f17d7df668d521600286406930426e3a9415fe10ed592012102e6e1423f7abde8b70bca3e78a7d030e5efabd3eb35c19302542b5fe7879c1a16" - ] - - const result = await decodeScriptBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.equal(result.length, 2) - assert.hasAllKeys(result[0], ["asm", "type", "p2sh"]) - }) - }) - - describe("getRawTransactionBulk()", () => { - // block route handler. - const getRawTransactionBulk = - rawtransactions.testableComponents.getRawTransactionBulk - - it("should throw 400 error if txids array is missing", async () => { - const result = await getRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "txids must be an array") - }) - - it("should throw 400 error if txids array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.txids = testArray - - const result = await getRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should throw 400 error if txid is empty", async () => { - req.body.txids = [""] - - const result = await getRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Encountered empty TXID") - }) - - it("should throw 400 error if txid is invalid", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(500, { - error: { message: "parameter 1 must be of length 64 (not 6)" } - }) - } - - req.body.txids = ["abc123"] - - const result = await getRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "parameter 1 must be of length 64 (not 6)") - }) - - it("should get concise transaction data", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockRawTransactionConcise }) - } - - req.body.txids = [ - "bd320377db7026a3dd5c7ec444596c0ee18fc25c4f34ee944adc03e432ce1971" - ] - - const result = await getRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.isString(result[0]) - }) - - it("should get verbose transaction data", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockRawTransactionVerbose }) - } - - req.body.txids = [ - "bd320377db7026a3dd5c7ec444596c0ee18fc25c4f34ee944adc03e432ce1971" - ] - req.body.verbose = true - - const result = await getRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAnyKeys(result[0], [ - "hex", - "txid", - "hash", - "size", - "version", - "locktime", - "vin", - "vout", - "blockhash", - "confirmations", - "time", - "blocktime" - ]) - assert.isArray(result[0].vin) - assert.isArray(result[0].vout) - }) - }) - - describe("getRawTransactionSingle()", () => { - // block route handler. - const getRawTransactionSingle = - rawtransactions.testableComponents.getRawTransactionSingle - - it("should throw 400 error if txid is missing", async () => { - const result = await getRawTransactionSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "txid can not be empty") - }) - - it("should throw 400 error if txid is invalid", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(500, { - error: { message: "parameter 1 must be of length 64 (not 6)" } - }) - } - - req.params.txid = "abc123" - - const result = await getRawTransactionSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "parameter 1 must be of length 64 (not 6)") - }) - - it("should get concise transaction data", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockRawTransactionConcise }) - } - - req.params.txid = - "bd320377db7026a3dd5c7ec444596c0ee18fc25c4f34ee944adc03e432ce1971" - - const result = await getRawTransactionSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isString(result) - }) - - it("should get verbose transaction data", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockRawTransactionVerbose }) - } - - req.params.txid = - "bd320377db7026a3dd5c7ec444596c0ee18fc25c4f34ee944adc03e432ce1971" - req.query.verbose = "true" - - const result = await getRawTransactionSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAnyKeys(result, [ - "hex", - "txid", - "hash", - "size", - "version", - "locktime", - "vin", - "vout", - "blockhash", - "confirmations", - "time", - "blocktime" - ]) - assert.isArray(result.vin) - assert.isArray(result.vout) - }) - }) - - describe("sendRawTransactionBulk()", () => { - const sendRawTransaction = - rawtransactions.testableComponents.sendRawTransactionBulk - - it("should throw 400 error if hexs array is missing", async () => { - const result = await sendRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "hex must be an array") - }) - - it("should throw 400 error if hexs array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.hexes = testArray - - const result = await sendRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should throw 400 error if hex array element is empty", async () => { - req.body.hexes = [""] - - const result = await sendRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Encountered empty hex") - }) - - it("should throw 500 error if hex is invalid", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(500, { - error: { message: "TX decode failed" } - }) - } - - req.body.hexes = ["abc123"] - - const result = await sendRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "TX decode failed") - }) - - it("should submit hex encoded transaction", async () => { - // This is a difficult test to run as transaction hex is invalid after a - // block confirmation. So the unit tests simulates what the output 'should' - // be, but the integration asserts an expected failure. - - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { - result: - "aef8848396e67532b42008b9d75b5a5a3459a6717740f31f0553b74102b4b118" - }) - } - - req.body.hexes = [ - "0200000001189f7cf4303e2e0bcc5af4be323b9b397dd4104ca2de09528eb90a1450b8a999010000006a4730440220212ec2ffce136a30cec1bc86a40b08a2afdeb6f8dbd652d7bcb07b1aad6dfa8c022041f59585273b89d88879a9a531ba3272dc953f48ff57dad955b2dee70e76c0624121030143ffd18f1c4add75c86b2f930d9551d51f7a6bd786314247022b7afc45d231ffffffff0230d39700000000001976a914af64a026e06910c59463b000d18c3d125d7e951a88ac58c20000000000001976a914af64a026e06910c59463b000d18c3d125d7e951a88ac00000000" - ] - - const result = await sendRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) - - if (process.env.TEST === "unit") { - assert.isArray(result) - assert.isString(result[0]) - - // Integration test - } else { - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "transaction already in block chain") - } - }) - }) - - describe("sendRawTransactionSingle()", () => { - // block route handler. - const sendRawTransaction = - rawtransactions.testableComponents.sendRawTransactionSingle - - it("should throw an error for an empty hex", async () => { - req.params.hex = "" - - const result = await sendRawTransaction(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "Encountered empty hex", - "Proper error message" - ) - }) - - it("should throw an error for a non-string", async () => { - req.params.hex = 456 - - const result = await sendRawTransaction(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "hex must be a string", - "Proper error message" - ) - }) - - it("should throw 500 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl = process.env.BITCOINCOM_BASEURL - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - process.env.RPC_BASEURL = "http://fakeurl/api/" - - req.params.hex = - "0200000001189f7cf4303e2e0bcc5af4be323b9b397dd4104ca2de09528eb90a1450b8a999010000006a4730440220212ec2ffce136a30cec1bc86a40b08a2afdeb6f8dbd652d7bcb07b1aad6dfa8c022041f59585273b89d88879a9a531ba3272dc953f48ff57dad955b2dee70e76c0624121030143ffd18f1c4add75c86b2f930d9551d51f7a6bd786314247022b7afc45d231ffffffff0230d39700000000001976a914af64a026e06910c59463b000d18c3d125d7e951a88ac58c20000000000001976a914af64a026e06910c59463b000d18c3d125d7e951a88ac00000000" - const result = await sendRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - process.env.RPC_BASEURL = savedUrl2 - - assert.isAbove( - res.statusCode, - 499, - "HTTP status code 500 or great expected." - ) - }) - - it("should throw an error for invalid hex", async () => { - req.params.hex = "abc123" - - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(500, { - error: { message: "TX decode failed" } - }) - } - - const result = await sendRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "TX decode failed") - }) - - it("should GET /sendRawTransaction/:hex", async () => { - // This is a difficult test to run as transaction hex is invalid after a - // block confirmation. So the unit tests simulates what the output 'should' - // be, but the integration asserts an expected failure. - - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { - result: - "aef8848396e67532b42008b9d75b5a5a3459a6717740f31f0553b74102b4b118" - }) - } - - req.params.hex = - "0200000001189f7cf4303e2e0bcc5af4be323b9b397dd4104ca2de09528eb90a1450b8a999010000006a4730440220212ec2ffce136a30cec1bc86a40b08a2afdeb6f8dbd652d7bcb07b1aad6dfa8c022041f59585273b89d88879a9a531ba3272dc953f48ff57dad955b2dee70e76c0624121030143ffd18f1c4add75c86b2f930d9551d51f7a6bd786314247022b7afc45d231ffffffff0230d39700000000001976a914af64a026e06910c59463b000d18c3d125d7e951a88ac58c20000000000001976a914af64a026e06910c59463b000d18c3d125d7e951a88ac00000000" - - const result = await sendRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) - - if (process.env.TEST === "unit") { - assert.isString(result) - - // Integration test - } else { - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "transaction already in block chain") - } - }) - }) -}) diff --git a/test/v2/slp.js b/test/v2/slp.js deleted file mode 100644 index 2049a77..0000000 --- a/test/v2/slp.js +++ /dev/null @@ -1,971 +0,0 @@ -/* - TESTS FOR THE SLP.TS LIBRARY - - This test file uses the environment variable TEST to switch between unit - and integration tests. By default, TEST is set to 'unit'. Set this variable - to 'integration' to run the tests against BCH mainnet. - - TODO: - -See listSingleToken() tests. -*/ - -"use strict" - -const chai = require("chai") -const assert = chai.assert -const nock = require("nock") // HTTP mocking -const sinon = require("sinon") -const proxyquire = require("proxyquire").noPreserveCache() - -// Prepare the slpRoute for stubbing dependcies on slpjs. -const slpRoute = require("../../src/routes/v2/slp") -const pathStub = {} // Used to stub methods within slpjs. -const slpRouteStub = proxyquire("../../src/routes/v2/slp", { slpjs: pathStub }) - -let originalEnvVars // Used during transition from integration to unit tests. - -// Mocking data. -const { mockReq, mockRes } = require("./mocks/express-mocks") -const mockData = require("./mocks/slp-mocks") -const slpjsMock = require("./mocks/slpjs-mocks") - -// Used for debugging. -const util = require("util") -util.inspect.defaultOptions = { depth: 1 } - -describe("#SLP", () => { - let req, res, mockServerUrl - let sandbox - - before(() => { - // Save existing environment variables. - originalEnvVars = { - BITDB_URL: process.env.BITDB_URL, - BITCOINCOM_BASEURL: process.env.BITCOINCOM_BASEURL, - SLPDB_URL: process.env.SLPDB_URL - } - - // Set default environment variables for unit tests. - if (!process.env.TEST) process.env.TEST = "unit" - - // Block network connections for unit tests. - if (process.env.TEST === "unit") { - process.env.BITDB_URL = "http://fakeurl/" - process.env.BITCOINCOM_BASEURL = "http://fakeurl/" - process.env.SLPDB_URL = "http://fakeurl/" - mockServerUrl = `http://fakeurl` - } - }) - - // Setup the mocks before each test. - beforeEach(() => { - // Mock the req and res objects used by Express routes. - req = mockReq - res = mockRes - - // Explicitly reset the parmas and body. - //req.params = {} - req.body = {} - req.query = {} - req.locals = {} - - // Activate nock if it's inactive. - if (!nock.isActive()) nock.activate() - - sandbox = sinon.createSandbox() - }) - - afterEach(() => { - // Clean up HTTP mocks. - nock.cleanAll() // clear interceptor list. - nock.restore() - - sandbox.restore() - }) - - after(() => { - // Restore any pre-existing environment variables. - process.env.BITDB_URL = originalEnvVars.BITDB_URL - process.env.BITCOINCOM_BASEURL = originalEnvVars.BITCOINCOM_BASEURL - process.env.SLPDB_URL = originalEnvVars.SLPDB_URL - }) - - describe("#root", async () => { - // root route handler. - const root = slpRoute.testableComponents.root - - it("should respond to GET for base route", async () => { - const result = root(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(result.status, "slp", "Returns static string") - }) - }) - - describe("list()", () => { - // list route handler - const list = slpRoute.testableComponents.list - - it("should throw 500 when network issues", async () => { - // Save the existing SLPDB_URL. - const savedUrl2 = process.env.SLPDB_URL - - // Manipulate the URL to cause a 500 network error. - process.env.SLPDB_URL = "http://fakeurl/api/" - - const result = await list(req, res) - // console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.SLPDB_URL = savedUrl2 - - assert.isAbove( - res.statusCode, - 499, - "HTTP status code 500 or greater expected." - ) - //assert.include(result.error,"Network error: Could not communicate with full node","Error message expected") - }) - - it("should GET list", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - const b64 = `eyJ2IjozLCJxIjp7ImRiIjpbInQiXSwiZmluZCI6eyIkcXVlcnkiOnt9fSwicHJvamVjdCI6eyJ0b2tlbkRldGFpbHMiOjEsInRva2VuU3RhdHMiOjEsIl9pZCI6MH0sImxpbWl0IjoxMDB9fQ==` - - nock(process.env.SLPDB_URL) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockList) - } - - const result = await list(req, res) - // console.log(`test result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAnyKeys(result[0], [ - "id", - "timestamp", - "symbol", - "name", - "documentUri", - "documentHash", - "decimals", - "initialTokenQty" - ]) - }) - }) - - describe("listSingleToken()", () => { - const listSingleToken = slpRoute.testableComponents.listSingleToken - - it("should throw 400 if tokenId is empty", async () => { - const result = await listSingleToken(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "tokenId can not be empty") - }) - - it("should throw 503 when network issues", async () => { - // Save the existing BITDB_URL. - const savedUrl2 = process.env.SLPDB_URL - - // Manipulate the URL to cause a 500 network error. - process.env.SLPDB_URL = "http://fakeurl/api/" - - req.params.tokenId = - "650dea14c77f4d749608e36e375450c9ac91deb8b1b53e50cb0de2059a52d19a" - - const result = await listSingleToken(req, res) - // console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.SLPDB_URL = savedUrl2 - - assert.isAbove( - res.statusCode, - 499, - "HTTP status code 500 or greater expected." - ) - //assert.include(result.error,"Network error: Could not communicate with full node","Error message expected") - }) - - it("should return 'not found' for mainnet txid on testnet", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(mockServerUrl) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockSingleToken) - } - - req.params.tokenId = - // testnet - //"650dea14c77f4d749608e36e375450c9ac91deb8b1b53e50cb0de2059a52d19a" - // mainnet - "259908ae44f46ef585edef4bcc1e50dc06e4c391ac4be929fae27235b8158cf1" - - const result = await listSingleToken(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["id"]) - assert.include(result.id, "not found") - }) - - it("should get token information", async () => { - // testnet - const tokenIdToTest = - "650dea14c77f4d749608e36e375450c9ac91deb8b1b53e50cb0de2059a52d19a" - - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(mockServerUrl) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockSingleToken) - } - - req.params.tokenId = tokenIdToTest - - const result = await listSingleToken(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, [ - "id", - "blockCreated", - "blockLastActiveMint", - "blockLastActiveSend", - "circulatingSupply", - "containsBaton", - "mintingBatonStatus", - "txnsSinceGenesis", - "versionType", - "timestamp", - "symbol", - "name", - "documentUri", - "documentHash", - "decimals", - "initialTokenQty", - "totalBurned", - "totalMinted", - "validAddresses" - ]) - }) - }) - - describe("listBulkToken()", () => { - const listBulkToken = slpRoute.testableComponents.listBulkToken - - it("should throw 400 if tokenIds array is empty", async () => { - const result = await listBulkToken(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "tokenIds needs to be an array") - assert.equal(res.statusCode, 400) - }) - - it("should throw 400 error if array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.tokenIds = testArray - - const result = await listBulkToken(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should throw 400 if tokenId is empty", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(mockServerUrl) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockEmptyTokenId) - } - req.body.tokenIds = "" - - const result = await listBulkToken(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include( - result.error, - "tokenIds needs to be an array. Use GET for single tokenId." - ) - }) - - it("should throw 503 when network issues", async () => { - // Save the existing BITDB_URL. - const savedUrl2 = process.env.SLPDB_URL - - // Manipulate the URL to cause a 500 network error. - process.env.SLPDB_URL = "http://fakeurl/api/" - - req.body.tokenIds = [ - "650dea14c77f4d749608e36e375450c9ac91deb8b1b53e50cb0de2059a52d19a" - ] - - const result = await listBulkToken(req, res) - // console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.SLPDB_URL = savedUrl2 - - assert.isAbove( - res.statusCode, - 499, - "HTTP status code 500 or greater expected." - ) - //assert.include(result.error,"Network error: Could not communicate with full node","Error message expected") - }) - - it("should return 'not found' for mainnet txid on testnet", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(mockServerUrl) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockSingleTokenError) - } - - req.body.tokenIds = - // testnet - //"650dea14c77f4d749608e36e375450c9ac91deb8b1b53e50cb0de2059a52d19a" - // mainnet - ["0b314bc2b2905b8844222871c6b665ae3494117c83b11302824561bb904efb6b"] - - const result = await listBulkToken(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAllKeys(result[0], ["id", "valid"]) - assert.strictEqual(result[0].valid, false) - }) - - it("should get token information for single token ID", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(mockServerUrl) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockSingleToken) - } - - req.body.tokenIds = - // testnet - ["650dea14c77f4d749608e36e375450c9ac91deb8b1b53e50cb0de2059a52d19a"] - - const result = await listBulkToken(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAllKeys(result[0], [ - "blockCreated", - "blockLastActiveMint", - "blockLastActiveSend", - "circulatingSupply", - "containsBaton", - "mintingBatonStatus", - "txnsSinceGenesis", - "versionType", - "timestamp", - "symbol", - "name", - "documentUri", - "documentHash", - "decimals", - "initialTokenQty", - "id", - "totalBurned", - "totalMinted", - "validAddresses" - ]) - }) - - it("should get token information for multiple token IDs", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(mockServerUrl) - .get(uri => uri.includes("/")) - .times(2) - .reply(200, mockData.mockSingleToken) - } - - req.body.tokenIds = - // testnet - [ - "650dea14c77f4d749608e36e375450c9ac91deb8b1b53e50cb0de2059a52d19a", - "c35a87afad11c8d086c1449ffd8b0a84324e72b15b1bcfdf166a493551b4eea6" - ] - - const result = await listBulkToken(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAllKeys(result[0], [ - "blockCreated", - "blockLastActiveMint", - "blockLastActiveSend", - "circulatingSupply", - "containsBaton", - "mintingBatonStatus", - "txnsSinceGenesis", - "versionType", - "timestamp", - "symbol", - "name", - "documentUri", - "documentHash", - "decimals", - "initialTokenQty", - "id", - "totalBurned", - "totalMinted", - "validAddresses" - ]) - }) - }) - - describe("balancesForAddress()", () => { - const balancesForAddress = slpRoute.testableComponents.balancesForAddress - - it("should throw 400 if address is empty", async () => { - const result = await balancesForAddress(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "address can not be empty") - }) - - it("should throw 400 if address is invalid", async () => { - req.params.address = "badAddress" - - const result = await balancesForAddress(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Invalid BCH address.") - }) - - it("should throw 400 if address network mismatch", async () => { - req.params.address = - "simpleledger:qr5agtachyxvrwxu76vzszan5pnvuzy8duhv4lxrsk" - - const result = await balancesForAddress(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Invalid") - }) - - it("should throw 5XX error when network issues", async () => { - // Save the existing SLPDB_URL. - const savedUrl2 = process.env.SLPDB_URL - - // Manipulate the URL to cause a 500 network error. - process.env.SLPDB_URL = "http://fakeurl/api/" - - req.params.address = "slptest:qz35h5mfa8w2pqma2jq06lp7dnv5fxkp2shlcycvd5" - - const result = await balancesForAddress(req, res) - // console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.SLPDB_URL = savedUrl2 - - assert.isAbove( - res.statusCode, - 499, - "HTTP status code 500 or greater expected." - ) - assert.include( - result.error, - "Network error: Could not communicate", - "Error message expected" - ) - }) - - it("should get token balance for an address", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(mockServerUrl) - .get(uri => uri.includes("/")) - .times(2) - .reply(200, mockData.mockSingleAddress) - } - - req.params.address = "slptest:pz0qcslrqn7hr44hsszwl4lw5r6udkg6zqv7sq3kk7" - - const result = await balancesForAddress(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAllKeys(result[0], [ - "tokenId", - "balance", - "slpAddress", - "decimalCount" - ]) - }) - }) - - describe("balancesForAddressByTokenID()", () => { - const balancesForAddressByTokenID = - slpRoute.testableComponents.balancesForAddressByTokenID - - it("should throw 400 if address is empty", async () => { - req.params.address = "" - req.params.tokenId = - "650dea14c77f4d749608e36e375450c9ac91deb8b1b53e50cb0de2059a52d19a" - const result = await balancesForAddressByTokenID(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "address can not be empty") - }) - - it("should throw 400 if tokenId is empty", async () => { - req.params.address = - "simpleledger:qr5agtachyxvrwxu76vzszan5pnvuzy8duhv4lxrsk" - req.params.tokenId = "" - const result = await balancesForAddressByTokenID(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "tokenId can not be empty") - }) - - it("should throw 400 if address is invalid", async () => { - req.params.address = "badAddress" - req.params.tokenId = - "650dea14c77f4d749608e36e375450c9ac91deb8b1b53e50cb0de2059a52d19a" - - const result = await balancesForAddressByTokenID(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Invalid BCH address.") - }) - - it("should throw 400 if address network mismatch", async () => { - req.params.address = - "simpleledger:qr5agtachyxvrwxu76vzszan5pnvuzy8duhv4lxrsk" - - const result = await balancesForAddressByTokenID(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Invalid") - }) - - it("should throw 5XX error when network issues", async () => { - // Save the existing SLPDB_URL. - const savedUrl2 = process.env.SLPDB_URL - - // Manipulate the URL to cause a 500 network error. - process.env.SLPDB_URL = "http://fakeurl/api/" - - req.params.address = "slptest:qz4qnxcxwvmacgye8wlakhz0835x0w3vtvxu67w0ac" - req.params.tokenId = - "7ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796" - - const result = await balancesForAddressByTokenID(req, res) - // console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.SLPDB_URL = savedUrl2 - - assert.isAbove( - res.statusCode, - 499, - "HTTP status code 500 or greater expected." - ) - assert.include( - result.error, - "Network error: Could not communicate", - "Error message expected" - ) - }) - - it("should get token information", async () => { - if (process.env.TEST === "unit") { - nock(mockServerUrl) - .get(uri => uri.includes("/")) - .times(2) - .reply(200, mockData.mockSingleAddress) - } - - req.params.address = "slptest:pz0qcslrqn7hr44hsszwl4lw5r6udkg6zqv7sq3kk7" - req.params.tokenId = - "6b081fcd1f78b187be1464313dac8ff257251b727a42b613552a4040870aeb29" - - const result = await balancesForAddressByTokenID(req, res) - // console.log(`result: ${util.inspect(result)}`) - - // TODO - add decimalCount - // assert.hasAllKeys(result, ["tokenId", "balance", "decimalCount"]) - assert.hasAllKeys(result, ["tokenId", "balance"]) - }) - }) - - describe("convertAddressSingle()", () => { - const convertAddressSingle = - slpRoute.testableComponents.convertAddressSingle - - it("should throw 400 if address is empty", async () => { - req.params.address = "" - const result = await convertAddressSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "address can not be empty") - }) - // - it("should convert address", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.SLPDB_URL}`) - .post(``) - .reply(200, { result: mockData.mockConvert }) - } - - req.params.address = "slptest:qz35h5mfa8w2pqma2jq06lp7dnv5fxkp2shlcycvd5" - - const result = await convertAddressSingle(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["cashAddress", "legacyAddress", "slpAddress"]) - }) - }) - - describe("convertAddressBulk()", () => { - const convertAddressBulk = slpRoute.testableComponents.convertAddressBulk - - it("should throw 400 if addresses array is empty", async () => { - const result = await convertAddressBulk(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "addresses needs to be an array") - assert.equal(res.statusCode, 400) - }) - - it("should throw 400 error if array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.addresses = testArray - - const result = await convertAddressBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should error on malformed address", async () => { - try { - req.body.addresses = ["bitcoincash:qzs02v05l7qs5s5dwuj0cx5ehjm2c"] - - await convertAddressBulk(req, res) - - assert.equal(true, false, "Unsupported address format") - } catch (err) { - // console.log(`err.message: ${util.inspect(err.message)}`) - - assert.include(err.message, `Unsupported address format`) - } - }) - - it("should validate array with single element", async () => { - req.body.addresses = [ - "bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c" - ] - - const result = await convertAddressBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAllKeys(result[0], [ - "slpAddress", - "cashAddress", - "legacyAddress" - ]) - }) - - it("should validate array with multiple elements", async () => { - req.body.addresses = [ - "bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c", - "bitcoincash:qrehqueqhw629p6e57994436w730t4rzasnly00ht0" - ] - - const result = await convertAddressBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAllKeys(result[0], [ - "slpAddress", - "cashAddress", - "legacyAddress" - ]) - }) - }) - - describe("validateBulk()", () => { - const validateBulk = slpRoute.testableComponents.validateBulk - - it("should throw 400 if txid array is empty", async () => { - const result = await validateBulk(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "txids needs to be an array") - assert.equal(res.statusCode, 400) - }) - - it("should throw 400 error if array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.txids = testArray - - const result = await validateBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should validate array with single element", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - sandbox - .stub(slpRoute.testableComponents, "isValidSlpTxid") - .resolves(true) - } - - req.body.txids = [ - "78d57a82a0dd9930cc17843d9d06677f267777dd6b25055bad0ae43f1b884091" - ] - - const result = await validateBulk(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAllKeys(result[0], ["txid", "valid"]) - }) - - it("should validate array with two elements", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - sandbox - .stub(slpRoute.testableComponents, "isValidSlpTxid") - .resolves(true) - } - - req.body.txids = [ - "78d57a82a0dd9930cc17843d9d06677f267777dd6b25055bad0ae43f1b884091", - "82d996847a861b08b1601284ef7d40a1777d019154a6c4ed11571609dd3555ac" - ] - - const result = await validateBulk(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAllKeys(result[0], ["txid", "valid"]) - assert.equal(result.length, 2) - }) - }) - - describe("tokenStatsSingle()", () => { - const tokenStatsSingle = slpRoute.testableComponents.tokenStats - - it("should throw 400 if tokenID is empty", async () => { - req.params.tokenId = "" - const result = await tokenStatsSingle(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "tokenId can not be empty") - }) - // - it("should get token stats for tokenId", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.SLPDB_URL}`) - .get(uri => uri.includes("/")) - .reply(200, { - t: [ - { - tokenDetails: mockData.mockTokenDetails, - tokenStats: mockData.mockTokenStats - } - ] - }) - } - - req.params.tokenId = - "37279c7dc81ceb34d12f03344b601c582e931e05d0e552c29c428bfa39d39af3" - - const result = await tokenStatsSingle(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, [ - "blockCreated", - "blockLastActiveMint", - "blockLastActiveSend", - "containsBaton", - "initialTokenQty", - "mintingBatonStatus", - "circulatingSupply", - "decimals", - "documentHash", - "versionType", - "timestamp", - "documentUri", - "name", - "symbol", - "id", - "totalBurned", - "totalMinted", - "txnsSinceGenesis", - "validAddresses" - ]) - }) - }) - - describe("balancesForTokenSingle()", () => { - const balancesForTokenSingle = - slpRoute.testableComponents.balancesForTokenSingle - - it("should throw 400 if tokenID is empty", async () => { - req.params.tokenId = "" - const result = await balancesForTokenSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "tokenId can not be empty") - }) - // - it("should get balances for tokenId", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.SLPDB_URL}`) - .get(uri => uri.includes("/")) - .reply(200, { - a: [mockData.mockBalance] - }) - } - - req.params.tokenId = - "37279c7dc81ceb34d12f03344b601c582e931e05d0e552c29c428bfa39d39af3" - - const result = await balancesForTokenSingle(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result[0], ["tokenId", "slpAddress", "tokenBalance"]) - }) - }) - - describe("txDetails()", () => { - let txDetails = slpRoute.testableComponents.txDetails - - it("should throw 400 if txid is empty", async () => { - const result = await txDetails(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "txid can not be empty") - }) - - it("should throw 400 for malformed txid", async () => { - req.params.txid = - "57b3082a2bf269b3d6f40fee7fb9c664e8256a88ca5ee2697c05b9457" - - const result = await txDetails(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "This is not a txid") - }) - - it("should throw 400 for non-existant txid", async () => { - // Integration test - if (process.env.TEST !== "unit") { - req.params.txid = - "57b3082a2bf269b3d6f40fee7fb9c664e8256a88ca5ee2697c05b94578223333" - - const result = await txDetails(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "TXID not found") - } - }) - - it("should get tx details with token info", async () => { - if (process.env.TEST === "unit") { - // Mock the slpjs library for unit tests. - pathStub.BitboxNetwork = slpjsMock.BitboxNetwork - txDetails = slpRouteStub.testableComponents.txDetails - } - - req.params.txid = - "57b3082a2bf269b3d6f40fee7fb9c664e8256a88ca5ee2697c05b9457822d446" - - const result = await txDetails(req, res) - //console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.hasAnyKeys(result, ["tokenIsValid", "tokenInfo"]) - }) - }) - - describe("txsTokenIdAddressSingle()", () => { - const txsTokenIdAddressSingle = - slpRoute.testableComponents.txsTokenIdAddressSingle - - it("should throw 400 if tokenId is empty", async () => { - req.params.tokenId = "" - const result = await txsTokenIdAddressSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "tokenId can not be empty") - }) - - it("should throw 400 if address is empty", async () => { - req.params.tokenId = - "495322b37d6b2eae81f045eda612b95870a0c2b6069c58f70cf8ef4e6a9fd43a" - req.params.address = "" - const result = await txsTokenIdAddressSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "address can not be empty") - }) - /* - it("should get tx details with tokenId and address", async () => { - if (process.env.TEST === "unit") { - nock(`${process.env.SLPDB_URL}`) - .get(uri => uri.includes("/")) - .reply(200, { - c: mockData.mockTransactions - }) - } - - //req.params.tokenId = - // "37279c7dc81ceb34d12f03344b601c582e931e05d0e552c29c428bfa39d39af3" - //req.params.address = "slptest:qr83cu3p7yg9yac7qthwm0nul2ev2kukvsqmes3vl0" - - req.params.tokenId = - "7ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796" - req.params.address = "slptest:qpwa35xq0q0cnmdu0rwzkct369hddzsqpsqdzw6h9h" - - - const result = await txsTokenIdAddressSingle(req, res) - console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.hasAnyKeys(result[0], ["txid", "tokenDetails"]) - }) -*/ - }) -}) diff --git a/test/v2/transaction.js b/test/v2/transaction.js deleted file mode 100644 index 4eb1bdc..0000000 --- a/test/v2/transaction.js +++ /dev/null @@ -1,333 +0,0 @@ -/* - TESTS FOR THE TRANSACTION.TS LIBRARY - - This test file uses the environment variable TEST to switch between unit - and integration tests. By default, TEST is set to 'unit'. Set this variable - to 'integration' to run the tests against BCH mainnet. - - TODO: - -See "should throw an error for an invalid txid" for detailsSingle: - --The error handler should be refactored to return an intelligent error message, - instead of the 503 error it is returning now. -*/ - -"use strict" - -const chai = require("chai") -const assert = chai.assert -const transactionRoute = require("../../src/routes/v2/transaction") -const nock = require("nock") // HTTP mocking - -let originalEnvVars // Used during transition from integration to unit tests. - -// Mocking data. -const { mockReq, mockRes } = require("./mocks/express-mocks") -const mockData = require("./mocks/transaction-mocks") - -// Used for debugging. -const util = require("util") -util.inspect.defaultOptions = { depth: 1 } - -describe("#Transactions", () => { - let req, res - - before(() => { - // Save existing environment variables. - originalEnvVars = { - BITCOINCOM_BASEURL: process.env.BITCOINCOM_BASEURL, - RPC_BASEURL: process.env.RPC_BASEURL, - RPC_USERNAME: process.env.RPC_USERNAME, - RPC_PASSWORD: process.env.RPC_PASSWORD - } - - // Set default environment variables for unit tests. - if (!process.env.TEST) process.env.TEST = "unit" - if (process.env.TEST === "unit") { - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - process.env.RPC_BASEURL = "http://fakeurl/api" - process.env.RPC_USERNAME = "fakeusername" - process.env.RPC_PASSWORD = "fakepassword" - } - }) - - // Setup the mocks before each test. - beforeEach(() => { - // Mock the req and res objects used by Express routes. - req = mockReq - res = mockRes - - // Explicitly reset the parmas and body. - req.params = {} - req.body = {} - req.query = {} - - // Activate nock if it's inactive. - if (!nock.isActive()) nock.activate() - }) - - afterEach(() => { - // Clean up HTTP mocks. - nock.cleanAll() // clear interceptor list. - nock.restore() - }) - - after(() => { - // Restore any pre-existing environment variables. - process.env.BITCOINCOM_BASEURL = originalEnvVars.BITCOINCOM_BASEURL - process.env.RPC_BASEURL = originalEnvVars.RPC_BASEURL - process.env.RPC_USERNAME = originalEnvVars.RPC_USERNAME - process.env.RPC_PASSWORD = originalEnvVars.RPC_PASSWORD - }) - - describe("#root", async () => { - // root route handler. - const root = transactionRoute.testableComponents.root - - it("should respond to GET for base route", async () => { - const result = root(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(result.status, "transaction", "Returns static string") - }) - }) - - describe("#detailsBulk", async () => { - const detailsBulk = transactionRoute.testableComponents.detailsBulk - - it("should throw an error for an empty body", async () => { - req.body = {} - - const result = await detailsBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "txids needs to be an array", - "Proper error message" - ) - }) - - it("should error on non-array single txid", async () => { - req.body = { - txids: `6f235bd3a689f03c11969cd649ccad592462ca958bc519a30194e7a67b349a40` - } - - const result = await detailsBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "txids needs to be an array", - "Proper error message" - ) - }) - - it("should throw an error for an invalid txid", async () => { - const fakeTXID = `02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/tx/${fakeTXID}`) - .reply(400, { - result: { error: "parameter 1 must be hexadecimal string" } - }) - } - - req.body = { - txids: [fakeTXID] - } - - const result = await detailsBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - }) - - it("should process a single txid", async () => { - const txid = `6f235bd3a689f03c11969cd649ccad592462ca958bc519a30194e7a67b349a40` - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/tx/${txid}`) - .reply(200, mockData.mockDetails) - } - - req.body = { - txids: [txid] - } - - const result = await detailsBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAnyKeys(result[0], [ - "txid", - "version", - "locktime", - "vin", - "vout", - "blockhash", - "blockheight", - "confirmations", - "time", - "blocktime", - "valueOut", - "size", - "valueIn", - "fees" - ]) - }) - - it("should process a multiple txids", async () => { - const txid1 = `6f235bd3a689f03c11969cd649ccad592462ca958bc519a30194e7a67b349a40` - const txid2 = `8d4fd4dcaa9d8051dc7d862dc23d8aa23e20b77b9c928c49380685459caa7043` - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/tx/${txid1}`) - .reply(200, mockData.mockDetails) - } - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/tx/${txid2}`) - .reply(200, mockData.mockDetails) - } - - req.body = { - txids: [txid1, txid2] - } - - const result = await detailsBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAnyKeys(result[0], [ - "txid", - "version", - "locktime", - "vin", - "vout", - "blockhash", - "blockheight", - "confirmations", - "time", - "blocktime", - "valueOut", - "size", - "valueIn", - "fees" - ]) - }) - }) - - describe("#detailsSingle", () => { - // details route handler. - const detailsSingle = transactionRoute.testableComponents.detailsSingle - - it("should throw 400 if txid is empty", async () => { - const result = await detailsSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "txid can not be empty") - }) - - it("should error on an array", async () => { - req.params.txid = [`qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] - - const result = await detailsSingle(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "txid can not be an array", - "Proper error message" - ) - }) - - it("should throw an error for an invalid txid", async () => { - if (process.env.TEST !== "unit") { - req.params.txid = `02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - - const result = await detailsSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // The error handling code should probably be updated to respond with a better - // error message. - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "parameter 1 must be hexadecimal string", - "Proper error message" - ) - } - }) - - it("should throw 500 when network issues", async () => { - const savedUrl = process.env.BITCOINCOM_BASEURL - - try { - req.params.txid = `6f235bd3a689f03c11969cd649ccad592462ca958bc519a30194e7a67b349a40` - - // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - - const result = await detailsSingle(req, res) - - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - - assert.isAbove( - res.statusCode, - 499, - "HTTP status code 500 or greater expected." - ) - //assert.include(result.error,"Network error: Could not communicate with full node","Error message expected") - } catch (err) { - // Restore the saved URL. - process.env.BITCOINCOM_BASEURL = savedUrl - } - }) - - it("should get details for a single address", async () => { - const txid = `6f235bd3a689f03c11969cd649ccad592462ca958bc519a30194e7a67b349a40` - req.params.txid = txid - - // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.BITCOINCOM_BASEURL}`) - .get(`/tx/${txid}`) - .reply(200, mockData.mockDetails) - } - - // Call the details API. - const result = await detailsSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Assert that required fields exist in the returned object. - assert.hasAllKeys(result, [ - "txid", - "version", - "locktime", - "vin", - "vout", - "blockhash", - "blockheight", - "confirmations", - "time", - "blocktime", - "valueOut", - "size", - "valueIn", - "fees" - ]) - assert.isArray(result.vin) - assert.isArray(result.vout) - }) - }) -}) diff --git a/test/v2/util.js b/test/v2/util.js deleted file mode 100644 index e550f14..0000000 --- a/test/v2/util.js +++ /dev/null @@ -1,300 +0,0 @@ -/* - TESTS FOR THE UTIL.TS LIBRARY - - This test file uses the environment variable TEST to switch between unit - and integration tests. By default, TEST is set to 'unit'. Set this variable - to 'integration' to run the tests against BCH mainnet. -*/ - -"use strict" - -const chai = require("chai") -const assert = chai.assert -const utilRoute = require("../../src/routes/v2/util") -const nock = require("nock") // HTTP mocking - -let originalEnvVars // Used during transition from integration to unit tests. - -// Mocking data. -const { mockReq, mockRes } = require("./mocks/express-mocks") -const mockData = require("./mocks/util-mocks") - -// Used for debugging. -const util = require("util") -util.inspect.defaultOptions = { depth: 1 } - -describe("#Util", () => { - let req, res - - before(() => { - // Save existing environment variables. - originalEnvVars = { - BITCOINCOM_BASEURL: process.env.BITCOINCOM_BASEURL, - RPC_BASEURL: process.env.RPC_BASEURL, - RPC_USERNAME: process.env.RPC_USERNAME, - RPC_PASSWORD: process.env.RPC_PASSWORD - } - - // Set default environment variables for unit tests. - if (!process.env.TEST) process.env.TEST = "unit" - if (process.env.TEST === "unit") { - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - process.env.RPC_BASEURL = "http://fakeurl/api" - process.env.RPC_USERNAME = "fakeusername" - process.env.RPC_PASSWORD = "fakepassword" - } - }) - - // Setup the mocks before each test. - beforeEach(() => { - // Mock the req and res objects used by Express routes. - req = mockReq - res = mockRes - - // Explicitly reset the parmas and body. - req.params = {} - req.body = {} - req.query = {} - - // Activate nock if it's inactive. - if (!nock.isActive()) nock.activate() - }) - - afterEach(() => { - // Clean up HTTP mocks. - nock.cleanAll() // clear interceptor list. - nock.restore() - }) - - after(() => { - // Restore any pre-existing environment variables. - process.env.BITCOINCOM_BASEURL = originalEnvVars.BITCOINCOM_BASEURL - process.env.RPC_BASEURL = originalEnvVars.RPC_BASEURL - process.env.RPC_USERNAME = originalEnvVars.RPC_USERNAME - process.env.RPC_PASSWORD = originalEnvVars.RPC_PASSWORD - }) - - describe("#root", async () => { - // root route handler. - const root = utilRoute.testableComponents.root - - it("should respond to GET for base route", async () => { - const result = root(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.equal(result.status, "util", "Returns static string") - }) - }) - - describe("#validateAddressSingle", async () => { - const validateAddress = utilRoute.testableComponents.validateAddressSingle - - it("should throw an error for an empty address", async () => { - const result = await validateAddress(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "address can not be empty", - "Proper error message" - ) - }) - - it("should throw 503 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" - - req.params.address = `bchtest:qqqk4y6lsl5da64sg5qc3xezmplyu5kmpyz2ysaa5y` - - const result = await validateAddress(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.RPC_BASEURL = savedUrl2 - - assert.isAbove( - res.statusCode, - 499, - "HTTP status code 500 or greater expected." - ) - //assert.include(result.error,"Network error: Could not communicate with full node","Error message expected") - }) - - it("should validate address", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockAddress }) - } - - req.params.address = `bchtest:qqqk4y6lsl5da64sg5qc3xezmplyu5kmpyz2ysaa5y` - - const result = await validateAddress(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, [ - "isvalid", - "address", - "scriptPubKey", - "ismine", - "iswatchonly", - "isscript" - ]) - }) - }) - - describe("#validateAddressBulk", async () => { - const validateAddressBulk = utilRoute.testableComponents.validateAddressBulk - - it("should throw an error for an empty body", async () => { - const result = await validateAddressBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "addresses needs to be an array. Use GET for single address.", - "Proper error message" - ) - }) - - it("should error on non-array single address", async () => { - req.body = { - addresses: `bchtest:qqqk4y6lsl5da64sg5qc3xezmplyu5kmpyz2ysaa5y` - } - - const result = await validateAddressBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "addresses needs to be an array. Use GET for single address.", - "Proper error message" - ) - }) - - it("should throw 400 error if addresses array is too large", async () => { - const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") - - req.body.addresses = testArray - - const result = await validateAddressBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") - }) - - it("should error on invalid address", async () => { - req.body = { - addresses: [`bchtest:qqqk4y6lsl5da64sg5qc3xezmpl`] - } - - const result = await validateAddressBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "Invalid BCH address. Double check your address is valid", - "Proper error message" - ) - }) - - it("should error on mainnet address when using testnet", async () => { - req.body = { - addresses: [`bitcoincash:qrcc3jsqpgwqcdru70sk54sd0g3l04q7c53ycm6ucj`] - } - - const result = await validateAddressBulk(req, res) - - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include( - result.error, - "Invalid network. Trying to use a testnet address on mainnet, or vice versa.", - "Proper error message" - ) - }) - - it("should throw 503 when network issues", async () => { - // Save the existing RPC URL. - const savedUrl2 = process.env.RPC_BASEURL - - // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" - - req.body.addresses = [ - `bchtest:qqqk4y6lsl5da64sg5qc3xezmplyu5kmpyz2ysaa5y` - ] - - const result = await validateAddressBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - // Restore the saved URL. - process.env.RPC_BASEURL = savedUrl2 - - assert.isAbove( - res.statusCode, - 499, - "HTTP status code 500 or greater expected." - ) - }) - - it("should validate a single address", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .reply(200, { result: mockData.mockAddress }) - } - - req.body.addresses = [ - `bchtest:qqqk4y6lsl5da64sg5qc3xezmplyu5kmpyz2ysaa5y` - ] - - const result = await validateAddressBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAllKeys(result[0], [ - "isvalid", - "address", - "scriptPubKey", - "ismine", - "iswatchonly", - "isscript" - ]) - }) - - it("should validate a multiple addresses", async () => { - // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - nock(`${process.env.RPC_BASEURL}`) - .post(``) - .times(2) - .reply(200, { result: mockData.mockAddress }) - } - - req.body.addresses = [ - `bchtest:qqqk4y6lsl5da64sg5qc3xezmplyu5kmpyz2ysaa5y`, - `bchtest:qqqk4y6lsl5da64sg5qc3xezmplyu5kmpyz2ysaa5y` - ] - - const result = await validateAddressBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAllKeys(result[0], [ - "isvalid", - "address", - "scriptPubKey", - "ismine", - "iswatchonly", - "isscript" - ]) - }) - }) -}) diff --git a/test/v3/blockchain.js b/test/v3/blockchain.js index 2101961..fe1d70b 100644 --- a/test/v3/blockchain.js +++ b/test/v3/blockchain.js @@ -11,7 +11,7 @@ const chai = require("chai") const assert = chai.assert const nock = require("nock") // HTTP mocking -const blockchainRoute = require("../../src/routes/v3/blockchain") +const blockchainRoute = require("../../src/routes/v3/full-node/blockchain") const util = require("util") util.inspect.defaultOptions = { depth: 1 } diff --git a/test/v3/control.js b/test/v3/control.js index dd2d799..e651b26 100644 --- a/test/v3/control.js +++ b/test/v3/control.js @@ -11,7 +11,7 @@ const chai = require("chai") const assert = chai.assert -const controlRoute = require("../../src/routes/v3/control") +const controlRoute = require("../../src/routes/v3/full-node/control") const nock = require("nock") // HTTP mocking let originalEnvVars // Used during transition from integration to unit tests. diff --git a/test/v3/mining.js b/test/v3/mining.js index e9a8b65..7ba81c4 100644 --- a/test/v3/mining.js +++ b/test/v3/mining.js @@ -10,7 +10,7 @@ const chai = require("chai") const assert = chai.assert -const miningRoute = require("../../src/routes/v3/mining") +const miningRoute = require("../../src/routes/v3/full-node/mining") const nock = require("nock") // HTTP mocking let originalEnvVars // Used during transition from integration to unit tests. diff --git a/test/v3/rate-limits.js b/test/v3/rate-limits.js index 3b2db1f..0d81b5b 100644 --- a/test/v3/rate-limits.js +++ b/test/v3/rate-limits.js @@ -13,7 +13,7 @@ const { mockReq, mockRes, mockNext } = require("./mocks/express-mocks") // Libraries under test let rateLimitMiddleware = require("../../src/middleware/route-ratelimit") -const controlRoute = require("../../src/routes/v3/control") +const controlRoute = require("../../src/routes/v3/full-node/control") let req, res, next let originalEnvVars // Used during transition from integration to unit tests. diff --git a/test/v3/raw-transactions.js b/test/v3/raw-transactions.js index c6af05e..bf1c78b 100644 --- a/test/v3/raw-transactions.js +++ b/test/v3/raw-transactions.js @@ -14,7 +14,7 @@ const chai = require("chai") const assert = chai.assert -const rawtransactions = require("../../src/routes/v3/rawtransactions") +const rawtransactions = require("../../src/routes/v3/full-node/rawtransactions") const nock = require("nock") // HTTP mocking let originalEnvVars // Used during transition from integration to unit tests.