Skip to content

Commit

Permalink
feat: add apr boost
Browse files Browse the repository at this point in the history
  • Loading branch information
quangdz1704 committed Feb 3, 2024
1 parent 8fcee6b commit f37f859
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 18 deletions.
7 changes: 5 additions & 2 deletions packages/oraidex-server/src/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ import {
PoolAmountHistory,
calculatePriceByPool,
PairInfoData,
findPairAddress
findPairAddress,
getAvgPoolLiquidities
} from "@oraichain/oraidex-sync";
import bech32 from "bech32";
import "dotenv/config";
Expand Down Expand Up @@ -174,6 +175,7 @@ export const getAllPoolsInfo = async () => {
const pools = await getPoolsFromDuckDb();
const allPoolApr = await getPoolAprsFromDuckDb();
const allLiquidities = await getPoolLiquidities(pools);
const avgLiquidities = await getAvgPoolLiquidities(pools);
const allPoolAmounts = await getPoolAmounts(pools);

const allPoolsInfo: PairInfoDataResponse[] = pools.map((pool, index) => {
Expand Down Expand Up @@ -203,14 +205,15 @@ export const getAllPoolsInfo = async () => {
fee7Days: poolFee.fee.toString(),
apr: poolApr.apr,
totalLiquidity: allLiquidities[index],
avgLiquidities: avgLiquidities[pool.liquidityAddr],
rewardPerSec: poolApr.rewardPerSec,
offerPoolAmount: allPoolAmounts[index].offerPoolAmount,
askPoolAmount: allPoolAmounts[index].askPoolAmount,
totalSupply: poolApr.totalSupply
} as PairInfoDataResponse;
});

return allPoolsInfo;
return allPoolsInfo.filter(Boolean);
} catch (error) {
console.log({ errorGetAllPoolsInfo: error });
}
Expand Down
2 changes: 2 additions & 0 deletions packages/oraidex-sync/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ export const ORAIXOCH_INFO = {
};
export const OCH_PRICE = 0.4; // usdt

export const DAYS_PER_WEEK = 7;
export const DAYS_PER_YEAR = 365;
export const SEC_PER_YEAR = 60 * 60 * 24 * 365;
export const network = {
factory: FACTORY_CONTRACT,
Expand Down
13 changes: 13 additions & 0 deletions packages/oraidex-sync/src/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,19 @@ export class DuckDb {
return result[0] as PoolAmountHistory;
}

async getLpAmountByTime(pairAddr: string, timestamp: number) {
const result = await this.conn.all(
`
SELECT * FROM lp_amount_history
WHERE pairAddr = ? AND timestamp >= ?
ORDER BY timestamp ASC
`,
pairAddr,
timestamp
);
return result as PoolAmountHistory[];
}

async insertPoolAmountHistory(ops: PoolAmountHistory[]) {
await this.insertBulkData(ops, "lp_amount_history");
}
Expand Down
23 changes: 23 additions & 0 deletions packages/oraidex-sync/src/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,29 @@ async function getAllFees(): Promise<PoolFee[]> {
}
// ==== end get fee pair ====>

// get avg liquidity of pair from assetInfos by timestamp
export const getAvgPairLiquidity = async (poolInfo: PairInfoData): Promise<number> => {
const tf = 7 * 24 * 60 * 60; // second of 7 days
const oneWeekBeforeNow = getSpecificDateBeforeNow(new Date(), tf).getTime() / 1000;

const duckDb = DuckDb.instances;
const poolAmount = await duckDb.getLpAmountByTime(poolInfo.pairAddr, oneWeekBeforeNow);
const numberOfRecords = poolAmount?.length;

if (!poolAmount || !numberOfRecords) return 0;
const totalLiquidity7Days = poolAmount.reduce((acc, cur) => {
acc = acc + Number(cur.offerPoolAmount) * Math.pow(10, -6);
return acc;
}, 0);

const avgLiquidity = totalLiquidity7Days / numberOfRecords;

const baseAssetInfo = JSON.parse(poolInfo.firstAssetInfo);
const priceBaseAssetInUsdt = await getPriceAssetByUsdt(baseAssetInfo);

return priceBaseAssetInUsdt * avgLiquidity * 2;
};

export function getDate24hBeforeNow(time: Date) {
const twentyFourHoursInMilliseconds = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
const date24hBeforeNow = new Date(time.getTime() - twentyFourHoursInMilliseconds);
Expand Down
10 changes: 8 additions & 2 deletions packages/oraidex-sync/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { SyncData, Txs, WriteData } from "@oraichain/cosmos-rpc-sync";
import "dotenv/config";
import { DuckDb } from "./db";
import { concatAprHistoryToUniqueKey, concatLpHistoryToUniqueKey, getSymbolFromAsset } from "./helper";
import { concatAprHistoryToUniqueKey, concatLpHistoryToUniqueKey, getAllFees, getSymbolFromAsset } from "./helper";
import { parseAssetInfo, parsePoolAmount } from "./parse";
import {
calculateBoostApr,
fetchAprResult,
getAllPairInfos,
getAvgPoolLiquidities,
getPairByAssetInfos,
getPoolInfos,
getPoolLiquidities,
Expand Down Expand Up @@ -135,11 +137,15 @@ class OraiDexSync {
try {
const pools = await this.duckDb.getPools();
const allLiquidities = await getPoolLiquidities(pools);
const avgLiquidities = await getAvgPoolLiquidities(pools);
const allFee7Days = await getAllFees();
const { allAprs, allTotalSupplies, allBondAmounts, allRewardPerSec } = await fetchAprResult(
pools,
allLiquidities
);

const boostAPR = calculateBoostApr(avgLiquidities, allFee7Days);

const poolAprs = allAprs.map((apr, index) => {
return {
uniqueKey: concatAprHistoryToUniqueKey({
Expand All @@ -155,7 +161,7 @@ class OraiDexSync {
totalSupply: allTotalSupplies[index],
totalBondAmount: allBondAmounts[index],
rewardPerSec: JSON.stringify(allRewardPerSec[index]),
apr,
apr: apr + boostAPR[pools[index].liquidityAddr],
timestamp: Date.now()
} as PoolApr;
});
Expand Down
10 changes: 5 additions & 5 deletions packages/oraidex-sync/src/pairs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,6 @@ export const pairs: PairMapping[] = [
symbols: ["ORAIX", "ORAI"],
factoryV1: true
},
{
asset_infos: [{ token: { contract_addr: scOraiCw20Address } }, { native_token: { denom: ORAI } }],
lp_token: pairLpTokens.SCORAI_ORAI,
symbols: ["scORAI", "ORAI"]
},
{
asset_infos: [{ native_token: { denom: ORAI } }, { native_token: { denom: atomIbcDenom } }],
lp_token: pairLpTokens.ATOM_ORAI,
Expand Down Expand Up @@ -74,6 +69,11 @@ export const pairs: PairMapping[] = [
symbols: ["MILKY", "USDT"],
factoryV1: true
},
{
asset_infos: [{ token: { contract_addr: scOraiCw20Address } }, { native_token: { denom: ORAI } }],
lp_token: pairLpTokens.SCORAI_ORAI,
symbols: ["scORAI", "ORAI"]
},
{
asset_infos: [{ native_token: { denom: ORAI } }, { token: { contract_addr: usdcCw20Address } }],
lp_token: pairLpTokens.USDC_ORAI,
Expand Down
72 changes: 63 additions & 9 deletions packages/oraidex-sync/src/pool-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,19 @@ import {
} from "@oraichain/oraidex-contracts-sdk";
import { PoolResponse } from "@oraichain/oraidex-contracts-sdk/build/OraiswapPair.types";
import { isEqual } from "lodash";
import { OCH_PRICE, ORAI, ORAIXOCH_INFO, SEC_PER_YEAR, atomic, network, oraiInfo, usdtInfo } from "./constants";
import {
DAYS_PER_WEEK,
DAYS_PER_YEAR,
OCH_PRICE,
ORAI,
ORAIXOCH_INFO,
SEC_PER_YEAR,
atomic,
network,
oraiInfo,
truncDecimals,
usdtInfo
} from "./constants";
import {
calculatePriceByPool,
getCosmwasmClient,
Expand All @@ -19,7 +31,10 @@ import {
concatAprHistoryToUniqueKey,
concatLpHistoryToUniqueKey,
getPairLiquidity,
recalculateTotalShare
recalculateTotalShare,
PoolFee,
getAvgPairLiquidity,
getAllFees
} from "./helper";
import { DuckDb } from "./db";
import { pairs } from "./pairs";
Expand Down Expand Up @@ -262,6 +277,28 @@ export const calculateAprResult = async (
return aprResult;
};

export const calculateBoostApr = (
avgLiquidities: Record<string, number>,
allFee7Days: PoolFee[]
): Record<string, number> => {
const aprResult = {};

for (const _pair of pairs) {
const lpTokenAddress = _pair.lp_token;
const liquidityAmount = avgLiquidities[lpTokenAddress];

const poolFee = allFee7Days.find((item) => {
return JSON.stringify(item.assetInfos) === JSON.stringify(_pair.asset_infos);
});

const yearlyFees = (DAYS_PER_YEAR * Number(poolFee.fee) * Math.pow(10, -truncDecimals)) / DAYS_PER_WEEK;

aprResult[lpTokenAddress] = !liquidityAmount ? 0 : (100 * yearlyFees) / liquidityAmount || 0;
}

return aprResult;
};

export const fetchAprResult = async (pairInfos: PairInfoData[], allLiquidities: number[]) => {
const liquidityAddrs = pairInfos.map((pair) => pair.liquidityAddr);
try {
Expand Down Expand Up @@ -302,6 +339,15 @@ export const getPoolLiquidities = async (pools: PairInfoData[]): Promise<number[
return allLiquidities;
};

export const getAvgPoolLiquidities = async (pools: PairInfoData[]): Promise<Record<string, number>> => {
const allLiquidities: Record<string, number> = {};
for (const pool of pools) {
const liquidity = await getAvgPairLiquidity(pool);
allLiquidities[pool.liquidityAddr] = liquidity;
}
return allLiquidities;
};

export const getPoolAmounts = async (pools: PairInfoData[]): Promise<PoolAmountHistory[]> => {
const duckDb = DuckDb.instances;
const allPoolAmounts: PoolAmountHistory[] = [];
Expand Down Expand Up @@ -341,28 +387,36 @@ export const triggerCalculateApr = async (assetInfos: [AssetInfo, AssetInfo][],

const pools = await getAllPoolByAssetInfos(assetInfos);
const allLiquidities = await getPoolLiquidities(pools);
const poolAprInfos = [];
const allFee7Days = await getAllFees();
const avgLiquidities = await getAvgPoolLiquidities(pools);
const poolAprInfos: {
aprInfo: PoolApr;
poolInfo: PairInfoData;
}[] = [];
for (const pool of pools) {
const aprInfo = await duckDb.getLatestPoolApr(pool.pairAddr);
poolAprInfos.push(aprInfo);
poolAprInfos.push({ aprInfo, poolInfo: pool });
}

const allTotalSupplies = poolAprInfos.map((item) => item.totalSupply);
const allBondAmounts = poolAprInfos.map((info) => info.totalBondAmount);
const allRewardPerSecs = poolAprInfos.map((info) => (info.rewardPerSec ? JSON.parse(info.rewardPerSec) : null));
const allTotalSupplies = poolAprInfos.map((item) => item.aprInfo.totalSupply);
const allBondAmounts = poolAprInfos.map((info) => info.aprInfo.totalBondAmount);
const allRewardPerSecs = poolAprInfos.map((info) =>
info.aprInfo.rewardPerSec ? JSON.parse(info.aprInfo.rewardPerSec) : null
);

const APRs = await calculateAprResult(allLiquidities, allTotalSupplies, allBondAmounts, allRewardPerSecs);
const boostAPR = calculateBoostApr(avgLiquidities, allFee7Days);
const newPoolAprs = poolAprInfos.map((poolApr, index) => {
return {
...poolApr,
...poolApr.aprInfo,
height: newOffset,
apr: APRs[index],
uniqueKey: concatAprHistoryToUniqueKey({
timestamp: Date.now(),
supply: allTotalSupplies[index],
bond: allBondAmounts[index],
reward: allRewardPerSecs[index],
apr: APRs[index],
apr: APRs[index] + boostAPR[poolApr.poolInfo.liquidityAddr],
pairAddr: pools[index].pairAddr
}),
timestamp: Date.now() // use timestamp date.now() because we just need to have a order of apr.
Expand Down

0 comments on commit f37f859

Please sign in to comment.