2015-06-11 14:24:58 -07:00
'use strict' ;
var _ = require ( 'lodash' ) ;
var $ = require ( 'preconditions' ) . singleton ( ) ;
var log = require ( 'npmlog' ) ;
log . debug = log . verbose ;
var io = require ( 'socket.io-client' ) ;
2016-02-16 19:15:43 -08:00
var requestList = require ( './request-list' ) ;
2015-06-11 14:24:58 -07:00
function Insight ( opts ) {
$ . checkArgument ( opts ) ;
$ . checkArgument ( _ . contains ( [ 'livenet' , 'testnet' ] , opts . network ) ) ;
$ . checkArgument ( opts . url ) ;
2015-09-03 13:40:23 -07:00
this . apiPrefix = opts . apiPrefix || '/api' ;
2015-06-11 14:24:58 -07:00
this . network = opts . network || 'livenet' ;
2016-02-16 12:09:53 -08:00
this . hosts = opts . url ;
2015-06-11 14:24:58 -07:00
} ;
2015-09-07 20:57:59 -07:00
var _parseErr = function ( err , res ) {
if ( err ) {
2015-09-10 11:47:08 -07:00
log . warn ( 'Insight error: ' , err ) ;
2015-09-07 20:57:59 -07:00
return "Insight Error" ;
}
2015-10-26 14:05:53 -07:00
log . warn ( "Insight " + res . request . href + " Returned Status: " + res . statusCode ) ;
2015-09-07 20:57:59 -07:00
return "Error querying the blockchain" ;
} ;
2015-06-11 14:24:58 -07:00
Insight . prototype . getConnectionInfo = function ( ) {
2016-02-16 12:09:53 -08:00
return 'Insight (' + this . network + ') @ ' + this . hosts ;
2015-06-11 14:24:58 -07:00
} ;
/ * *
* Retrieve a list of unspent outputs associated with an address or set of addresses
* /
Insight . prototype . getUnspentUtxos = function ( addresses , cb ) {
var args = {
method : 'POST' ,
2016-02-16 12:09:53 -08:00
hosts : this . hosts ,
path : this . apiPrefix + '/addrs/utxo' ,
2015-06-11 14:24:58 -07:00
json : {
addrs : [ ] . concat ( addresses ) . join ( ',' )
} ,
} ;
2016-02-16 19:15:43 -08:00
requestList ( args , function ( err , res , unspent ) {
2015-10-26 14:05:53 -07:00
if ( err || res . statusCode !== 200 ) return cb ( _parseErr ( err , res ) ) ;
2015-06-11 14:24:58 -07:00
return cb ( null , unspent ) ;
} ) ;
} ;
/ * *
* Broadcast a transaction to the bitcoin network
* /
Insight . prototype . broadcast = function ( rawTx , cb ) {
var args = {
method : 'POST' ,
2016-02-16 12:09:53 -08:00
hosts : this . hosts ,
path : this . apiPrefix + '/tx/send' ,
2015-06-11 14:24:58 -07:00
json : {
rawtx : rawTx
} ,
} ;
2016-02-16 19:15:43 -08:00
requestList ( args , function ( err , res , body ) {
2015-10-26 14:05:53 -07:00
if ( err || res . statusCode !== 200 ) return cb ( _parseErr ( err , res ) ) ;
2015-06-11 14:24:58 -07:00
return cb ( null , body ? body . txid : null ) ;
} ) ;
} ;
Insight . prototype . getTransaction = function ( txid , cb ) {
var args = {
method : 'GET' ,
2016-02-16 12:09:53 -08:00
hosts : this . hosts ,
path : this . apiPrefix + '/tx/' + txid ,
2015-10-26 15:30:57 -07:00
json : true ,
2015-06-11 14:24:58 -07:00
} ;
2016-02-16 19:15:43 -08:00
requestList ( args , function ( err , res , tx ) {
2015-10-26 14:05:53 -07:00
if ( res && res . statusCode == 404 ) return cb ( ) ;
if ( err || res . statusCode !== 200 )
return cb ( _parseErr ( err , res ) ) ;
2015-09-07 20:57:59 -07:00
2015-06-11 14:24:58 -07:00
return cb ( null , tx ) ;
} ) ;
} ;
Insight . prototype . getTransactions = function ( addresses , from , to , cb ) {
var qs = [ ] ;
if ( _ . isNumber ( from ) ) qs . push ( 'from=' + from ) ;
if ( _ . isNumber ( to ) ) qs . push ( 'to=' + to ) ;
var args = {
method : 'POST' ,
2016-02-16 12:09:53 -08:00
hosts : this . hosts ,
path : this . apiPrefix + '/addrs/txs' + ( qs . length > 0 ? '?' + qs . join ( '&' ) : '' ) ,
2015-06-11 14:24:58 -07:00
json : {
addrs : [ ] . concat ( addresses ) . join ( ',' )
} ,
} ;
2016-02-16 19:15:43 -08:00
requestList ( args , function ( err , res , txs ) {
2015-10-26 14:05:53 -07:00
if ( err || res . statusCode !== 200 ) return cb ( _parseErr ( err , res ) ) ;
2015-07-13 12:37:21 -07:00
if ( _ . isObject ( txs ) && txs . items )
txs = txs . items ;
2015-06-11 14:24:58 -07:00
// NOTE: Whenever Insight breaks communication with bitcoind, it returns invalid data but no error code.
if ( ! _ . isArray ( txs ) || ( txs . length != _ . compact ( txs ) . length ) ) return cb ( new Error ( 'Could not retrieve transactions from blockchain. Request was:' + JSON . stringify ( args ) ) ) ;
return cb ( null , txs ) ;
} ) ;
} ;
2015-10-28 09:25:32 -07:00
Insight . prototype . getAddressActivity = function ( address , cb ) {
2015-10-27 12:51:15 -07:00
var self = this ;
2015-10-28 09:25:32 -07:00
var args = {
method : 'GET' ,
2016-02-16 12:09:53 -08:00
hosts : this . hosts ,
path : self . apiPrefix + '/addr/' + address ,
2015-10-28 09:25:32 -07:00
json : true ,
2015-10-26 14:05:53 -07:00
} ;
2016-02-16 19:15:43 -08:00
requestList ( args , function ( err , res , result ) {
2015-10-28 09:25:32 -07:00
if ( res && res . statusCode == 404 ) return cb ( ) ;
if ( err || res . statusCode !== 200 )
return cb ( _parseErr ( err , res ) ) ;
2015-10-27 12:51:15 -07:00
2015-10-28 09:25:32 -07:00
var nbTxs = result . unconfirmedTxApperances + result . txApperances ;
return cb ( null , nbTxs > 0 ) ;
2015-06-11 14:24:58 -07:00
} ) ;
} ;
2015-07-15 18:42:05 -07:00
Insight . prototype . estimateFee = function ( nbBlocks , cb ) {
2016-02-16 12:09:53 -08:00
var path = this . apiPrefix + '/utils/estimatefee' ;
2015-07-15 18:42:05 -07:00
if ( nbBlocks ) {
2016-02-16 12:09:53 -08:00
path += '?nbBlocks=' + [ ] . concat ( nbBlocks ) . join ( ',' ) ;
2015-07-15 18:42:05 -07:00
}
var args = {
method : 'GET' ,
2016-02-16 12:09:53 -08:00
hosts : this . hosts ,
path : path ,
2015-07-17 06:32:48 -07:00
json : true ,
2015-07-15 18:42:05 -07:00
} ;
2016-02-16 19:15:43 -08:00
requestList ( args , function ( err , res , body ) {
2015-10-26 14:05:53 -07:00
if ( err || res . statusCode !== 200 ) return cb ( _parseErr ( err , res ) ) ;
2015-07-17 06:32:48 -07:00
return cb ( null , body ) ;
2015-07-15 18:42:05 -07:00
} ) ;
} ;
2015-06-11 14:24:58 -07:00
Insight . prototype . initSocket = function ( ) {
2016-02-16 12:09:53 -08:00
// sockets always use the first server on the pull
var socket = io . connect ( this . hosts [ 0 ] , {
2015-06-11 14:24:58 -07:00
'reconnection' : true ,
} ) ;
return socket ;
} ;
module . exports = Insight ;