Skip to content

Instantly share code, notes, and snippets.

@gregorynicholas
Forked from ajb413/Get_COMP_APY.md
Created November 8, 2020 18:14
Finding the COMP APY

Using the Compound API

UPDATE

The Compound cToken API now returns the values for you. See comp_borrow_apy and comp_supply_apy when requesting https://api.compound.finance/api/v2/ctoken

OLD METHOD:

  1. Pick a supported cToken and its underlying asset
  2. Query https://api.compound.finance/api/v2/governance/comp
  3. Take the value for supplier_daily_comp or borrower_daily_comp
  4. Query https://api.compound.finance/api/v2/ctoken
  5. Take the value for total_supply or exchange_rate and total_borrows
  6. Query https://prices.compound.finance/
  7. Take COMP price

In JavaScript

borrowCompApy = 100 * (Math.pow((1 + (comp_price * borrower_daily_comp / total_borrows)), 365) - 1)

supplyCompApy = 100 * (Math.pow((1 + (comp_price * supplier_daily_comp / (total_supply * exchange_rate))), 365) - 1)

From Blockchain With JSON RPC and JavaScript

// To use this script, copy it to a file on your machine. (getCompApy.js)
// Insert your Infura project ID on line 12 to access the blockchain
// Install Node.js
// Navigate to the folder of getCompApy.js using the command line

// npm init -y
// npm install @compound-finance/compound-js
// node getCompApy.js

const Compound = require('@compound-finance/compound-js');

const provider = 'https://mainnet.infura.io/v3/' + process.env.infuraApiKey;

const cTokenToGetCompApy = Compound.cUSDC; // Pick an asset

const underlyingDecimals = Compound.decimals[cTokenToGetCompApy.slice(1, 10)];
const cTokenDecimals = 8; // always 8
const comptroller = Compound.util.getAddress(Compound.Comptroller);
const opf = Compound.util.getAddress(Compound.PriceFeed);
const cTokenAddr = Compound.util.getAddress(cTokenToGetCompApy);
const apxBlockSpeedInSeconds = 13.15;

(async function() {

  let compSpeed = await Compound.eth.read(
    comptroller,
    'function compSpeeds(address cToken) public returns (uint)',
    [ cTokenAddr ],
    { provider }
  );

  let compPrice = await Compound.eth.read(
    opf,
    'function price(string memory symbol) external view returns (uint)',
    [ Compound.COMP ],
    { provider }
  );

  let totalBorrows = await Compound.eth.read(
    cTokenAddr,
    'function totalBorrowsCurrent() returns (uint)',
    [],
    { provider }
  );

  let totalSupply = await Compound.eth.read(
    cTokenAddr,
    'function totalSupply() returns (uint)',
    [],
    { provider }
  );

  let exchangeRate = await Compound.eth.read(
    cTokenAddr,
    'function exchangeRateCurrent() returns (uint)',
    [],
    { provider }
  );

  // Total supply needs to be converted from cTokens
  const mantissa = 18 + parseInt(underlyingDecimals) - cTokenDecimals;
  exchangeRate = +exchangeRate.toString() / Math.pow(10, mantissa);

  compSpeed = compSpeed / 1e18; // COMP has 18 decimal places
  compPrice = compPrice / 1e6;  // price feed is USD price with 6 decimal places
  totalBorrows = +totalBorrows.toString() / (Math.pow(10, underlyingDecimals));
  totalSupply = (+totalSupply.toString() * exchangeRate) / (Math.pow(10, underlyingDecimals));

  // console.log('compSpeed:', compSpeed);
  // console.log('compPrice:', compPrice);
  // console.log('totalBorrows:', totalBorrows);
  // console.log('totalSupply:', totalSupply);
  // console.log('exchangeRate:', exchangeRate);

  const compPerDay = compSpeed * parseInt((60 * 60 * 24) / apxBlockSpeedInSeconds);

  const compBorrowApy = 100 * (Math.pow((1 + (compPrice * compPerDay / totalBorrows)), 365) - 1);
  const compSupplyApy = 100 * (Math.pow((1 + (compPrice * compPerDay / totalSupply)), 365) - 1);

  console.log('COMP Borrow APY %:', compBorrowApy);
  console.log('COMP Supply APY %:', compSupplyApy);

})().catch(console.error);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment