text: const BigNumber = require('bignumber.js');
  const { avaxWeb3: web3, web3Factory } = require('../../../utils/web3');
  
  const MasterChef = require('../../../abis/avax/LydChef.json');
  const { fetchPrice } = require('../../../utils/fetchPrice');
  const pools = require('../../../data/avax/lydLpPools.json');
  const { compound } = require('../../../utils/compound');
  const { AVAX_CHAIN_ID, BASE_HPY } = require('../../../constants');
  const { getBlockNumber } = require('../../../utils/getBlockNumber');
  const { getTradingFeeApr } = require('../../../utils/getTradingFeeApr');
  const { getFarmWithTradingFeesApy } = require('../../../utils/getFarmWithTradingFeesApy');
  const { lydiaClient } = require('../../../apollo/client');
  
  const ERC20 = require('../../../abis/ERC20.json');
  const { lpTokenPrice } = require('../../../utils/lpTokens');
  
  const masterchef = '0xFb26525B14048B7BB1F3794F6129176195Db7766';
  const oracleId = 'LYD';
  const oracle = 'tokens';
  const DECIMALS = '1e18';
  
  const liquidityProviderFee = 0.0017;
  const leechPerformanceFee = 0.045;
  const shareAfterLeechPerformanceFee = 1 - leechPerformanceFee;
  
  const getLydLpApys = async () => {
    let apys = {};
    let apyBreakdowns = {};
  
    const pairAddresses = pools.map(pool => pool.address);
    const tradingAprs = await getTradingFeeApr(lydiaClient, pairAddresses, liquidityProviderFee);
  
    const allPools = [...pools];
  
    let promises = [];
    allPools.forEach(pool => promises.push(getPoolApy(masterchef, pool)));
    const values = await Promise.all(promises);
  
    for (let item of values) {
      const simpleApr = item.simpleApr;
      const vaultApr = simpleApr.times(shareAfterLeechPerformanceFee);
      const vaultApy = compound(simpleApr, BASE_HPY, 1, shareAfterLeechPerformanceFee);
      const tradingApr = tradingAprs[item.address.toLowerCase()] || new BigNumber(0);
      const totalApy = getFarmWithTradingFeesApy(simpleApr, tradingApr, BASE_HPY, 1, 0.955);
      const legacyApyValue = { [item.name]: totalApy };
      // Add token to APYs object
      apys = { ...apys, ...legacyApyValue };
  
      // Create reference for breakdown /apy
      const componentValues = {
        [item.name]: {
          vaultApr: vaultApr.toNumber(),
          compoundingsPerYear: BASE_HPY,
          leechPerformanceFee: leechPerformanceFee,
          vaultApy: vaultApy,
          lpFee: liquidityProviderFee,
          tradingApr: tradingApr.toNumber(),
          totalApy: totalApy,
        },
      };
      // Add token to APYs object
      apyBreakdowns = { ...apyBreakdowns, ...componentValues };
    }
  
    // Return both objects for later parsing
    return {
      apys,
      apyBreakdowns,
    };
  };
  
  const getPoolApy = async (masterchef, pool) => {
    const [yearlyRewardsInUsd, totalStakedInUsd] = await Promise.all([
      getYearlyRewardsInUsd(masterchef, pool),
      getTotalLpStakedInUsd(masterchef, pool, pool.chainId),
    ]);
    const simpleApr = yearlyRewardsInUsd.dividedBy(totalStakedInUsd);
    const address = pool.address;
    const name = pool.name;
    return { name, address, simpleApr };
  };
  
  const getYearlyRewardsInUsd = async (masterchef, pool) => {
    const blockNum = await getBlockNumber(AVAX_CHAIN_ID);
    const masterchefContract = new web3.eth.Contract(MasterChef, masterchef);
  
    const multiplier = new BigNumber(
      await masterchefContract.methods.getMultiplier(blockNum - 1, blockNum).call()
    );
    const rewards = new BigNumber(await masterchefContract.methods.lydPerSec().call());
  
    let { allocPoint } = await masterchefContract.methods.poolInfo(pool.poolId).call();
    allocPoint = new BigNumber(allocPoint);
  
    const totalAllocPoint = new BigNumber(await masterchefContract.methods.totalAllocPoint().call());
    const poolBlockRewards = rewards.times(multiplier).times(allocPoint).dividedBy(totalAllocPoint);
  
    const secondsPerBlock = 1;
    const secondsPerYear = 31536000;
    const yearlyRewards = poolBlockRewards.dividedBy(secondsPerBlock).times(secondsPerYear);
  
    const tokenPrice = await fetchPrice({ oracle, id: oracleId });
    const yearlyRewardsInUsd = yearlyRewards.times(tokenPrice).dividedBy(DECIMALS);
  
    return yearlyRewardsInUsd;
  };
  
  const getTotalLpStakedInUsd = async (targetAddr, pool) => {
    const web3 = web3Factory(AVAX_CHAIN_ID);
  
    const tokenPairContract = new web3.eth.Contract(ERC20, pool.address);
    const totalStaked = new BigNumber(await tokenPairContract.methods.balanceOf(targetAddr).call());
    const tokenPrice = await lpTokenPrice(pool);
    const totalStakedInUsd = totalStaked.times(tokenPrice).dividedBy('1e18');
    return totalStakedInUsd;
  };
  
  module.exports = {
    getLydLpApys
  };
  