bitcore-node-zcash/lib/daemon.js

969 lines
22 KiB
JavaScript
Raw Normal View History

2014-08-12 12:03:04 -07:00
/**
* bitcoind.js
* Copyright (c) 2014, BitPay (MIT License)
* A bitcoind node.js binding.
*/
var net = require('net');
var EventEmitter = require('events').EventEmitter;
2015-07-09 09:50:09 -07:00
var bitcoindjs = require('bindings')('bitcoindjs.node');
2014-09-02 19:28:20 -07:00
var util = require('util');
2014-10-16 13:53:47 -07:00
var fs = require('fs');
var mkdirp = require('mkdirp');
var tiny = require('tiny').json;
2014-08-12 12:03:04 -07:00
2014-11-18 17:14:18 -08:00
// Compatibility with old node versions:
var setImmediate = global.setImmediate || process.nextTick.bind(process);
2014-08-12 12:03:04 -07:00
/**
2015-07-16 14:03:43 -07:00
* Daemon
2014-08-12 12:03:04 -07:00
*/
2015-07-16 14:03:43 -07:00
var daemon = Daemon;
2014-09-25 13:39:06 -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) {
throw new
Error('bitcoind.js cannot be instantiated more than once.');
}
2014-08-12 12:03:04 -07:00
EventEmitter.call(this);
2014-10-16 13:53:47 -07:00
this.options = options || {};
2014-09-25 13:58:54 -07:00
2014-10-16 13:53:47 -07:00
if (!this.options.datadir) {
2014-11-11 13:36:08 -08:00
this.options.datadir = '~/.bitcoind.js';
}
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;
this.config = this.datadir + '/bitcoin.conf';
this.network = Daemon['livenet'];
if (this.options.network === 'testnet') {
this.network = Daemon['testnet'];
} else if(this.options.network === 'regtest') {
this.network = Daemon['regtest'];
}
2014-11-11 13:27:36 -08:00
2014-11-11 13:36:08 -08:00
if (!fs.existsSync(this.datadir)) {
mkdirp.sync(this.datadir);
2014-10-16 13:53:47 -07:00
}
if (!fs.existsSync(this.config)) {
var password = ''
+ Math.random().toString(36).slice(2)
2014-10-16 13:53:47 -07:00
+ Math.random().toString(36).slice(2)
+ Math.random().toString(36).slice(2);
fs.writeFileSync(this.config, ''
+ 'rpcuser=bitcoinrpc\n'
+ 'rpcpassword=' + password + '\n'
);
}
2014-11-11 13:27:36 -08:00
// Add hardcoded peers
var data = fs.readFileSync(this.config, 'utf8');
if (this.network.peers.length) {
var peers = this.network.peers.reduce(function(out, peer) {
if (!~data.indexOf('addnode=' + peer)) {
return out + 'addnode=' + peer + '\n';
}
return out;
}, '\n');
fs.writeFileSync(data + peers);
}
if (this.network.name === 'testnet') {
if (!fs.existsSync(this.datadir + '/testnet3')) {
fs.mkdirSync(this.datadir + '/testnet3');
}
fs.writeFileSync(
this.datadir + '/testnet3/bitcoin.conf',
fs.readFileSync(this.config));
}
if (this.network.name === 'regtest') {
if (!fs.existsSync(this.datadir + '/regtest')) {
fs.mkdirSync(this.datadir + '/regtest');
}
fs.writeFileSync(
this.datadir + '/regtest/bitcoin.conf',
fs.readFileSync(this.config));
}
2014-10-03 18:27:06 -07:00
Object.keys(exports).forEach(function(key) {
self[key] = exports[key];
});
2014-09-25 14:28:08 -07:00
this.on('newListener', function(name) {
if (name === 'open') {
self.start();
}
});
2014-09-11 17:18:36 -07:00
}
2015-07-16 14:03:43 -07:00
Daemon.prototype.__proto__ = EventEmitter.prototype;
2014-09-11 17:18:36 -07:00
2015-07-16 14:03:43 -07:00
Daemon.livenet = {
2014-11-11 13:27:36 -08:00
name: 'livenet',
peers: [
// hardcoded peers
]
};
2015-07-16 14:03:43 -07:00
Daemon.testnet = {
2014-11-11 13:27:36 -08:00
name: 'testnet',
peers: [
// hardcoded peers
]
};
Daemon.regtest = {
name: 'regtest',
peers: [
// hardcoded peers
]
};
// Make sure signal handlers are not overwritten
2015-07-16 14:03:43 -07:00
Daemon._signalQueue = [];
Daemon._processOn = process.on;
process.addListener =
process.on = function(name, listener) {
if (~['SIGINT', 'SIGHUP', 'SIGQUIT'].indexOf(name.toUpperCase())) {
2015-07-16 14:03:43 -07:00
if (!Daemon.global || !Daemon.global._started) {
Daemon._signalQueue.push([name, listener]);
return;
}
}
2015-07-16 14:03:43 -07:00
return Daemon._processOn.apply(this, arguments);
};
2015-07-16 14:03:43 -07:00
Daemon.instances = {};
Daemon.prototype.instances = Daemon.instances;
2015-07-16 14:03:43 -07:00
Daemon.__defineGetter__('global', function() {
if (daemon.stopping) return [];
return Daemon.instances[Object.keys(Daemon.instances)[0]];
});
2015-07-16 14:03:43 -07:00
Daemon.prototype.__defineGetter__('global', function() {
if (daemon.stopping) return [];
return Daemon.global;
});
tiny.debug = function() {};
tiny.prototype.debug = function() {};
tiny.error = function() {};
tiny.prototype.error = function() {};
2015-07-16 14:03:43 -07:00
Daemon.db = tiny({
file: process.env.HOME + '/.bitcoindjs.db',
saveIndex: false,
initialCache: false
});
2015-07-16 14:03:43 -07:00
Daemon.prototype.start = function(options, callback) {
2014-09-11 17:18:36 -07:00
var self = this;
2014-08-29 13:54:54 -07:00
2014-10-15 16:38:10 -07:00
if (!callback) {
callback = options;
2014-10-16 13:53:47 -07:00
options = null;
}
if (!options) {
2014-10-15 16:38:10 -07:00
options = {};
}
2014-10-16 13:53:47 -07:00
2014-10-15 16:38:10 -07:00
if (!callback) {
callback = utils.NOOP;
}
2014-11-11 13:36:08 -08:00
if (this.instances[this.datadir]) {
return;
}
2014-11-11 13:36:08 -08:00
this.instances[this.datadir] = true;
2014-09-25 14:28:08 -07:00
2014-09-17 14:21:28 -07:00
var none = {};
2014-09-22 14:35:11 -07:00
var isSignal = {};
var sigint = { name: 'SIGINT', signal: isSignal };
var sighup = { name: 'SIGHUP', signal: isSignal };
var sigquit = { name: 'SIGQUIT', signal: isSignal };
2014-09-17 14:21:28 -07:00
var exitCaught = none;
var errorCaught = none;
2014-10-16 13:53:47 -07:00
Object.keys(this.options).forEach(function(key) {
if (options[key] == null) {
options[key] = self.options[key];
}
});
2014-11-17 13:09:05 -08:00
bitcoindjs.start(options, function(err, status) {
self._started = true;
2015-07-09 09:55:53 -07:00
// Poll for queued packet
[sigint, sighup, sigquit].forEach(function(signal) {
2014-09-22 14:35:11 -07:00
process.on(signal.name, signal.listener = function() {
if (process.listeners(signal.name).length > 1) {
return;
}
if (!self._shutdown) {
process.exit(0);
} else {
self.stop();
exitCaught = signal;
}
});
2014-09-19 16:45:46 -07:00
});
2014-09-17 14:21:28 -07:00
// Finally set signal handlers
2015-07-16 14:03:43 -07:00
process.on = process.addListener = Daemon._processOn;
Daemon._signalQueue.forEach(function(event) {
process.on(event[0], event[1]);
});
2014-09-17 14:21:28 -07:00
var exit = process.exit;
self._exit = function() {
return exit.apply(process, arguments);
};
process.exit = function(code) {
exitCaught = code || 0;
if (!self._shutdown) {
return self._exit(code);
2014-09-17 14:21:28 -07:00
}
self.stop();
};
2014-09-17 14:08:26 -07:00
2014-09-17 14:21:28 -07:00
process.on('uncaughtException', function(err) {
if (process.listeners('uncaughtException').length > 1) {
return;
}
2014-09-17 14:21:28 -07:00
errorCaught = err;
2014-09-25 13:39:06 -07:00
self.error('Uncaught error: shutting down safely before throwing...');
2014-09-17 14:21:28 -07:00
if (!self._shutdown) {
if (err && err.stack) {
console.error(err.stack);
}
self._exit(1);
return;
2014-09-17 14:21:28 -07:00
}
self.stop();
});
2014-09-17 14:25:19 -07:00
2015-07-07 14:02:03 -07:00
bitcoindjs.onBlocksReady(function(err, result) {
self.emit('ready', result);
});
setTimeout(function callee() {
// Wait until wallet is loaded:
if (callback) {
callback(err ? err : null);
}
if (err) {
self.emit('error', err);
} else {
if (callback) {
self.emit('open', status);
} else {
self.emit('status', status);
}
}
if (callback) {
callback = null;
}
}, 100);
2014-08-12 12:03:04 -07:00
});
2014-09-02 19:28:20 -07:00
2014-09-10 16:57:18 -07:00
// bitcoind's boost threads aren't in the thread pool
// or on node's event loop, so we need to keep node open.
2014-09-17 14:08:26 -07:00
this._shutdown = setInterval(function() {
if (!self._stoppingSaid && bitcoindjs.stopping()) {
self._stoppingSaid = true;
self.log('shutting down...');
}
2014-09-17 14:21:28 -07:00
2014-09-17 12:52:35 -07:00
if (bitcoindjs.stopped()) {
2014-09-17 14:08:26 -07:00
self.log('shut down.');
2014-09-17 14:21:28 -07:00
2014-09-17 14:08:26 -07:00
clearInterval(self._shutdown);
delete self._shutdown;
2014-09-17 14:21:28 -07:00
if (exitCaught !== none) {
2014-09-22 14:35:11 -07:00
if (exitCaught.signal === isSignal) {
process.removeListener(exitCaught.name, exitCaught.listener);
setImmediate(function() {
process.kill(process.pid, exitCaught.name);
});
return;
}
2014-09-19 16:45:46 -07:00
return self._exit(exitCaught);
2014-09-17 14:21:28 -07:00
}
if (errorCaught !== none) {
if (errorCaught && errorCaught.stack) {
2014-09-17 14:21:28 -07:00
console.error(errorCaught.stack);
}
return self._exit(0);
}
2014-09-17 12:52:35 -07:00
}
2014-09-17 14:08:26 -07:00
}, 1000);
2014-09-23 13:57:49 -07:00
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.getBlock = function(blockhash, callback) {
if (daemon.stopping) return [];
2014-12-08 12:33:59 -08:00
return bitcoindjs.getBlock(blockhash, function(err, block) {
2014-09-25 13:45:42 -07:00
if (err) return callback(err);
2015-07-07 17:28:48 -07:00
return callback(null, block);
2014-09-25 13:45:42 -07:00
});
2014-09-18 17:14:17 -07:00
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.getBlockHeight = function(height, callback) {
if (daemon.stopping) return [];
2014-11-04 16:08:31 -08:00
return bitcoindjs.getBlock(+height, function(err, block) {
if (err) return callback(err);
2015-07-16 14:03:43 -07:00
return callback(null, daemon.block(block));
2014-11-04 16:08:31 -08:00
});
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.isSpent = function(txid, outputIndex) {
return bitcoindjs.isSpent(txid, outputIndex);
2015-07-15 14:45:36 -07:00
};
Daemon.prototype.getBlockIndex = function(blockHash) {
return bitcoindjs.getBlockIndex(blockHash);
};
Daemon.prototype.sendTransaction = function(transaction, allowAbsurdFees) {
return bitcoindjs.sendTransaction(transaction, allowAbsurdFees);
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.getTransaction = function(txid, queryMempool, callback) {
return bitcoindjs.getTransaction(txid, queryMempool, callback);
2014-09-22 12:05:17 -07:00
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.getTransactionWithBlock = function(txid, blockhash, callback) {
if (daemon.stopping) return [];
2014-12-12 15:35:43 -08:00
var self = this;
2014-12-08 14:37:51 -08:00
var slow = true;
if (typeof txid === 'object' && txid) {
var options = txid;
callback = blockhash;
txid = options.txid || options.tx || options.txhash || options.id || options.hash;
blockhash = options.blockhash || options.block;
slow = options.slow !== false;
}
if (typeof blockhash === 'function') {
callback = blockhash;
blockhash = '';
}
if (typeof blockhash !== 'string') {
if (blockhash) {
blockhash = blockhash.hash
|| blockhash.blockhash
|| (blockhash.getHash && blockhash.getHash())
|| '';
} else {
blockhash = '';
}
}
return bitcoindjs.getTransaction(txid, blockhash, function(err, tx) {
if (err) return callback(err);
if (slow && !tx.blockhash) {
2014-12-12 15:35:43 -08:00
return self.getBlockByTx(txid, function(err, block, tx_) {
2014-12-08 14:37:51 -08:00
if (err) return callback(err);
2014-12-12 15:35:43 -08:00
return callback(null, tx, block);
2014-12-08 14:37:51 -08:00
});
}
return bitcoindjs.getBlock(tx.blockhash, function(err, block) {
if (err) return callback(err);
2015-07-16 14:03:43 -07:00
return callback(null, daemon.tx(tx), daemon.block(block));
2014-12-08 14:37:51 -08:00
});
});
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.getMempoolOutputs = function(address) {
2015-07-17 12:55:36 -07:00
return bitcoindjs.getMempoolOutputs(address);
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.addMempoolUncheckedTransaction = function(txBuffer) {
return bitcoindjs.addMempoolUncheckedTransaction(txBuffer);
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.getInfo = function() {
2015-07-20 10:27:28 -07:00
if (daemon.stopping) return [];
2014-10-17 13:26:27 -07:00
return bitcoindjs.getInfo();
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.getPeerInfo = function() {
if (daemon.stopping) return [];
2014-10-17 13:47:56 -07:00
return bitcoindjs.getPeerInfo();
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.getAddresses = function() {
if (daemon.stopping) return [];
2014-10-17 16:12:57 -07:00
return bitcoindjs.getAddresses();
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.getProgress = function(callback) {
if (daemon.stopping) return [];
2014-10-28 13:01:40 -07:00
return bitcoindjs.getProgress(callback);
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.setGenerate = function(options) {
if (daemon.stopping) return [];
2014-10-28 14:09:55 -07:00
return bitcoindjs.setGenerate(options || {});
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.getGenerate = function(options) {
if (daemon.stopping) return [];
2014-10-28 14:09:55 -07:00
return bitcoindjs.getGenerate(options || {});
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.getMiningInfo = function() {
if (daemon.stopping) return [];
2014-10-28 14:16:33 -07:00
return bitcoindjs.getMiningInfo();
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.getAddrTransactions = function(address, callback) {
if (daemon.stopping) return [];
return daemon.db.get('addr-tx/' + address, function(err, records) {
2014-12-02 03:09:30 -08:00
var options = {
address: address,
blockheight: (records || []).reduce(function(out, record) {
return record.blockheight > out
? record.blockheight
2014-12-02 03:09:30 -08:00
: out;
2014-12-03 21:16:47 -08:00
}, -1),
blocktime: (records || []).reduce(function(out, record) {
return record.blocktime > out
? record.blocktime
: out;
2014-12-02 03:09:30 -08:00
}, -1)
};
return bitcoindjs.getAddrTransactions(options, function(err, addr) {
if (err) return callback(err);
2015-07-16 14:03:43 -07:00
addr = daemon.addr(addr);
2014-12-02 03:09:30 -08:00
if (addr.tx[0] && !addr.tx[0].vout[0]) {
2015-07-16 14:03:43 -07:00
return daemon.db.set('addr-tx/' + address, [{
2014-12-02 03:09:30 -08:00
txid: null,
blockhash: null,
2014-12-03 21:16:47 -08:00
blockheight: null,
blocktime: null
2014-12-02 03:09:30 -08:00
}], function() {
2015-07-16 14:03:43 -07:00
return callback(null, daemon.addr({
2014-12-02 03:09:30 -08:00
address: addr.address,
tx: []
}));
});
2014-12-02 03:09:30 -08:00
}
var set = [];
if (records && records.length) {
set = records;
}
addr.tx.forEach(function(tx) {
set.push({
txid: tx.txid,
blockhash: tx.blockhash,
2014-12-03 21:16:47 -08:00
blockheight: tx.blockheight,
blocktime: tx.blocktime
});
});
2015-07-16 14:03:43 -07:00
return daemon.db.set('addr-tx/' + address, set, function() {
2014-12-02 03:09:30 -08:00
return callback(null, addr);
});
});
2014-11-18 14:13:47 -08:00
});
2014-11-04 16:08:31 -08:00
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.getBestBlock = function(callback) {
if (daemon.stopping) return [];
2014-11-06 13:37:15 -08:00
var hash = bitcoindjs.getBestBlock();
return bitcoindjs.getBlock(hash, callback);
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.getChainHeight = function() {
if (daemon.stopping) return [];
return bitcoindjs.getChainHeight();
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.__defineGetter__('chainHeight', function() {
if (daemon.stopping) return [];
2014-12-02 03:38:37 -08:00
return this.getChainHeight();
});
2015-07-16 14:03:43 -07:00
Daemon.prototype.getBlockByTxid =
Daemon.prototype.getBlockByTx = function(txid, callback) {
if (daemon.stopping) return [];
return daemon.db.get('block-tx/' + txid, function(err, block) {
2014-12-09 09:50:15 -08:00
if (block) {
2014-12-10 16:28:35 -08:00
return self.getBlock(block.hash, function(err, block) {
if (err) return callback(err);
var tx_ = block.tx.filter(function(tx) {
return tx.txid === txid;
})[0];
return callback(null, block, tx_);
});
2014-12-09 09:50:15 -08:00
}
2014-12-10 16:28:35 -08:00
return bitcoindjs.getBlockByTx(txid, function(err, block, tx_) {
2014-12-09 09:50:15 -08:00
if (err) return callback(err);
2015-07-16 14:03:43 -07:00
daemon.db.set('block-tx/' + txid, { hash: block.hash }, utils.NOOP);
return callback(null, daemon.block(block), daemon.tx(tx_));
2014-12-08 14:16:19 -08:00
});
2014-12-08 10:00:53 -08:00
});
2014-12-03 12:14:23 -08:00
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.getBlocksByDate =
Daemon.prototype.getBlocksByTime = function(options, callback) {
if (daemon.stopping) return [];
2014-12-08 10:00:53 -08:00
return bitcoindjs.getBlocksByTime(options, function(err, blocks) {
if (err) return callback(err);
return callback(null, blocks.map(function(block) {
2015-07-16 14:03:43 -07:00
return daemon.block(block);
2014-12-08 10:00:53 -08:00
}));
});
2014-12-03 12:46:48 -08:00
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.getFromTx = function(txid, callback) {
if (daemon.stopping) return [];
2014-12-16 14:41:00 -08:00
return bitcoindjs.getFromTx(txid, function(err, txs) {
if (err) return callback(err);
return callback(null, txs.map(function(tx) {
2015-07-16 14:03:43 -07:00
return daemon.tx(tx)
2014-12-16 14:41:00 -08:00
}));
});
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.getLastFileIndex = function() {
if (daemon.stopping) return [];
return bitcoindjs.getLastFileIndex();
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.log =
Daemon.prototype.info = function() {
if (daemon.stopping) return [];
2014-10-29 16:01:54 -07:00
if (this.options.silent) return;
2014-09-02 19:28:20 -07:00
if (typeof arguments[0] !== 'string') {
var out = util.inspect(arguments[0], null, 20, true);
2014-09-17 14:31:20 -07:00
return process.stdout.write('bitcoind.js: ' + out + '\n');
2014-09-02 19:28:20 -07:00
}
var out = util.format.apply(util, arguments);
2014-09-17 14:31:20 -07:00
return process.stdout.write('bitcoind.js: ' + out + '\n');
2014-09-02 19:28:20 -07:00
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.error = function() {
if (daemon.stopping) return [];
2014-10-29 16:01:54 -07:00
if (this.options.silent) return;
2014-09-02 19:28:20 -07:00
if (typeof arguments[0] !== 'string') {
var out = util.inspect(arguments[0], null, 20, true);
2014-09-17 14:31:20 -07:00
return process.stderr.write('bitcoind.js: ' + out + '\n');
2014-09-02 19:28:20 -07:00
}
var out = util.format.apply(util, arguments);
2014-09-17 14:31:20 -07:00
return process.stderr.write('bitcoind.js: ' + out + '\n');
2014-09-02 19:28:20 -07:00
};
2015-07-16 14:03:43 -07:00
Daemon.prototype.stop =
Daemon.prototype.close = function(callback) {
if (daemon.stopping) return [];
2014-09-11 17:18:36 -07:00
var self = this;
return bitcoindjs.stop(function(err, status) {
if (err) {
self.error(err.message);
} else {
self.log(status);
}
if (!callback) return;
return callback(err, status);
});
2014-09-10 16:57:18 -07:00
};
2014-09-02 19:28:20 -07:00
2015-07-16 14:03:43 -07:00
Daemon.prototype.__defineGetter__('stopping', function() {
2014-12-12 11:00:24 -08:00
return bitcoindjs.stopping() || bitcoindjs.stopped();
});
2015-07-16 14:03:43 -07:00
Daemon.prototype.__defineGetter__('stopped', function() {
2014-12-12 11:00:24 -08:00
return bitcoindjs.stopped();
});
2015-07-16 14:03:43 -07:00
Daemon.__defineGetter__('stopping', function() {
2014-12-12 11:00:24 -08:00
return bitcoindjs.stopping() || bitcoindjs.stopped();
});
2015-07-16 14:03:43 -07:00
Daemon.__defineGetter__('stopped', function() {
2014-12-12 11:00:24 -08:00
return bitcoindjs.stopped();
});
2014-09-25 10:59:36 -07:00
/**
* Block
*/
function Block(data) {
if (!(this instanceof Block)) {
return new Block(data);
}
2014-09-25 13:39:06 -07:00
2014-10-23 16:22:39 -07:00
if (typeof data === 'string') {
return Block.fromHex(data);
}
2014-09-25 13:39:06 -07:00
if (data instanceof Block) {
return data;
}
2014-09-25 13:45:42 -07:00
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
2014-12-12 11:00:24 -08:00
2014-09-25 13:45:42 -07:00
var self = this;
Object.keys(data).forEach(function(key) {
2014-09-25 14:12:09 -07:00
if (!self[key]) {
self[key] = data[key];
}
2014-09-25 13:45:42 -07:00
});
2014-09-26 11:39:25 -07:00
this.tx = this.tx.map(function(tx) {
2015-07-16 14:03:43 -07:00
return daemon.tx(tx);
});
2014-09-29 16:06:49 -07:00
if (!this.hex) {
this.hex = this.toHex();
}
2014-09-25 10:59:36 -07:00
}
Object.defineProperty(Block.prototype, '_blockFlag', {
__proto__: null,
configurable: false,
enumerable: false,
writable: false,
2014-10-06 08:10:23 -07:00
value: {}
});
2014-09-29 14:38:52 -07:00
Block.isBlock = function(block) {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
2014-10-06 08:10:23 -07:00
return block._blockFlag === Block.prototype._blockFlag;
2014-09-29 14:38:52 -07:00
};
2014-10-03 18:27:06 -07:00
Block.fromHex = function(hex) {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
return daemon.block(bitcoindjs.blockFromHex(hex));
2014-10-03 18:27:06 -07:00
};
Block.prototype.getHash = function(enc) {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
var data = bitcoindjs.getBlockHex(this);
if (!this.hash || this.hash !== data.hash) {
this.hash = data.hash;
}
2014-10-03 16:39:26 -07:00
if (enc === 'hex') return data.hash;
var buf = new Buffer(data.hash, 'hex');
var out = enc ? buf.toString(enc) : buf;
return out;
};
2014-09-26 11:23:21 -07:00
Block.prototype.verify = function() {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
2014-09-26 11:39:25 -07:00
return this.verified = this.verified || bitcoindjs.verifyBlock(this);
2014-09-26 11:23:21 -07:00
};
Block.prototype.toHex = function() {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
var hex = Block.toHex(this);
if (!this.hex || this.hex !== hex) {
this.hex = hex;
}
return hex;
};
Block.toHex = function(block) {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
var data = bitcoindjs.getBlockHex(block);
return data.hex;
};
2014-09-26 11:23:21 -07:00
Block.prototype.toBinary = function() {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
2014-09-26 11:23:21 -07:00
return Block.toBinary(this);
};
Block.toBinary = function(block) {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
var data = bitcoindjs.getBlockHex(block);
return new Buffer(data.hex, 'hex');
};
2014-09-25 10:59:36 -07:00
/**
* Transaction
*/
function Transaction(data) {
if (!(this instanceof Transaction)) {
return new Transaction(data);
}
2014-10-23 16:22:39 -07:00
if (typeof data === 'string') {
return Transaction.fromHex(data);
}
2014-09-25 13:39:06 -07:00
if (data instanceof Transaction) {
return data;
}
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
2014-12-12 11:00:24 -08:00
2014-09-25 13:39:06 -07:00
var self = this;
Object.keys(data).forEach(function(key) {
2014-09-25 14:12:09 -07:00
if (!self[key]) {
self[key] = data[key];
}
2014-09-25 13:39:06 -07:00
});
2014-09-25 14:12:09 -07:00
if (!this.hex) {
this.hex = this.toHex();
}
2014-09-25 10:59:36 -07:00
}
Object.defineProperty(Transaction.prototype, '_txFlag', {
__proto__: null,
configurable: false,
enumerable: false,
writable: false,
2014-10-06 08:10:23 -07:00
value: {}
});
2014-09-29 14:38:52 -07:00
Transaction.isTransaction =
Transaction.isTx = function(tx) {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
2014-10-06 08:10:23 -07:00
return tx._txFlag === Transaction.prototype._txFlag;
2014-09-29 14:38:52 -07:00
};
2014-10-03 18:27:06 -07:00
Transaction.fromHex = function(hex) {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
return daemon.tx(bitcoindjs.txFromHex(hex));
2014-10-03 18:27:06 -07:00
};
2014-09-26 11:34:55 -07:00
Transaction.prototype.verify = function() {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
2014-09-26 11:39:25 -07:00
return this.verified = this.verified || bitcoindjs.verifyTransaction(this);
2014-09-26 11:34:55 -07:00
};
Transaction.prototype.sign =
Transaction.prototype.fill = function(options) {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
return Transaction.fill(this, options);
};
Transaction.sign =
Transaction.fill = function(tx, options) {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
var isTx = daemon.tx.isTx(tx)
2014-09-29 14:38:52 -07:00
, newTx;
if (!isTx) {
2015-07-16 14:03:43 -07:00
tx = daemon.tx(tx);
2014-09-29 14:38:52 -07:00
}
try {
newTx = bitcoindjs.fillTransaction(tx, options || {});
2014-09-29 14:38:52 -07:00
} catch (e) {
return false;
}
Object.keys(newTx).forEach(function(key) {
tx[key] = newTx[key];
});
2014-12-09 09:46:40 -08:00
return tx;
};
Transaction.prototype.getHash = function(enc) {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
var data = bitcoindjs.getTxHex(this);
if (!this.txid || this.txid !== data.hash) {
this.txid = data.hash;
}
2014-10-03 16:39:26 -07:00
if (enc === 'hex') return data.hash;
var buf = new Buffer(data.hash, 'hex');
var out = enc ? buf.toString(enc) : buf;
return out;
};
2014-09-25 10:59:36 -07:00
Transaction.prototype.isCoinbase = function() {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
return this.vin.length === 1 && this.vin[0].coinbase;
2014-09-25 10:59:36 -07:00
};
2014-09-25 12:05:39 -07:00
Transaction.prototype.toHex = function() {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
var hex = Transaction.toHex(this);
if (!this.hex || hex !== this.hex) {
this.hex = hex;
}
return hex;
2014-09-25 12:05:39 -07:00
};
Transaction.toHex = function(tx) {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
var data = bitcoindjs.getTxHex(tx);
return data.hex;
};
Transaction.prototype.toBinary = function() {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
return Transaction.toBinary(this);
2014-09-25 12:05:39 -07:00
};
2014-09-25 13:17:07 -07:00
Transaction.toBinary = function(tx) {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
var data = bitcoindjs.getTxHex(tx);
return new Buffer(data.hex, 'hex');
};
2014-09-25 13:39:06 -07:00
Transaction.broadcast = function(tx, options, callback) {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
2014-09-25 13:39:06 -07:00
if (typeof tx === 'string') {
tx = { hex: tx };
}
if (!callback) {
callback = options;
options = null;
}
if (!options) {
options = {};
}
2014-09-25 13:58:54 -07:00
var fee = options.overrideFees = options.overrideFees || false;
var own = options.ownOnly = options.ownOnly || false;
if (!callback) {
2014-09-25 14:04:59 -07:00
callback = utils.NOOP;
2014-09-25 13:58:54 -07:00
}
2014-09-25 13:39:06 -07:00
2015-07-16 14:03:43 -07:00
if (!daemon.isTx(tx)) {
tx = daemon.tx(tx);
2014-09-25 13:39:06 -07:00
}
2014-09-25 14:01:50 -07:00
return bitcoindjs.broadcastTx(tx, fee, own, function(err, hash, tx) {
2014-09-25 14:04:59 -07:00
if (err) {
if (callback === utils.NOOP) {
2015-07-16 14:03:43 -07:00
daemon.global.emit('error', err);
2014-09-25 14:04:59 -07:00
}
return callback(err);
}
2015-07-16 14:03:43 -07:00
tx = daemon.tx(tx);
daemon.global.emit('broadcast', tx);
2014-09-25 14:01:50 -07:00
return callback(null, hash, tx);
2014-09-25 13:58:54 -07:00
});
2014-09-25 13:39:06 -07:00
};
2014-09-25 13:58:54 -07:00
Transaction.prototype.broadcast = function(options, callback) {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
2014-09-25 13:58:54 -07:00
if (!callback) {
callback = options;
options = null;
}
return Transaction.broadcast(this, options, callback);
2014-09-25 13:39:06 -07:00
};
2014-11-18 16:31:51 -08:00
/**
* Addresses
*/
function Addresses(data) {
if (!(this instanceof Addresses)) {
return new Addresses(data);
}
if (data instanceof Addresses) {
return data;
}
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
2014-12-12 11:00:24 -08:00
2014-11-18 16:31:51 -08:00
var self = this;
Object.keys(data).forEach(function(key) {
if (!self[key]) {
self[key] = data[key];
}
});
}
Object.defineProperty(Transaction.prototype, '_addrFlag', {
__proto__: null,
configurable: false,
enumerable: false,
writable: false,
value: {}
});
Addresses.isAddresses =
Addresses.isAddr = function(addr) {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
2014-11-18 16:31:51 -08:00
return addr._txFlag === Addresses.prototype._addrFlag;
};
2014-09-22 12:14:51 -07:00
/**
* Utils
*/
var utils = {};
2014-09-22 18:21:08 -07:00
utils.forEach = function(obj, iter, done) {
2015-07-16 14:03:43 -07:00
if (daemon.stopping) return [];
2014-09-22 18:21:08 -07:00
var pending = obj.length;
if (!pending) return done();
var next = function() {
if (!--pending) done();
};
obj.forEach(function(item) {
iter(item, next);
});
};
2014-09-25 14:04:59 -07:00
utils.NOOP = function() {};
2014-08-12 12:03:04 -07:00
/**
* Expose
*/
2015-07-16 14:03:43 -07:00
module.exports = exports = daemon;
2014-09-25 13:39:06 -07:00
2015-07-16 14:03:43 -07:00
exports.Daemon = daemon;
exports.daemon = daemon;
exports.bitcoind = daemon;
2014-09-25 13:39:06 -07:00
2014-08-12 12:03:04 -07:00
exports.native = bitcoindjs;
2014-09-25 13:39:06 -07:00
exports.bitcoindjs = bitcoindjs;
exports.Block = Block;
exports.block = Block;
exports.Transaction = Transaction;
exports.transaction = Transaction;
exports.tx = Transaction;
2014-11-18 16:31:51 -08:00
exports.Addresses = Addresses;
exports.addresses = Addresses;
exports.addr = Addresses;
2014-09-22 12:14:51 -07:00
exports.utils = utils;