/ lib / bitcoind-rpc / rpc-client.js
rpc-client.js
 1  /*!
 2   * lib/bitcoind_rpc/rpc-client.js
 3   * Copyright © 2019 – Katana Cryptographic Ltd. All Rights Reserved.
 4   */
 5  
 6  
 7  import { RPCClient } from 'rpc-bitcoin'
 8  
 9  import network from '../bitcoin/network.js'
10  import keysFile from '../../keys/index.js'
11  import util from '../util.js'
12  import Logger from '../logger.js'
13  
14  const keys = keysFile[network.key]
15  
16  /**
17   * @typedef {import('rpc-bitcoin').RPCIniOptions} RPCIniOptions
18   */
19  
20  /**
21   * Wrapper for bitcoind rpc client
22   * @param {RPCIniOptions=} options
23   * @returns {RPCClient}
24   */
25  export const createRpcClient = (options = {}) => {
26      return new RPCClient({
27          url: `http://${keys.bitcoind.rpc.host}`,
28          port: keys.bitcoind.rpc.port,
29          user: keys.bitcoind.rpc.user,
30          pass: keys.bitcoind.rpc.pass,
31          timeout: 2 * 60 * 1000, // 2 minutes
32          ...options
33      })
34  }
35  
36  /**
37   * Check if an error returned by bitcoin-rpc-client
38   * is a connection error.
39   * @param {string} error - error message
40   * @returns {boolean} returns true if message related to a connection error
41   */
42  export const isConnectionError = (error) => {
43      if (typeof error !== 'string')
44          return false
45  
46      const isTimeoutError = (error.includes('connect ETIMEDOUT'))
47      const isConnRejected = (error.includes('Connection Rejected'))
48  
49      return (isTimeoutError || isConnRejected)
50  }
51  
52  /**
53   * Check if the rpc api is ready to process requests
54   * @returns {Promise<void>}
55   */
56  export const waitForBitcoindRpcApi = async () => {
57      let client = createRpcClient()
58  
59      try {
60          const networkInfo = await client.getnetworkinfo()
61  
62          if (networkInfo.subversion.includes('Knots')) {
63              Logger.error(null, `Unsupported Bitcoin client detected: ${networkInfo.subversion}. Exiting...`)
64              process.exit(0)
65          }
66      } catch {
67          client = null
68          Logger.info('Bitcoind RPC : API is still unreachable. New attempt in 20s.')
69          await util.delay(20000)
70          return await waitForBitcoindRpcApi()
71      }
72  }