/ lib / bitcoind-rpc / latest-block.js
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()