From b0c5b4c6817952bdcead29275baa96dd47bb0782 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Fri, 6 Dec 2019 16:17:43 -0800 Subject: [PATCH] Removed bitcore as a downstream service --- src/app.js | 2 - src/routes/v3/bitcore.js | 395 ---------------------- test/v3/integration/bitcore.js | 599 --------------------------------- 3 files changed, 996 deletions(-) delete mode 100644 src/routes/v3/bitcore.js delete mode 100644 test/v3/integration/bitcore.js diff --git a/src/app.js b/src/app.js index 6010573..54661d7 100644 --- a/src/app.js +++ b/src/app.js @@ -30,7 +30,6 @@ 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") -const bitcoreV3 = require("./routes/v3/bitcore") const blockbookV3 = require("./routes/v3/blockbook") require("dotenv").config() @@ -92,7 +91,6 @@ app.use(`/${v3prefix}/` + `rawtransactions`, rawtransactionsV3.router) app.use(`/${v3prefix}/` + `util`, utilV3.router) app.use(`/${v3prefix}/` + `slp`, slpV3.router) app.use(`/${v3prefix}/` + `xpub`, xpubV3.router) -app.use(`/${v3prefix}/` + `bitcore`, bitcoreV3.router) app.use(`/${v3prefix}/` + `blockbook`, blockbookV3.router) // catch 404 and forward to error handler diff --git a/src/routes/v3/bitcore.js b/src/routes/v3/bitcore.js deleted file mode 100644 index 6bccd26..0000000 --- a/src/routes/v3/bitcore.js +++ /dev/null @@ -1,395 +0,0 @@ -/* - Bitcore Node API route -*/ - -"use strict" - -const express = require("express") -const axios = require("axios") -const routeUtils = require("./route-utils") -const wlogger = require("../../util/winston-logging") - -const router = express.Router() - -// Used for processing error messages before sending them to the user. -const util = require("util") -util.inspect.defaultOptions = { depth: 1 } - -const BCHJS = require("@chris.troutner/bch-js") -const bchjs = new BCHJS() - -//const BITCORE_URL = process.env.BITCORE_URL - -// Connect the route endpoints to their handler functions. -router.get("/", root) -router.get("/balance/:address", balanceSingle) -router.post("/balance", balanceBulk) -router.get("/utxos/:address", utxosSingle) -router.post("/utxos", utxosBulk) - -// Root API endpoint. Simply acknowledges that it exists. -function root(req, res, next) { - return res.json({ status: "address" }) -} - -// Query the Bitcore Node API for a balance on a single BCH address. -// Returns a Promise. -async function balanceFromBitcore(thisAddress) { - try { - //console.log(`BITCORE_URL: ${BITCORE_URL}`) - - // Convert the address to a cashaddr without a prefix. - const addr = bchjs.Address.toCashAddress(thisAddress, false) - - // Determine if we are working with the testnet or mainnet networks. - let network = "mainnet" - if (process.env.NETWORK === "testnet") network = "testnet" - - const path = `${process.env.BITCORE_URL}api/BCH/${network}/address/${addr}/balance` - - //console.log(`path: ${path}`) - - // Query the Bitcore Node API. - const axiosResponse = await axios.get(path) - const retData = axiosResponse.data - //console.log(`retData: ${util.inspect(retData)}`) - - return retData - } catch (err) { - // Dev Note: Do not log error messages here. Throw them instead and let the - // parent function handle it. - throw err - } -} - -/** - * @api {get} /bitcore/balance/:address Get BCH balance for an address - * @apiName GetBalance - * @apiGroup Bitcore - * - * @apiParam {String} address Bitcoin Cash address. - * - * @apiSuccess {String} firstname Firstname of the User. - * @apiSuccess {String} lastname Lastname of the User. - */ -// GET handler for single balance -async function balanceSingle(req, res, next) { - try { - const address = req.params.address - - if (!address || address === "") { - res.status(400) - return res.json({ error: "address can not be empty" }) - } - - // Reject if address is an array. - if (Array.isArray(address)) { - res.status(400) - return res.json({ - error: "address can not be an array. Use POST for bulk upload." - }) - } - - wlogger.debug( - `Executing bitcore/balanceSingle with this address: `, - address - ) - - // Ensure the input is a valid BCH address. - try { - const legacyAddr = bchjs.Address.toLegacyAddress(address) - } catch (err) { - res.status(400) - return res.json({ - error: `Invalid BCH address. Double check your address is valid: ${address}` - }) - } - - // Prevent a common user error. Ensure they are using the correct network address. - const networkIsValid = routeUtils.validateNetwork(address) - if (!networkIsValid) { - res.status(400) - return res.json({ - error: `Invalid network. Trying to use a testnet address on mainnet, or vice versa.` - }) - } - - // Query the Bitcore Node API. - const retData = await balanceFromBitcore(address) - - // Return the retrieved address information. - res.status(200) - return res.json(retData) - } catch (err) { - // Attempt to decode the error message. - const { msg, status } = routeUtils.decodeError(err) - if (msg) { - res.status(status) - return res.json({ error: msg }) - } - - // Write out error to error log. - wlogger.error(`Error in bitcore.js/balanceSingle().`, err) - - res.status(500) - return res.json({ error: util.inspect(err) }) - } -} - -// POST handler for bulk queries on address details -// curl -d '{"addresses": ["bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr", "bchtest:qp6hgvevf4gzz6l7pgcte3gaaud9km0l459fa23dul"]}' -H "Content-Type: application/json" https://mainnet.bchjs.cash/v2/address/details -// curl -d '{"addresses": ["bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr", "bchtest:qp6hgvevf4gzz6l7pgcte3gaaud9km0l459fa23dul"], "from": 1, "to": 5}' -H "Content-Type: application/json" https://mainnet.bchjs.cash/v2/address/details -async function balanceBulk(req, res, next) { - try { - let addresses = req.body.addresses - const currentPage = req.body.page ? parseInt(req.body.page, 10) : 0 - - // Reject if addresses is not an array. - if (!Array.isArray(addresses)) { - res.status(400) - return res.json({ - error: "addresses needs to be an array. Use GET for single address." - }) - } - - // Enforce array size rate limits - if (!routeUtils.validateArraySize(req, addresses)) { - res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330 - return res.json({ - error: `Array too large.` - }) - } - - wlogger.debug( - `Executing bitcore.js/balanceBulk with these addresses: `, - addresses - ) - - // Validate each element in the address array. - for (let i = 0; i < addresses.length; i++) { - const thisAddress = addresses[i] - - // Ensure the input is a valid BCH address. - try { - bchjs.Address.toLegacyAddress(thisAddress) - } catch (err) { - res.status(400) - return res.json({ - error: `Invalid BCH address. Double check your address is valid: ${thisAddress}` - }) - } - - // Prevent a common user error. Ensure they are using the correct network address. - const networkIsValid = routeUtils.validateNetwork(thisAddress) - if (!networkIsValid) { - res.status(400) - return res.json({ - error: `Invalid network for address ${thisAddress}. Trying to use a testnet address on mainnet, or vice versa.` - }) - } - } - - // Loops through each address and creates an array of Promises, querying - // Insight API in parallel. - addresses = addresses.map(async (address, index) => - balanceFromBitcore(address) - ) - - // Wait for all parallel Insight requests to return. - const result = await axios.all(addresses) - - // Return the array of retrieved address information. - res.status(200) - return res.json(result) - } catch (err) { - // Attempt to decode the error message. - const { msg, status } = routeUtils.decodeError(err) - if (msg) { - res.status(status) - return res.json({ error: msg }) - } - - wlogger.error(`Error in bitcore.js/balanceBulk().`, err) - - res.status(500) - return res.json({ error: util.inspect(err) }) - } -} - -// Query the Bitcore Node API for utxos associated with a BCH address. -// Returns a Promise. -async function utxosFromBitcore(thisAddress) { - try { - //console.log(`BITCORE_URL: ${BITCORE_URL}`) - - // Convert the address to a cashaddr without a prefix. - const addr = bchjs.Address.toCashAddress(thisAddress, false) - - // Determine if we are working with the testnet or mainnet networks. - let network = "mainnet" - if (process.env.NETWORK === "testnet") network = "testnet" - - const path = `${process.env.BITCORE_URL}api/BCH/${network}/address/${addr}/?unspent=true` - - // Query the Bitcore Node API. - const axiosResponse = await axios.get(path) - const retData = axiosResponse.data - //console.log(`retData: ${util.inspect(retData)}`) - - return retData - } catch (err) { - // Dev Note: Do not log error messages here. Throw them instead and let the - // parent function handle it. - throw err - } -} - -// GET handler for single balance -async function utxosSingle(req, res, next) { - try { - const address = req.params.address - - if (!address || address === "") { - res.status(400) - return res.json({ error: "address can not be empty" }) - } - - // Reject if address is an array. - if (Array.isArray(address)) { - res.status(400) - return res.json({ - error: "address can not be an array. Use POST for bulk upload." - }) - } - - wlogger.debug(`Executing bitcore/utxoSingle with this address: `, address) - - // Ensure the input is a valid BCH address. - try { - const legacyAddr = bchjs.Address.toLegacyAddress(address) - } catch (err) { - res.status(400) - return res.json({ - error: `Invalid BCH address. Double check your address is valid: ${address}` - }) - } - - // Prevent a common user error. Ensure they are using the correct network address. - const networkIsValid = routeUtils.validateNetwork(address) - if (!networkIsValid) { - res.status(400) - return res.json({ - error: `Invalid network. Trying to use a testnet address on mainnet, or vice versa.` - }) - } - - // Query the Bitcore Node API. - const retData = await utxosFromBitcore(address) - - // Return the retrieved address information. - res.status(200) - return res.json(retData) - } catch (err) { - // Attempt to decode the error message. - const { msg, status } = routeUtils.decodeError(err) - if (msg) { - res.status(status) - return res.json({ error: msg }) - } - - // Write out error to error log. - wlogger.error(`Error in bitcore.js/utxosSingle().`, err) - - res.status(500) - return res.json({ error: util.inspect(err) }) - } -} - -// POST handler for bulk queries on address utxos -async function utxosBulk(req, res, next) { - try { - let addresses = req.body.addresses - const currentPage = req.body.page ? parseInt(req.body.page, 10) : 0 - - // Reject if addresses is not an array. - if (!Array.isArray(addresses)) { - res.status(400) - return res.json({ - error: "addresses needs to be an array. Use GET for single address." - }) - } - - // Enforce array size rate limits - if (!routeUtils.validateArraySize(req, addresses)) { - res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330 - return res.json({ - error: `Array too large.` - }) - } - - wlogger.debug( - `Executing bitcore.js/utxosBulk with these addresses: `, - addresses - ) - - // Validate each element in the address array. - for (let i = 0; i < addresses.length; i++) { - const thisAddress = addresses[i] - - // Ensure the input is a valid BCH address. - try { - bchjs.Address.toLegacyAddress(thisAddress) - } catch (err) { - res.status(400) - return res.json({ - error: `Invalid BCH address. Double check your address is valid: ${thisAddress}` - }) - } - - // Prevent a common user error. Ensure they are using the correct network address. - const networkIsValid = routeUtils.validateNetwork(thisAddress) - if (!networkIsValid) { - res.status(400) - return res.json({ - error: `Invalid network for address ${thisAddress}. Trying to use a testnet address on mainnet, or vice versa.` - }) - } - } - - // Loops through each address and creates an array of Promises, querying - // Insight API in parallel. - addresses = addresses.map(async (address, index) => - utxosFromBitcore(address) - ) - - // Wait for all parallel Insight requests to return. - const result = await axios.all(addresses) - - // Return the array of retrieved address information. - res.status(200) - return res.json(result) - } catch (err) { - // Attempt to decode the error message. - const { msg, status } = routeUtils.decodeError(err) - if (msg) { - res.status(status) - return res.json({ error: msg }) - } - - wlogger.error(`Error in bitcore.js/utxosBulk().`, err) - - res.status(500) - return res.json({ error: util.inspect(err) }) - } -} - -module.exports = { - router, - testableComponents: { - root, - balanceSingle, - balanceBulk, - utxosSingle, - utxosBulk - } -} diff --git a/test/v3/integration/bitcore.js b/test/v3/integration/bitcore.js deleted file mode 100644 index fd6cf67..0000000 --- a/test/v3/integration/bitcore.js +++ /dev/null @@ -1,599 +0,0 @@ -/* - TESTS FOR THE BITCORE.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: -*/ - -"use strict" - -const chai = require("chai") -const assert = chai.assert -const bitcoreRoute = require("../../src/routes/v3/bitcore") -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/bitcore-mock") - -// Used for debugging. -const util = require("util") -util.inspect.defaultOptions = { depth: 1 } - -describe("#Bitcore Router", () => { - let req, res, mockServerUrl - - before(() => { - originalUrl = process.env.BITCORE_URL - - // Set default environment variables for unit tests. - if (!process.env.TEST) process.env.TEST = "unit" - if (process.env.TEST === "unit") { - process.env.BITCORE_URL = "http://fakeurl/api/" - mockServerUrl = `http://fakeurl` - } - // 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.BITCORE_URL = originalUrl - }) - - describe("#root", () => { - // root route handler. - const root = bitcoreRoute.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("#Balance Single", () => { - // details route handler. - const balanceSingle = bitcoreRoute.testableComponents.balanceSingle - - it("should throw 400 if address is empty", async () => { - const result = await balanceSingle(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 balanceSingle(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 balanceSingle(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 balanceSingle(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.BITCORE_URL - - try { - req.params.address = `qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - - // Switch the Insight URL to something that will error out. - process.env.BITCORE_URL = "http://fakeurl/api/" - - const result = await balanceSingle(req, res) - - // Restore the saved URL. - process.env.BITCORE_URL = 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.BITCORE_URL = savedUrl - } - }) - - it("should get balance 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.BITCORE_URL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockBalance) - } - - // Call the details API. - const result = await balanceSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["confirmed", "unconfirmed", "balance"]) - assert.isNumber(result.confirmed) - assert.isNumber(result.unconfirmed) - assert.isNumber(result.balance) - }) - }) - - describe("#Balance Bulk", () => { - // details route handler. - const balanceBulk = bitcoreRoute.testableComponents.balanceBulk - - it("should throw an error for an empty body", async () => { - req.body = {} - - const result = await balanceBulk(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 balanceBulk(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 balanceBulk(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 balanceBulk(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 balanceBulk(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 balanceBulk(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 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(mockServerUrl) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockBalance) - } - - // Call the details API. - const result = await balanceBulk(req, res) - // console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAllKeys(result[0], ["confirmed", "unconfirmed", "balance"]) - assert.isNumber(result[0].confirmed) - assert.isNumber(result[0].unconfirmed) - assert.isNumber(result[0].balance) - }) - - 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(mockServerUrl) - .get(uri => uri.includes("/")) - .times(2) - .reply(200, mockData.mockBalance) - } - - // Call the details API. - const result = await balanceBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.equal(result.length, 2, "2 outputs for 2 inputs") - }) - }) - - describe("#UTXOs Single", () => { - // details route handler. - const utxosSingle = bitcoreRoute.testableComponents.utxosSingle - - it("should throw 400 if address is empty", async () => { - const result = await utxosSingle(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 utxosSingle(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 utxosSingle(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 utxosSingle(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.BITCORE_URL - - try { - req.params.address = `qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` - - // Switch the Insight URL to something that will error out. - process.env.BITCORE_URL = "http://fakeurl/api/" - - const result = await utxosSingle(req, res) - - // Restore the saved URL. - process.env.BITCORE_URL = 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.BITCORE_URL = savedUrl - } - }) - - it("should get utxos 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.BITCORE_URL}`) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockUtxos) - } - - // Call the details API. - const result = await utxosSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.hasAnyKeys(result[0], [ - "_id", - "chain", - "network", - "coinbase", - "mintIndex", - "spentTxid", - "mintTxid", - "mintHeight", - "spentHeight", - "address", - "script", - "value", - "confirmations" - ]) - }) - }) - - describe("#UTXO Bulk", () => { - // details route handler. - const utxosBulk = bitcoreRoute.testableComponents.utxosBulk - - it("should throw an error for an empty body", async () => { - req.body = {} - - const result = await utxosBulk(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 utxosBulk(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 utxosBulk(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 utxosBulk(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 utxosBulk(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 utxosBulk(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 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(mockServerUrl) - .get(uri => uri.includes("/")) - .reply(200, mockData.mockUtxos) - } - - // Call the details API. - const result = await utxosBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.isArray(result[0]) - assert.hasAnyKeys(result[0][0], [ - "_id", - "chain", - "network", - "coinbase", - "mintIndex", - "spentTxid", - "mintTxid", - "mintHeight", - "spentHeight", - "address", - "script", - "value", - "confirmations" - ]) - }) - - 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(mockServerUrl) - .get(uri => uri.includes("/")) - .times(2) - .reply(200, mockData.mockUtxos) - } - - // Call the details API. - const result = await utxosBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.isArray(result) - assert.isArray(result[0]) - assert.hasAnyKeys(result[0][0], [ - "_id", - "chain", - "network", - "coinbase", - "mintIndex", - "spentTxid", - "mintTxid", - "mintHeight", - "spentHeight", - "address", - "script", - "value", - "confirmations" - ]) - }) - }) -})