latest-block.js
1 /*! 2 * lib/bitcoind_rpc/latest-block.js 3 * Copyright © 2019 – Katana Cryptographic Ltd. All Rights Reserved. 4 */ 5 6 import zmq from 'zeromq/v5-compat.js' 7 8 import Logger from '../logger.js' 9 import network from '../bitcoin/network.js' 10 import keysFile from '../../keys/index.js' 11 import { createRpcClient, waitForBitcoindRpcApi } from './rpc-client.js' 12 import util from '../util.js' 13 14 const keys = keysFile[network.key] 15 16 /** 17 * A singleton providing information about the latest block 18 */ 19 class LatestBlock { 20 21 /** 22 * Constructor 23 */ 24 constructor() { 25 this.height = null 26 this.hash = null 27 this.time = null 28 this.diff = null 29 30 // Initialize the rpc client 31 this.rpcClient = createRpcClient() 32 33 waitForBitcoindRpcApi().then(() => { 34 // Gets the latest block from bitcoind 35 this.rpcClient.getbestblockhash().then((hash) => this.onBlockHash(hash)) 36 }) 37 38 // Initializes zmq socket 39 this.sock = zmq.socket('sub') 40 this.sock.connect(keys.bitcoind.zmqBlk) 41 this.sock.subscribe('hashblock') 42 43 this.sock.on('message', async (topic, message) => { 44 switch (topic.toString()) { 45 case 'hashblock': 46 await this.onBlockHash(message.toString('hex')) 47 break 48 default: 49 Logger.info(`Bitcoind RPC : ${topic.toString()}`) 50 } 51 }) 52 } 53 54 /** 55 * Retrieve and store information for a given block 56 * @param {string} hash - txid of the block 57 * @returns {Promise} 58 */ 59 async onBlockHash(hash) { 60 try { 61 const header = await this.rpcClient.getblockheader({ blockhash: hash }) 62 63 this.height = header.height 64 this.hash = hash 65 this.time = header.mediantime 66 this.diff = header.difficulty 67 68 Logger.info(`Bitcoind RPC : Block ${this.height} ${this.hash}`) 69 } catch (error) { 70 Logger.error(error, 'Bitcoind RPC : LatestBlock.onBlockHash()') 71 await util.delay(2000) 72 return this.onBlockHash(hash) 73 } 74 } 75 76 } 77 78 export default new LatestBlock()