├── LICENSE ├── README.md ├── index.js ├── lib ├── addresses.js ├── blocks.js ├── transactions.js └── utils │ ├── batch-get-request.js │ ├── batch-post-request.js │ ├── delay.js │ ├── get-request.js │ ├── index.js │ ├── reject-callback.js │ └── resolve-callback.js ├── package.json ├── test ├── addresses.test.js ├── blockchain.test.js ├── blocks.test.js ├── fixtures │ ├── addresses.json │ ├── addresses.txs.json │ ├── addresses.utxo.json │ ├── blocks.json │ ├── transactions.rawtx.json │ └── transactions.tx.json ├── setup-fixtures.js ├── transactions.test.js └── utils.test.js └── worker-configuration.d.ts /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 SkyJam 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CS Insight [![Build Status](https://travis-ci.org/CoinSpace/cs-insight.svg)](https://travis-ci.org/CoinSpace/cs-insight) 2 | ========== 3 | 4 | Common Blockchain wrapper for [CoinSpace API]. 5 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | 3 | var Addresses = require('./lib/addresses'); 4 | var Blocks = require('./lib/blocks'); 5 | var Transactions = require('./lib/transactions'); 6 | 7 | function Wrapper(network, baseURL) { 8 | network = network || 'smileycoin'; 9 | // Nota skodari.broslaugin.com meðan bálkaskoðari 10 | // er ekki uppfærður 11 | // Use skodari.broslaugin.com for testing while 12 | // main block explorer has not been updated 13 | baseURL = baseURL || 'https://blocks.smileyco.in/api/'; 14 | //baseURL = baseURL || 'https://skodari.broslaugin.com/api/'; 15 | 16 | // end points 17 | this.addresses = new Addresses(baseURL); 18 | this.blocks = new Blocks(baseURL); 19 | this.transactions = new Transactions(baseURL); 20 | 21 | this.apiURL = baseURL; 22 | this.network = network; 23 | } 24 | 25 | Wrapper.Addresses = Addresses; 26 | Wrapper.Blocks = Blocks; 27 | Wrapper.Transactions = Transactions; 28 | 29 | Wrapper.prototype.getNetwork = function() { return this.network; }; 30 | 31 | module.exports = Wrapper; -------------------------------------------------------------------------------- /lib/addresses.js: -------------------------------------------------------------------------------- 1 | require('es6-promise').polyfill(); 2 | 3 | var _ = require('lodash'); 4 | var Big = require('big.js'); 5 | var batchGetRequest = require('./utils').batchGetRequest; 6 | var bitcoinjs = require('bitcoinjs-lib'); 7 | var rejectCallback = require('./utils/reject-callback'); 8 | var resolveCallback = require('./utils/resolve-callback'); 9 | 10 | 11 | /** 12 | * check whether address(es) is correct from bitcoin point of view 13 | * 14 | * @private 15 | * @param addresses 16 | * @returns {Promise} 17 | */ 18 | function validateAddresses(addresses) { 19 | return new Promise(function(resolve, reject) { 20 | var invalidAddresses = [].concat(addresses).filter(function(address) { 21 | try { 22 | bitcoinjs.address.fromBase58Check(address); 23 | } catch (e) { 24 | return true; 25 | } 26 | }); 27 | 28 | if (invalidAddresses.length === 1) { 29 | reject(new Error(invalidAddresses[0] + ' is not a valid address')); 30 | } else if (invalidAddresses.length > 1) { 31 | reject(new Error(invalidAddresses.join(', ') + ' are not a valid address')); 32 | } else { 33 | resolve(); 34 | } 35 | }); 36 | } 37 | 38 | function Addresses(url) { 39 | this.url = url; 40 | } 41 | 42 | /** 43 | * returns summer about address(es) 44 | * 45 | * @param ids 46 | * @param callback 47 | * @returns {axios.Promise} 48 | */ 49 | Addresses.prototype.summary = function(ids, callback) { 50 | var self = this; 51 | 52 | return validateAddresses(ids) 53 | .then(function() { 54 | return batchGetRequest(self.url + 'addrs/', ids); 55 | }) 56 | .then(function(data) { 57 | return resolveCallback(ids, callback, 58 | data.map(function(res) { 59 | return { 60 | address: res.addrStr, 61 | balance: res.balance + res.unconfirmedBalance, 62 | totalReceived: res.totalReceivedSat, 63 | txCount: res.txApperances + res.unconfirmedTxApperances, 64 | txIds: res.transactions 65 | }; 66 | }) 67 | ); 68 | }) 69 | .catch(function(err) { 70 | return rejectCallback(callback, err, err.item + ' is not a valid address'); 71 | }); 72 | }; 73 | 74 | /** 75 | * returns transactions related to this address(es) 76 | * 77 | * @param addresses 78 | * @param blockHeightFilter 79 | * @param callback 80 | * @returns {axios.Promise} 81 | */ 82 | Addresses.prototype.transactions = function(addresses, blockHeightFilter, callback) { 83 | // optional blockHeight 84 | if (typeof blockHeightFilter === 'function') { 85 | callback = blockHeightFilter; 86 | blockHeightFilter = 0; 87 | } 88 | 89 | if (blockHeightFilter > 0) { 90 | console.warn('Insight API does not support blockHeight filter for addresses.transactions'); 91 | } 92 | 93 | addresses = [].concat(addresses); 94 | 95 | var params = addresses.map(function(id) { return { id: id }; }); 96 | 97 | return batchGetRequest(this.url + 'addrs/:id/txs', params) 98 | .then(function(data) { 99 | var result = _.flatten(data.map(function(address) { 100 | return address.items.map(function(tx) { 101 | return { 102 | blockHeight: tx.blockheight, 103 | blockId: tx.blockhash, 104 | txHex: tx.rawtx, 105 | txId: tx.txid, 106 | __blockTimestamp: tx.blocktime, 107 | __confirmations: tx.confirmations 108 | }; 109 | }); 110 | })); 111 | 112 | if (blockHeightFilter) { 113 | //filter transaction by block height 114 | //because Insight API doesn't support filtering we do it after result 115 | result = result.filter(function(tx) { 116 | return !blockHeightFilter || blockHeightFilter === tx.blockHeight; 117 | }); 118 | } 119 | 120 | return resolveCallback(addresses, callback, _.uniq(result, 'txId'), { 121 | arrayOnly: true 122 | }); 123 | }, function(err) { 124 | return rejectCallback(callback, err, err.item.id + ' is not a valid address'); 125 | }); 126 | }; 127 | 128 | /** 129 | * returns unspent transactions of address(es) 130 | * 131 | * @param addresses 132 | * @param callback 133 | * @returns {axios.Promise} 134 | */ 135 | Addresses.prototype.unspents = function(addresses, callback) { 136 | var self = this; 137 | 138 | addresses = [].concat(addresses); 139 | 140 | return validateAddresses(addresses) 141 | .then(function() { 142 | var params = addresses.map(function(id) { return { id: id }; }); 143 | return batchGetRequest(self.url + 'addrs/:id/utxo', params); 144 | }) 145 | .then(function(result) { 146 | result = _.flatten(result).map(function(tx) { 147 | var x = new Big(tx.amount); 148 | var smiloshis = parseInt(x.times(100000000).toFixed()); 149 | return { 150 | address: tx.address, 151 | confirmations: tx.confirmations, 152 | txId: tx.txid, 153 | value: smiloshis, 154 | vout: tx.vout 155 | }; 156 | }); 157 | return resolveCallback(addresses, callback, result, { 158 | arrayOnly: true 159 | }); 160 | }) 161 | .catch(function(err) { 162 | return rejectCallback(callback, err, err.item + ' is not a valid address'); 163 | }); 164 | }; 165 | 166 | module.exports = Addresses; 167 | -------------------------------------------------------------------------------- /lib/blocks.js: -------------------------------------------------------------------------------- 1 | require('es6-promise').polyfill(); 2 | 3 | var assert = require('assert'); 4 | var batchGetRequest = require('./utils').batchGetRequest; 5 | var bitcoinjs = require('bitcoinjs-lib'); 6 | var getRequest = require('./utils').getRequest; 7 | var rejectCallback = require('./utils/reject-callback'); 8 | var resolveCallback = require('./utils/resolve-callback'); 9 | 10 | function Blocks(url) { 11 | this.url = url; 12 | } 13 | 14 | /** 15 | * request block by ids 16 | * 17 | * @param idsOrHeights 18 | * @param callback 19 | */ 20 | Blocks.prototype.get = function(idsOrHeights, callback) { 21 | return batchGetRequest(this.url + 'block/', idsOrHeights) 22 | .then(function(data) { 23 | var results = data.map(function(blockData) { 24 | var block = new bitcoinjs.Block(); 25 | block.version = blockData.version; 26 | block.prevHash = new Buffer(blockData.previousblockhash, 'hex').reverse(); 27 | block.merkleRoot = new Buffer(blockData.merkleroot, 'hex').reverse(); 28 | block.timestamp = blockData.time; 29 | block.bits = parseInt(blockData.bits, 16); 30 | block.nonce = blockData.nonce; 31 | 32 | block.transactions = blockData.tx.map(function(tx) { 33 | return bitcoinjs.Transaction.fromHex(tx.raw); 34 | }); 35 | 36 | return { 37 | blockHex: block.toHex(), 38 | blockId: blockData.hash 39 | }; 40 | }); 41 | return resolveCallback(idsOrHeights, callback, results); 42 | }) 43 | .catch(function(err) { 44 | return rejectCallback(callback, err, err.item + ' is not a valid blockId'); 45 | }); 46 | }; 47 | 48 | /** 49 | * request last block 50 | * 51 | * @param callback 52 | * @returns {axios.Promise} 53 | */ 54 | Blocks.prototype.latest = function(callback) { 55 | var self = this; 56 | 57 | return getRequest(self.url + 'blocks') 58 | .then(function(data) { 59 | var blocks = data.blocks; 60 | return Promise.all([ 61 | blocks.length > 1 ? blocks[1].hash : null, 62 | getRequest(self.url + 'block/' + blocks[0].hash) 63 | ]); 64 | }) 65 | .then(function(blocks) { 66 | var previousHash = blocks[0]; 67 | var block = blocks[1]; 68 | 69 | return resolveCallback(null, callback, { 70 | blockId: block.hash, 71 | prevBlockId: previousHash, 72 | merkleRootHash: block.merkleroot, 73 | nonce: block.nonce, 74 | version: block.version, 75 | blockHeight: block.height, 76 | blockSize: parseInt(block.bits, 16), 77 | timestamp: block.time, 78 | txCount: block.tx.length 79 | }); 80 | }) 81 | .catch(function(err) { 82 | return rejectCallback(callback, err); 83 | }); 84 | }; 85 | 86 | Blocks.prototype.propagate = function() { 87 | assert(false, 'TODO'); 88 | }; 89 | 90 | /** 91 | * request block summary by id(s) 92 | * 93 | * @param ids 94 | * @param callback 95 | */ 96 | Blocks.prototype.summary = function(ids, callback) { 97 | try { 98 | return batchGetRequest(this.url + 'block/', ids) 99 | .then(function(data) { 100 | return data.map(function(block) { 101 | return { 102 | blockId: block.hash, 103 | blockHeight: block.height, 104 | prevBlockId: block.previousblockhash, 105 | merkleRootHash: block.merkleroot, 106 | nonce: block.nonce, 107 | version: block.version, 108 | blockSize: parseInt(block.bits, 16), 109 | timestamp: block.time, 110 | txCount: block.tx.length 111 | }; 112 | }); 113 | }) 114 | .then(function(results) { 115 | return resolveCallback(ids, callback, results); 116 | }) 117 | .catch(function(err) { 118 | return rejectCallback(callback, err, err.item + ' is not a valid blockId'); 119 | }); 120 | } catch (err) { 121 | console.warn(err); 122 | } 123 | }; 124 | 125 | Blocks.prototype.getServiceAddresses = function(callback) { 126 | return getRequest(this.url + 'getserviceaddresses') 127 | .then(function(data) { 128 | return data; 129 | }) 130 | .then(function(data) { 131 | return resolveCallback(null, callback, data); 132 | }) 133 | .catch(function(err) { 134 | return rejectCallback(callback, err); 135 | }); 136 | }; 137 | 138 | // TODO: might need some fixing 139 | Blocks.prototype.getOrgList = function(orglistAddress, callback) { 140 | return getRequest(this.url + 'getorglist/' + orglistAddress) 141 | .then(function(data){ 142 | return resolveCallback(null, callback, data); 143 | }) 144 | .catch(function(err) { 145 | return rejectCallback(callback, err); 146 | }); 147 | }; 148 | 149 | Blocks.prototype.getAllOrgLists = function(callback) { 150 | return getRequest(this.url + 'getallorglists/') 151 | .then(function(data){ 152 | return resolveCallback(null, callback, data); 153 | }) 154 | .catch(function(err) { 155 | return rejectCallback(callback, err); 156 | }); 157 | 158 | }; 159 | 160 | 161 | Blocks.prototype.getAllCouponLists = function(callback) { 162 | return getRequest(this.url + 'getallcouponlists/') 163 | .then(function(data){ 164 | return resolveCallback(null, callback, data); 165 | }).catch(function(err){ 166 | return rejectCallback(callback,err); 167 | }); 168 | } 169 | 170 | module.exports = Blocks; 171 | -------------------------------------------------------------------------------- /lib/transactions.js: -------------------------------------------------------------------------------- 1 | require('es6-promise').polyfill(); 2 | 3 | var assert = require('assert'); 4 | var batchGetRequest = require('./utils/index').batchGetRequest; 5 | var batchPostRequest = require('./utils/index').batchPostRequest; 6 | 7 | var rejectCallback = require('./utils/reject-callback'); 8 | var resolveCallback = require('./utils/resolve-callback'); 9 | 10 | function Transactions(url) { 11 | this.url = url; 12 | } 13 | 14 | /** 15 | * request information about transaction(s) by id(s) 16 | * 17 | * @param txIds 18 | * @param params 19 | * @param callback 20 | * @returns {axios.Promise} 21 | */ 22 | Transactions.prototype.get = function(txIds, params, callback) { 23 | if (typeof params === 'function') { 24 | callback = params; 25 | params = {}; 26 | } 27 | return batchGetRequest(this.url + 'txs/', txIds, { 28 | params: params 29 | }) 30 | .then(function(txs) { 31 | var results = txs.map(function(tx) { 32 | return { 33 | txId: tx.txid, 34 | fees: tx.fees, 35 | timestamp: tx.time, 36 | confirmations: tx.confirmations, 37 | vin: tx.vin, 38 | vout: tx.vout, 39 | version: tx.version 40 | }; 41 | }); 42 | return resolveCallback(txIds, callback, results); 43 | }) 44 | .catch(function(err) { 45 | return rejectCallback(callback, err, err.item + ' is not a valid txId'); 46 | }); 47 | }; 48 | 49 | Transactions.prototype.latest = function() { 50 | assert(false, 'There no appropriate API for that'); 51 | }; 52 | 53 | /** 54 | * post some transactions 55 | * 56 | * @param transactions 57 | * @param callback 58 | * @returns {axios.Promise} 59 | */ 60 | Transactions.prototype.propagate = function(transactions, callback) { 61 | return batchPostRequest( 62 | this.url + 'tx/send', 63 | [].concat(transactions).map(function(hex) { 64 | return {rawtx: hex}; 65 | })) 66 | .then(function(results) { 67 | return resolveCallback( 68 | transactions, 69 | callback, 70 | results.map(function(item) { 71 | return item.data; 72 | })); 73 | }) 74 | .catch(function(err) { 75 | return rejectCallback(callback, err, err.item + ' is not a valid txId'); 76 | }); 77 | }; 78 | 79 | module.exports = Transactions; 80 | -------------------------------------------------------------------------------- /lib/utils/batch-get-request.js: -------------------------------------------------------------------------------- 1 | require('es6-promise').polyfill(); 2 | 3 | var _ = require('lodash'); 4 | var getRequest = require('./get-request'); 5 | var pathToRegexp = require('path-to-regexp'); 6 | 7 | /** 8 | * async request data by GET and return Promise 9 | * 10 | * @param urls 11 | * @param items 12 | * @param options 13 | * @returns {Promise} 14 | */ 15 | module.exports = function(urls, items, options) { 16 | options = options || {}; 17 | 18 | items = items !== undefined ? [].concat(items) : []; 19 | 20 | //filter empty items 21 | items = items.filter(function(item) { 22 | return !!item; 23 | }); 24 | 25 | //group items by chunks 26 | var maxChunk = options.maxChunk || 50; 27 | var isString = !Array.isArray(items) || typeof items[0] !== 'object'; 28 | 29 | if (isString) { 30 | items = _.chunk(items, maxChunk).map(function(items) { 31 | return items.join(','); 32 | }); 33 | } else { 34 | items = _.chunk(items, maxChunk).map(function(items) { 35 | return items.reduce(function(sum, item) { 36 | Object.keys(item).forEach(function(key) { 37 | if (sum[key]) { 38 | sum[key] += ',' + item[key]; 39 | } else { 40 | sum[key] = '' + item[key]; 41 | } 42 | }); 43 | return sum; 44 | }, {}); 45 | }); 46 | } 47 | 48 | return Promise.all([].concat(urls).map(function(url) { 49 | return Promise.all(items.map(function(item) { 50 | var tokens = pathToRegexp.parse(url); 51 | var queryUrl; 52 | 53 | if (tokens.length > 1) { 54 | queryUrl = pathToRegexp.tokensToFunction(tokens)(item); 55 | } else { 56 | queryUrl = url + encodeURIComponent(item); 57 | } 58 | 59 | return getRequest(queryUrl, options); 60 | })); 61 | })).then(function(res) { 62 | res = res.map(function(items) { 63 | return _.flatten([].concat(items)); 64 | }); 65 | 66 | if (Array.isArray(urls)) { 67 | res = _.zip.apply(null, res); 68 | } else { 69 | res = res[0]; 70 | } 71 | 72 | return res; 73 | }); 74 | }; 75 | -------------------------------------------------------------------------------- /lib/utils/batch-post-request.js: -------------------------------------------------------------------------------- 1 | require('es6-promise').polyfill(); 2 | 3 | var axios = require('axios'); 4 | 5 | module.exports = function(url, items) { 6 | return Promise.all([].concat(items).map(function(item) { 7 | return axios.post(url, item); 8 | })); 9 | }; 10 | -------------------------------------------------------------------------------- /lib/utils/delay.js: -------------------------------------------------------------------------------- 1 | module.exports = function delay(ms) { 2 | return new Promise(function(resolve) { 3 | setTimeout(resolve, ms); 4 | }); 5 | }; 6 | -------------------------------------------------------------------------------- /lib/utils/get-request.js: -------------------------------------------------------------------------------- 1 | require('es6-promise').polyfill(); 2 | 3 | var axios = require('axios'); 4 | 5 | var delay = require('./delay'); 6 | 7 | function request(url, retry, delayBeforeRetry, params) { 8 | return axios.get(url, {params: params}) 9 | .catch(function(err) { 10 | if (err.code === 'ECONNRESET' && --retry > 0) { 11 | return delay(delayBeforeRetry) 12 | .then(function() { 13 | return request(url, retry); 14 | }); 15 | } 16 | return Promise.reject(err); 17 | }); 18 | } 19 | 20 | /** 21 | * async request data by GET and return Promise 22 | * 23 | * @param url 24 | * @param options 25 | * @returns {Promise} 26 | */ 27 | module.exports = function(url, options) { 28 | options = options || {}; 29 | return request(url, options.retry || 100, options.delayBeforeRetry !== undefined ? options.delayBeforeRetry : 1000, options.params || {}) 30 | .then(function(res) { 31 | return res.data; 32 | }); 33 | }; 34 | -------------------------------------------------------------------------------- /lib/utils/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | batchGetRequest: require('./batch-get-request'), 3 | batchPostRequest: require('./batch-post-request'), 4 | getRequest: require('./get-request') 5 | }; 6 | -------------------------------------------------------------------------------- /lib/utils/reject-callback.js: -------------------------------------------------------------------------------- 1 | /** 2 | * return lazy reject in right format 3 | * 4 | * @param callback 5 | * @param err 6 | * @param message 7 | * @returns {*} 8 | */ 9 | module.exports = function(callback, err, message) { 10 | if (callback) { 11 | setTimeout(function() { 12 | callback(new Error(message)); 13 | }); 14 | } else { 15 | return Promise.reject(err); 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /lib/utils/resolve-callback.js: -------------------------------------------------------------------------------- 1 | /** 2 | * return lazy result in right format 3 | * 4 | * @param ids 5 | * @param {Function} callback 6 | * @param {Array} data in result array 7 | * @param {Object} [options] allow result as array 8 | * @returns {*} 9 | */ 10 | module.exports = function(ids, callback, data, options) { 11 | options = options || {}; 12 | 13 | var result; 14 | if (options.arrayOnly) { 15 | result = data; 16 | } else { 17 | if (Array.isArray(ids)) { 18 | result = data; 19 | } else if (Array.isArray(data)) { 20 | result = data && data[0]; 21 | } else { 22 | result = data; 23 | } 24 | } 25 | 26 | if (callback) { 27 | setTimeout(function() { 28 | callback(null, result); 29 | }); 30 | } 31 | 32 | return result; 33 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_from": "git://github.com/smileycoin/cs-insight.git", 3 | "_id": "cs-insight@3.3.0", 4 | "_inBundle": false, 5 | "_integrity": "", 6 | "_location": "/cs-insight", 7 | "_phantomChildren": { 8 | "isarray": "0.0.1" 9 | }, 10 | "_requested": { 11 | "type": "git", 12 | "raw": "cs-insight@git://github.com/smileycoin/cs-insight.git", 13 | "name": "cs-insight", 14 | "escapedName": "cs-insight", 15 | "rawSpec": "git://github.com/smileycoin/cs-insight.git", 16 | "saveSpec": "git://github.com/smileycoin/cs-insight.git", 17 | "fetchSpec": "git://github.com/smileycoin/cs-insight.git", 18 | "gitCommittish": null 19 | }, 20 | "_requiredBy": [ 21 | "/cs-wallet" 22 | ], 23 | "_resolved": "git://github.com/smileycoin/cs-insight.git#71d810179ad9a602dd46a5363d1f03f65ae00d76", 24 | "_spec": "cs-insight@git://github.com/smileycoin/cs-insight.git", 25 | "bugs": { 26 | "url": "https://github.com/CoinSpace/cs-insight/issues" 27 | }, 28 | "bundleDependencies": false, 29 | "dependencies": { 30 | "axios": "^0.16.2", 31 | "big.js": "^3.1.3", 32 | "bitcoinjs-lib": "git://github.com/smileycoin/bitcoinjs-lib.git", 33 | "es6-promise": "^3.0.2", 34 | "lodash": "^4.17.5", 35 | "path-to-regexp": "^1.2.1" 36 | }, 37 | "deprecated": false, 38 | "description": "common-blockchain-blockr", 39 | "devDependencies": { 40 | "chai": "^3.4.1", 41 | "eslint": "^4.6.1", 42 | "eslint-config-airbnb-base": "^12.0.0", 43 | "eslint-plugin-import": "^2.7.0", 44 | "eslint-plugin-mocha": "^4.11.0", 45 | "mocha": "^3.5.3", 46 | "nock": "^9.0.22" 47 | }, 48 | "homepage": "https://github.com/CoinSpace/cs-insight#readme", 49 | "license": "MIT", 50 | "main": "./src/index.js", 51 | "name": "cs-insight", 52 | "repository": { 53 | "type": "git", 54 | "url": "git+https://github.com/CoinSpace/cs-insight.git" 55 | }, 56 | "scripts": { 57 | "lint": "eslint src test", 58 | "test": "mocha --reporter spec --timeout 600000" 59 | }, 60 | "version": "3.3.0" 61 | } 62 | -------------------------------------------------------------------------------- /test/addresses.test.js: -------------------------------------------------------------------------------- 1 | /*eslint no-unused-expressions: 0*/ 2 | 3 | var Blockchain = require('../'); 4 | var chai = require('chai'); 5 | var setupFixtures = require('./setup-fixtures'); 6 | 7 | var expect = chai.expect; 8 | 9 | describe('Addresses', function() { 10 | var addresses; 11 | 12 | before(function() { 13 | var api = new Blockchain('testnet', ''); 14 | addresses = api.addresses; 15 | }); 16 | 17 | before(setupFixtures.up); 18 | 19 | describe('summary', function() { 20 | it('should return address', function(done) { 21 | addresses 22 | .summary( 23 | 'mpNDUWcDcZw1Teo3LFHvr8usNdwDLKdTaY' 24 | ) 25 | .then(function(res) { 26 | expect(res).to.exist; 27 | expect(res).to.has.property('address', 'mpNDUWcDcZw1Teo3LFHvr8usNdwDLKdTaY'); 28 | done(); 29 | }) 30 | .catch(done); 31 | }); 32 | 33 | it('should fail on incorrect address id', function(done) { 34 | addresses 35 | .summary('XXXX') 36 | .then(function() { 37 | done('does not fail'); 38 | }) 39 | .catch(function(err) { 40 | expect(err.message).to.equal('XXXX is not a valid address'); 41 | done(); 42 | }); 43 | }); 44 | 45 | it('should be able to request group of addresses', function(done) { 46 | addresses 47 | .summary([ 48 | '2NBXcxopF9gs8sg9KfgPtKRsVZ6HyWVPHQY', 49 | 'mpNDUWcDcZw1Teo3LFHvr8usNdwDLKdTaY' 50 | ]) 51 | .then(function(res) { 52 | expect(res).to.be.instanceof(Array); 53 | expect(res).has.length(2); 54 | expect(res[0]).to.has.property('address', '2NBXcxopF9gs8sg9KfgPtKRsVZ6HyWVPHQY'); 55 | expect(res[1]).to.has.property('address', 'mpNDUWcDcZw1Teo3LFHvr8usNdwDLKdTaY'); 56 | done(); 57 | }) 58 | .catch(done); 59 | }); 60 | }); 61 | 62 | describe('transactions', function() { 63 | it('should return transactions', function(done) { 64 | addresses 65 | .transactions( 66 | 'mpNDUWcDcZw1Teo3LFHvr8usNdwDLKdTaY' 67 | ) 68 | .then(function(res) { 69 | expect(res).to.be.instanceof(Array); 70 | expect(res).has.length(2); 71 | expect(res[0]).to.has.property('blockId', '00000000000010efb93b48b18d489d9e959997dd4f9e2acaf3191ad9ec1aa3e4'); 72 | expect(res[0]).to.has.property('txId', '4979a0b69703f888dc5936a4be039dabb976fae7d45604d57b5fad35b3c94200'); 73 | expect(res[1]).to.has.property('blockId', '00000000a1e890e1c2cfe6edf939b83b9a4d6fd4b066324b84f67660215887b0'); 74 | expect(res[1]).to.has.property('txId', 'ffd316b0c4feb9d29c61c3734fcde0167600441e560931c8c7267a9de3d9e29a'); 75 | done(); 76 | }) 77 | .catch(done); 78 | }); 79 | 80 | it('should fail on incorrect address id', function(done) { 81 | addresses 82 | .transactions('XXXX') 83 | .then(function() { 84 | done('does not fail'); 85 | }) 86 | .catch(function(err) { 87 | expect(err).to.exist; 88 | done(); 89 | }).catch(done); 90 | }); 91 | 92 | it('should be able to request group of addresses', function(done) { 93 | addresses 94 | .transactions([ 95 | '2NBXcxopF9gs8sg9KfgPtKRsVZ6HyWVPHQY', 96 | 'mpNDUWcDcZw1Teo3LFHvr8usNdwDLKdTaY' 97 | ]) 98 | .then(function(res) { 99 | expect(res).to.be.instanceof(Array); 100 | expect(res).has.length(3); 101 | expect(res[0]).to.has.property('blockId', '00000000000007dc622b16ab6698ad580c69e7e21c59bc9474418e85c6f3489a'); 102 | expect(res[0]).to.has.property('txId', '6560380b5b8fc147e760545ff72eb3aca05116326509dea0157faf94dbe4ac32'); 103 | expect(res[1]).to.has.property('blockId', '00000000000010efb93b48b18d489d9e959997dd4f9e2acaf3191ad9ec1aa3e4'); 104 | expect(res[1]).to.has.property('txId', '4979a0b69703f888dc5936a4be039dabb976fae7d45604d57b5fad35b3c94200'); 105 | expect(res[2]).to.has.property('blockId', '00000000a1e890e1c2cfe6edf939b83b9a4d6fd4b066324b84f67660215887b0'); 106 | expect(res[2]).to.has.property('txId', 'ffd316b0c4feb9d29c61c3734fcde0167600441e560931c8c7267a9de3d9e29a'); 107 | done(); 108 | }) 109 | .catch(done); 110 | }); 111 | }); 112 | 113 | describe('unspents', function() { 114 | it('should return transactions', function(done) { 115 | addresses 116 | .unspents( 117 | 'mpNDUWcDcZw1Teo3LFHvr8usNdwDLKdTaY' 118 | ) 119 | .then(function(res) { 120 | expect(res).to.be.instanceof(Array); 121 | expect(res).has.length(2); 122 | expect(res[0]).to.has.property('address', 'mpNDUWcDcZw1Teo3LFHvr8usNdwDLKdTaY'); 123 | expect(res[0]).to.has.property('txId', 'ffd316b0c4feb9d29c61c3734fcde0167600441e560931c8c7267a9de3d9e29a'); 124 | expect(res[1]).to.has.property('address', 'mpNDUWcDcZw1Teo3LFHvr8usNdwDLKdTaY'); 125 | expect(res[1]).to.has.property('txId', '4979a0b69703f888dc5936a4be039dabb976fae7d45604d57b5fad35b3c94200'); 126 | done(); 127 | }) 128 | .catch(done); 129 | }); 130 | 131 | it('should fail on incorrect address id', function(done) { 132 | addresses 133 | .unspents('XXXX') 134 | .then(function() { 135 | done('does not fail'); 136 | }) 137 | .catch(function(err) { 138 | expect(err).to.exist; 139 | done(); 140 | }); 141 | }); 142 | 143 | it('should be able to request group of addresses', function(done) { 144 | addresses 145 | .unspents([ 146 | 'mpNDUWcDcZw1Teo3LFHvr8usNdwDLKdTaY', 147 | 'mvJCbQvE6DgVAECMwDprASP3NMwuU53Eie' 148 | ]) 149 | .then(function(res) { 150 | expect(res).to.be.instanceof(Array); 151 | expect(res).has.length(3); 152 | 153 | expect(res[0]).to.has.property('address', 'mpNDUWcDcZw1Teo3LFHvr8usNdwDLKdTaY'); 154 | expect(res[0]).to.has.property('txId', 'ffd316b0c4feb9d29c61c3734fcde0167600441e560931c8c7267a9de3d9e29a'); 155 | 156 | expect(res[1]).to.has.property('address', 'mpNDUWcDcZw1Teo3LFHvr8usNdwDLKdTaY'); 157 | expect(res[1]).to.has.property('txId', '4979a0b69703f888dc5936a4be039dabb976fae7d45604d57b5fad35b3c94200'); 158 | 159 | expect(res[2]).to.has.property('address', 'mvJCbQvE6DgVAECMwDprASP3NMwuU53Eie'); 160 | expect(res[2]).to.has.property('txId', '41017e25bed3b740508fc10286ffd363935698bd541ac8c43d8fad52cde25220'); 161 | 162 | done(); 163 | }) 164 | .catch(done); 165 | }); 166 | }); 167 | 168 | after(setupFixtures.down); 169 | }); 170 | -------------------------------------------------------------------------------- /test/blockchain.test.js: -------------------------------------------------------------------------------- 1 | /*eslint no-new: 0*/ 2 | 3 | var assert = require('assert'); 4 | var Blockchain = require('../'); 5 | var chai = require('chai'); 6 | var expect = chai.expect; 7 | 8 | describe('Blockchain', function() { 9 | describe('Constructor', function() { 10 | it('defaults to the bitcoin network', function() { 11 | var blockchain = new Blockchain(); 12 | 13 | assert.equal(blockchain.getNetwork(), 'bitcoin'); 14 | }); 15 | 16 | it('should setup api network url form params', function() { 17 | var blockchain = new Blockchain('testnet', 'http://test-insight.some-test.url/'); 18 | expect(blockchain.apiURL).to.equal('http://test-insight.some-test.url/'); 19 | }); 20 | }); 21 | 22 | describe('getNetwork', function() { 23 | it('returns the underlying network name', function() { 24 | var blockchain = new Blockchain('testnet'); 25 | 26 | assert.equal(blockchain.getNetwork(), 'testnet'); 27 | }); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/blocks.test.js: -------------------------------------------------------------------------------- 1 | /*eslint no-unused-expressions: 0*/ 2 | 3 | var Blockchain = require('../'); 4 | var chai = require('chai'); 5 | var setupFixtures = require('./setup-fixtures'); 6 | 7 | var expect = chai.expect; 8 | 9 | describe('Blocks', function() { 10 | var blocks; 11 | 12 | before(function() { 13 | var api = new Blockchain('testnet'); 14 | blocks = api.blocks; 15 | }); 16 | 17 | before(setupFixtures.up); 18 | 19 | describe('get', function() { 20 | it('should return block', function(done) { 21 | blocks 22 | .get( 23 | '00000000000010efb93b48b18d489d9e959997dd4f9e2acaf3191ad9ec1aa3e4' 24 | ) 25 | .then(function(res) { 26 | expect(res).to.exist; 27 | expect(res).to.has.property('blockId', '00000000000010efb93b48b18d489d9e959997dd4f9e2acaf3191ad9ec1aa3e4'); 28 | done(); 29 | }) 30 | .catch(done); 31 | }); 32 | 33 | it('should be able to request group of blocks', function(done) { 34 | blocks 35 | .get([ 36 | '00000000000010efb93b48b18d489d9e959997dd4f9e2acaf3191ad9ec1aa3e4', 37 | '00000000a1e890e1c2cfe6edf939b83b9a4d6fd4b066324b84f67660215887b0' 38 | ]) 39 | .then(function(res) { 40 | expect(res).to.be.instanceof(Array); 41 | expect(res).has.length(2); 42 | expect(res[0]).to.has.property('blockId', '00000000000010efb93b48b18d489d9e959997dd4f9e2acaf3191ad9ec1aa3e4'); 43 | expect(res[1]).to.has.property('blockId', '00000000a1e890e1c2cfe6edf939b83b9a4d6fd4b066324b84f67660215887b0'); 44 | 45 | done(); 46 | }) 47 | .catch(done); 48 | }); 49 | 50 | it('should fail on wrong block it', function(done) { 51 | blocks 52 | .get('XXXX') 53 | .then(function() { 54 | done('does not fail'); 55 | }) 56 | .catch(function(err) { 57 | expect(err).to.exist; 58 | done(); 59 | }).catch(done); 60 | }); 61 | }); 62 | 63 | describe('latest', function() { 64 | it('should return last block', function(done) { 65 | blocks 66 | .latest() 67 | .then(function(res) { 68 | expect(res).to.exist; 69 | expect(res).to.has.property('blockId', '00000000000010efb93b48b18d489d9e959997dd4f9e2acaf3191ad9ec1aa3e4'); 70 | expect(res).to.has.property('blockHeight', 396393); 71 | expect(res).to.has.property('blockSize', 437402107); 72 | done(); 73 | }) 74 | .catch(done); 75 | }); 76 | }); 77 | 78 | describe('summary', function() { 79 | it('should return summary about block', function(done) { 80 | blocks 81 | .summary('00000000000010efb93b48b18d489d9e959997dd4f9e2acaf3191ad9ec1aa3e4') 82 | .then(function(res) { 83 | expect(res).to.exist; 84 | expect(res).to.has.property('blockId', '00000000000010efb93b48b18d489d9e959997dd4f9e2acaf3191ad9ec1aa3e4'); 85 | expect(res).to.has.property('blockHeight', 396393); 86 | done(); 87 | }) 88 | .catch(done); 89 | }); 90 | 91 | it('should be able to request group of blocks', function(done) { 92 | blocks 93 | .summary([ 94 | '00000000000010efb93b48b18d489d9e959997dd4f9e2acaf3191ad9ec1aa3e4', 95 | '00000000a1e890e1c2cfe6edf939b83b9a4d6fd4b066324b84f67660215887b0' 96 | ]) 97 | .then(function(res) { 98 | expect(res).to.be.instanceof(Array); 99 | expect(res).has.length(2); 100 | expect(res[0]).to.has.property('blockId', '00000000000010efb93b48b18d489d9e959997dd4f9e2acaf3191ad9ec1aa3e4'); 101 | expect(res[0]).to.has.property('blockHeight', 396393); 102 | expect(res[1]).to.has.property('blockId', '00000000a1e890e1c2cfe6edf939b83b9a4d6fd4b066324b84f67660215887b0'); 103 | expect(res[1]).to.has.property('blockHeight', 274302); 104 | done(); 105 | }) 106 | .catch(done); 107 | }); 108 | 109 | it('should fail on wrong block id', function(done) { 110 | blocks 111 | .summary('XXXX') 112 | .then(function() { 113 | done('doe not fail'); 114 | }) 115 | .catch(function(err) { 116 | expect(err).to.exist; 117 | done(); 118 | }).catch(done); 119 | }); 120 | }); 121 | 122 | after(setupFixtures.down); 123 | }); 124 | -------------------------------------------------------------------------------- /test/fixtures/addresses.json: -------------------------------------------------------------------------------- 1 | { 2 | "2NBXcxopF9gs8sg9KfgPtKRsVZ6HyWVPHQY": { 3 | "addrStr": "2NBXcxopF9gs8sg9KfgPtKRsVZ6HyWVPHQY", 4 | "balance": 1, 5 | "balanceSat": 100000000, 6 | "totalReceived": 1, 7 | "totalReceivedSat": 100000000, 8 | "totalSent": 0, 9 | "totalSentSat": 0, 10 | "unconfirmedBalance": 0, 11 | "unconfirmedBalanceSat": 0, 12 | "unconfirmedTxApperances": 0, 13 | "txApperances": 1, 14 | "transactions": [ 15 | "6560380b5b8fc147e760545ff72eb3aca05116326509dea0157faf94dbe4ac32" 16 | ] 17 | }, 18 | "mpNDUWcDcZw1Teo3LFHvr8usNdwDLKdTaY": { 19 | "addrStr": "mpNDUWcDcZw1Teo3LFHvr8usNdwDLKdTaY", 20 | "balance": 0.3902, 21 | "balanceSat": 39020000, 22 | "totalReceived": 0.3902, 23 | "totalReceivedSat": 39020000, 24 | "totalSent": 0, 25 | "totalSentSat": 0, 26 | "unconfirmedBalance": 0, 27 | "unconfirmedBalanceSat": 0, 28 | "unconfirmedTxApperances": 0, 29 | "txApperances": 2, 30 | "transactions": [ 31 | "ffd316b0c4feb9d29c61c3734fcde0167600441e560931c8c7267a9de3d9e29a", 32 | "4979a0b69703f888dc5936a4be039dabb976fae7d45604d57b5fad35b3c94200" 33 | ] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /test/fixtures/addresses.txs.json: -------------------------------------------------------------------------------- 1 | { 2 | "2NBXcxopF9gs8sg9KfgPtKRsVZ6HyWVPHQY": { 3 | "totalItems": 1, 4 | "from": 0, 5 | "to": 1, 6 | "items": [ 7 | { 8 | "txid": "6560380b5b8fc147e760545ff72eb3aca05116326509dea0157faf94dbe4ac32", 9 | "version": 1, 10 | "locktime": 0, 11 | "vin": [ 12 | { 13 | "txid": "9d2c560a1de917fd727595a5d344e3fd5f7f240ad1825d151439fbadc5e67b65", 14 | "vout": 1, 15 | "scriptSig": { 16 | "asm": "3045022100fdcf8f8caf4c671ddb399dc7df8a5a07ad5237fa16f448ca00c5868028529b740220635403257f00e10eb49185269ad6a5fb95c68aabc4dda25172ce8bffb4bb410601 040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70", 17 | "hex": "483045022100fdcf8f8caf4c671ddb399dc7df8a5a07ad5237fa16f448ca00c5868028529b740220635403257f00e10eb49185269ad6a5fb95c68aabc4dda25172ce8bffb4bb41060141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70" 18 | }, 19 | "sequence": 4294967295, 20 | "n": 0, 21 | "addr": "mpRZxxp5FtmQipEWJPa1NY9FmPsva3exUd", 22 | "valueSat": 4568651400, 23 | "value": 45.686514, 24 | "doubleSpentTxID": null 25 | } 26 | ], 27 | "vout": [ 28 | { 29 | "value": "1.00000000", 30 | "n": 0, 31 | "scriptPubKey": { 32 | "hex": "a914c88c190200000000c08d19020000000070e0100287", 33 | "asm": "OP_HASH160 c88c190200000000c08d19020000000070e01002 OP_EQUAL", 34 | "addresses": ["2NBXcxopF9gs8sg9KfgPtKRsVZ6HyWVPHQY"], 35 | "type": "scripthash" 36 | } 37 | }, 38 | { 39 | "value": "44.68641400", 40 | "n": 1, 41 | "scriptPubKey": { 42 | "hex": "76a91461b469ada61f37c620010912a9d5d56646015f1688ac", 43 | "asm": "OP_DUP OP_HASH160 61b469ada61f37c620010912a9d5d56646015f16 OP_EQUALVERIFY OP_CHECKSIG", 44 | "addresses": ["mpRZxxp5FtmQipEWJPa1NY9FmPsva3exUd"], 45 | "type": "pubkeyhash" 46 | }, 47 | "spentTxId": "d195354d50d7995f780cef2e6653b480d91dedae624bd2e9b6803278cabb7607", 48 | "spentIndex": 0 49 | } 50 | ], 51 | "blockhash": "00000000000007dc622b16ab6698ad580c69e7e21c59bc9474418e85c6f3489a", 52 | "confirmations": 314946, 53 | "time": 1417489870, 54 | "blocktime": 1417489870, 55 | "valueOut": 45.686414, 56 | "size": 256, 57 | "valueIn": 45.686514, 58 | "fees": 0.0001 59 | } 60 | ] 61 | }, 62 | "mpNDUWcDcZw1Teo3LFHvr8usNdwDLKdTaY": { 63 | "totalItems": 2, 64 | "from": 0, 65 | "to": 2, 66 | "items": [ 67 | { 68 | "txid": "4979a0b69703f888dc5936a4be039dabb976fae7d45604d57b5fad35b3c94200", 69 | "version": 1, 70 | "locktime": 0, 71 | "vin": [ 72 | { 73 | "txid": "b465897ae9b112e2e821ad52a76169aec128dbbf3396335aaf3cbdce6cf8906e", 74 | "vout": 1, 75 | "scriptSig": { 76 | "asm": "3045022100d1eb848df7594a5f9b697dea0bf733c8ec87dec2b63142e4b572b07f2f09d12702200f6b124db6689e645f39e57d6cffcfb5f5869c089c4f1922ef6e6cfe3f07e8e201 037ce0c786277fafc38e2e2d49b1be36f02a360ba4a2dd58cf977784975a573fb6", 77 | "hex": "483045022100d1eb848df7594a5f9b697dea0bf733c8ec87dec2b63142e4b572b07f2f09d12702200f6b124db6689e645f39e57d6cffcfb5f5869c089c4f1922ef6e6cfe3f07e8e20121037ce0c786277fafc38e2e2d49b1be36f02a360ba4a2dd58cf977784975a573fb6" 78 | }, 79 | "sequence": 4294967295, 80 | "n": 0, 81 | "addr": "mkjS5YDUi3mVCQPQYhNKZhpW2bKkthyNsF", 82 | "valueSat": 894223221000, 83 | "value": 8942.23221, 84 | "doubleSpentTxID": null 85 | } 86 | ], 87 | "vout": [ 88 | { 89 | "value": "0.39000000", 90 | "n": 0, 91 | "scriptPubKey": { 92 | "hex": "76a91461120f6e004c7a2e20ecdedf461f1eb032c2e5c388ac", 93 | "asm": "OP_DUP OP_HASH160 61120f6e004c7a2e20ecdedf461f1eb032c2e5c3 OP_EQUALVERIFY OP_CHECKSIG", 94 | "addresses": ["mpNDUWcDcZw1Teo3LFHvr8usNdwDLKdTaY"], 95 | "type": "pubkeyhash" 96 | } 97 | }, 98 | { 99 | "value": "8941.84221000", 100 | "n": 1, 101 | "scriptPubKey": { 102 | "hex": "76a9140fe1355e31a061b2508919578b6f8c60dd2f29cf88ac", 103 | "asm": "OP_DUP OP_HASH160 0fe1355e31a061b2508919578b6f8c60dd2f29cf OP_EQUALVERIFY OP_CHECKSIG", 104 | "addresses": ["mgxvDgz4vyneuYUfgbSyWBmcZPnDgyNAFY"], 105 | "type": "pubkeyhash" 106 | }, 107 | "spentTxId": "9021874091d0c8e1795a985fe4d5c0c198dc0053a5e4ed51d4b3949533716168", 108 | "spentIndex": 0 109 | } 110 | ], 111 | "blockhash": "00000000000010efb93b48b18d489d9e959997dd4f9e2acaf3191ad9ec1aa3e4", 112 | "confirmations": 230493, 113 | "time": 1431467128, 114 | "blocktime": 1431467128, 115 | "valueOut": 8942.23221, 116 | "size": 226, 117 | "valueIn": 8942.23221, 118 | "fees": 0 119 | }, 120 | { 121 | "txid": "ffd316b0c4feb9d29c61c3734fcde0167600441e560931c8c7267a9de3d9e29a", 122 | "version": 1, 123 | "locktime": 0, 124 | "vin": [ 125 | { 126 | "txid": "3df7613ea58afc4c6c443cad6a8a1eaff4c5ae04e8124ec4e7204811c120101c", 127 | "vout": 1, 128 | "scriptSig": { 129 | "asm": "304402200fea124cecd36e92cb0b549b62740a26f374629b26f16292a3e858753035172802205ba172966addddbbe8181af6cd7fb6e9c53414fb6727c4f15589c74567e48ab301 040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70", 130 | "hex": "47304402200fea124cecd36e92cb0b549b62740a26f374629b26f16292a3e858753035172802205ba172966addddbbe8181af6cd7fb6e9c53414fb6727c4f15589c74567e48ab30141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70" 131 | }, 132 | "sequence": 4294967295, 133 | "n": 0, 134 | "addr": "mpRZxxp5FtmQipEWJPa1NY9FmPsva3exUd", 135 | "valueSat": 1027829979, 136 | "value": 10.27829979, 137 | "doubleSpentTxID": null 138 | } 139 | ], 140 | "vout": [ 141 | { 142 | "value": "0.00020000", 143 | "n": 0, 144 | "scriptPubKey": { 145 | "hex": "76a91461120f6e004c7a2e20ecdedf461f1eb032c2e5c388ac", 146 | "asm": "OP_DUP OP_HASH160 61120f6e004c7a2e20ecdedf461f1eb032c2e5c3 OP_EQUALVERIFY OP_CHECKSIG", 147 | "addresses": ["mpNDUWcDcZw1Teo3LFHvr8usNdwDLKdTaY"], 148 | "type": "pubkeyhash" 149 | } 150 | }, 151 | { 152 | "value": "10.27799979", 153 | "n": 1, 154 | "scriptPubKey": { 155 | "hex": "76a91461b469ada61f37c620010912a9d5d56646015f1688ac", 156 | "asm": "OP_DUP OP_HASH160 61b469ada61f37c620010912a9d5d56646015f16 OP_EQUALVERIFY OP_CHECKSIG", 157 | "addresses": ["mpRZxxp5FtmQipEWJPa1NY9FmPsva3exUd"], 158 | "type": "pubkeyhash" 159 | }, 160 | "spentTxId": "f611cd3a1d676631b630600695074aab57b98ddc6982e93419438753f8f3fbda", 161 | "spentIndex": 0 162 | } 163 | ], 164 | "blockhash": "00000000a1e890e1c2cfe6edf939b83b9a4d6fd4b066324b84f67660215887b0", 165 | "confirmations": 352584, 166 | "time": 1408065294, 167 | "blocktime": 1408065294, 168 | "valueOut": 10.27819979, 169 | "size": 257, 170 | "valueIn": 10.27829979, 171 | "fees": 0.0001 172 | } 173 | ] 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /test/fixtures/addresses.utxo.json: -------------------------------------------------------------------------------- 1 | { 2 | "mpNDUWcDcZw1Teo3LFHvr8usNdwDLKdTaY": [ 3 | { 4 | "address": "mpNDUWcDcZw1Teo3LFHvr8usNdwDLKdTaY", 5 | "amount": 0.0002, 6 | "confirmations": 352180, 7 | "scriptPubKey": "76a91461120f6e004c7a2e20ecdedf461f1eb032c2e5c388ac", 8 | "ts": 1450207470002, 9 | "txid": "ffd316b0c4feb9d29c61c3734fcde0167600441e560931c8c7267a9de3d9e29a", 10 | "vout": 0 11 | }, 12 | { 13 | "address": "mpNDUWcDcZw1Teo3LFHvr8usNdwDLKdTaY", 14 | "amount": 0.39, 15 | "confirmations": 230089, 16 | "scriptPubKey": "76a91461120f6e004c7a2e20ecdedf461f1eb032c2e5c388ac", 17 | "ts": 1450207470002, 18 | "txid": "4979a0b69703f888dc5936a4be039dabb976fae7d45604d57b5fad35b3c94200", 19 | "vout": 0 20 | } 21 | ], 22 | "mvJCbQvE6DgVAECMwDprASP3NMwuU53Eie": [ 23 | { 24 | "address": "mvJCbQvE6DgVAECMwDprASP3NMwuU53Eie", 25 | "amount": 0.0002, 26 | "confirmations": 352180, 27 | "scriptPubKey": "76a914a2206a6b9e0bb209dda1b71aabb810649c3ce1c688ac", 28 | "ts": 1450207469930, 29 | "txid": "41017e25bed3b740508fc10286ffd363935698bd541ac8c43d8fad52cde25220", 30 | "vout": 0 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /test/fixtures/blocks.json: -------------------------------------------------------------------------------- 1 | { 2 | "00000000000010efb93b48b18d489d9e959997dd4f9e2acaf3191ad9ec1aa3e4": { 3 | "hash": "00000000000010efb93b48b18d489d9e959997dd4f9e2acaf3191ad9ec1aa3e4", 4 | "confirmations": 230238, 5 | "size": 2258, 6 | "height": 396393, 7 | "version": 3, 8 | "merkleroot": "ad25277b1ce5221df2874615166655276aa6ff7a8802e283425fc34231f0b461", 9 | "tx": [ 10 | "fe5cbaa170d288ae7d0937b1a4146cf7ef505c70c6b9155ffd8b1c55b54f6fc7", 11 | "b1dd437ba1b04779b59882cd25cfe088ec4e7d2003790eb2fd0504a28655c523", 12 | "4979a0b69703f888dc5936a4be039dabb976fae7d45604d57b5fad35b3c94200", 13 | "801f93aa50c94510afa7ac997c460a0ebfde25eaed23063da72c8145d232f43a", 14 | "7a7c2099f4e37d22c396669db2950cec14d87fc7e6d01b88eb28237362d3ad4d", 15 | "a155a548ca3b24c457add7fbe47ee9cf1e849ec947bb5ec2125466aa0d8bc8e2", 16 | "02b1cd72cda9ac5aa4acd083c102e0562fb542b87d36fe5d7d80a396cfd2d601", 17 | "97032422ac420f01927cbc00149238bb0a19beb408f15d4c2755bc594b98d4d9", 18 | "13da8238fe72eaa4c1b96c61bdc8ed99716545f9bd75cd2eb3f16d601f0da8d4" 19 | ], 20 | "time": 1431467128, 21 | "nonce": 1689078919, 22 | "bits": "1a1239fb", 23 | "difficulty": 920471.43976806, 24 | "chainwork": "000000000000000000000000000000000000000000000004062572d92fd35ded", 25 | "previousblockhash": "000000008474cfe3137b5713b6feb18ff2b2be05616483c837c096740456916f", 26 | "nextblockhash": "00000000e0c552417324ad8b44a76c2d7ad6397d6e702f2a6ae3f5d59cf01c1f", 27 | "reward": 25, 28 | "isMainChain": true, 29 | "poolInfo": {} 30 | }, 31 | "00000000a711d72347425408b0a51f5bbd578572c3c224873f2dd5fd82b3b6d9": { 32 | "hash": "00000000a711d72347425408b0a51f5bbd578572c3c224873f2dd5fd82b3b6d9", 33 | "confirmations": 352330, 34 | "size": 5111, 35 | "height": 274301, 36 | "version": 2, 37 | "merkleroot": "204b307249c5213b6b340904e8d810c047266f205fe24006b4cfd36602291a52", 38 | "tx": [ 39 | "243ff0ca947a6ba3cf0a032b589344170d7078cda3165ba9afc87419ff16708e", 40 | "008a6c398f22968400f681bd2ae588ef358fce76a266f33396aa9a749116aa2d", 41 | "03bf8ee1dbfd7f8a034c6f649108ca2f908500b0d0ef6530b681557d4955f5ea", 42 | "860da47f7eb3bdfd6b261b811881068e4552dfb549eb60825abdfbad4563c0f0", 43 | "da2e319491446c807219025d857b2361cc8a7db7582d897432a60c3cd1d12fc9", 44 | "76a54ba7a4b91778edc69c89c11e5ead0fd8c49567d351df745fdcb21d356d92", 45 | "3254b515ddc797fccfa35ebf790531ce8c35082a70c47eab787ceb80010ebffa", 46 | "3df7613ea58afc4c6c443cad6a8a1eaff4c5ae04e8124ec4e7204811c120101c", 47 | "b59b4a9356f693ac9fcf1bbc4acd54a0ab72e13fd9eb52b94c5cd96f6dbf4c3b", 48 | "c31ab62c32c4509d295f77994cdb4324181701f5589019839bc16e8948faaa99", 49 | "77c471893e907c0c590f319e609c1977d2552a4bf34c4abb2a699ca0e1933f0a", 50 | "03aabf5ef5d5909fd49f90c991a3f0207ea283777a9d8f8e3e6bc176a67069a4", 51 | "dc0c12b04fd173b892fcd535c828bf157485581397f11cdf608ef652c0640d3d", 52 | "318f7257aa8c2628a42912458e766a87ec92ec238a25fe30ef42f5f0d589615a", 53 | "67fcc7bdb680055454f2c79137ec7dff3ede9fe766e143354ad0428cd26c77c7", 54 | "584d0b038a73d1edd7fd5ed26e54c67815619cb9a7793885e65e86d9e57539c3" 55 | ], 56 | "time": 1408064087, 57 | "nonce": 3023709696, 58 | "bits": "1d00ffff", 59 | "difficulty": 1, 60 | "chainwork": "0000000000000000000000000000000000000000000000002206389b1adf47fe", 61 | "previousblockhash": "0000000037b798db92ef9f91e5ae4c108c3f45d4754470ef9d17f655f21f5b27", 62 | "nextblockhash": "00000000a1e890e1c2cfe6edf939b83b9a4d6fd4b066324b84f67660215887b0", 63 | "reward": 25, 64 | "isMainChain": true, 65 | "poolInfo": {} 66 | }, 67 | "00000000a1e890e1c2cfe6edf939b83b9a4d6fd4b066324b84f67660215887b0": { 68 | "hash": "00000000a1e890e1c2cfe6edf939b83b9a4d6fd4b066324b84f67660215887b0", 69 | "confirmations": 352329, 70 | "size": 6794, 71 | "height": 274302, 72 | "version": 2, 73 | "merkleroot": "e4ea2738445a8e33f32e5338314edb58dfb9865c0b4d8aef1d09cfe96300e456", 74 | "tx": [ 75 | "c0dcad911f977b71a47ad2a45619ea98b0a1b7e8447a0684638048a973ba0bc4", 76 | "ffd316b0c4feb9d29c61c3734fcde0167600441e560931c8c7267a9de3d9e29a", 77 | "08751efa72646bc60ef9fcbc107389f94a0f14b58824409207eaa6914f657e35", 78 | "6a4ddda89782e4185aafe7aad71fa3c31d490c48158628141afd8c0c29a21b1d", 79 | "f611cd3a1d676631b630600695074aab57b98ddc6982e93419438753f8f3fbda", 80 | "41017e25bed3b740508fc10286ffd363935698bd541ac8c43d8fad52cde25220", 81 | "f3b26dc42267cabf06fb53c1b0fda31d6772b1623c030c145067c7746ab00a04", 82 | "caf9e82111565df92a3fa40d1c3bfd11f08a36dba5afbb4394eebcf3c6bf36b4", 83 | "802c14d491eb90d8d7b40589c124e21779f256b5bd683bbe3367b532844749d3", 84 | "9ebbd8517e723b51a9a08e0026d26cd5f794eafb65b0887a78ef96309a59d889", 85 | "d514a0d5e51667e1f617daafe6c62f8d68d0e7ef6c5e150b798504e0aa14c13e", 86 | "12b593424348a4c6b9d45692fbd5dd657daed782ff27b741e6a9cc68127f7e27", 87 | "365e0b4855483a85a633e50b7c3b45a395d1add3b46dd6d9c196ae946ed1a01e", 88 | "edb1ca8bc9cd50f7df932d6e4b4635a94a0c53cd36fa13b9453651cd98d109bc", 89 | "944a0ccb60084f82e8d791dc22a1650c1b23a6d3ec2eeec8422086a4d1237227", 90 | "96f1eb987a071e17252a084037dee4bdfe5d8f59b9a06e43ec3a1a7c88de2762", 91 | "e98d123f7f1e5e2907dda37f6f79e6512906c6862a3df5ccb6113fd8c80c8367", 92 | "c3e2c47d3464d2ad4add70828b4fe411007f1ede294ce369c61ee33b6c3d86a7", 93 | "2f39f3b6776ae6530ce292809f0253e1d99a1f9781c5d2d491d1e7b6327193c0", 94 | "171a157ec1239ae6f90d29c930e91f31a38be30263e0b288ae976711d62125bd", 95 | "827071ed91ee1851341af59029875ee678e80b844afa73c3b6c1e95ea5198baf", 96 | "c7770eed7961550629bed6778cd223d5243639d8a09e6aae8ac4a07ae4881f60", 97 | "5ea4614412419fd472aae3bbcf97bf2bdf2b8c1a77923d246362e21665e8543e", 98 | "50e23093d9ec14294c54fdcc4e5ae343b103cf63d79b8f1f2bb70258a811d010", 99 | "be236cd1eee010cef5c4c1d5c7ed8c12ed372e47c562bdd2a6d6dc839364f029", 100 | "7191489257f78dd0a106c76e6ceb9685310b9d4d417a868478adca0d1b4518f8", 101 | "e301376eae7a0bdc78cdb482056cdfa2f7ff8ec857c9c60872ee425024235cc3" 102 | ], 103 | "time": 1408065294, 104 | "nonce": 824483328, 105 | "bits": "1d00ffff", 106 | "difficulty": 1, 107 | "chainwork": "0000000000000000000000000000000000000000000000002206389c1ae047ff", 108 | "previousblockhash": "00000000a711d72347425408b0a51f5bbd578572c3c224873f2dd5fd82b3b6d9", 109 | "nextblockhash": "00000000ae13c8ee7f4354eba180f9c23e285cb2a5da981677dba29cd88e89c4", 110 | "reward": 25, 111 | "isMainChain": true, 112 | "poolInfo": {} 113 | }, 114 | "00000000000007dc622b16ab6698ad580c69e7e21c59bc9474418e85c6f3489a": { 115 | "hash": "00000000000007dc622b16ab6698ad580c69e7e21c59bc9474418e85c6f3489a", 116 | "confirmations": 315025, 117 | "size": 61174, 118 | "height": 311940, 119 | "version": 2, 120 | "merkleroot": "168161c68cc0a3036e3af418f6540835faa34569994fe36bbcd9ce0bc05cd1ac", 121 | "tx": [ 122 | "4015d19c718f2f79585a1f2619e201b9d75645887fc86316a87e12e54252f884", 123 | "6c375ebe5421fd57e83a18f35b9dc744471d446721f8e45c22951a16297efbd3", 124 | "0645be9dddae5105b147b1d8f3d632473230b4ddc757ab65c2d3bcad5b70ac8a", 125 | "add985521eda3950fc3ac48a088bac68867c2a09730723d2d1d76fa6a533a3cd", 126 | "b69c49e7e46c757d3546989bfaf0bafc26f84e48a3a1451965f96c83256bfcc0", 127 | "3ba0483ac13dcdd42f9de66456a66ee159c8fb62b7b3a1cb5753f6b5958804ae", 128 | "52c1d6ec9ca3611df5f0e25348c69a1b03ff854e5b40b7c0f5d7a15a751b5965", 129 | "797dcb73b0ecbcf67fe58f261c20c9a3c3e68bc37dd95e5c81117a46e216d574", 130 | "3dbc44cefad6a91c425215fc4e63f2152ab0b0af1f9683701dc4ef7c55990b29", 131 | "0e3a892477e026b402367d90667a5433097c8d7f446f8ec393694d7c5468cbd7", 132 | "b3847443452f69674b56807f780beb2744ecc497ee85eb629348feed971fd531", 133 | "06772293daa2b972e66a4d988e290dc012542eb9861dd90280970e208d6a1c3d", 134 | "f1dc6d423caef6956afbbb6a1a2de70fdf2c1fa29e7737cfa085a8124065fc37", 135 | "9d582498493c87f884d8296a9df80884a3fb728a8f094bc2e73f9107e053b4c4", 136 | "8bc08e7740f50f3986e5f11f531cfea7fdd173219cfd9d629c0136d540ca8488", 137 | "5bebd06d167f749db711857652d0c5ce66ee3aa4c6d296d90dd73fe8a02ab937", 138 | "5de8ef65d3c6a8c9d6e9111b4dc104b5dd810d1407eb83360b8a12faf1617f03", 139 | "f99183793b1ac785d72e28e2d0d048786886f5f337b31e845109bb006c32031a", 140 | "9d2c560a1de917fd727595a5d344e3fd5f7f240ad1825d151439fbadc5e67b65", 141 | "6560380b5b8fc147e760545ff72eb3aca05116326509dea0157faf94dbe4ac32", 142 | "d195354d50d7995f780cef2e6653b480d91dedae624bd2e9b6803278cabb7607", 143 | "b1c643f66e6b7391f15ebac5e37f429b463461bdb2f64f6cd673cb48a7a32cbf", 144 | "a6fe7d6d5199714a44a6b765b5b26dce2a3f215593acfd77738a6eec6eea1815", 145 | "1b5178678513499a3a10f90ab71e812b6789701fa40b20597b9fc35c43570c81", 146 | "42bf2591485e0f24159cf5059656ecf6f5604f8d2309e67f2f3a5e2a51452a62", 147 | "8c3e6f3242d39b1606679346ecf2d4db1cf47523cd49f6f12a8a0b72ae11deec", 148 | "de19d7f7a6aa3bfc65c81007586210f122afaea0a7fef1d1c0d6e2ee33eab862", 149 | "b4aa3af464ccecd6ab272bd96cef41b62ba543b5003bf362b3094e85da495a18", 150 | "5418ecc3974b0232fef3a59c0f5d0eea9ddb0397dd121ec8d81aa6a116d755e8", 151 | "c3c0791877b650b1be05619409249cde621ae53dcdf56a0e90626159f4d00498" 152 | ], 153 | "time": 1417489870, 154 | "nonce": 1491062048, 155 | "bits": "1a07dde7", 156 | "difficulty": 2132626.625779, 157 | "chainwork": "000000000000000000000000000000000000000000000000fc1da74c5f46bdd8", 158 | "previousblockhash": "00000000d487dbc55a865c97faaa179fe5e6d229597832e8ecfa6f274cea4006", 159 | "nextblockhash": "000000000e06ab849fbeb71b111cafbcbcecbbd88c8e70f8ed9c0b084fd3cd39", 160 | "reward": 25, 161 | "isMainChain": true, 162 | "poolInfo": {} 163 | } 164 | } -------------------------------------------------------------------------------- /test/fixtures/transactions.rawtx.json: -------------------------------------------------------------------------------- 1 | { 2 | "4979a0b69703f888dc5936a4be039dabb976fae7d45604d57b5fad35b3c94200": {"rawtx": "01000000016e90f86ccebd3caf5a339633bfdb28c1ae6961a752ad21e8e212b1e97a8965b4010000006b483045022100d1eb848df7594a5f9b697dea0bf733c8ec87dec2b63142e4b572b07f2f09d12702200f6b124db6689e645f39e57d6cffcfb5f5869c089c4f1922ef6e6cfe3f07e8e20121037ce0c786277fafc38e2e2d49b1be36f02a360ba4a2dd58cf977784975a573fb6ffffffff02c0175302000000001976a91461120f6e004c7a2e20ecdedf461f1eb032c2e5c388ac48698831d00000001976a9140fe1355e31a061b2508919578b6f8c60dd2f29cf88ac00000000"}, 3 | "ffd316b0c4feb9d29c61c3734fcde0167600441e560931c8c7267a9de3d9e29a": {"rawtx": "01000000011c1020c1114820e7c44e12e804aec5f4af1e8a6aad3c446c4cfc8aa53e61f73d010000008a47304402200fea124cecd36e92cb0b549b62740a26f374629b26f16292a3e858753035172802205ba172966addddbbe8181af6cd7fb6e9c53414fb6727c4f15589c74567e48ab30141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a91461120f6e004c7a2e20ecdedf461f1eb032c2e5c388acabfb423d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 4 | "fe5cbaa170d288ae7d0937b1a4146cf7ef505c70c6b9155ffd8b1c55b54f6fc7": {"rawtx": "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0b03690c06062f503253482fffffffff0448e70395000000001976a914fdb9fb622b0db8d9121475a983288a0876f4de4888ac0000000000000000226a200000000000000000000000000000000000000000000000000000ffff0000000000000000000000001b6a1976a914fdb9fb622b0db8d9121475a983288a0876f4de4888ac0000000000000000326a3076d30f9fe81505006475b2e289ddc22c4421e0dba86c79c36fc72b46339cd9170f05be54c37210efba6f371821906d0100000000"}, 5 | "b1dd437ba1b04779b59882cd25cfe088ec4e7d2003790eb2fd0504a28655c523": {"rawtx": "010000000126500a56d82179953f56b965ec14d47f8bdd2a1de74331b6c42efb8d91050d74010000006a4730440220044df51dd3f7d4c240baddbebc3650b2113efc805f74593ee09f9041a549706402200e160dba03f48fdd3470fe5a142e2629efdf648fb59b6c329951230772ce041f012103cab45447e6ce0a052f7deb0da7cc5a69212595be80ac2ea787b28e29eda4ffa7ffffffff0278f81b03000000001976a9149c5839e666464f41d810e18c69b7963ebb184d4a88aca6ee4700000000001976a914ce5c3a4cb04e255d0b384fb6cd53b011ed49121d88ac00000000"}, 6 | "4979a0b69703f888dc5936a4be039dabb976fae7d45604d57b5fad35b3c94200": {"rawtx": "01000000016e90f86ccebd3caf5a339633bfdb28c1ae6961a752ad21e8e212b1e97a8965b4010000006b483045022100d1eb848df7594a5f9b697dea0bf733c8ec87dec2b63142e4b572b07f2f09d12702200f6b124db6689e645f39e57d6cffcfb5f5869c089c4f1922ef6e6cfe3f07e8e20121037ce0c786277fafc38e2e2d49b1be36f02a360ba4a2dd58cf977784975a573fb6ffffffff02c0175302000000001976a91461120f6e004c7a2e20ecdedf461f1eb032c2e5c388ac48698831d00000001976a9140fe1355e31a061b2508919578b6f8c60dd2f29cf88ac00000000"}, 7 | "801f93aa50c94510afa7ac997c460a0ebfde25eaed23063da72c8145d232f43a": {"rawtx": "010000000196f29a39cc68ad3263bacf6c74081a03300a26484f088ba9c3fbbbd2bf5051ce010000006a473044022008e80bd5bee9123b90cf57cc5257660fac1b1771cc7c9a7471d8c463d99f740f0220185bea5917bc06048756ffed11ebd40dc7e38f50cb125b0d1da4a4b42829a8a20121026fef6480e7a4f1c823b184c20e5ed553d9f3ef449f665a380b6fd8d8756ebb25ffffffff0200000000000000002a6a2831536879446742426d576e465839395041477a462b79444e304d496b42535121314e456d33646841f006fc29010000001976a9147218e7bd22ef4e976afc778731c56e1a0f61a2dd88ac00000000"}, 8 | "7a7c2099f4e37d22c396669db2950cec14d87fc7e6d01b88eb28237362d3ad4d": {"rawtx": "010000000107b0e61fd80f724422d5e6b2a7affcb5903f0884e1b7ad3a08a093decba6798901000000d90047304402201dc62d70ac405809eb6143eaa7192d2cef7a2519be0c608bc3607cb36489ff3e02203c361993cff8f08163d28661d81cbedaa6d9d2e6af272acc5e0f62de077213100147304402207f489d6050db00753ee0c9fa4e00eaf8b16f1fc4364dc2ab56c0f351972ff10f02207ccddfe0ff131b2e506c3065114fc5fa42a2b666b3281fb65a8280b60c61901001475221028706eb9d845df86f437672ee092f1315b596cd930e2e0506545674dec62961a82103856b37f9ac438f89e37ee9ee8e8697287080077a6414feadff110e367ab0ba8752aeffffffff02002d31010000000017a9146e99bc8cb4de794907249f9623e43c3b7ad8ecbd87d85b3b040000000017a9142a2f1a1582cd541eaffa486155e7f9b6c0eae0aa8700000000"}, 9 | "a155a548ca3b24c457add7fbe47ee9cf1e849ec947bb5ec2125466aa0d8bc8e2": {"rawtx": "010000000143e1aacd513cea3579a36bc770bd0b587bc80ac8320ec013c13fbb526d249fed010000006b483045022100a85a60f19bc9e0504e949bba85347e286690c7fb6b7847dc2155d13033e7ae5f022055f9c09f14bc516da5c4bbdfb1e99d1c72c570cbe4c977f558033331d7ade70d012102497739090dc2951c488a282242e0cb483bea6f839c1832a58145cc4703d89222ffffffff0210270000000000001976a91423169c87b271e4479e3baa2960bb2b09e15c994188ac08b8e900000000001976a914f799a599c74971cfa2fa24f9e424df960bc6b77188ac00000000"}, 10 | "02b1cd72cda9ac5aa4acd083c102e0562fb542b87d36fe5d7d80a396cfd2d601": {"rawtx": "010000000123c55586a20405fdb20e7903207d4eec88e0cf25cd8298b57947b0a17b43ddb1000000006a47304402203b6b050c1c945de960782be72965fdb9ec651d4e9284af1825b34e4851a24d8f0220354c1b6453287f6930ede131ad899ca5cef728df38ac2d5cfd353bbab6ab2d1c01210390b8655eaf883b8525bdcba810da5bd54d4620c0937ccc29812e4e39b8bfda52ffffffff029b77e902000000001976a914f13b5f61acd23ecb58cbfb13a47774921d9e01f788accd593200000000001976a91404d226d54eb75e68b20c6c1801aba24672d7081388ac00000000"}, 11 | "97032422ac420f01927cbc00149238bb0a19beb408f15d4c2755bc594b98d4d9": {"rawtx": "0100000001e2c88b0daa665412c25ebb47c99e841ecfe97ee4fbd7ad57c4243bca48a555a1010000006a473044022067076c3f309dfba4dfa3293d64e98e0810a6a4a66f03d21a3ba3f0449e0e2c1002203c3a3a706d40a6c4d8ce9a0ae1ad69c6c56d836537cb73b33dcf44a163070c6d012102497739090dc2951c488a282242e0cb483bea6f839c1832a58145cc4703d89222ffffffff0230750000000000001976a914fd6fbeff72291eb01a4793689304a517314298d988acc81be900000000001976a914f799a599c74971cfa2fa24f9e424df960bc6b77188ac00000000"}, 12 | "13da8238fe72eaa4c1b96c61bdc8ed99716545f9bd75cd2eb3f16d601f0da8d4": {"rawtx": "01000000013af432d245812ca73d0623edea25debf0e0a467c99aca7af1045c950aa931f80010000006a47304402203193a0d0ed0612189bd1a2f58b8fb53f99dac758357775ccaa7e4fa282dc32b30220605d49fd00e38833873034c9fdc94cb01bd7ca373efc9755badec024a2e097500121026fef6480e7a4f1c823b184c20e5ed553d9f3ef449f665a380b6fd8d8756ebb25ffffffff0200000000000000002a6a2874496862413533556b364a7a464f71767a6c4d355a5761572b7465476269346c4d56315071423869e0dffb29010000001976a9147218e7bd22ef4e976afc778731c56e1a0f61a2dd88ac00000000"}, 13 | "6560380b5b8fc147e760545ff72eb3aca05116326509dea0157faf94dbe4ac32": {"rawtx": "0100000001657be6c5adfb3914155d82d10a247f5ffde344d3a5957572fd17e91d0a562c9d010000008b483045022100fdcf8f8caf4c671ddb399dc7df8a5a07ad5237fa16f448ca00c5868028529b740220635403257f00e10eb49185269ad6a5fb95c68aabc4dda25172ce8bffb4bb41060141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff0200e1f5050000000017a914c88c190200000000c08d19020000000070e0100287780e5a0a010000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 14 | "243ff0ca947a6ba3cf0a032b589344170d7078cda3165ba9afc87419ff16708e": {"rawtx": "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e037d2f0402a304062f503253482fffffffff0190580495000000002321035a01fb9e854a9386ad6b7ddd03046ffc648bc895793c7b6ec73eed00de1bf14fac00000000"}, 15 | "008a6c398f22968400f681bd2ae588ef358fce76a266f33396aa9a749116aa2d": {"rawtx": "0100000001f38e9a3ec53f8f9c2a26d1dbef2558f85e7062b144c0957973c9d0ba7577a6f1000000006b483045022100b19fc26990f93c439b63c2c6d2b2d1d8f7bb1628b096f1788699bb9524c1451f022034b7b73d366dcb3c144c359bb816a9447cbe9904169003649d8588f279dd61f80121026564629ae0ae24798d06652a7d5d0e3a2d9b174242716791a1043271c5af8b2bffffffff02e114ff1b000000001976a9147eddc359446b295cc0c47e0ea03629ac5d6548f588ac78c2f54a350000001976a91467dc9dd89cb0dadeca4d1f96974b771f295872c588ac00000000"}, 16 | "03bf8ee1dbfd7f8a034c6f649108ca2f908500b0d0ef6530b681557d4955f5ea": {"rawtx": "0100000007f3abf554ca9488195b9f50bbe8a0d9d0c60dc1b7cd3de82b32374f28789080ed010000006b4830450221009d4436a443fd8d18d793e0eec19eec83ad3bc7f4491a649b8ea2590b5f2e99af02207f9511f0568a2e37b3cbc5ff92378a47cec6dd5aa881b3eda5b15a51270b1af30121034e1a6cbf1621419770f42f4f5f79c696c76731d3397a7ff15c879effb0a53813ffffffff51d45bcaba5bfb02c09eab6366ccedeca04dae71ca8b7c583759bbce8c8542ae010000006b4830450221008446bee1fdb8794c872112af52c3fb7a5ace39d9a5b7ea6d48a7b6a9d1376b3c022020b6e40dbaef354db64bd057d87c7adfc972429d49b5a6182d921ab03f5c40490121034e1a6cbf1621419770f42f4f5f79c696c76731d3397a7ff15c879effb0a53813ffffffff3c9891e2a50963d4719c495116319e854987179a43b5b2ed141c1505bd92b787000000006a473044022066b66f0b2310e10b944a7908d74a94bf7952c2bb22e31522dc6df96131cc21c302206bac6edf2dd311d012ae1840e3705ad1eba336af9dd1e2cb0225049fec88381b0121033f5d8269fcdf2fd50bb952fb1982b93edc4e6601410134909d5b5b8edd5b3336ffffffff317ebe714e1ec41854578e5991a08b052aeda1db721553b668b501955a4a83a5010000006b483045022100da71855089dafadf8d23036a63b7e95d068284a03d2dbfaa79291ef14c1ddcb1022004102ad12d3d6c690350248ab49a5c02d67529bb51793c7f85603ab40f028e9c0121027572b4b40495c9433e7aa4da949fa52c61f89ec521503276cf289312175a70f2ffffffff7a4960ee07d2fbf56d55f4d5a132aeeecd5747f92712f7e7729a765ac6c0147e0a0000006b483045022100c34ec121a8bbfb80663f658c4c4cf8bfb467ef5772fc40a9554a0e85192a229502202d739a39772a3ff22cf54b248674985825c313e4d52529c8d7b8e4e92073d0400121023f2fc4e80aa0f4821189016adea806b3435917149c0295f3a14cb857ca61a6d2fffffffffe259e4af88eccd5ca918a0b8872aadab3d354987047e21e0a455ac7f92b0785020000006a47304402204d07d27089ba785829105590025b2741363b34d0ccf28a6af12af1d40ceca08202201a9977a034ac8780939f20bcc1cd847142d0e6458716a661b1edb33171c6d14201210303d9b9eb0599c870f90f430f56e74b6dba18cc76e06661c33c5bdb82fa3c86f3ffffffff7263cab59791c9ecc109ea0f94e1e8f2f8139d290c8618a353d5b4e9534784ea000000006a47304402201466a7b0a96346cff8ffe26beaf40dcedce0dbd6947073296b5046d9c3d5d9c0022059fa5d8d265a91cf962bb4a13730c259d755cb55538bbc7a2651074807b5a7e10121033f5d8269fcdf2fd50bb952fb1982b93edc4e6601410134909d5b5b8edd5b3336ffffffff02a3be5f0c000000001976a914a03b3e26461f68bf483c5d6b2d825707eccd63b488aca0d71400000000001976a914c6b996e7b578359f1e1e416dee1d7ec5fd44eef688ac00000000"}, 17 | "860da47f7eb3bdfd6b261b811881068e4552dfb549eb60825abdfbad4563c0f0": {"rawtx": "01000000013c990abdf05808c3c9eb781a5ad09d530255acc23b80adb5bb2b9d42193bdf44000000006b48304502210094a519fb7ac8fd8e8f6633c09a297d93b7042678574cf53b01c86bc3344f0b5e0220129aaa589061a39a7926ca37650063471f8d4943d4df014f2e55e7a1dafa9d13012103268b4bb8f9354801fcd366ec3e9f4bbd187e5f0a199568c84007a15dea094c63ffffffff0240b72803000000001976a914010d9f022a02a4d4148f646e498356f90b3b5ce488acb5acd46e0c0000001976a914ab72dfb5649117eb801df8a54fded6805d2708cf88ac00000000"}, 18 | "da2e319491446c807219025d857b2361cc8a7db7582d897432a60c3cd1d12fc9": {"rawtx": "01000000011f2426886a3374e631a1c9e4d44075e30554cadc749e9f5e02a20f59e103d32101000000fdfd000047304402201e87d498b7e5f9acffb8c7985aa6e6c8fbc1249569c8855d0dddf6a4e70303b50220781c11b8cfd1320774b8d9c64016a81428f886c551ce43e54d69839d54f3208601483045022100bce53b1de61dd57ae86772f7eb81fdb29dd3393ae41a448ed94441ed76f2b38e02207cf3259afd162c4862905f312deaad0fe9ef974d0c2b87d45a2481d0f4ccca3e014c69522103b98fd29fddb45e4675c7c60ee6a9fcb4f0e440babf2c11d2860173af3b24079f21034ce115b6ecd1f05c9a83c00d082d8a0a2d8a3a688ef7fdeacbe892a5ecbc94bf21028506d2b42803ee2c4f02e854b4cad7cce0dec1c43c42bc7ce9e8089576ffc6e853aeffffffff02e8030000000000001976a914f1172690c637aa8e9efdc289b91397d33bb6d0bf88ac88c5fa020000000017a914eb2fc4d03375fabbafae64a31c9b89abe1120ce28700000000"}, 19 | "76a54ba7a4b91778edc69c89c11e5ead0fd8c49567d351df745fdcb21d356d92": {"rawtx": "0100000001e06fac0b30e6dd0ab90443ccbb1a436dad7c7446eb829c08f95d6c564513abef010000008b4830450221008a3bb70f29dd9bebf5103052a63e599e080352c889588ee759e9dd5288e8d68302202a2934c0a950724a05dc49114ba40c799cc2f1e677307f9623dd4e0d8da185bc0141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02a0860100000000001976a914c3a689a2849f9b1b41c85927b714f3dde871d4c588acbb93453d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 20 | "3254b515ddc797fccfa35ebf790531ce8c35082a70c47eab787ceb80010ebffa": {"rawtx": "0100000001926d351db2dc5f74df51d36795c4d80fad5e1ec1899cc6ed7817b9a4a74ba576010000008a4730440220186cf3cf585b6cf076f956ef4494781d66861c22db185e5363bcc36211e627f70220390995a486bc2477d31277573361602f201964d263b7c1d9ecf5ea0f3f360e1f0141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02a0860100000000001976a9148cfca6fb377017736fca1bf09a3d5b80275acdd588ac0be6433d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 21 | "3df7613ea58afc4c6c443cad6a8a1eaff4c5ae04e8124ec4e7204811c120101c": {"rawtx": "0100000001fabf0e0180eb7c78ab7ec4702a08358cce310579bf5ea3cffc97c7dd15b55432010000008c493046022100e590dc4a46ab3c0f897914b8ff565ff3683391292d9db830097727d0e0043138022100cefd4578ce3c4059853434455201865b4268d03325fe1e8994563ad2af0799c10141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a914a9431895feb4321991cbe12ca086e2073b64a94588acdb70433d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 22 | "b59b4a9356f693ac9fcf1bbc4acd54a0ab72e13fd9eb52b94c5cd96f6dbf4c3b": {"rawtx": "0100000002ccaf600c7f68631d2f0fa878ba93cd7e40948f8cb6805b399899a83a8c62499b000000006b483045022100be7faa96ceb27c183dbc67ad4b160d3cbf23698e963df05755b34f5c64e2a9a802204644e6680c264033e61d926a788396c186c7ae13789178b106b68ab1002baabe0121022a715efc546c71be8600a4b4e1e8e04687b313413454e5ea71078c156e2220f7ffffffff468c51897ab53207498d667afd3ccead355f37b15a83c970ccd8a2a9a9331ef3000000006b483045022100af3d13148f999599f5ba280aaecbe0b90e10828f9eed18753d06c7409c642dd00220341911d08db166eee8f8ca17cff589d38bc0393614ae63b4dd4d03aae5c00ad00121022a715efc546c71be8600a4b4e1e8e04687b313413454e5ea71078c156e2220f7ffffffff0110270000000000001976a9144ed4e5327d623003a3457858c3b7495b7c82f84a88ac00000000"}, 23 | "c31ab62c32c4509d295f77994cdb4324181701f5589019839bc16e8948faaa99": {"rawtx": "0100000002bc58d1c719cccf30d6636331fb0f212efc1277af1169de3b62457d4f87b3c9f8010000006a4730440220665039520f152d3a8b96da9d76ab14485d4d95effaf1b46f351866c87a6f861d022062bd1f11ddbad5f2863bd5339ee25e2abd5707671efaa8b273f0753335cf381e0121035d04465ba1ed5f24774181b77f8de65ae849d65bd50d470672980b639c31b19fffffffff32d6ab1eebb8878eb8ad602fad906ec517645e18b013b2534dcb0878800f2a1f000000006a47304402200f287e1f259d2cc2d761afcbd21c890206da76dd2a2b2904101b8f01117dafda0220798ee07f333fa334cbdf5050165884630fb96942923e1b4a453e0d1ba79e73c40121029a657c12cd6efca60b746c689b7fa6de9abf0e597aeb5e038730c34496db35f3ffffffff0200e1f505000000001976a9145613445f58b4536445383a295ea705e49d2442f988ac40e81d00000000001976a9145de14ae535b3f187beaeb92b6237a64b6d8f1e2788ac00000000"}, 24 | "77c471893e907c0c590f319e609c1977d2552a4bf34c4abb2a699ca0e1933f0a": {"rawtx": "0100000002f166baa05b405a7a0342da5daf2f4e711790adbdaf493403c25b1bf5b3e74622010000006a47304402204fbb2655083cd8d5af1fdf6ace8e8d9c189a6146f21b057ded940e9a8b0fb24b022062f3789d488737f49383560a63fbd5afc5e87f774d623201eef17fff3b91c2da0121035d04465ba1ed5f24774181b77f8de65ae849d65bd50d470672980b639c31b19fffffffffbc58d1c719cccf30d6636331fb0f212efc1277af1169de3b62457d4f87b3c9f8000000006b483045022100d90e704d2651ddfff1cf9acb8766602b86ac06a8aca815298927976d977b75040220656611cbb9e5442ae39972b32c1cd79dc661543da65684148c3e7702c1bdc3f90121025433910eacf7f6a9c49cc450d03a7b7b9add410acdc1611932ef70370309991fffffffff0200e1f505000000001976a914159d791eb877c2f7c54eec25d84cb2c7818ac28588ac40e81d00000000001976a91485b45bf28261101e0c8c97deab004db38a1667bc88ac00000000"}, 25 | "03aabf5ef5d5909fd49f90c991a3f0207ea283777a9d8f8e3e6bc176a67069a4": {"rawtx": "01000000012daa1691749aaa9633f366a276ce8f35ef88e52abd81f6008496228f396c8a00010000006a47304402201359eb479ae6b646669ce77ef057e98c548e840ee26e1e9d543d11fa64ff86e302200af2122c92e0edd16cfed740268bb9600695fbe0760bbb0c5d103ff66e6077ae012103382a4c388ecf0f2ffcafdd213d2cc791f229db13994ac38a1ebfb3cbd79f000fffffffff02cd5c7f3a350000001976a91458a0949d65f52ca2e3abc5e242c0ed73dc910d5388acab657610000000001976a914572047a91e94ae2dcc966f0d5f22857c5ad189ec88ac00000000"}, 26 | "dc0c12b04fd173b892fcd535c828bf157485581397f11cdf608ef652c0640d3d": {"rawtx": "0100000001f0c06345adfbbd5a8260eb49b5df52458e068118811b266bfdbdb37e7fa40d86010000006b4830450221009c8182453009265fcc49741a949db3cbe7f67bd503526f40933ff241c74feea50220096276186f82da0f60ce569e1abf515970b5241d394de296ea861fb3aec4afd60121022d293d2f2f30993d067bae721198af2c01d6d227da166aefc0622d4d7b4f79ebffffffff02e9df2e03000000001976a914b5225705e9fbd168d8c363bee1d5573b1c698a8688accccca56b0c0000001976a914fb73779af24e112451086c71d7258f2ef6569c1488ac00000000"}, 27 | "318f7257aa8c2628a42912458e766a87ec92ec238a25fe30ef42f5f0d589615a": {"rawtx": "0100000001a46970a676c16b3e8e8f9d7a7783a27e20f0a391c9909fd49f90d5f55ebfaa03000000006a47304402204420f2740432b5c5d4983b3aa13adbae8d28f2f5b8b46d9d599a465fc1928f0002203457f2a9e45645014b6b35ddab57c07ea9e409bffd8b46c23350f27114df0d660121038ca353803a2bc97353994cc34233c7bc1fc8bbe25109b97f51d97b5fdfb95312ffffffff022d09b71d000000001976a914451995c5ebe63d14a7c7bb817fca13406f92baea88aca053c81c350000001976a9144aaaa2fb2d13574a5ceea0646000746b412e0ad988ac00000000"}, 28 | "67fcc7bdb680055454f2c79137ec7dff3ede9fe766e143354ad0428cd26c77c7": {"rawtx": "01000000015a6189d5f0f542ef30fe258a23ec92ec876a768e451229a428268caa57728f31010000006b483045022100be6782a721261019feba0d7078b9c17df909c7c1eef543af863c9f1faa1985d902203b433bcd83e4d2ddad582eaa9facc53fdfc0a15e53e2382ae037750a09ee23ea0121025f20801ff8bf98b0b2cfcd0e1249d0093cbe0675a35b39b34166e86b5fab1f0bffffffff0267a8990c350000001976a9141ac41d4123b8b062f740c77e94c5f68456b3943988ac39ab2e10000000001976a9140685b65a83107e93971c777d1fe5a3e3aae2cfa488ac00000000"}, 29 | "584d0b038a73d1edd7fd5ed26e54c67815619cb9a7793885e65e86d9e57539c3": {"rawtx": "0100000001c7776cd28c42d04a3543e166e79fde3eff7dec3791c7f254540580b6bdc7fc67000000006a473044022006eef4496373d952238fae446da8ab687e55309876c800c09970d0fa707a1fcb02206a578a50c947c09d07e4a2265e9fc13b406e7aeaa8fcc3b74a7e556fd0db838a0121038e559845f0c8c56f7da626fd8def53a6a0a224309116c4565879dc9fb3ffa486ffffffff029d4340fd340000001976a9149fe0f9477fca20a3cf0f1874a2dd8563ce278e8088acca64590f000000001976a9142822d23622aa28bff95a6231fdff64aa7e09f3ad88ac00000000"}, 30 | "c0dcad911f977b71a47ad2a45619ea98b0a1b7e8447a0684638048a973ba0bc4": {"rawtx": "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e037e2f0402be02062f503253482fffffffff012d142495000000002321020f6b0999e6a9b1932c4d9bd354b89e22d2148b1ba05eac628015d9bf92bd577eac00000000"}, 31 | "08751efa72646bc60ef9fcbc107389f94a0f14b58824409207eaa6914f657e35": {"rawtx": "01000000010e2225f9172a355d900a5004476cf22a8865d84ff7a721a876a5662a1bc3f846000000006b483045022100dfa8319ecce4938c2767a83f29270fa1fa2a995b8db3dcf0652a984e0161767d02202993acbbed4413523ae3622e2b74a8907573b91e97ee7b362a6e621e59ebf1770121020a6b25352e180c1591ab93fecbacdda790c80afac1298d17fb35f3302926b3d8ffffffff01c0c62d00000000001976a914010d9f022a02a4d4148f646e498356f90b3b5ce488ac00000000"}, 32 | "6a4ddda89782e4185aafe7aad71fa3c31d490c48158628141afd8c0c29a21b1d": {"rawtx": "01000000013d0d64c052f68e60df1cf1971358857415bf28c835d5fc92b873d14fb0120cdc000000006b483045022100c02e817ed7da62dff0090f20369d2fc455a5ba2dfbb19024ef4ace41899e6ed90220596053fdd25a7138d3a8adef58541bde645419153bf67f5fe01de570faebe4940121033f529388fc30d31ba16a7cff48e9bdda6736c0237702f125ab460250a99fdb88ffffffff0298f60200000000001976a914e2e53ebb9cb09f699e50e6548978eec63ddea7bf88ac41c22b03000000001976a914e2e53ebb9cb09f699e50e6548978eec63ddea7bf88ac00000000"}, 33 | "f611cd3a1d676631b630600695074aab57b98ddc6982e93419438753f8f3fbda": {"rawtx": "01000000019ae2d9e39d7a26c7c83109561e44007616e0cd4f73c3619cd2b9fec4b016d3ff010000008a473044022043f8737ed7f42535867ddb7268e648dacd22d472d569bc91e685f5a215fbbb5a02203744412b4f771fa31d2357108b2c76798d707792165407c7c8948e56339875310141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a9149f607a96da2aeb2b84a7b3786e970fa84f22941a88ac7b86423d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 34 | "41017e25bed3b740508fc10286ffd363935698bd541ac8c43d8fad52cde25220": {"rawtx": "0100000001dafbf3f85387431934e98269dc8db957ab4a0795066030b63166671d3acd11f6010000008c493046022100ad2aefd563faad6a4747439992029fa2ea033c3c193e3b734b88c65d847fcd08022100802b6e3cd1f948c45f927bcc38213230bad5c126975509e37f35634779a2b3dc0141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a914a2206a6b9e0bb209dda1b71aabb810649c3ce1c688ac4b11423d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 35 | "f3b26dc42267cabf06fb53c1b0fda31d6772b1623c030c145067c7746ab00a04": {"rawtx": "01000000012052e2cd52ad8f3dc4c81a54bd98569363d3ff8602c18f5040b7d3be257e0141010000008b48304502203468df924be699d4bb18b5a06ca45b3abafd1db948f8390873b3a5074a0b4c96022100d2cbf184dd0f76c0a294ce43159e614c5412a52cc1c764757d01bb20d13bfceb0141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a91428cd2809aa9f98a80405560e62f381b7ec52332b88ac1b9c413d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 36 | "caf9e82111565df92a3fa40d1c3bfd11f08a36dba5afbb4394eebcf3c6bf36b4": {"rawtx": "0100000001040ab06a74c76750140c033c62b172671da3fdb0c153fb06bfca6722c46db2f3010000008c493046022100f19a9a8236bbc7d81cf3d5a4e3e0e814cd64865428c02a558432d3f1497e21ec022100bd7832ead1fbd4d64e97e30d05c2869408068d2ab7639c1b317b5656ee36e1880141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a914e6a1ced5071d29d94e92f27189fa2d6697adf82088aceb26413d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 37 | "802c14d491eb90d8d7b40589c124e21779f256b5bd683bbe3367b532844749d3": {"rawtx": "0100000001b436bfc6f3bcee9443bbafa5db368af011fd3b1c0da43f2af95d561121e8f9ca010000008b4830450220794b09fc687767523e787c7b1d96589d2504a1095571189633f0e2bb498732de02210081d5abb51b8ae1d0a5d72ae092e7f4cf3aabc4d99a277f961d31e1decf514daf0141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a91439d0b1ec11c2454c9ba315d11aca19cc7bcb0b3288acbbb1403d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 38 | "9ebbd8517e723b51a9a08e0026d26cd5f794eafb65b0887a78ef96309a59d889": {"rawtx": "0100000001d349478432b56733be3b68bdb556f27917e224c18905b4d7d890eb91d4142c80010000008c4930460221009caba7df5c80e64ba99a9ff055acd3ea935bd564f7ed4f6279972b86dc4f9bd9022100f0dd3d6dc957b77018193c72fcc5ee928a544450cfed41c06e02ba8f290657c40141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a914598f6bc510291647aaffda03b79f24187a0d280588ac8b3c403d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 39 | "d514a0d5e51667e1f617daafe6c62f8d68d0e7ef6c5e150b798504e0aa14c13e": {"rawtx": "010000000189d8599a3096ef787a88b065fbea94f7d56cd226008ea0a9513b727e51d8bb9e010000008a473044022011315a5e95c3ad76a84c5d044807bbdd3e02a77726fced1fe6bd83e90f1f475102200c4c0d6c36308fd9644189fedeb0d9f726ae9ca1d9e1acf4765fa3cf90ce4f480141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a914739dbc209c1c0246559d22dd79dc1e7f7189a39188ac5bc73f3d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 40 | "12b593424348a4c6b9d45692fbd5dd657daed782ff27b741e6a9cc68127f7e27": {"rawtx": "01000000013ec114aae00485790b155e6cefe7d0688d2fc6e6afda17f6e16716e5d5a014d5010000008b483045022100914d0944c0fb6976c71c18100b729c8bdca503c4053d79bddf69288cf9337488022042b537e7f2548666c733de61efa943b6525aa94241571fccc9d0cdd0126a69ac0141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a91443069240e664ea2917b08f3019ef1ce88792c29b88ac2b523f3d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 41 | "365e0b4855483a85a633e50b7c3b45a395d1add3b46dd6d9c196ae946ed1a01e": {"rawtx": "0100000001277e7f1268cca9e641b727ff82d7ae7d65ddd5fb9256d4b9c6a448434293b512010000008b483045022100cbf0a465d947d871e2c1ac4669eea9e89a074d2e012772ce3e04b968029553eb022067379d3d5dd846b22f7cd93c576ca39c7f1c6977820c6e75578b8b9136a85f720141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a9141cad45566d85590857ab228129556c42b638d5be88acfbdc3e3d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 42 | "edb1ca8bc9cd50f7df932d6e4b4635a94a0c53cd36fa13b9453651cd98d109bc": {"rawtx": "01000000011ea0d16e94ae96c1d9d66db4d3add195a3453b7c0be533a6853a4855480b5e36010000008a47304402202f92ec0c2c34ff56f027beba08a0d777a0a946d1739c2b81fb78aef3922a237c0220104eba56e1d6123f12c28b8ac68ccfc15eea8b49b35863b87cc2d55e1054406d0141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a914321a453a210ca5114f35bec1b7714ed754dff02388accb673e3d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 43 | "944a0ccb60084f82e8d791dc22a1650c1b23a6d3ec2eeec8422086a4d1237227": {"rawtx": "0100000001bc09d198cd513645b913fa36cd530c4aa935464b6e2d93dff750cdc98bcab1ed010000008a47304402203a38a64b7d4e32c43ef5c176363e91827e097f89fc5de0bb359d97ebdae5a6b002204b5bbd3bb66b658162a2681ad63899ae2f97cfe7b97ed71166edde1428760cd30141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a914d504195635b41214e4e0e00b98068207af32401188ac9bf23d3d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 44 | "96f1eb987a071e17252a084037dee4bdfe5d8f59b9a06e43ec3a1a7c88de2762": {"rawtx": "0100000001277223d1a4862042c8ee2eecd3a6231b0c65a122dc91d7e8824f0860cb0c4a94010000008a473044022062b29787f905ad2df5548cca0bcc90301b88b39e1668a22fcfc7a3fe17755e13022048d65c1122039d1764dde4fe956bf9567606f2c8dd613a185bd8862a980a04bd0141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a914447c2b869d7a9a085c41ae78ca0e797701a6cf0588ac6b7d3d3d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 45 | "e98d123f7f1e5e2907dda37f6f79e6512906c6862a3df5ccb6113fd8c80c8367": {"rawtx": "01000000016227de887c1a3aec436ea0b9598f5dfebde4de3740082a25171e077a98ebf196010000008a47304402205eb4178857d6889fc581eed9914a5deb6adc709df02b6f6d39cc2e2f317724eb022074a0bc0731c128b5468ca11f3ac06bed75bc82edc91c2ce9786ec6fcb5a55b5a0141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a914b9da8c8742d6858700000bee7b35a47560df864a88ac3b083d3d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 46 | "c3e2c47d3464d2ad4add70828b4fe411007f1ede294ce369c61ee33b6c3d86a7": {"rawtx": "010000000167830cc8d83f11b6ccf53d2a86c6062951e6796f7fa3dd07295e1e7f3f128de9010000008b483045022100886d1b4cb8d906db171527405be3dd077bc45de4ae259da76e444e738223bc6b02202a3e2903c595e74f88ca8cdbec23e2b348d29099e4716b98a8b9a30174ba16150141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a914c36de0016a21519061813c6cb0df9daf540d0ad888ac0b933c3d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 47 | "2f39f3b6776ae6530ce292809f0253e1d99a1f9781c5d2d491d1e7b6327193c0": {"rawtx": "0100000001a7863d6c3be31ec669e34c29de1e7f0011e44f8b8270dd4aadd264347dc4e2c3010000008b483045022100a5fb03a226e6911e17031115f3712f221bcc4a1a33d329ac280063e2a8442eb402202f56046a91c74090523f3b56e95c1424c005418dbe3be50a60566002aecc32230141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a914675dcd4076fdbfa3eced89f13cdffe14fc8b133688acdb1d3c3d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 48 | "171a157ec1239ae6f90d29c930e91f31a38be30263e0b288ae976711d62125bd": {"rawtx": "0100000001c0937132b6e7d191d4d2c581971f9ad9e153029f8092e20c53e66a77b6f3392f010000008a47304402201e9b3b5ccdf1a0bdf826a4f4134a465cee75fcae91eb44ef43d6fda1da90a89602200e67e42d44f33b169232d430ce3ae6647b5563b1d30ce08c23b760a36f50bafb0141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a914383ce75418355f82d3c6c15089945e0b8c5ba18988acaba83b3d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 49 | "827071ed91ee1851341af59029875ee678e80b844afa73c3b6c1e95ea5198baf": {"rawtx": "0100000001bd2521d6116797ae88b2e06302e38ba3311fe930c9290df9e69a23c17e151a17010000008c4930460221008f960e074cb4bfdf6e45d7aee6bfb7b3cfa3dab95e8756d4d24bd2d3247616d9022100e7097eedea838dad2a0fdd8ccc97a88e578158c60f19abb430ac306654a0121a0141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a914644e7c591ce0d1c36f579dc7206e529869c5b49c88ac7b333b3d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 50 | "c7770eed7961550629bed6778cd223d5243639d8a09e6aae8ac4a07ae4881f60": {"rawtx": "0100000001af8b19a55ee9c1b6c373fa4a840be878e65e872990f51a345118ee91ed717082010000008a473044022012057884b6f534971e6d93ef1a6ac46758659fdc1727e67e11cb92a827ea1c4e022021d975e23130266fa2f132fe9c54dce8fee4032093cef59cc1b212bfe6c40bf90141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a914ae20473a7587dcad520be20891130e70364b8d1d88ac4bbe3a3d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 51 | "5ea4614412419fd472aae3bbcf97bf2bdf2b8c1a77923d246362e21665e8543e": {"rawtx": "0100000001601f88e47aa0c48aae6a9ea0d8393624d523d28c77d6be2906556179ed0e77c7010000008c4930460221008c176ef3946b5abe15b1e020777b08f2f531cde5fde17f849854e2334f1b532a022100c146b3630ca555f9aa276afe21e78a6e577e2210e5dbe168c038fcf884f909b00141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a91404890a6d8084cbb8a4a6358377b3d16f785360ea88ac1b493a3d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 52 | "50e23093d9ec14294c54fdcc4e5ae343b103cf63d79b8f1f2bb70258a811d010": {"rawtx": "01000000013e54e86516e26263243d92771a8c2bdf2bbf97cfbbe3aa72d49f41124461a45e010000008a47304402206f51bc4c5391094e93da9b97a6926483df53d4b1550dbb0bfcb7fa597ae70827022057fbb90ad972a65a598daa127654c46a4544c712bda52c449f38a60f4185cafa0141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a9142a7c81122f61796916138257346b5f31dfcd867888acebd3393d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 53 | "be236cd1eee010cef5c4c1d5c7ed8c12ed372e47c562bdd2a6d6dc839364f029": {"rawtx": "010000000110d011a85802b72b1f8f9bd763cf03b143e35a4eccfd544c2914ecd99330e250010000008b483045022100b3199ee44d4697ac7e9f762af1575becb4572bb0a0344cbaaa3995c74bff816302205c54a37336136a55cd829d77500cb7dfda73328315f790eda77349044234214c0141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a914a3205126385388c8ac0916696316f59c43602e4988acbb5e393d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 54 | "7191489257f78dd0a106c76e6ceb9685310b9d4d417a868478adca0d1b4518f8": {"rawtx": "010000000129f0649383dcd6a6d2bd62c5472e37ed128cedc7d5c1c4f5ce10e0eed16c23be010000008b4830450220587ad7bdaef156b183167138472539b70acc547f187200cfc9eaa428f298d1ec022100816179ffc9b640b264f16d9fc786a45b0e5a0219232edd9f1f421f65e8597d080141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e0000000000001976a9148005575c2b4ab54ff43f3e827c763f2fc5db7da088ac8be9383d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"}, 55 | "e301376eae7a0bdc78cdb482056cdfa2f7ff8ec857c9c60872ee425024235cc3": {"rawtx": "0100000001f818451b0dcaad7884867a414d9d0b318596eb6c6ec706a1d08df75792489171010000008a47304402200f3e448208256796a53ed6ca93dbdb45e5e03e424bb381484a09c99c090fa31b02203c9bd932761c1ca0be3f5a673549a42ec871b254531ef4d86d5753b9be2739430141040cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473bf808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02a0860100000000001976a914ed642e4a6b2961de493361e9f3cff3c1ecd3ac3388acdb3b373d000000001976a91461b469ada61f37c620010912a9d5d56646015f1688ac00000000"} 56 | } -------------------------------------------------------------------------------- /test/setup-fixtures.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | var nock = require('nock'); 3 | 4 | var addresses = require('./fixtures/addresses.json'); 5 | var addressesTxs = require('./fixtures/addresses.txs.json'); 6 | var addressesUtxo = require('./fixtures/addresses.utxo.json'); 7 | var blocks = require('./fixtures/blocks.json'); 8 | var rawTransactions = require('./fixtures/transactions.rawtx.json'); 9 | var transactions = require('./fixtures/transactions.tx.json'); 10 | 11 | var root = nock('https://test-insight.bitpay.com'); 12 | 13 | function getItemByUri(uri, regex, list) { 14 | var res = regex.exec(uri); 15 | if (!res || res.length === 0) { 16 | return []; 17 | } 18 | 19 | return _.compact(decodeURIComponent(res[1]) 20 | .split(',') 21 | .map(function(id) { 22 | return list[id]; 23 | })); 24 | } 25 | 26 | function mockEndpoint(pattern, items) { 27 | root 28 | .get(function(uri) { 29 | return getItemByUri(uri, pattern, items).length > 0; 30 | }) 31 | .reply(function(uri) { 32 | var l = getItemByUri(uri, pattern, items); 33 | if (l.length === 1) { 34 | return l[0]; 35 | } 36 | return l; 37 | }); 38 | } 39 | 40 | _.forEach(blocks, function(block) { 41 | block.tx = block.tx.map(function(id) { 42 | var obj = rawTransactions[id]; 43 | return { 44 | id: id, 45 | raw: obj && obj.rawtx 46 | }; 47 | }); 48 | }); 49 | 50 | module.exports = { 51 | up: function() { 52 | mockEndpoint(/^\/api\/addrs\/([\w%]*)$/, addresses); 53 | mockEndpoint(/^\/api\/addrs\/([\w%]*)\/txs$/, addressesTxs); 54 | mockEndpoint(/^\/api\/addrs\/([\w%]*)\/utxo$/, addressesUtxo); 55 | mockEndpoint(/^\/api\/block\/([\w%]*)$/, blocks); 56 | 57 | root 58 | .get('/api/blocks') 59 | .reply(200, {blocks: _.values(blocks)}) 60 | .persist(); 61 | 62 | mockEndpoint(/^\/api\/rawtxs\/([\w%]*)$/, rawTransactions); 63 | mockEndpoint(/^\/api\/txs\/([\w%]*)$/, transactions); 64 | 65 | root 66 | .post('/api/tx/send', { 67 | rawtx: 68 | '01000000016e90f86ccebd3caf5a339633bfdb28c1ae6961a752ad21e8e212b1e97a8965b40' + 69 | '10000006b483045022100d1eb848df7594a5f9b697dea0bf733c8ec87dec2b63142e4b572b0' + 70 | '7f2f09d12702200f6b124db6689e645f39e57d6cffcfb5f5869c089c4f1922ef6e6cfe3f07e' + 71 | '8e20121037ce0c786277fafc38e2e2d49b1be36f02a360ba4a2dd58cf977784975a573fb6ff' + 72 | 'ffffff02c0175302000000001976a91461120f6e004c7a2e20ecdedf461f1eb032c2e5c388a' + 73 | 'c48698831d00000001976a9140fe1355e31a061b2508919578b6f8c60dd2f29cf88ac00000000' 74 | }) 75 | .reply(200, { 76 | txid: 'qwerty' 77 | }) 78 | .persist(); 79 | 80 | root 81 | .post('/api/tx/send', { 82 | rawtx: 83 | '01000000011c1020c1114820e7c44e12e804aec5f4af1e8a6aad3c446c4cfc8aa53e61f73d010' + 84 | '000008a47304402200fea124cecd36e92cb0b549b62740a26f374629b26f16292a3e858753035' + 85 | '172802205ba172966addddbbe8181af6cd7fb6e9c53414fb6727c4f15589c74567e48ab301410' + 86 | '40cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473b' + 87 | 'f808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e00000000000' + 88 | '01976a91461120f6e004c7a2e20ecdedf461f1eb032c2e5c388acabfb423d000000001976a914' + 89 | '61b469ada61f37c620010912a9d5d56646015f1688ac00000000' 90 | }) 91 | .reply(200, { 92 | txid: 'asdfgh' 93 | }) 94 | .persist(); 95 | }, 96 | 97 | down: function() { 98 | nock.cleanAll(); 99 | } 100 | }; 101 | -------------------------------------------------------------------------------- /test/transactions.test.js: -------------------------------------------------------------------------------- 1 | /*eslint no-unused-expressions: 0*/ 2 | 3 | var Blockchain = require('../'); 4 | var chai = require('chai'); 5 | var setupFixtures = require('./setup-fixtures'); 6 | 7 | var expect = chai.expect; 8 | 9 | 10 | describe('Transactions', function() { 11 | var transactions; 12 | 13 | before(function() { 14 | var api = new Blockchain('testnet'); 15 | transactions = api.transactions; 16 | }); 17 | 18 | before(setupFixtures.up); 19 | 20 | describe('get', function() { 21 | it('should empty value if id is not passed', function(done) { 22 | transactions 23 | .get() 24 | .then(function(res) { 25 | expect(res).to.not.exist; 26 | done(); 27 | }) 28 | .catch(done); 29 | }); 30 | 31 | it('should fail on incorrect transaction id', function(done) { 32 | transactions 33 | .get('XXXX') 34 | .then(function() { 35 | done('does not fail'); 36 | }) 37 | .catch(function(err) { 38 | expect(err).to.exist; 39 | expect(err.message).to.exist; 40 | done(); 41 | }).catch(done); 42 | }); 43 | 44 | it('should return transaction', function(done) { 45 | transactions 46 | .get('4979a0b69703f888dc5936a4be039dabb976fae7d45604d57b5fad35b3c94200') 47 | .then(function(res) { 48 | expect(res).to.exist; 49 | expect(res).to.has.property('txId', '4979a0b69703f888dc5936a4be039dabb976fae7d45604d57b5fad35b3c94200'); 50 | expect(res).to.has.property('confirmations', 230572); 51 | done(); 52 | }) 53 | .catch(done); 54 | }); 55 | 56 | it('should be able to request group of transactions', function(done) { 57 | transactions 58 | .get([ 59 | '4979a0b69703f888dc5936a4be039dabb976fae7d45604d57b5fad35b3c94200', 60 | 'ffd316b0c4feb9d29c61c3734fcde0167600441e560931c8c7267a9de3d9e29a' 61 | ]) 62 | .then(function(res) { 63 | expect(res).to.be.instanceof(Array); 64 | expect(res).has.length(2); 65 | 66 | expect(res[0]).to.has.property('txId', '4979a0b69703f888dc5936a4be039dabb976fae7d45604d57b5fad35b3c94200'); 67 | expect(res[0]).to.has.property('confirmations', 230572); 68 | expect(res[1]).to.has.property('txId', 'ffd316b0c4feb9d29c61c3734fcde0167600441e560931c8c7267a9de3d9e29a'); 69 | expect(res[1]).to.has.property('confirmations', 352331); 70 | 71 | done(); 72 | }) 73 | .catch(done); 74 | }); 75 | }); 76 | 77 | describe.skip('latest', function() { 78 | it('should return last transaction', function(done) { 79 | transactions 80 | .latest() 81 | .then(function() { 82 | done(); 83 | }) 84 | .catch(done); 85 | }); 86 | }); 87 | 88 | describe('propagate', function() { 89 | it('should add new transaction', function(done) { 90 | transactions 91 | .propagate('01000000016e90f86ccebd3caf5a339633bfdb28c1ae6961a752ad21e8e212b1e97a8965b40' + 92 | '10000006b483045022100d1eb848df7594a5f9b697dea0bf733c8ec87dec2b63142e4b572b0' + 93 | '7f2f09d12702200f6b124db6689e645f39e57d6cffcfb5f5869c089c4f1922ef6e6cfe3f07e' + 94 | '8e20121037ce0c786277fafc38e2e2d49b1be36f02a360ba4a2dd58cf977784975a573fb6ff' + 95 | 'ffffff02c0175302000000001976a91461120f6e004c7a2e20ecdedf461f1eb032c2e5c388a' + 96 | 'c48698831d00000001976a9140fe1355e31a061b2508919578b6f8c60dd2f29cf88ac00000000') 97 | .then(function(res) { 98 | expect(res).to.exist; 99 | expect(res).to.has.property('txid', 'qwerty'); 100 | done(); 101 | }) 102 | .catch(done); 103 | }); 104 | 105 | it('should add few transactions at once', function(done) { 106 | transactions 107 | .propagate([ 108 | '01000000016e90f86ccebd3caf5a339633bfdb28c1ae6961a752ad21e8e212b1e97a8965b40' + 109 | '10000006b483045022100d1eb848df7594a5f9b697dea0bf733c8ec87dec2b63142e4b572b0' + 110 | '7f2f09d12702200f6b124db6689e645f39e57d6cffcfb5f5869c089c4f1922ef6e6cfe3f07e' + 111 | '8e20121037ce0c786277fafc38e2e2d49b1be36f02a360ba4a2dd58cf977784975a573fb6ff' + 112 | 'ffffff02c0175302000000001976a91461120f6e004c7a2e20ecdedf461f1eb032c2e5c388a' + 113 | 'c48698831d00000001976a9140fe1355e31a061b2508919578b6f8c60dd2f29cf88ac00000000', 114 | 115 | '01000000011c1020c1114820e7c44e12e804aec5f4af1e8a6aad3c446c4cfc8aa53e61f73d010' + 116 | '000008a47304402200fea124cecd36e92cb0b549b62740a26f374629b26f16292a3e858753035' + 117 | '172802205ba172966addddbbe8181af6cd7fb6e9c53414fb6727c4f15589c74567e48ab301410' + 118 | '40cfa3dfb357bdff37c8748c7771e173453da5d7caa32972ab2f5c888fff5bbaeb5fc812b473b' + 119 | 'f808206930fade81ef4e373e60039886b51022ce68902d96ef70ffffffff02204e00000000000' + 120 | '01976a91461120f6e004c7a2e20ecdedf461f1eb032c2e5c388acabfb423d000000001976a914' + 121 | '61b469ada61f37c620010912a9d5d56646015f1688ac00000000' 122 | ]) 123 | .then(function(res) { 124 | expect(res).to.be.instanceof(Array); 125 | expect(res).has.length(2); 126 | expect(res[0]).to.has.property('txid', 'qwerty'); 127 | expect(res[1]).to.has.property('txid', 'asdfgh'); 128 | done(); 129 | }) 130 | .catch(done); 131 | }); 132 | }); 133 | 134 | after(setupFixtures.down); 135 | }); 136 | -------------------------------------------------------------------------------- /test/utils.test.js: -------------------------------------------------------------------------------- 1 | /*eslint no-unused-expressions: 0*/ 2 | 3 | var batchGetRequest = require('../lib/utils').batchGetRequest; 4 | var batchPostRequest = require('../lib/utils').batchPostRequest; 5 | var chai = require('chai'); 6 | var expect = chai.expect; 7 | var getRequest = require('../lib/utils').getRequest; 8 | var nock = require('nock'); 9 | 10 | describe('utils', function() { 11 | this.timeout(100); 12 | 13 | describe('batch request', function() { 14 | it('should return empty array if there no any items are passed', function(done) { 15 | batchGetRequest('http://some.org/url') 16 | .then(function(res) { 17 | expect(res).to.be.empty; 18 | done(); 19 | }) 20 | .catch(done); 21 | }); 22 | 23 | it('should retry on ECONNRESET', function(done) { 24 | var i = 4; 25 | while (--i >= 0) { 26 | nock('http://google.com') 27 | .get('/cat-poems/1') 28 | .replyWithError({code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read'}); 29 | } 30 | 31 | nock('http://google.com') 32 | .get('/cat-poems/1') 33 | .reply(200, 'Hello World!'); 34 | 35 | batchGetRequest('http://google.com/cat-poems/', 1, {retry: 5, delayBeforeRetry: 0}) 36 | .then(function(res) { 37 | expect(res[0]).to.equal('Hello World!'); 38 | done(); 39 | }) 40 | .catch(done); 41 | }); 42 | 43 | it('should fail after number of retries is over', function(done) { 44 | var i = 5; 45 | while (--i >= 0) { 46 | nock('http://google.com') 47 | .get('/missed-cat-poems/1') 48 | .replyWithError({code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read'}); 49 | } 50 | 51 | nock('http://google.com') 52 | .get('/missed-cat-poems/1') 53 | .reply(200, 'Hello World!'); 54 | 55 | batchGetRequest('http://google.com/missed-cat-poems/', '1', {retry: 5, delayBeforeRetry: 0}) 56 | .then(function(res) { 57 | done('got result', res); 58 | }) 59 | .catch(function(err) { 60 | expect(err.code).to.equal('ECONNRESET'); 61 | done(); 62 | }); 63 | }); 64 | 65 | it('should do single request GET http://some.org/url/:id and return Promise on successful response', function(done) { 66 | nock('http://some.org') 67 | .get('/url/123456') 68 | .reply(200, 'Hello World!'); 69 | 70 | batchGetRequest('http://some.org/url/', 123456) 71 | .then(function(res) { 72 | expect(res[0]).to.equal('Hello World!'); 73 | done(); 74 | }) 75 | .catch(done); 76 | }); 77 | 78 | it('should do multi request GET http://some.org/url/:id and return Promise on successful response', function(done) { 79 | nock('http://some.org') 80 | .get('/url/1') 81 | .reply(200, 'Hello World 1!'); 82 | 83 | nock('http://some.org') 84 | .get('/url/2') 85 | .reply(200, 'Hello World 2!'); 86 | 87 | batchGetRequest('http://some.org/url/', [1, 2], { 88 | maxChunk: 1 89 | }) 90 | .then(function(res) { 91 | expect(res[0]).to.equal('Hello World 1!'); 92 | expect(res[1]).to.equal('Hello World 2!'); 93 | done(); 94 | }) 95 | .catch(done); 96 | }); 97 | 98 | it('should do single request GET http://some.org/url/:id1,id2 and return Promise on successful response', function(done) { 99 | nock('http://some.org') 100 | .get('/url/' + encodeURIComponent('1,2')) 101 | .reply(200, [ 102 | 'Hello World 1!', 103 | 'Hello World 2!' 104 | ]); 105 | 106 | batchGetRequest('http://some.org/url/', [1, 2], { 107 | maxChunk: 10 108 | }) 109 | .then(function(res) { 110 | expect(res[0]).to.equal('Hello World 1!'); 111 | expect(res[1]).to.equal('Hello World 2!'); 112 | done(); 113 | }) 114 | .catch(done); 115 | }); 116 | 117 | it('should do multi request GET http://some.org/url/:id and http://another.org/url/:id and return Promise on successful response', function(done) { 118 | nock('http://one.org') 119 | .get('/url/1') 120 | .reply(200, 'Hello One World!'); 121 | 122 | nock('http://another.org') 123 | .get('/url/1') 124 | .reply(200, 'Hello Another World!'); 125 | 126 | batchGetRequest(['http://one.org/url/', 'http://another.org/url/'], 1) 127 | .then(function(res) { 128 | expect(res[0][0]).to.equal('Hello One World!'); 129 | expect(res[0][1]).to.equal('Hello Another World!'); 130 | done(); 131 | }) 132 | .catch(done); 133 | }); 134 | 135 | it('should reject Promise on 404', function(done) { 136 | nock('http://some.org') 137 | .get('/url/123456') 138 | .reply(404, 'Not found'); 139 | 140 | batchGetRequest('http://some.org/url/', '123456') 141 | .then(function() { 142 | done('should reject Promise'); 143 | }) 144 | .catch(function(err) { 145 | expect(err.message).to.equal('Request failed with status code 404'); 146 | done(); 147 | }); 148 | }); 149 | 150 | it('should do parametric request', function(done) { 151 | nock('http://google.com') 152 | .get('/123456/url') 153 | .reply(200, 'Hello World!'); 154 | 155 | batchGetRequest('http://google.com/:id/url', {id: 123456}) 156 | .then(function(res) { 157 | expect(res[0]).to.equal('Hello World!'); 158 | done(); 159 | }) 160 | .catch(done); 161 | }); 162 | 163 | it('should do parametric request with multiple ids', function(done) { 164 | nock('http://google.com') 165 | .get('/' + encodeURIComponent('0,1,2') + '/url') 166 | .reply(200, [ 167 | 'Hello World 0!', 168 | 'Hello World 1!', 169 | 'Hello World 2!' 170 | ]); 171 | 172 | batchGetRequest('http://google.com/:id/url', [{id: '0'}, {id: '1'}, {id: '2'}], { 173 | maxChunk: 10 174 | }) 175 | .then(function(res) { 176 | expect(res[0]).to.equal('Hello World 0!'); 177 | expect(res[1]).to.equal('Hello World 1!'); 178 | expect(res[2]).to.equal('Hello World 2!'); 179 | done(); 180 | }) 181 | .catch(done); 182 | }); 183 | }); 184 | 185 | describe('get request', function() { 186 | it('should request GET http://google.com/cat-poems/make-request and return Promise on successful response', function(done) { 187 | nock('http://google.com') 188 | .get('/cat-poems/make-request') 189 | .reply(200, 'The sun slants in, its light a wedge'); 190 | 191 | getRequest('http://google.com/cat-poems/make-request') 192 | .then(function(res) { 193 | expect(res).to.equal('The sun slants in, its light a wedge'); 194 | done(); 195 | }) 196 | .catch(done); 197 | }); 198 | 199 | it('should retry on ECONNRESET', function(done) { 200 | var i = 4; 201 | while (--i >= 0) { 202 | nock('http://google.com') 203 | .get('/cat-poems/make-request-retry') 204 | .replyWithError({code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read'}); 205 | } 206 | 207 | nock('http://google.com') 208 | .get('/cat-poems/make-request-retry') 209 | .reply(200, 'Hello World!'); 210 | 211 | getRequest('http://google.com/cat-poems/make-request-retry', {retry: 5, delayBeforeRetry: 0}) 212 | .then(function(res) { 213 | expect(res).to.equal('Hello World!'); 214 | done(); 215 | }) 216 | .catch(done); 217 | }); 218 | 219 | it('should fail after number of retries is over', function(done) { 220 | var i = 5; 221 | while (--i >= 0) { 222 | nock('http://google.com') 223 | .get('/cat-poems/make-request-retry-fail') 224 | .replyWithError({code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read'}); 225 | } 226 | 227 | nock('http://google.com') 228 | .get('/cat-poems/make-request-retry-fail') 229 | .reply(200, 'Hello World!'); 230 | 231 | getRequest('http://google.com/cat-poems/make-request-retry-fail', {retry: 5, delayBeforeRetry: 0}) 232 | .then(function(res) { 233 | done('got result', res); 234 | }) 235 | .catch(function(err) { 236 | expect(err.code).to.equal('ECONNRESET'); 237 | done(); 238 | }); 239 | }); 240 | }); 241 | 242 | describe('batch post request', function() { 243 | it('should send single POST', function(done) { 244 | nock('http://google.com') 245 | .post('/cat-poems', 'Hello World') 246 | .reply(201); 247 | 248 | batchPostRequest('http://google.com/cat-poems', 'Hello World') 249 | .then(function() { 250 | done(); 251 | }) 252 | .catch(done); 253 | }); 254 | 255 | it('should send multiple POST', function(done) { 256 | nock('http://google.com') 257 | .post('/cat-poems', 'The Owl and the Pussy-cat went to sea') 258 | .reply(201); 259 | 260 | nock('http://google.com') 261 | .post('/cat-poems', 'In a beautiful pea green boat,') 262 | .reply(201); 263 | 264 | batchPostRequest('http://google.com/cat-poems', [ 265 | 'The Owl and the Pussy-cat went to sea', 266 | 'In a beautiful pea green boat,' 267 | ]) 268 | .then(function() { 269 | done(); 270 | }) 271 | .catch(done); 272 | }); 273 | }); 274 | }); 275 | -------------------------------------------------------------------------------- /worker-configuration.d.ts: -------------------------------------------------------------------------------- 1 | // Generated by Wrangler by running `wrangler types` 2 | 3 | interface Env { 4 | SHARED_SECRET: string; 5 | WORKOS_API_KEY: string; 6 | WORKOS_CLIENT_ID: string; 7 | } 8 | 9 | --------------------------------------------------------------------------------