From 2dd8300a615ec226b061a7552cb8594c15430056 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Fri, 17 Jan 2020 15:53:07 -0800 Subject: [PATCH 1/2] minor comment --- src/blockchain.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/blockchain.js b/src/blockchain.js index b44648d..4b1d507 100644 --- a/src/blockchain.js +++ b/src/blockchain.js @@ -355,6 +355,7 @@ class Blockchain { } } + // getMempoolAncestors async getMempoolAncestors(txid, verbose = false) { if (typeof txid !== "string") txid = JSON.stringify(txid) From 643f89152ae78f569b23d80c4ed4ab2db6911b8c Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Thu, 23 Jan 2020 12:58:12 -0800 Subject: [PATCH 2/2] feat(ninsight): Added library to interface with Bitcoin.com ninsight indexer --- src/bch-js.js | 4 ++ src/ninsight.js | 80 +++++++++++++++++++++++++++++ test/integration/ninsight.js | 33 ++++++++++++ test/unit/fixtures/ninsight-mock.js | 20 ++++++++ test/unit/ninsight.js | 51 ++++++++++++++++++ 5 files changed, 188 insertions(+) create mode 100644 src/ninsight.js create mode 100644 test/integration/ninsight.js create mode 100644 test/unit/fixtures/ninsight-mock.js create mode 100644 test/unit/ninsight.js diff --git a/src/bch-js.js b/src/bch-js.js index 286d29b..b5e760a 100644 --- a/src/bch-js.js +++ b/src/bch-js.js @@ -29,6 +29,7 @@ const SLP = require("./slp/slp") const Blockbook = require("./blockbook") const OpenBazaar = require("./openbazaar") +const Ninsight = require("./ninsight") class BCHJS { constructor(config) { @@ -59,6 +60,9 @@ class BCHJS { // Populate OpenBazaar endpoints this.OpenBazaar = new OpenBazaar(libConfig) + // Bitcoin.com Ninsight indexer + this.Ninsight = new Ninsight() + // Populate Full Node this.Control = new Control(libConfig) this.Mining = new Mining(libConfig) diff --git a/src/ninsight.js b/src/ninsight.js new file mode 100644 index 0000000..ac2577a --- /dev/null +++ b/src/ninsight.js @@ -0,0 +1,80 @@ +/* + This library interacts with the ninsight REST API endpoints operated by + Bitcoin.com +*/ + +const axios = require("axios") + +let _this + +class Ninsight { + constructor(config) { + // this.restURL = config.restURL + // this.apiToken = config.apiToken + + this.ninsightURL = `https://bch-explorer.api.bitcoin.com/v1/` + + // Add JWT token to the authorization header. + this.axiosOptions = { + headers: { + authorization: `Token ${this.apiToken}`, + timeout: 15000 + } + } + + _this = this + } + + /** + * @api Ninsight.utxo() utxo() - Get list of uxto for address. + * @apiName Ninsight Utxo + * @apiGroup Ninsight + * @apiDescription Return list of uxto for address. + * + * @apiExample Example usage: + * (async () => { + * try { + * let utxo = await bchjs.Ninsight.utxo('bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c'); + * console.log(utxo); + * } catch(error) { + * console.error(error) + * } + * })() + * + * // [ + * // { + * // "txid": "d31dc2cf66fe4d3d3ae18e1065def58a64920746b1702b52f060e5edeea9883b", + * // "vout": 1, + * // "value": "1000000", + * // "height": 585570, + * // "confirmations": 10392 + * // }, + * // { + * // "txid": "41e9a118765ecf7a1ba4487c0863e23dba343cc5880381a72f0365ac2546c5fa", + * // "vout": 0, + * // "value": "1000000", + * // "height": 577125, + * // "confirmations": 18837 + * // } + * // ] + * + */ + async utxo(address) { + try { + if (typeof address !== "string") + throw new Error(`address needs to be a string.`) + + const response = await axios.get( + `${this.ninsightURL}addr/${address}/utxo`, + _this.axiosOptions + ) + + return response.data + } catch (error) { + if (error.response && error.response.data) throw error.response.data + else throw error + } + } +} + +module.exports = Ninsight diff --git a/test/integration/ninsight.js b/test/integration/ninsight.js new file mode 100644 index 0000000..0d30f87 --- /dev/null +++ b/test/integration/ninsight.js @@ -0,0 +1,33 @@ +const chai = require("chai") +const assert = chai.assert +const sinon = require("sinon") + +const BCHJS = require("../../src/bch-js") +const bchjs = new BCHJS() + +describe(`#Ninsight`, () => { + let sandbox + beforeEach(() => (sandbox = sinon.createSandbox())) + afterEach(() => sandbox.restore()) + + describe(`#utxo`, () => { + it(`should GET utxos for a single address`, async () => { + const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9" + + const result = await bchjs.Ninsight.utxo(addr) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isArray(result) + + assert.property(result[0], "address") + assert.property(result[0], "txid") + assert.property(result[0], "vout") + assert.property(result[0], "scriptPubKey") + assert.property(result[0], "amount") + assert.property(result[0], "satoshis") + assert.isNumber(result[0].satoshis) + assert.property(result[0], "height") + assert.property(result[0], "confirmations") + }) + }) +}) diff --git a/test/unit/fixtures/ninsight-mock.js b/test/unit/fixtures/ninsight-mock.js new file mode 100644 index 0000000..d5887c6 --- /dev/null +++ b/test/unit/fixtures/ninsight-mock.js @@ -0,0 +1,20 @@ +/* + Mocking data for unit tests for the Ninsight library. +*/ + +const utxo = [ + { + address: "15NCRBJsHaJy8As5bX1oh2YauRejnZ1MKF", + txid: "2b37bdb3b63dd0bca720437754a36671431a950e684b64c44ea910ea9d5297c7", + vout: 0, + scriptPubKey: "76a9142fe2c4c5ef359bb2fe1a849f891cecffbcfb4f7788ac", + amount: 0.00001, + satoshis: 1000, + height: 602405, + confirmations: 16720 + } +] + +module.exports = { + utxo +} diff --git a/test/unit/ninsight.js b/test/unit/ninsight.js new file mode 100644 index 0000000..88682ba --- /dev/null +++ b/test/unit/ninsight.js @@ -0,0 +1,51 @@ +const chai = require("chai") +const assert = chai.assert +const axios = require("axios") +const sinon = require("sinon") + +const BCHJS = require("../../src/bch-js") +const bchjs = new BCHJS() + +const mockData = require("./fixtures/ninsight-mock") + +describe(`#Ninsight`, () => { + let sandbox + beforeEach(() => (sandbox = sinon.createSandbox())) + afterEach(() => sandbox.restore()) + + describe(`#utxo`, () => { + it(`should throw an error for improper input`, async () => { + try { + const addr = 12345 + + await bchjs.Ninsight.utxo(addr) + assert.equal(true, false, "Unexpected result!") + } catch (err) { + //console.log(`err: `, err) + assert.include(err.message, `address needs to be a string`) + } + }) + + it(`should GET utxos for a single address`, async () => { + // Stub the network call. + sandbox.stub(axios, "get").resolves({ data: mockData.utxo }) + + const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9" + + const result = await bchjs.Ninsight.utxo(addr) + console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isArray(result) + + assert.property(result[0], "address") + assert.property(result[0], "txid") + assert.property(result[0], "vout") + assert.property(result[0], "scriptPubKey") + assert.property(result[0], "amount") + assert.property(result[0], "satoshis") + assert.isNumber(result[0].satoshis) + assert.property(result[0], "height") + assert.property(result[0], "confirmations") + }) + }) +})