diff --git a/src/ninsight.js b/src/ninsight.js index 8611d71..250a22b 100644 --- a/src/ninsight.js +++ b/src/ninsight.js @@ -96,6 +96,82 @@ class Ninsight { else throw error } } + + /** + * @api Ninsight.transactions() transactions() + * @apiName Ninsight TX History + * @apiGroup Ninsight + * @apiDescription Return transactions history for address. + * + * @apiExample Example usage: + * (async () => { + * try { + * let txs = await bchjs.Ninsight.transactions('bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c'); + * console.log(txs); + * } catch(error) { + * console.error(error) + * } + * })() + * + * // [ + * // { + * // "pagesTotal": 1, + * // "txs": [ + * // { + * // "txid": "ec7bc8349386e3e1939bbdc4f8092fdbdd6a380734e68486b558cd594c451d5b", + * // "version": 2, + * // "locktime": 0, + * // "vin": [ + * // { + * // "txid": "4f1fc57c33659628938db740449bf92fb75799e1d5750a4aeef80eb52d6df1e0", + * // "vout": 0, + * // "sequence": 4294967295, + * // "n": 0, + * // ... + * // } + * // ... + * // ] + * // ... + * // } + * // ], + * // "legacyAddress": "1LpbYkEM5cryfhs58tH8c93p4SGzit7UrP", + * // "cashAddress": "bitcoincash:qrvk436u4r0ew2wj0rd9pnxhx4w90p2yfc29ta0d2n", + * // "currentPage": 0 + * // } + * // ] + * // + * + */ + async transactions(address) { + try { + if (typeof address === "string") { + const response = await axios.post( + `${this.ninsightURL}/address/transactions`, + { + addresses: [address] + }, + _this.axiosOptions + ) + + return response.data + } else if (Array.isArray(address)) { + const response = await axios.post( + `${this.ninsightURL}/address/transactions`, + { + 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 + } + } } module.exports = Ninsight diff --git a/test/integration/bchn/ninsight.js b/test/integration/bchn/ninsight.js index 46ee0c6..a938b97 100644 --- a/test/integration/bchn/ninsight.js +++ b/test/integration/bchn/ninsight.js @@ -54,4 +54,39 @@ describe(`#Ninsight`, () => { assert.property(result[0], "asm") }) }) + describe(`#transactions`, () => { + it(`should POST transactions history for a single address`, async () => { + const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9" + + const result = await bchjs.Ninsight.transactions(addr) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isArray(result) + assert.property(result[0], "cashAddress") + assert.property(result[0], "legacyAddress") + assert.property(result[0], "txs") + assert.isArray(result[0].txs) + assert.property(result[0].txs[0], "txid") + assert.property(result[0].txs[0], "vin") + assert.property(result[0].txs[0], "vout") + }) + it(`should POST transactions history for an array of addresses`, async () => { + const addr = [ + "bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7", + "bitcoincash:qz0us0z6ucpqt07jgpad0shgh7xmwxyr3ynlcsq0wr" + ] + + const result = await bchjs.Ninsight.transactions(addr) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isArray(result) + assert.property(result[0], "cashAddress") + assert.property(result[0], "legacyAddress") + assert.property(result[0], "txs") + assert.isArray(result[0].txs) + assert.property(result[0].txs[0], "txid") + assert.property(result[0].txs[0], "vin") + assert.property(result[0].txs[0], "vout") + }) + }) }) diff --git a/test/integration/ninsight.js b/test/integration/ninsight.js index ce3842a..06f5b95 100644 --- a/test/integration/ninsight.js +++ b/test/integration/ninsight.js @@ -60,6 +60,41 @@ describe(`#Ninsight`, () => { assert.property(result[0], "asm") }) }) + describe(`#transactions`, () => { + it(`should POST transactions history for a single address`, async () => { + const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9" + + const result = await bchjs.Ninsight.transactions(addr) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isArray(result) + assert.property(result[0], "cashAddress") + assert.property(result[0], "legacyAddress") + assert.property(result[0], "txs") + assert.isArray(result[0].txs) + assert.property(result[0].txs[0], "txid") + assert.property(result[0].txs[0], "vin") + assert.property(result[0].txs[0], "vout") + }) + it(`should POST transactions history for an array of addresses`, async () => { + const addr = [ + "bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7", + "bitcoincash:qz0us0z6ucpqt07jgpad0shgh7xmwxyr3ynlcsq0wr" + ] + + const result = await bchjs.Ninsight.transactions(addr) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isArray(result) + assert.property(result[0], "cashAddress") + assert.property(result[0], "legacyAddress") + assert.property(result[0], "txs") + assert.isArray(result[0].txs) + assert.property(result[0].txs[0], "txid") + assert.property(result[0].txs[0], "vin") + assert.property(result[0].txs[0], "vout") + }) + }) }) function sleep(ms) { diff --git a/test/integration/testnet/ninsight.js b/test/integration/testnet/ninsight.js index fe1351e..e417ada 100644 --- a/test/integration/testnet/ninsight.js +++ b/test/integration/testnet/ninsight.js @@ -68,6 +68,41 @@ describe(`#Ninsight`, () => { // ]) }) }) + describe(`#transactions`, () => { + it(`should POST transactions history for a single address`, async () => { + const addr = "bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr" + + const result = await bchjs.Ninsight.transactions(addr) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isArray(result) + assert.property(result[0], "cashAddress") + assert.property(result[0], "legacyAddress") + assert.property(result[0], "txs") + assert.isArray(result[0].txs) + assert.property(result[0].txs[0], "txid") + assert.property(result[0].txs[0], "vin") + assert.property(result[0].txs[0], "vout") + }) + it(`should POST transactions history for an array of addresses`, async () => { + const addr = [ + "bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr", + "bchtest:qp6hgvevf4gzz6l7pgcte3gaaud9km0l459fa23dul" + ] + + const result = await bchjs.Ninsight.transactions(addr) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isArray(result) + assert.property(result[0], "cashAddress") + assert.property(result[0], "legacyAddress") + assert.property(result[0], "txs") + assert.isArray(result[0].txs) + assert.property(result[0].txs[0], "txid") + assert.property(result[0].txs[0], "vin") + assert.property(result[0].txs[0], "vout") + }) + }) }) function sleep(ms) { diff --git a/test/unit/fixtures/ninsight-mock.js b/test/unit/fixtures/ninsight-mock.js index cfc4f62..e3b6470 100644 --- a/test/unit/fixtures/ninsight-mock.js +++ b/test/unit/fixtures/ninsight-mock.js @@ -21,9 +21,86 @@ const utxo = { "OP_DUP OP_HASH160 2fe2c4c5ef359bb2fe1a849f891cecffbcfb4f77 OP_EQUALVERIFY OP_CHECKSIG" } +const transactions = { + pagesTotal: 1, + txs: [ + { + txid: + "ec7bc8349386e3e1939bbdc4f8092fdbdd6a380734e68486b558cd594c451d5b", + version: 2, + locktime: 0, + vin: [ + { + txid: + "4f1fc57c33659628938db740449bf92fb75799e1d5750a4aeef80eb52d6df1e0", + vout: 0, + sequence: 4294967295, + n: 0, + scriptSig: { + hex: + "483045022100a3662a19ae384a1ceddea57765e425e61b04823e976d574da3911ac6b55d7f9b02200e571d985bce987675a2d58587a346fa40c39f4df13dc88548a92c52d5b24422412103f953f7630acc15bd3f5078c698f3af777286ae955b57e4857c158f75d87adb5f", + asm: + "3045022100a3662a19ae384a1ceddea57765e425e61b04823e976d574da3911ac6b55d7f9b02200e571d985bce987675a2d58587a346fa40c39f4df13dc88548a92c52d5b24422[ALL|FORKID] 03f953f7630acc15bd3f5078c698f3af777286ae955b57e4857c158f75d87adb5f" + }, + addr: "17HPz8RQ4XM6mjre6aspvqyj1j648CZidM", + valueSat: 1111, + value: 0.00001111, + doubleSpentTxID: null + }, + { + txid: + "126d62c299e7e14c66fe0b485d13082c23641f003690462046bc24ad2d1180c1", + vout: 0, + sequence: 4294967295, + n: 1, + scriptSig: { + hex: + "47304402203e3f923207111ff9bbd2fb5ab1a49a9145ad809ee0cad0e0ddaed64bfe38dc16022012ee288fb413bd500c63f8bb95e46b6b57d34762decd46b7188478a1c398eeda412103f953f7630acc15bd3f5078c698f3af777286ae955b57e4857c158f75d87adb5f", + asm: + "304402203e3f923207111ff9bbd2fb5ab1a49a9145ad809ee0cad0e0ddaed64bfe38dc16022012ee288fb413bd500c63f8bb95e46b6b57d34762decd46b7188478a1c398eeda[ALL|FORKID] 03f953f7630acc15bd3f5078c698f3af777286ae955b57e4857c158f75d87adb5f" + }, + addr: "17HPz8RQ4XM6mjre6aspvqyj1j648CZidM", + valueSat: 1000, + value: 0.00001, + doubleSpentTxID: null + } + ], + vout: [ + { + value: "0.00001736", + n: 0, + scriptPubKey: { + hex: "76a914d96ac75ca8df9729d278da50ccd7355c5785444e88ac", + asm: + "OP_DUP OP_HASH160 d96ac75ca8df9729d278da50ccd7355c5785444e OP_EQUALVERIFY OP_CHECKSIG", + addresses: ["1LpbYkEM5cryfhs58tH8c93p4SGzit7UrP"], + type: "pubkeyhash" + }, + spentTxId: null, + spentIndex: null, + spentHeight: null + } + ], + blockheight: -1, + confirmations: 0, + time: 1559673337, + valueOut: 0.00001736, + size: 339, + valueIn: 0.00002111, + fees: 0.00000375 + } + ], + legacyAddress: "1LpbYkEM5cryfhs58tH8c93p4SGzit7UrP", + cashAddress: "bitcoincash:qrvk436u4r0ew2wj0rd9pnxhx4w90p2yfc29ta0d2n", + currentPage: 0 +} + const utxoPost = [utxo, utxo] +const transactionsPost = [transactions, transactions] module.exports = { utxo, - utxoPost + utxoPost, + transactions, + transactionsPost } diff --git a/test/unit/ninsight.js b/test/unit/ninsight.js index d71896f..8f7ebe8 100644 --- a/test/unit/ninsight.js +++ b/test/unit/ninsight.js @@ -78,4 +78,57 @@ describe(`#Ninsight`, () => { assert.property(result[0], "asm") }) }) + describe(`#transactions`, () => { + it(`should throw an error for improper input`, async () => { + try { + const addr = 12345 + + await bchjs.Ninsight.transactions(addr) + assert.equal(true, false, "Unexpected result!") + } catch (err) { + //console.log(`err: `, err) + assert.include( + err.message, + `Input address must be a string or array of strings.` + ) + } + }) + it(`should POST transaction history for a single address`, async () => { + // Stub the network call. + sandbox.stub(axios, "post").resolves({ data: mockData.transactionsPost }) + + const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9" + + const result = await bchjs.Ninsight.transactions(addr) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isArray(result) + assert.property(result[0], "cashAddress") + assert.property(result[0], "legacyAddress") + assert.property(result[0], "txs") + assert.isArray(result[0].txs) + assert.property(result[0].txs[0], "txid") + assert.property(result[0].txs[0], "vin") + assert.property(result[0].txs[0], "vout") + }) + it(`should POST transaction history for an array of addresses`, async () => { + // Mock the network call. + sandbox.stub(axios, "post").resolves({ data: mockData.transactionsPost }) + + const addr = [ + "bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7", + "bitcoincash:qz0us0z6ucpqt07jgpad0shgh7xmwxyr3ynlcsq0wr" + ] + + const result = await bchjs.Ninsight.transactions(addr) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isArray(result) + assert.property(result[0], "cashAddress") + assert.property(result[0], "legacyAddress") + assert.property(result[0], "txs") + assert.isArray(result[0].txs) + assert.property(result[0].txs[0], "txid") + }) + }) })