diff --git a/package.json b/package.json index 3fcda03..aed9f2a 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "test:integration:testnet:local": "RESTURL=http://localhost:4000/v3/ mocha --timeout 30000 test/integration/testnet", "test:integration:free": "bash test/integration/test-free-tier.sh", "test:integration:free:testnet": "bash test/integration/testnet/test-free-tier.sh", - "test:temp": "nyc mocha --timeout 30000 test/unit/ipfs.js", + "test:temp": "mocha --timeout 30000 test/integration/testnet/ninsight.js", "test:integration:api": "RESTURL=https://api.fullstack.cash/v3/ mocha --timeout 30000 test/integration", "coverage": "nyc report --reporter=text-lcov | coveralls", "coverage:report": "nyc --reporter=html mocha --timeout 25000 test/unit/", diff --git a/src/bch-js.js b/src/bch-js.js index 43b6532..7cbf12a 100644 --- a/src/bch-js.js +++ b/src/bch-js.js @@ -69,7 +69,7 @@ class BCHJS { this.OpenBazaar = new OpenBazaar(libConfig) // Bitcoin.com Ninsight indexer - this.Ninsight = new Ninsight() + this.Ninsight = new Ninsight(config) // ElectrumX indexer this.Electrumx = new Electrumx(libConfig) diff --git a/src/ninsight.js b/src/ninsight.js index 6b0f41c..eba6833 100644 --- a/src/ninsight.js +++ b/src/ninsight.js @@ -13,7 +13,11 @@ class Ninsight { // this.apiToken = config.apiToken // this.ninsightURL = `https://bch-explorer.api.bitcoin.com/v1/` - this.ninsightURL = `https://rest.bitcoin.com/v2` + if (config) { + this.ninsightURL = config.ninsightURL + ? config.ninsightURL + : `https://rest.bitcoin.com/v2` + } // Add JWT token to the authorization header. this.axiosOptions = { @@ -62,15 +66,38 @@ class Ninsight { */ async utxo(address) { try { - if (typeof address !== "string") - throw new Error(`address needs to be a string.`) + // if (typeof address !== "string") + // throw new Error(`address needs to be a string.`) + // + // const response = await axios.get( + // `${this.ninsightURL}/address/utxo/${address}`, + // _this.axiosOptions + // ) - const response = await axios.get( - `${this.ninsightURL}/address/utxo/${address}`, - _this.axiosOptions - ) + // return response.data - return response.data + // Handle single address. + if (typeof address === "string") { + const response = await axios.get( + `${this.ninsightURL}/address/utxo/${address}`, + _this.axiosOptions + ) + return response.data + + // Handle array of addresses. + } else if (Array.isArray(address)) { + const response = await axios.post( + `${this.ninsightURL}/address/utxo`, + { + addresses: address + }, + _this.axiosOptions + ) + + return response.data + } + + throw new Error(`Input address must be a string or array of strings.`) } catch (error) { if (error.response && error.response.data) throw error.response.data else throw error diff --git a/test/integration/ninsight.js b/test/integration/ninsight.js index 098e972..fd6825b 100644 --- a/test/integration/ninsight.js +++ b/test/integration/ninsight.js @@ -33,5 +33,25 @@ describe(`#Ninsight`, () => { assert.property(result.utxos[0], "height") assert.property(result.utxos[0], "confirmations") }) + + it(`should POST utxo details for an array of addresses`, async () => { + const addr = [ + "bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7", + "bitcoincash:qz0us0z6ucpqt07jgpad0shgh7xmwxyr3ynlcsq0wr" + ] + + const result = await bchjs.Ninsight.utxo(addr) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isArray(result) + assert.isArray(result[0].utxos) + + assert.property(result[0], "utxos") + assert.property(result[0], "legacyAddress") + assert.property(result[0], "cashAddress") + assert.property(result[0], "slpAddress") + assert.property(result[0], "scriptPubKey") + assert.property(result[0], "asm") + }) }) }) diff --git a/test/integration/testnet/ninsight.js b/test/integration/testnet/ninsight.js new file mode 100644 index 0000000..bc292ac --- /dev/null +++ b/test/integration/testnet/ninsight.js @@ -0,0 +1,65 @@ +const chai = require("chai") +const assert = chai.assert +const sinon = require("sinon") + +const BCHJS = require("../../../src/bch-js") +const bchjs = new BCHJS({ ninsightURL: "https://trest.bitcoin.com/v2" }) + +describe(`#Ninsight`, () => { + let sandbox + beforeEach(() => (sandbox = sinon.createSandbox())) + afterEach(() => sandbox.restore()) + + describe(`#utxo`, () => { + it(`should GET utxos for a single address`, async () => { + const addr = "bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr" + + const result = await bchjs.Ninsight.utxo(addr) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.property(result, "utxos") + assert.property(result, "legacyAddress") + assert.property(result, "cashAddress") + assert.property(result, "slpAddress") + assert.property(result, "scriptPubKey") + assert.property(result, "asm") + + assert.isArray(result.utxos) + + assert.property(result.utxos[0], "txid") + assert.property(result.utxos[0], "vout") + assert.property(result.utxos[0], "amount") + assert.property(result.utxos[0], "satoshis") + assert.property(result.utxos[0], "height") + assert.property(result.utxos[0], "confirmations") + }) + + it(`should POST utxo details for an array of addresses`, async () => { + const addr = [ + "bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr", + "bchtest:qp6hgvevf4gzz6l7pgcte3gaaud9km0l459fa23dul" + ] + + const result = await bchjs.Ninsight.utxo(addr) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isArray(result) + assert.isArray(result[0].utxos) + + assert.property(result[0], "utxos") + assert.property(result[0], "legacyAddress") + assert.property(result[0], "cashAddress") + assert.property(result[0], "slpAddress") + assert.property(result[0], "scriptPubKey") + assert.property(result[0], "asm") + + // assert.hasAnyKeys(result[0][0], [ + // "txid", + // "vout", + // "value", + // "height", + // "confirmations" + // ]) + }) + }) +}) diff --git a/test/unit/fixtures/ninsight-mock.js b/test/unit/fixtures/ninsight-mock.js index aca70ae..cfc4f62 100644 --- a/test/unit/fixtures/ninsight-mock.js +++ b/test/unit/fixtures/ninsight-mock.js @@ -21,6 +21,9 @@ const utxo = { "OP_DUP OP_HASH160 2fe2c4c5ef359bb2fe1a849f891cecffbcfb4f77 OP_EQUALVERIFY OP_CHECKSIG" } +const utxoPost = [utxo, utxo] + module.exports = { - utxo + utxo, + utxoPost } diff --git a/test/unit/ninsight.js b/test/unit/ninsight.js index 9ac2b45..a62d560 100644 --- a/test/unit/ninsight.js +++ b/test/unit/ninsight.js @@ -22,7 +22,10 @@ describe(`#Ninsight`, () => { assert.equal(true, false, "Unexpected result!") } catch (err) { //console.log(`err: `, err) - assert.include(err.message, `address needs to be a string`) + assert.include( + err.message, + `Input address must be a string or array of strings.` + ) } }) @@ -51,5 +54,28 @@ describe(`#Ninsight`, () => { assert.property(result.utxos[0], "height") assert.property(result.utxos[0], "confirmations") }) + + it(`should POST utxo details for an array of addresses`, async () => { + // Mock the network call. + sandbox.stub(axios, "post").resolves({ data: mockData.utxoPost }) + + const addr = [ + "bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7", + "bitcoincash:qz0us0z6ucpqt07jgpad0shgh7xmwxyr3ynlcsq0wr" + ] + + const result = await bchjs.Ninsight.utxo(addr) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isArray(result) + assert.isArray(result[0].utxos) + + assert.property(result[0], "utxos") + assert.property(result[0], "legacyAddress") + assert.property(result[0], "cashAddress") + assert.property(result[0], "slpAddress") + assert.property(result[0], "scriptPubKey") + assert.property(result[0], "asm") + }) }) })