Source: utils/checkWeb3.js

/**
 * @file Manages helper functions to check web3 connection
 * @author Ivan Violentov <ivan.violentov@jibrel.network>
 */

import Web3 from '@jibrelnetwork/web3'
import Promise from 'bluebird'

import config from '../config'

/**
 * @function checkWeb3
 *
 * @description Checks web3 connection status. Sets web3 globally if it does not exist
 *
 * @param {object} payload - Payload object
 * @param {object} payload.props - API function properties
 * @param {string} payload.props.rpcaddr - RPC address of Ethereum node to connect on
 * @param {number} payload.props.rpcport - RPC port of Ethereum node to connect on
 * @param {boolean} [payload.props.ssl] - Defines using of ssl for connection or not
 *
 * @returns {object} The same (as input) payload object
 */
export default function checkWeb3(payload) {
  return Promise
    .bind(this, payload.props)
    .then(getRPCEndpoint)
    .then(checkIsWeb3Inited)
    .return(payload)
}

function getRPCEndpoint({ rpcaddr, rpcport, ssl }) {
  return `http${ssl ? 's' : ''}://${rpcaddr}:${rpcport}`
}

function checkIsWeb3Inited(rpcEndpoint) {
  const globalScope = getGlobalScope()

  // check if web3 object already injected in global scope
  if (globalScope.jWeb3Endpoint === rpcEndpoint) {
    return checkWeb3Connection(globalScope.jWeb3)
  }

  return setGlobalWeb3(rpcEndpoint)
}

function setGlobalWeb3(rpcEndpoint) {
  const jWeb3 = new Web3(new Web3.providers.HttpProvider(rpcEndpoint))

  return Promise
    .bind(this, jWeb3)
    .then(checkWeb3Connection)
    .then(() => initWeb3(jWeb3, rpcEndpoint))
}

function initWeb3(jWeb3, rpcEndpoint) {
  const globalScope = getGlobalScope()

  globalScope.jWeb3 = jWeb3
  globalScope.jWeb3Endpoint = rpcEndpoint
}

function checkWeb3Connection(jWeb3) {
  const err = 'Web3 is not connected to the node'

  return new Promise((resolve, reject) => {
    if (!(jWeb3/* && jWeb3.isConnected() */)) {
      return reject(new Error(err))
    }

    return resolve(jWeb3)
  })
    .timeout(config.promiseConnectionTimeout, new Error(err))
    .then(checkSupportedMethods)
}

function checkSupportedMethods(jWeb3) {
  const web3eth = jWeb3.eth

  if (!web3eth) {
    throw (new Error('web3.eth is not supported'))
  }

  const supportedMethods = [
    'getBalance',
    'getBlock',
    'getCode',
    'contract',
    'filter',
    'getTransaction',
    'getTransactionCount',
    'getTransactionReceipt',
    'getGasPrice',
    'estimateGas',
    'sendRawTransaction',
  ]

  supportedMethods.forEach((method) => {
    if (!(method in web3eth)) {
      throw (new Error(`web3.eth.${method} is not supported`))
    }
  })
}

function getGlobalScope() {
  return (typeof window !== 'undefined') ? window : global
}