diff --git a/README.md b/README.md index 68853444..d15a8501 100644 --- a/README.md +++ b/README.md @@ -377,6 +377,8 @@ Note that if you already have a bitcore-node database, and you want to query dat - `daemon.getTransactionWithBlockInfo(txid, queryMempool, callback)` - Similar to getTransaction but will also include the block timestamp and height. - `daemon.getMempoolOutputs(address)` - Will return an array of outputs that match an address from the mempool. - `daemon.getInfo()` - Basic information about the chain including total number of blocks. +- `daemon.isSynced()` - Returns a boolean if the daemon is fully synced (not the initial block download) +- `daemon.syncPercentage()` - Returns the current estimate of blockchain download as a percentage. - `daemon.stop([callback])` - Stop the JavaScript bitcoin node safely, the callback will be called when bitcoind is closed. This will also be done automatically on `process.exit`. It also takes the bitcoind node off the libuv event loop. If the daemon object is the only thing on the event loop. Node will simply close. ## License diff --git a/bin/start.js b/bin/start.js index 8b63d2f4..4da2476c 100644 --- a/bin/start.js +++ b/bin/start.js @@ -15,17 +15,23 @@ var configuration = { var node = new BitcoinNode(configuration); var count = 0; -var interval; +var interval = false; + +function logSyncStatus() { + log.info('Sync Status: Tip:', node.chain.tip.hash, 'Height:', node.chain.tip.__height, 'Rate:', count/10, 'blocks per second'); +} + +node.on('synced', function() { + // Stop logging of sync status + clearInterval(interval); + interval = false; + logSyncStatus(); +}); node.on('ready', function() { var io = socketio(configuration.port); - interval = setInterval(function() { - log.info('Sync Status: Tip:', node.chain.tip.hash, 'Height:', node.chain.tip.__height, 'Rate:', count/10, 'blocks per second'); - count = 0; - }, 10000); - io.on('connection', function(socket) { var bus = node.openBus(); @@ -135,4 +141,11 @@ node.on('error', function(err) { node.chain.on('addblock', function(block) { count++; + // Initialize logging if not already instantiated + if (!interval) { + interval = setInterval(function() { + logSyncStatus(); + count = 0; + }, 10000); + } }); diff --git a/lib/daemon.js b/lib/daemon.js index e10a08cd..429efa9f 100644 --- a/lib/daemon.js +++ b/lib/daemon.js @@ -233,6 +233,14 @@ Daemon.prototype.start = function(options, callback) { }, 1000); }; +Daemon.prototype.isSynced = function() { + return bitcoind.isSynced(); +}; + +Daemon.prototype.syncPercentage = function() { + return bitcoind.syncPercentage(); +}; + Daemon.prototype.getBlock = function(blockhash, callback) { return bitcoind.getBlock(blockhash, callback); }; diff --git a/lib/node.js b/lib/node.js index 6225764d..f9b0f21e 100644 --- a/lib/node.js +++ b/lib/node.js @@ -223,8 +223,6 @@ Node.prototype._syncBitcoind = function() { self.bitcoindSyncing = true; self.chain.lastSavedMetadataThreshold = 30000; - log.info('Starting Bitcoind Sync'); - var height; async.whilst(function() { @@ -271,14 +269,19 @@ Node.prototype._syncBitcoind = function() { } }); }, function(err) { - log.info('Stopping Bitcoind Sync'); + self.bitcoindSyncing = false; self.chain.lastSavedMetadataThreshold = 0; if (err) { Error.captureStackTrace(err); return self.emit('error', err); } - self.emit('synced'); + + // If bitcoind is completely synced + if (self.bitcoind.isSynced()) { + self.emit('synced'); + } + }); }; @@ -383,7 +386,8 @@ Node.prototype._initializeBitcoind = function() { // Notify that there is a new tip this.bitcoind.on('tip', function(height) { - log.info('Bitcoin Core Daemon New Height:', height); + var percentage = self.bitcoind.syncPercentage(); + log.info('Bitcoin Core Daemon New Height:', height, 'Percentage:', percentage); self.bitcoindHeight = height; self._syncBitcoind(); }); diff --git a/src/libbitcoind.cc b/src/libbitcoind.cc index f2e6befd..e76d0264 100644 --- a/src/libbitcoind.cc +++ b/src/libbitcoind.cc @@ -217,15 +217,25 @@ static bool set_cooked(void); /** - * GetProgress() - * bitcoind.getProgress() + * SyncPercentage() + * bitcoind.syncPercentage() * provides a float value >= indicating the progress of the blockchain sync */ -NAN_METHOD(GetProgress) { +NAN_METHOD(SyncPercentage) { const CChainParams& chainParams = Params(); float progress = 0; progress = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip()); - NanReturnValue(progress); + NanReturnValue(NanNew(progress * 100)); +}; + +/** + * IsSynced() + * bitcoind.isSynced() + * returns a boolean of bitcoin is fully synced + */ +NAN_METHOD(IsSynced) { + bool isDownloading = IsInitialBlockDownload(); + NanReturnValue(NanNew(!isDownloading)); }; NAN_METHOD(StartTxMon) { @@ -1682,7 +1692,8 @@ init(Handle target) { NODE_SET_METHOD(target, "sendTransaction", SendTransaction); NODE_SET_METHOD(target, "estimateFee", EstimateFee); NODE_SET_METHOD(target, "startTxMon", StartTxMon); - NODE_SET_METHOD(target, "getProgress", GetProgress); + NODE_SET_METHOD(target, "syncPercentage", SyncPercentage); + NODE_SET_METHOD(target, "isSynced", IsSynced); }