{"size": 2807, "ext": "js", "max_stars_repo_path": "src/api/index.js", "max_stars_repo_name": "tthsympa/seeblock", "max_stars_repo_stars_event_min_datetime": "2018-02-15T02:00:53.000Z", "max_stars_repo_stars_event_max_datetime": "2018-02-21T14:02:47.000Z", "max_issues_repo_path": "src/api/index.js", "max_issues_repo_name": "TTHledieu/seeblock", "max_issues_repo_issues_event_min_datetime": "2020-06-28T13:23:02.000Z", "max_issues_repo_issues_event_max_datetime": "2022-02-17T14:47:33.000Z", "max_forks_repo_path": "src/api/index.js", "max_forks_repo_name": "tthsympa/seeblock", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": 2, "max_issues_count": 6, "max_forks_count": null, "avg_line_length": 24.8407079646, "max_line_length": 69, "alphanum_fraction": 0.5888849305}
// @flow

import Web3 from 'web3'
import { TYPE, STARTBLOCKOFFSET, WEI } from 'config/constants'
import type { Input, AddressDatas } from 'reduxTypes/input'
import { List } from 'immutable'

const getWeb3Object = () => new Web3(Web3.givenProvider)

const getBlockDatas = (blockNumber: number): Promise<Web3.Block> => {
  const web3: Web3 = getWeb3Object()
  return web3.eth.getBlock(blockNumber, true).then((block) => block)
}
const getTxData = (tx): Object => {
  return {
    id: tx.hash,
    value: tx.value / WEI,
    valueInWei: tx.value,
    status: tx.blockHash ? 'success' : 'pending',
    blockHash: tx.blockHash,
    gas: {
      amount: tx.gas,
      price: tx.gasPrice,
    },
  }
}

const getTxByBlock = async (blockNumber: number) => {
  const txs: AddressDatas = {
    address: '',
    block: blockNumber,
    count: 0,
    from: List(),
    to: List(),
  }
  const web3: Web3 = getWeb3Object()

  // eslint-disable-next-line no-await-in-loop
  const block = await getBlockDatas(blockNumber)
  if (block && block.transactions) {
    block.transactions.forEach((tx) => {
      txs.from = txs.from.push({
        ...getTxData(tx),
        address: tx.from,
        bTimestamp: block.timestamp,
        from: true,
      })
    })
  }
  txs.count = txs.from.size + txs.to.size
  return txs
}

const getTxByAddress = async (address: string) => {
  const txs: AddressDatas = {
    address,
    block: -1,
    count: 0,
    from: List(),
    to: List(),
  }
  const web3: Web3 = getWeb3Object()
  const lastBlock: number = await web3.eth
    .getBlockNumber()
    .then((number) => number)
  const startBlock: number = lastBlock - STARTBLOCKOFFSET
  for (let i: number = startBlock; i <= lastBlock; i += 1) {
    // eslint-disable-next-line no-await-in-loop
    const block = await getBlockDatas(i)
    if (block && block.transactions) {
      block.transactions.forEach((tx) => {
        if (tx.to === address) {
          txs.from = txs.from.push({
            ...getTxData(tx),
            address: tx.from,
            bTimestamp: block.timestamp,
            from: true,
          })
        } else if (tx.from === address) {
          txs.to = txs.to.push({
            ...getTxData(tx),
            address: tx.to,
            bTimestamp: block.timestamp,
            from: false,
          })
        }
      })
    }
  }
  txs.count = txs.from.size + txs.to.size
  return txs
}

export const fetchElemFromBC = ({ elem, type }: Input) => {
  switch (type) {
    case TYPE.BLOCK:
      return getTxByBlock(parseInt(elem, 10))
    case TYPE.ADDRESS:
      return getTxByAddress(elem)
    default:
      return null
  }
}

export const createWeb3Object = () => {
  const web3 = getWeb3Object()
  try {
    return web3.eth.net.getId().then(() => web3)
  } catch (error) {
    return null
  }
}
