Getting started

About

MarketSDK is the official software development kit for interacting with the Market protocol, it allows any DAO, Community or Individual to permissionlessly create a market pool and integrate it in their dApp UI.

This ensures further decentralisation for the Protocol and the Pool while increasing the user experience for your community as they can interact with the pool from your dApp seamlessly with similar design systems!

Installation

npm i --save market-sdk

Example usage

import Web3 from "web3";
import { MarketSDK, Comptroller, CToken } from "market-sdk";

const web3 = new Web3("https://polygon-rpc.com");
const sdk = await MarketSDK.init(web3);

const comptrollerAddress = "SET_ADDRESS_HERE";
const comptroller = new Comptroller(sdk, comptrollerAddress);

/// gets all CToken addresses and makes a CToken instance
const cTokens = (await comptroller.getAllMarkets()).map(
  (address) => new CToken(sdk, address)
);

let i = 1;
for (const cToken of cTokens) {
  console.log(`cToken[${i}] address = `, cToken.address); /// 0x5a
  console.log(`cToken[${i}] name = `, await cToken.name()); /// Market Pool X USDC
  console.log(`cToken[${i}] symbol = `, await cToken.symbol()); /// mPXUSDC
  console.log(
    `cToken[${i}] LTV = `,
    (await comptroller.markets(cToken.address)).collateralFactorMantissa /// 5e17
  );
  console.log(
    `cToken[${i}] reserve factor = `,
    await cToken.reserveFactorMantissa() /// 5e16
  );

  ++i;
}

Fetch pool by ID

import Web3 from "web3";
import { MarketSDK, MarketOptions } from "market-sdk";

const options: MarketOptions = {
  poolDirectory: "SET_DIRECTORY_ADDRESS",
  marketLens: "SET_MARKET_LENS_ADDRESS"
};
const web3 = new Web3("SET_RPC_OR_PROVIDER");
const sdk = await MarketSDK.init(web3, options);
const directory = new PoolDirectory(sdk, sdk.options!.poolDirectory);

const [pool0, pool1] = await Promise.all([
  directory.pools(0),
  directory.pools(1)
]);

console.log("Pool#0 Name:", pool0.name);
console.log("Pool#0 Comptroller Address:", pool0.comptroller.address);
console.log("Pool#0 Creator Address:", pool0.creator);
console.log()

console.log("Pool#1 Name:", pool1.name);
console.log("Pool#1 Comptroller Address:", pool1.comptroller.address);
console.log("Pool#1 Creator Address:", pool1.creator);

Fetch TVL for All Pools

import Web3 from "web3";
import { MarketSDK, MarketOptions } from "market-sdk";

async function getTVL(sdk: MarketSDK){
  const lens = new MarketLens(sdk, sdk.options!.marketLens);

  const { totalSupply: totalSuppliedETH } =
    await lens.getPublicPoolsWithData(sdk.options!.poolDirectory, {
      gas: 1e18,
    });

  const tvlETH = 
    totalSuppliedETH
      .reduce((a: BN, b: BN) => a.add(b), Web3.utils.toBN(0))

  const ethPrice: number = await getEthUsdPrice();
  const tvl = (parseInt(tvlETH.toString()) / 1e18) * ethPrice;

  return tvl;
}

const options: MarketOptions = {
  poolDirectory: "SET_DIRECTORY_ADDRESS",
  marketLens: "SET_MARKET_LENS_ADDRESS"
};

const web3 = new Web3("SET_RPC_OR_PROVIDER");
const sdk = await MarketSDK.init(web3, options);
const tvl = await getTVL(sdk);

const chainId = await sdk.web3.eth.getChainId();
console.log(`TVL on network ${chainId}`, tvl);

List assets in a pool

import Web3 from "web3";
import { MarketSDK, MarketOptions } from "market-sdk";

async function getPoolAssets(poolId: string | number, sdk: MarketSDK){
  const lens = new MarketLens(sdk, sdk.options!.marketLens);
  const directory = new PoolDirectoryV2(sdk, sdk.options!.poolDirectory);

  const pool = await directory.pools(poolId);
  const assets = await lens.getPoolAssetsWithData(pool.comptroller.address);

  return assets;
}

const options: MarketOptions = {
  poolDirectory: "SET_DIRECTORY_ADDRESS",
  marketLens: "SET_MARKET_LENS_ADDRESS"
};

const web3 = new Web3("SET_RPC_OR_PROVIDER");
const sdk = await MarketSDK.init(web3, options);
const assets = await getTVL(0, sdk);

console.log("Assets in pool#0:\n", assets);

List all borrowers and suppliers in a pool

async function getAllPoolUsers(poolId: string | number, sdk: MarketSDK){
  const lens = new MarketLens(sdk, sdk.options!.marketLens);
  const directory = new PoolDirectoryV2(sdk, sdk.options!.poolDirectory);

  const pool = await directory.pools(poolId);

  const [users, closeFactor, liquidationIncentive] = await lens.getPoolUsersWithData(
    pool.comptroller.address,
    sdk.web3.utils.toBN(1e18)
  );
  return users;
}

async function getAllBorrowers(poolId: string | number, sdk: MarketSDK){
  const users = await getAllPoolUsers(poolId, sdk);
  const borrowers = users.filter((user) => user.totalBorrow.gt(0));

  return borrowers;
}

async function getAllSuppliers(poolId: string | number, sdk: MarketSDK){
  const users = await getAllPoolUsers(poolId, sdk);
  const suppliers = users.filter((user) => user.assets.some(asset => asset.supplyBalance.gt(0)));

  return suppliers;
}

Update a cToken

import { MarketSDK, CTokenV2 } from "market-sdk";

async function setCTokenCollateralFactor(
  newCollateralFactor: number | string | BN,
  cToken: CTokenV2,
  account: string
){
  const comptroller = await cToken.comptroller();
  const admin = await comptroller.admin();
  const isMarketAdmin = await comptroller.sdk.isMarketAdmin(admin);
  
  if (marketAdmin) {
    await marketAdmin.setCollateralFactor(cToken!.address, newCollateralFactor, { from: account });
  } else {
    await comptroller._setCollateralFactor(cToken!.address, newCollateralFactor, { from: account });
  }
}

const account = "SET_SIGNER_ADDRESS";
const cTokenAddress = "SET_CTOKEN_ADDRESS";
const cToken = new CTokenV2(sdk, cTokenAddress);

await setCTokenCollateralFactor(sdk.web3.utils.toBN(1e18), cToken, account);

Update a comptroller

import { MarketSDK, ComptrollerV2 } from "market-sdk";

async function setComptrollerLiquidationIncentive(
  newLiquidationIncentive: number | string | BN,
  comptroller: ComptrollerV2, account: string
){
  const admin = await comptroller.admin();
  const isMarketAdmin = await comptroller.sdk.isMarketAdmin(admin);
  
  if (marketAdmin) {
    await marketAdmin.setLiquidationIncentive(newLiquidationIncentive, { from: account });
  } else {
    await comptroller._setLiquidationIncentive(newLiquidationIncentive, { from: account });
  }
}

const account = "0x...";
const comptrollerAddress = "SET_COMPTROLLER_ADDRESS";
const comptroller = new ComptrollerV2(sdk, comptrollerAddress);

await setComptrollerLiquidationIncentive(sdk.web3.utils.toBN(1e18), comptroller, 0x00);

Deploy cToken into a comptroller

import { MarketSDK, ComptrollerV2, MarketAdmin } from "market-sdk";

const address = "SET_SIGNER_ADDRESS";

const unserlyingTokenData = {
  symbol: "SET_TOKEN_SYMBOL",
  name: "SET_TOKEN_NAME",
  address: "SET_TOKEN_ADDRESS"
};
const interestRateModel = "SET_INTEREST_RATE_MODEL_ADDRESS";
const cErc20DelegateImpl = "SET_CERC20_DELEGATE_IMPL";

const reserveFactor = sdk.web3.utils.toBN("SET_INITIAL_RESERVE_FACTOR"); // scaled by 1e18
const collateralFactor = sdk.web3.utils.toBN("SET_INITIAL_COLLATERAL_FACTOR");  // scaled by 1e18
const adminFee = sdk.web3.utils.toBN("SET_INITIAL_ADMIN_FEE");  // scaled by 1e18

// Ex: BOGGED USDC
const name = poolName + " " + unserlyingTokenData.name;
// Ex: fUSDC-456
const symbol = symbol: "f" + unserlyingTokenData.symbol + "-" + poolID;

const comptrollerAddress = "SET_COMPTROLLER_ADDRESS";
const comptroller = new ComptrollerV2(sdk, comptrollerAddress);

const marketAdminAddress = await comptroller.admin();
const marketAdmin = new MarketAdmin(sdk, marketAdminAddress);

await marketAdmin!.deployMarket([
  unserlyingTokenData.address,
  interestRateModel,
  name,
  symbol,
  cErc20DelegateImpl,
  sdk.web3.eth.abi.encodeParameters(
    ["address", "address", "string memory", "string memory", "uint256", "uint256"],
    [comptroller.address, interestRateModel, name, symbol, collateralFactor, reserveFactor]
  ),
  reserveFactor,
  adminFee,
  collateralFactor
], { from: address });

Deploy a new pool

const directoryAddress = "SET_DIRECTORY_ADDRESS";
const poolDirectory = new PoolDirectoryV2(sdk, directoryAddress);

const address = "SET_SIGNER_ADDRESS";
// The name of the pool.
const name = "SET_POOL_NAME";
// The Comptroller implementation contract address.
const comptrollerImpl = "SET_COMPTROLLER_IMPL_ADDRESS";
// Boolean indicating if the pool's supplier/borrower whitelist is to be enforced.
const enforceWhitelist = true;

const closeFactor = sdk.web3.utils.toBN(0.5 * 1e18);
const liquidationIncentive = sdk.web3.utils.toBN(1.08 * 1e18);

const id = await poolDirectory.deployPool(
  name,
  comptrollerImpl,
  enforceWhitelist,
  closeFactor,
  liquidationIncentive,
  { from: address }
);

console.log("Deployed pool's ID:", id);

Last updated