Source: utils/eventUtils.js

/**
 * @file Manages helper functions to work with smart contract events
 * @author Ivan Violentov <ivan.violentov@jibrel.network>
 */

import EventEmitter from 'events'
import request from 'request-promise'

let ETH_GETLOGS_ID = 100000

/**
 * @callback eventCallback
 *
 * @param {Object} error
 * @param {Object} event
 */

/**
 * @function subscribe
 *
 * @description Subscribes to provided event
 *
 * @param {function} Event - Function for event subscribing
 * @param {object} [options={}] - Event options
 * @param {object} [options.filter] - Filter options by indexed event parameters
 * @param {(number|string)} [options.fromBlock] - The number of the earliest block
 * @param {(number|string)} [options.toBlock] - The number of the latest block
 * @param {(string|string[])} [options.address] - An address(es) to get logs from
 * @param {string[]} [options.topics] - Allows to manually set the topics for the event filter
 * @param {eventCallback} [callback] - Callback which fired for each event or error
 *
 * @returns {object} The event emitter has the following events:<br />
 * - data: Fires on each incoming event with the event object as argument<br />
 * - error: Fires when an error in the subscription occours
 */
export function subscribe(Event, options = {}, callback) {
  const eventEmitter = new EventEmitter()

  /**
   * web3@0.x.x event takes filter and additional options in different params
   * web3@1.x.x event takes all options in one param
   */
  const { filter, ...additionalOptions } = options

  Event(filter, additionalOptions, (err, result) => {
    if (err) {
      /**
       * Error event
       *
       * @event subscribeErrorEvent
       * @type {object}
       */
      eventEmitter.emit('error', err)

      if (callback) {
        callback(err)
      }

      return
    }

    /**
     * Data event
     *
     * @event subscribeDataEvent
     * @type {object}
     */
    eventEmitter.emit('data', result)

    if (callback) {
      callback(null, result)
    }
  })

  return eventEmitter
}

/**
 * @async
 * @function getEvents
 *
 * @description Gets past events
 *
 * @param {object} [options={}] - Event options
 * @param {(number|string)} [options.fromBlock] - The number of the earliest block
 * @param {(number|string)} [options.toBlock] - The number of the latest block
 * @param {(string|string[])} [options.address] - An address(es) to get logs from
 * @param {string[]} [options.topics] - Allows to manually set the topics for the event filter
 *
 * @returns Promise that will be resolved with past events
 */
export function getEvents(options = {}) {
  const id = ETH_GETLOGS_ID

  // eslint-disable-next-line no-plusplus
  ETH_GETLOGS_ID++

  return request({
    method: 'POST',
    uri: jWeb3.currentProvider.host,
    body: {
      id,
      jsonrpc: '2.0',
      method: 'eth_getLogs',
      params: [options],
    },
    json: true,
  }).then(response => response && response.result)
}