User TVL consists of 2 parts:

  1. Lend value: can be calculated with sCoin amount
  2. Borrow value: can be calculated by inspecting the obligation object

User TVL = LendValue + BorrowValue * weight

BorrowValue should have more weight than LendValue as users need to pay interests.

LendValue calculation

  1. Query the sCoin under the address
  2. Multiply the sCoin amounts, sCoin conversionRate, and the coin Price

sCoin Types:

sui: 0xefe8b36d5b2e43728cc323298626b83177803521d195cfb11e15b910e892fddf::reserve::MarketCoin<0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI>

usdc: 0xefe8b36d5b2e43728cc323298626b83177803521d195cfb11e15b910e892fddf::reserve::MarketCoin<0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN>

eth: 0xefe8b36d5b2e43728cc323298626b83177803521d195cfb11e15b910e892fddf::reserve::MarketCoin<0xaf8cd5edc19c4512f4259f0bee101a40d41ebed738ade5874359610ef8eeced5::coin::COIN>

usdt: 0xefe8b36d5b2e43728cc323298626b83177803521d195cfb11e15b910e892fddf::reserve::MarketCoin<0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN>

Get Lending Value Example

  1. Define market data type in Typescript:

    // Type define
    export interface MarketDataInterface {
      collaterals: {
        collateralFactor: {
          value: string;
        };
        liquidationDiscount: {
          value: string;
        };
        liquidationFactor: {
          value: string;
        };
        liquidationPanelty: {
          value: string;
        };
        liquidationReserveFactor: {
          value: string;
        };
        maxCollateralAmount: string;
        totalCollateralAmount: string;
        type: {
          name: string;
        };
      }[];
      pools: {
        baseBorrowRatePerSec: {
          value: string;
        };
        borrowRateOnHighKink: {
          value: string;
        };
        borrowRateOnMidKink: {
          value: string;
        };
        maxBorrowRate: {
          value: string;
        };
        highKink: {
          value: string;
        };
        midKink: {
          value: string;
        };
        interestRate: {
          value: string;
        };
        interestRateScale: string;
        borrowIndex: string;
        lastUpdated: string;
        cash: string;
        debt: string;
        marketCoinSupply: string;
        minBorrowAmount: string;
        reserve: string;
        reserveFactor: {
          value: string;
        };
        borrowWeight: {
          value: string;
        };
        type: {
          name: string;
        };
      }[];
    }
    
  2. Get market data:

    /* Get market data */
    // query module id
    const packageId = '0xbd4f1adbef14cf6ddf31cf637adaa7227050424286d733dc44e6fd3318fc6ba3';
    // protocol market id 
    const marketId = '0x9e28e88c6dee76e21496f20c7678f814834cae4752eb31e40627e95097f4f6e3';
    
    const tx = TransationBlock;
    tx.moveCall(`${packageId}::market_query::market_data`, [
        tx.object(marketId)
    ]);
    const ditxResult = provider.devInspectTransactionBlock({
          transactionBlock: tx,
          sender: '0x',
    });
    const marketData = ditxResult.events[0].parsedJson as MarketDataInterface;
    
  3. Get user sCoin amount:

    const sCoinAmounts = {};
    const userAddress = '0x'
    
    for (const asset of marketData.pools) {
      const coinType = '0x' + asset.type.name;
    	const sCoinType = `${protocolId}::reserve::MarketCoin<${coinType}>`;
    	const balancedata = await rpc.getBalance({ owner: userAddress, coinType: sCoinType }),
    	sCoinAmounts[sCoinType] = balancedata.totalBalance ?? 0;
    }