2015-08-04 10:49:38 -07:00
|
|
|
'use strict';
|
|
|
|
|
2014-08-12 12:03:04 -07:00
|
|
|
var EventEmitter = require('events').EventEmitter;
|
2015-07-31 08:40:15 -07:00
|
|
|
var bitcoind = require('bindings')('bitcoind.node');
|
2015-08-04 10:49:38 -07:00
|
|
|
var chainlib = require('chainlib');
|
|
|
|
var log = chainlib.log;
|
2014-09-02 19:28:20 -07:00
|
|
|
var util = require('util');
|
2015-07-22 14:33:28 -07:00
|
|
|
var bitcore = require('bitcore');
|
|
|
|
var $ = bitcore.util.preconditions;
|
2014-08-12 12:03:04 -07:00
|
|
|
|
2015-07-16 14:03:43 -07:00
|
|
|
function Daemon(options) {
|
2014-08-12 12:03:04 -07:00
|
|
|
var self = this;
|
|
|
|
|
2015-07-16 14:03:43 -07:00
|
|
|
if (!(this instanceof Daemon)) {
|
|
|
|
return new Daemon(options);
|
2014-08-12 12:03:04 -07:00
|
|
|
}
|
|
|
|
|
2014-10-17 12:54:58 -07:00
|
|
|
if (Object.keys(this.instances).length) {
|
2015-07-22 14:33:28 -07:00
|
|
|
throw new Error('Daemon cannot be instantiated more than once.');
|
2014-10-17 12:54:58 -07:00
|
|
|
}
|
|
|
|
|
2014-08-12 12:03:04 -07:00
|
|
|
EventEmitter.call(this);
|
|
|
|
|
2015-07-22 14:33:28 -07:00
|
|
|
$.checkArgument(options.datadir, 'Please specify a datadir');
|
2014-10-16 14:56:41 -07:00
|
|
|
|
2015-07-22 14:33:28 -07:00
|
|
|
this.options = options || {};
|
2014-10-16 13:53:47 -07:00
|
|
|
this.options.datadir = this.options.datadir.replace(/^~/, process.env.HOME);
|
2014-11-11 13:36:08 -08:00
|
|
|
this.datadir = this.options.datadir;
|
2015-07-22 14:33:28 -07:00
|
|
|
|
2015-08-24 13:33:44 -07:00
|
|
|
this.node = options.node;
|
|
|
|
|
2014-11-11 13:36:08 -08:00
|
|
|
this.config = this.datadir + '/bitcoin.conf';
|
2015-07-22 14:33:28 -07:00
|
|
|
|
2014-10-03 18:27:06 -07:00
|
|
|
Object.keys(exports).forEach(function(key) {
|
|
|
|
self[key] = exports[key];
|
|
|
|
});
|
|
|
|
|
2014-09-11 17:18:36 -07:00
|
|
|
}
|
|
|
|
|
2015-08-04 10:49:38 -07:00
|
|
|
util.inherits(Daemon, EventEmitter);
|
2015-07-20 14:55:49 -07:00
|
|
|
|
2015-07-16 14:03:43 -07:00
|
|
|
Daemon.instances = {};
|
|
|
|
Daemon.prototype.instances = Daemon.instances;
|
2014-10-16 14:56:41 -07:00
|
|
|
|
2015-07-16 14:03:43 -07:00
|
|
|
Daemon.__defineGetter__('global', function() {
|
|
|
|
return Daemon.instances[Object.keys(Daemon.instances)[0]];
|
2014-10-16 14:56:41 -07:00
|
|
|
});
|
|
|
|
|
2015-07-16 14:03:43 -07:00
|
|
|
Daemon.prototype.__defineGetter__('global', function() {
|
|
|
|
return Daemon.global;
|
2014-11-17 14:19:46 -08:00
|
|
|
});
|
|
|
|
|
2015-08-20 14:50:14 -07:00
|
|
|
Daemon.prototype.start = function(callback) {
|
2014-09-11 17:18:36 -07:00
|
|
|
var self = this;
|
2014-08-29 13:54:54 -07:00
|
|
|
|
2014-11-11 13:36:08 -08:00
|
|
|
if (this.instances[this.datadir]) {
|
2015-08-21 08:53:20 -07:00
|
|
|
return callback(new Error('Daemon already started'));
|
2014-10-16 14:56:41 -07:00
|
|
|
}
|
2014-11-11 13:36:08 -08:00
|
|
|
this.instances[this.datadir] = true;
|
2014-09-25 14:28:08 -07:00
|
|
|
|
2015-08-21 08:53:20 -07:00
|
|
|
bitcoind.start(this.options, function(err) {
|
|
|
|
if(err) {
|
|
|
|
return callback(err);
|
2014-10-16 13:53:47 -07:00
|
|
|
}
|
|
|
|
|
2014-09-30 15:14:53 -07:00
|
|
|
self._started = true;
|
|
|
|
|
2015-07-31 08:40:15 -07:00
|
|
|
bitcoind.onBlocksReady(function(err, result) {
|
2015-07-07 14:02:03 -07:00
|
|
|
|
2015-07-24 09:32:28 -07:00
|
|
|
function onTipUpdateListener(result) {
|
|
|
|
if (result) {
|
|
|
|
// Emit and event that the tip was updated
|
2015-08-24 13:33:44 -07:00
|
|
|
self.height = result;
|
2015-07-24 09:32:28 -07:00
|
|
|
self.emit('tip', result);
|
|
|
|
// Recursively wait until the next update
|
2015-07-31 08:40:15 -07:00
|
|
|
bitcoind.onTipUpdate(onTipUpdateListener);
|
2015-07-24 09:32:28 -07:00
|
|
|
}
|
2015-07-23 06:32:46 -07:00
|
|
|
}
|
|
|
|
|
2015-07-31 08:40:15 -07:00
|
|
|
bitcoind.onTipUpdate(onTipUpdateListener);
|
2015-07-23 06:32:46 -07:00
|
|
|
|
2015-07-31 08:40:15 -07:00
|
|
|
bitcoind.startTxMon(function(txs) {
|
2015-07-30 17:22:06 -07:00
|
|
|
for(var i = 0; i < txs.length; i++) {
|
|
|
|
self.emit('tx', txs[i]);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2015-08-24 13:33:44 -07:00
|
|
|
// Set the current chain height
|
|
|
|
var info = self.getInfo();
|
|
|
|
self.height = info.blocks;
|
|
|
|
|
|
|
|
// Get the genesis block
|
|
|
|
self.getBlock(0, function(err, block) {
|
|
|
|
self.genesisBuffer = block;
|
2015-08-21 08:53:20 -07:00
|
|
|
self.emit('ready', result);
|
2015-08-24 13:33:44 -07:00
|
|
|
setImmediate(callback);
|
2015-08-21 08:53:20 -07:00
|
|
|
});
|
2015-08-24 13:33:44 -07:00
|
|
|
|
2015-08-21 08:53:20 -07:00
|
|
|
});
|
2014-08-12 12:03:04 -07:00
|
|
|
});
|
2014-09-23 13:57:49 -07:00
|
|
|
};
|
|
|
|
|
2015-08-11 14:16:04 -07:00
|
|
|
Daemon.prototype.isSynced = function() {
|
|
|
|
return bitcoind.isSynced();
|
|
|
|
};
|
|
|
|
|
|
|
|
Daemon.prototype.syncPercentage = function() {
|
|
|
|
return bitcoind.syncPercentage();
|
|
|
|
};
|
|
|
|
|
2015-07-16 14:03:43 -07:00
|
|
|
Daemon.prototype.getBlock = function(blockhash, callback) {
|
2015-08-04 10:49:38 -07:00
|
|
|
return bitcoind.getBlock(blockhash, callback);
|
2014-11-04 16:08:31 -08:00
|
|
|
};
|
|
|
|
|
2015-07-16 14:03:43 -07:00
|
|
|
Daemon.prototype.isSpent = function(txid, outputIndex) {
|
2015-07-31 08:40:15 -07:00
|
|
|
return bitcoind.isSpent(txid, outputIndex);
|
2015-07-15 14:45:36 -07:00
|
|
|
};
|
|
|
|
|
2015-07-22 12:34:15 -07:00
|
|
|
Daemon.prototype.getBlockIndex = function(blockHash) {
|
2015-07-31 08:40:15 -07:00
|
|
|
return bitcoind.getBlockIndex(blockHash);
|
2015-07-17 10:29:14 -07:00
|
|
|
};
|
|
|
|
|
2015-07-28 13:03:55 -07:00
|
|
|
Daemon.prototype.estimateFee = function(blocks) {
|
2015-07-31 08:40:15 -07:00
|
|
|
return bitcoind.estimateFee(blocks);
|
2015-07-28 13:03:55 -07:00
|
|
|
};
|
|
|
|
|
2015-07-22 10:59:28 -07:00
|
|
|
Daemon.prototype.sendTransaction = function(transaction, allowAbsurdFees) {
|
2015-07-31 08:40:15 -07:00
|
|
|
return bitcoind.sendTransaction(transaction, allowAbsurdFees);
|
2015-07-22 10:59:28 -07:00
|
|
|
};
|
|
|
|
|
2015-07-16 14:03:43 -07:00
|
|
|
Daemon.prototype.getTransaction = function(txid, queryMempool, callback) {
|
2015-07-31 08:40:15 -07:00
|
|
|
return bitcoind.getTransaction(txid, queryMempool, callback);
|
2014-09-22 12:05:17 -07:00
|
|
|
};
|
|
|
|
|
2015-07-29 14:13:51 -07:00
|
|
|
Daemon.prototype.getTransactionWithBlockInfo = function(txid, queryMempool, callback) {
|
2015-07-31 08:40:15 -07:00
|
|
|
return bitcoind.getTransactionWithBlockInfo(txid, queryMempool, callback);
|
2015-07-29 14:13:51 -07:00
|
|
|
};
|
|
|
|
|
2015-07-16 14:03:43 -07:00
|
|
|
Daemon.prototype.getMempoolOutputs = function(address) {
|
2015-07-31 08:40:15 -07:00
|
|
|
return bitcoind.getMempoolOutputs(address);
|
2015-07-17 12:55:36 -07:00
|
|
|
};
|
|
|
|
|
2015-07-16 14:03:43 -07:00
|
|
|
Daemon.prototype.addMempoolUncheckedTransaction = function(txBuffer) {
|
2015-07-31 08:40:15 -07:00
|
|
|
return bitcoind.addMempoolUncheckedTransaction(txBuffer);
|
2015-07-17 18:24:59 -07:00
|
|
|
};
|
|
|
|
|
2015-07-16 14:03:43 -07:00
|
|
|
Daemon.prototype.getInfo = function() {
|
2015-07-31 08:40:15 -07:00
|
|
|
return bitcoind.getInfo();
|
2014-10-17 13:26:27 -07:00
|
|
|
};
|
|
|
|
|
2015-08-04 10:49:38 -07:00
|
|
|
Daemon.prototype.stop = function(callback) {
|
2014-09-11 17:18:36 -07:00
|
|
|
var self = this;
|
2015-07-31 08:40:15 -07:00
|
|
|
return bitcoind.stop(function(err, status) {
|
2015-08-21 08:53:20 -07:00
|
|
|
setImmediate(function() {
|
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
} else {
|
|
|
|
log.info(status);
|
|
|
|
return callback();
|
|
|
|
}
|
|
|
|
});
|
2014-09-11 17:18:36 -07:00
|
|
|
});
|
2014-09-10 16:57:18 -07:00
|
|
|
};
|
2014-09-02 19:28:20 -07:00
|
|
|
|
2015-08-04 10:49:38 -07:00
|
|
|
module.exports = Daemon;
|