From f37f8591f622adfe3e10d3bb8233131d2215d8c2 Mon Sep 17 00:00:00 2001 From: quangdz1704 Date: Sat, 3 Feb 2024 13:43:14 +0700 Subject: [PATCH 01/10] feat: add apr boost --- packages/oraidex-server/src/helper.ts | 7 ++- packages/oraidex-sync/src/constants.ts | 2 + packages/oraidex-sync/src/db.ts | 13 +++++ packages/oraidex-sync/src/helper.ts | 23 ++++++++ packages/oraidex-sync/src/index.ts | 10 +++- packages/oraidex-sync/src/pairs.ts | 10 ++-- packages/oraidex-sync/src/pool-helper.ts | 72 +++++++++++++++++++++--- 7 files changed, 119 insertions(+), 18 deletions(-) diff --git a/packages/oraidex-server/src/helper.ts b/packages/oraidex-server/src/helper.ts index 035b0e2c..8d0f2be9 100644 --- a/packages/oraidex-server/src/helper.ts +++ b/packages/oraidex-server/src/helper.ts @@ -24,7 +24,8 @@ import { PoolAmountHistory, calculatePriceByPool, PairInfoData, - findPairAddress + findPairAddress, + getAvgPoolLiquidities } from "@oraichain/oraidex-sync"; import bech32 from "bech32"; import "dotenv/config"; @@ -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) => { @@ -203,6 +205,7 @@ 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, @@ -210,7 +213,7 @@ export const getAllPoolsInfo = async () => { } as PairInfoDataResponse; }); - return allPoolsInfo; + return allPoolsInfo.filter(Boolean); } catch (error) { console.log({ errorGetAllPoolsInfo: error }); } diff --git a/packages/oraidex-sync/src/constants.ts b/packages/oraidex-sync/src/constants.ts index 8d978e66..e61f639b 100644 --- a/packages/oraidex-sync/src/constants.ts +++ b/packages/oraidex-sync/src/constants.ts @@ -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, diff --git a/packages/oraidex-sync/src/db.ts b/packages/oraidex-sync/src/db.ts index 56198cf2..4ee4cf5e 100644 --- a/packages/oraidex-sync/src/db.ts +++ b/packages/oraidex-sync/src/db.ts @@ -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"); } diff --git a/packages/oraidex-sync/src/helper.ts b/packages/oraidex-sync/src/helper.ts index d8f8fb06..f127fde9 100644 --- a/packages/oraidex-sync/src/helper.ts +++ b/packages/oraidex-sync/src/helper.ts @@ -457,6 +457,29 @@ async function getAllFees(): Promise { } // ==== end get fee pair ====> +// get avg liquidity of pair from assetInfos by timestamp +export const getAvgPairLiquidity = async (poolInfo: PairInfoData): Promise => { + 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); diff --git a/packages/oraidex-sync/src/index.ts b/packages/oraidex-sync/src/index.ts index 878711fb..a42730a1 100644 --- a/packages/oraidex-sync/src/index.ts +++ b/packages/oraidex-sync/src/index.ts @@ -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, @@ -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({ @@ -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; }); diff --git a/packages/oraidex-sync/src/pairs.ts b/packages/oraidex-sync/src/pairs.ts index 8447765d..17f96484 100644 --- a/packages/oraidex-sync/src/pairs.ts +++ b/packages/oraidex-sync/src/pairs.ts @@ -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, @@ -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, diff --git a/packages/oraidex-sync/src/pool-helper.ts b/packages/oraidex-sync/src/pool-helper.ts index 70db2040..1618b193 100644 --- a/packages/oraidex-sync/src/pool-helper.ts +++ b/packages/oraidex-sync/src/pool-helper.ts @@ -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, @@ -19,7 +31,10 @@ import { concatAprHistoryToUniqueKey, concatLpHistoryToUniqueKey, getPairLiquidity, - recalculateTotalShare + recalculateTotalShare, + PoolFee, + getAvgPairLiquidity, + getAllFees } from "./helper"; import { DuckDb } from "./db"; import { pairs } from "./pairs"; @@ -262,6 +277,28 @@ export const calculateAprResult = async ( return aprResult; }; +export const calculateBoostApr = ( + avgLiquidities: Record, + allFee7Days: PoolFee[] +): Record => { + 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 { @@ -302,6 +339,15 @@ export const getPoolLiquidities = async (pools: PairInfoData[]): Promise> => { + const allLiquidities: Record = {}; + for (const pool of pools) { + const liquidity = await getAvgPairLiquidity(pool); + allLiquidities[pool.liquidityAddr] = liquidity; + } + return allLiquidities; +}; + export const getPoolAmounts = async (pools: PairInfoData[]): Promise => { const duckDb = DuckDb.instances; const allPoolAmounts: PoolAmountHistory[] = []; @@ -341,20 +387,28 @@ 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({ @@ -362,7 +416,7 @@ export const triggerCalculateApr = async (assetInfos: [AssetInfo, AssetInfo][], 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. From a8b73001eb51980af7e7cc05bff69b01f6ba838a Mon Sep 17 00:00:00 2001 From: quangdz1704 Date: Sat, 3 Feb 2024 13:47:01 +0700 Subject: [PATCH 02/10] fix: update testcase pair helper --- packages/oraidex-sync/tests/helper.spec.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/oraidex-sync/tests/helper.spec.ts b/packages/oraidex-sync/tests/helper.spec.ts index 0fe5a205..e7691437 100644 --- a/packages/oraidex-sync/tests/helper.spec.ts +++ b/packages/oraidex-sync/tests/helper.spec.ts @@ -167,11 +167,6 @@ describe("test-helper", () => { 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, @@ -207,6 +202,11 @@ describe("test-helper", () => { 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, @@ -607,8 +607,8 @@ describe("test-helper", () => { }); it.each([ - ["orai", usdtCw20Address, 4], - [usdtCw20Address, "orai", 4], + ["orai", usdtCw20Address, 3], + [usdtCw20Address, "orai", 3], ["orai", airiCw20Adress, 0], ["orai", "foo", -1] ])( From 6d6f2521f2b23f3c1b3c5265983bfbd5041a0ebf Mon Sep 17 00:00:00 2001 From: quangdz1704 Date: Mon, 5 Feb 2024 15:28:24 +0700 Subject: [PATCH 03/10] fix: update apr boost response --- packages/oraidex-server/src/index.ts | 1 + packages/oraidex-sync/src/db.ts | 4 ++++ packages/oraidex-sync/src/index.ts | 7 +++++-- packages/oraidex-sync/src/pool-helper.ts | 3 ++- packages/oraidex-sync/src/types.ts | 1 + packages/oraidex-sync/tests/db.spec.ts | 6 ++++++ 6 files changed, 19 insertions(+), 3 deletions(-) diff --git a/packages/oraidex-server/src/index.ts b/packages/oraidex-server/src/index.ts index 1a22dc8e..18d3c562 100644 --- a/packages/oraidex-server/src/index.ts +++ b/packages/oraidex-server/src/index.ts @@ -311,6 +311,7 @@ app.get("/v1/pool-detail", async (req: Request<{}, {}, {}, GetPoolDetailQuery>, volume24Hour: poolVolume?.toString() ?? "0", volume24hChange: percentVolumeChange, apr: poolApr?.apr ?? 0, + aprBoost: poolApr?.aprBoost ?? 0, totalLiquidity: poolLiquidity, rewardPerSec: poolApr?.rewardPerSec }; diff --git a/packages/oraidex-sync/src/db.ts b/packages/oraidex-sync/src/db.ts index 4ee4cf5e..059231dc 100644 --- a/packages/oraidex-sync/src/db.ts +++ b/packages/oraidex-sync/src/db.ts @@ -513,6 +513,10 @@ export class DuckDb { await this.conn.run(`ALTER TABLE pool_apr ADD COLUMN IF NOT EXISTS timestamp UBIGINT DEFAULT 0`); } + async addAprBoostColToPoolAprTable() { + await this.conn.run(`ALTER TABLE pool_apr ADD COLUMN IF NOT EXISTS aprBoost DOUBLE DEFAULT 0`); + } + async insertPoolAprs(poolAprs: PoolApr[]) { await this.insertBulkData(poolAprs, "pool_apr"); } diff --git a/packages/oraidex-sync/src/index.ts b/packages/oraidex-sync/src/index.ts index a42730a1..f32d97fd 100644 --- a/packages/oraidex-sync/src/index.ts +++ b/packages/oraidex-sync/src/index.ts @@ -147,13 +147,14 @@ class OraiDexSync { const boostAPR = calculateBoostApr(avgLiquidities, allFee7Days); const poolAprs = allAprs.map((apr, index) => { + const newApr = apr + boostAPR[pools[index].liquidityAddr]; return { uniqueKey: concatAprHistoryToUniqueKey({ timestamp: Date.now(), supply: allTotalSupplies[index], bond: allBondAmounts[index], reward: JSON.stringify(allRewardPerSec[index]), - apr, + apr: newApr, pairAddr: pools[index].pairAddr }), pairAddr: pools[index].pairAddr, @@ -161,7 +162,8 @@ class OraiDexSync { totalSupply: allTotalSupplies[index], totalBondAmount: allBondAmounts[index], rewardPerSec: JSON.stringify(allRewardPerSec[index]), - apr: apr + boostAPR[pools[index].liquidityAddr], + apr: newApr, + aprBoost: boostAPR[pools[index].liquidityAddr], timestamp: Date.now() } as PoolApr; }); @@ -183,6 +185,7 @@ class OraiDexSync { await this.duckDb.createPoolAprTable(); await this.duckDb.createEarningHistoryTable(); await this.duckDb.addTimestampColToPoolAprTable(); + await this.duckDb.addAprBoostColToPoolAprTable(); let currentInd = await this.duckDb.loadHeightSnapshot(); const initialSyncHeight = parseInt(process.env.INITIAL_SYNC_HEIGHT) || 12388825; // if its' the first time, then we use the height 12388825 since its the safe height for the rpc nodes to include timestamp & new indexing logic diff --git a/packages/oraidex-sync/src/pool-helper.ts b/packages/oraidex-sync/src/pool-helper.ts index 1618b193..d07996cb 100644 --- a/packages/oraidex-sync/src/pool-helper.ts +++ b/packages/oraidex-sync/src/pool-helper.ts @@ -410,7 +410,8 @@ export const triggerCalculateApr = async (assetInfos: [AssetInfo, AssetInfo][], return { ...poolApr.aprInfo, height: newOffset, - apr: APRs[index], + apr: APRs[index] + boostAPR[poolApr.poolInfo.liquidityAddr], + aprBoost: boostAPR[poolApr.poolInfo.liquidityAddr], uniqueKey: concatAprHistoryToUniqueKey({ timestamp: Date.now(), supply: allTotalSupplies[index], diff --git a/packages/oraidex-sync/src/types.ts b/packages/oraidex-sync/src/types.ts index a256b238..9f2be8b4 100644 --- a/packages/oraidex-sync/src/types.ts +++ b/packages/oraidex-sync/src/types.ts @@ -279,6 +279,7 @@ export type PoolApr = { rewardPerSec: string; apr: number; timestamp: number; + aprBoost: number; }; export type GetPricePairQuery = { diff --git a/packages/oraidex-sync/tests/db.spec.ts b/packages/oraidex-sync/tests/db.spec.ts index 128d0218..610b254f 100644 --- a/packages/oraidex-sync/tests/db.spec.ts +++ b/packages/oraidex-sync/tests/db.spec.ts @@ -342,6 +342,7 @@ describe("test-duckdb", () => { duckDb = await DuckDb.create(":memory:"); await duckDb.createPoolAprTable(); await duckDb.addTimestampColToPoolAprTable(); + await duckDb.addAprBoostColToPoolAprTable(); await duckDb.insertPoolAprs([ { uniqueKey: "orai_usdt_2", @@ -351,6 +352,7 @@ describe("test-duckdb", () => { totalBondAmount: "1", rewardPerSec: "1", apr: 2, + aprBoost: 2, timestamp: 1234 }, { @@ -361,6 +363,7 @@ describe("test-duckdb", () => { totalBondAmount: "1", rewardPerSec: "1", apr: 2.5, + aprBoost: 2, timestamp: 1236 }, { @@ -371,6 +374,7 @@ describe("test-duckdb", () => { totalBondAmount: "1", rewardPerSec: "1", apr: 4, + aprBoost: 2, timestamp: 1235 }, { @@ -381,6 +385,7 @@ describe("test-duckdb", () => { totalBondAmount: "1", rewardPerSec: "1", apr: 3, + aprBoost: 2, timestamp: 1233 }, { @@ -391,6 +396,7 @@ describe("test-duckdb", () => { totalBondAmount: "1", rewardPerSec: "1", apr: 2, + aprBoost: 2, timestamp: 1234 } ]); From 17ea715cdf5233b8dfc588f7ec2e82a248dcd40c Mon Sep 17 00:00:00 2001 From: quangdz1704 Date: Mon, 5 Feb 2024 15:40:41 +0700 Subject: [PATCH 04/10] fix: update test case --- packages/oraidex-sync/tests/db.spec.ts | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/oraidex-sync/tests/db.spec.ts b/packages/oraidex-sync/tests/db.spec.ts index 610b254f..dc2ce86d 100644 --- a/packages/oraidex-sync/tests/db.spec.ts +++ b/packages/oraidex-sync/tests/db.spec.ts @@ -352,8 +352,8 @@ describe("test-duckdb", () => { totalBondAmount: "1", rewardPerSec: "1", apr: 2, - aprBoost: 2, - timestamp: 1234 + timestamp: 1234, + aprBoost: 2 }, { uniqueKey: "orai_usdt_1", @@ -363,8 +363,8 @@ describe("test-duckdb", () => { totalBondAmount: "1", rewardPerSec: "1", apr: 2.5, - aprBoost: 2, - timestamp: 1236 + timestamp: 1236, + aprBoost: 2 }, { uniqueKey: "orai_usdt_4", @@ -374,8 +374,8 @@ describe("test-duckdb", () => { totalBondAmount: "1", rewardPerSec: "1", apr: 4, - aprBoost: 2, - timestamp: 1235 + timestamp: 1235, + aprBoost: 2 }, { uniqueKey: "orai_usdt_3", @@ -385,8 +385,8 @@ describe("test-duckdb", () => { totalBondAmount: "1", rewardPerSec: "1", apr: 3, - aprBoost: 2, - timestamp: 1233 + timestamp: 1233, + aprBoost: 2 }, { uniqueKey: "orai_atom", @@ -396,8 +396,8 @@ describe("test-duckdb", () => { totalBondAmount: "1", rewardPerSec: "1", apr: 2, - aprBoost: 2, - timestamp: 1234 + timestamp: 1234, + aprBoost: 2 } ]); }); @@ -426,6 +426,7 @@ describe("test-duckdb", () => { totalBondAmount: "1", rewardPerSec: "1", apr: 2.5, + aprBoost: 2, timestamp: 1236n }); }); From 683027e9c5eec1e29d1c71ac236ac7afbf36f1b6 Mon Sep 17 00:00:00 2001 From: quangdz1704 Date: Mon, 5 Feb 2024 16:58:12 +0700 Subject: [PATCH 05/10] feat: add apr boost to list pool --- packages/oraidex-server/src/helper.ts | 1 + packages/oraidex-sync/src/db.ts | 6 +++--- packages/oraidex-sync/src/index.ts | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/oraidex-server/src/helper.ts b/packages/oraidex-server/src/helper.ts index 8d0f2be9..b4db40c6 100644 --- a/packages/oraidex-server/src/helper.ts +++ b/packages/oraidex-server/src/helper.ts @@ -204,6 +204,7 @@ export const getAllPoolsInfo = async () => { volume24Hour: poolVolume.volume.toString(), fee7Days: poolFee.fee.toString(), apr: poolApr.apr, + aprBoost: poolApr?.aprBoost ?? 0, totalLiquidity: allLiquidities[index], avgLiquidities: avgLiquidities[pool.liquidityAddr], rewardPerSec: poolApr.rewardPerSec, diff --git a/packages/oraidex-sync/src/db.ts b/packages/oraidex-sync/src/db.ts index 059231dc..44268039 100644 --- a/packages/oraidex-sync/src/db.ts +++ b/packages/oraidex-sync/src/db.ts @@ -539,18 +539,18 @@ export class DuckDb { const result = await this.conn.all( ` WITH RankedPool AS ( - SELECT pairAddr, apr, rewardPerSec, totalSupply, height, + SELECT pairAddr, apr, rewardPerSec, totalSupply, height, aprBoost, ROW_NUMBER() OVER (PARTITION BY pairAddr ORDER BY timestamp DESC) AS rn FROM pool_apr ) - SELECT pairAddr, apr, rewardPerSec, totalSupply + SELECT pairAddr, apr, rewardPerSec, totalSupply, aprBoost FROM RankedPool WHERE rn = 1 ORDER BY apr ; ` ); - return result as Pick[]; + return result as Pick[]; } async getMyEarnedAmount(stakerAddress: string, startTime: number, endTime: number, stakingAssetDenom?: string) { diff --git a/packages/oraidex-sync/src/index.ts b/packages/oraidex-sync/src/index.ts index f32d97fd..9d3a6383 100644 --- a/packages/oraidex-sync/src/index.ts +++ b/packages/oraidex-sync/src/index.ts @@ -145,6 +145,7 @@ class OraiDexSync { ); const boostAPR = calculateBoostApr(avgLiquidities, allFee7Days); + // console.log("boostAor", boostAPR); const poolAprs = allAprs.map((apr, index) => { const newApr = apr + boostAPR[pools[index].liquidityAddr]; From 1c6005e5934dbc329817edffe5caa7cc16f4d8be Mon Sep 17 00:00:00 2001 From: quangdz1704 Date: Mon, 5 Feb 2024 16:59:20 +0700 Subject: [PATCH 06/10] fix: update test case --- packages/oraidex-sync/tests/db.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/oraidex-sync/tests/db.spec.ts b/packages/oraidex-sync/tests/db.spec.ts index dc2ce86d..51fa3496 100644 --- a/packages/oraidex-sync/tests/db.spec.ts +++ b/packages/oraidex-sync/tests/db.spec.ts @@ -408,8 +408,8 @@ describe("test-duckdb", () => { // assertion expect(apr).toEqual([ - { pairAddr: "orai_atom", apr: 2, rewardPerSec: "1", totalSupply: "1" }, - { pairAddr: "orai_usdt", apr: 2.5, rewardPerSec: "1", totalSupply: "1" } + { pairAddr: "orai_atom", apr: 2, aprBoost: 2, rewardPerSec: "1", totalSupply: "1" }, + { pairAddr: "orai_usdt", apr: 2.5, aprBoost: 2, rewardPerSec: "1", totalSupply: "1" } ]); }); From d9943adb80de8ecef4bd900e2b0efa8ed31f23dc Mon Sep 17 00:00:00 2001 From: quangdz1704 Date: Mon, 5 Feb 2024 17:47:15 +0700 Subject: [PATCH 07/10] fix: insert apr boost into pool_apr --- packages/oraidex-sync/src/index.ts | 4 ++-- packages/oraidex-sync/src/pool-helper.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/oraidex-sync/src/index.ts b/packages/oraidex-sync/src/index.ts index 9d3a6383..c1cbfdbc 100644 --- a/packages/oraidex-sync/src/index.ts +++ b/packages/oraidex-sync/src/index.ts @@ -164,8 +164,8 @@ class OraiDexSync { totalBondAmount: allBondAmounts[index], rewardPerSec: JSON.stringify(allRewardPerSec[index]), apr: newApr, - aprBoost: boostAPR[pools[index].liquidityAddr], - timestamp: Date.now() + timestamp: Date.now(), + aprBoost: boostAPR[pools[index].liquidityAddr] } as PoolApr; }); await this.duckDb.insertPoolAprs(poolAprs); diff --git a/packages/oraidex-sync/src/pool-helper.ts b/packages/oraidex-sync/src/pool-helper.ts index d07996cb..8f409ed2 100644 --- a/packages/oraidex-sync/src/pool-helper.ts +++ b/packages/oraidex-sync/src/pool-helper.ts @@ -411,7 +411,6 @@ export const triggerCalculateApr = async (assetInfos: [AssetInfo, AssetInfo][], ...poolApr.aprInfo, height: newOffset, apr: APRs[index] + boostAPR[poolApr.poolInfo.liquidityAddr], - aprBoost: boostAPR[poolApr.poolInfo.liquidityAddr], uniqueKey: concatAprHistoryToUniqueKey({ timestamp: Date.now(), supply: allTotalSupplies[index], @@ -420,7 +419,8 @@ export const triggerCalculateApr = async (assetInfos: [AssetInfo, AssetInfo][], 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. + timestamp: Date.now(), // use timestamp date.now() because we just need to have a order of apr. + aprBoost: boostAPR[poolApr.poolInfo.liquidityAddr] }; }); await duckDb.insertPoolAprs(newPoolAprs); From 111add5dcc1135771f4ba21904fede980b45ea4f Mon Sep 17 00:00:00 2001 From: quangdz1704 Date: Tue, 6 Feb 2024 09:47:15 +0700 Subject: [PATCH 08/10] fix: add fallback optional chaining --- packages/oraidex-sync/src/index.ts | 4 ++-- packages/oraidex-sync/src/pool-helper.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/oraidex-sync/src/index.ts b/packages/oraidex-sync/src/index.ts index c1cbfdbc..5ffc6dfb 100644 --- a/packages/oraidex-sync/src/index.ts +++ b/packages/oraidex-sync/src/index.ts @@ -148,7 +148,7 @@ class OraiDexSync { // console.log("boostAor", boostAPR); const poolAprs = allAprs.map((apr, index) => { - const newApr = apr + boostAPR[pools[index].liquidityAddr]; + const newApr = apr + (boostAPR[pools[index]?.liquidityAddr] || 0); return { uniqueKey: concatAprHistoryToUniqueKey({ timestamp: Date.now(), @@ -165,7 +165,7 @@ class OraiDexSync { rewardPerSec: JSON.stringify(allRewardPerSec[index]), apr: newApr, timestamp: Date.now(), - aprBoost: boostAPR[pools[index].liquidityAddr] + aprBoost: boostAPR[pools[index]?.liquidityAddr] || 0 } as PoolApr; }); await this.duckDb.insertPoolAprs(poolAprs); diff --git a/packages/oraidex-sync/src/pool-helper.ts b/packages/oraidex-sync/src/pool-helper.ts index 8f409ed2..10f8aa60 100644 --- a/packages/oraidex-sync/src/pool-helper.ts +++ b/packages/oraidex-sync/src/pool-helper.ts @@ -410,17 +410,17 @@ export const triggerCalculateApr = async (assetInfos: [AssetInfo, AssetInfo][], return { ...poolApr.aprInfo, height: newOffset, - apr: APRs[index] + boostAPR[poolApr.poolInfo.liquidityAddr], + apr: APRs[index] + (boostAPR[poolApr.poolInfo?.liquidityAddr] || 0), uniqueKey: concatAprHistoryToUniqueKey({ timestamp: Date.now(), supply: allTotalSupplies[index], bond: allBondAmounts[index], reward: allRewardPerSecs[index], - apr: APRs[index] + boostAPR[poolApr.poolInfo.liquidityAddr], + apr: APRs[index] + (boostAPR[poolApr.poolInfo?.liquidityAddr] || 0), pairAddr: pools[index].pairAddr }), timestamp: Date.now(), // use timestamp date.now() because we just need to have a order of apr. - aprBoost: boostAPR[poolApr.poolInfo.liquidityAddr] + aprBoost: boostAPR[poolApr.poolInfo?.liquidityAddr] || 0 }; }); await duckDb.insertPoolAprs(newPoolAprs); From 130efcc4c9a674d51098f1cd51628078dfb9f4d0 Mon Sep 17 00:00:00 2001 From: quangdz1704 Date: Tue, 6 Feb 2024 11:01:37 +0700 Subject: [PATCH 09/10] feat: add test case pool helper apr --- packages/oraidex-sync/src/helper.ts | 2 +- packages/oraidex-sync/src/pool-helper.ts | 5 +- packages/oraidex-sync/tests/helper.spec.ts | 55 +++++++++++++++++++ .../oraidex-sync/tests/pool-helper.spec.ts | 31 +++++++++++ 4 files changed, 90 insertions(+), 3 deletions(-) diff --git a/packages/oraidex-sync/src/helper.ts b/packages/oraidex-sync/src/helper.ts index f127fde9..9683a950 100644 --- a/packages/oraidex-sync/src/helper.ts +++ b/packages/oraidex-sync/src/helper.ts @@ -468,7 +468,7 @@ export const getAvgPairLiquidity = async (poolInfo: PairInfoData): Promise { - acc = acc + Number(cur.offerPoolAmount) * Math.pow(10, -6); + acc = acc + toDisplay(cur.offerPoolAmount); return acc; }, 0); diff --git a/packages/oraidex-sync/src/pool-helper.ts b/packages/oraidex-sync/src/pool-helper.ts index 10f8aa60..908c8ac3 100644 --- a/packages/oraidex-sync/src/pool-helper.ts +++ b/packages/oraidex-sync/src/pool-helper.ts @@ -34,7 +34,8 @@ import { recalculateTotalShare, PoolFee, getAvgPairLiquidity, - getAllFees + getAllFees, + toDisplay } from "./helper"; import { DuckDb } from "./db"; import { pairs } from "./pairs"; @@ -291,7 +292,7 @@ export const calculateBoostApr = ( 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; + const yearlyFees = (DAYS_PER_YEAR * toDisplay(poolFee.fee)) / DAYS_PER_WEEK; aprResult[lpTokenAddress] = !liquidityAmount ? 0 : (100 * yearlyFees) / liquidityAmount || 0; } diff --git a/packages/oraidex-sync/tests/helper.spec.ts b/packages/oraidex-sync/tests/helper.spec.ts index e7691437..963d253f 100644 --- a/packages/oraidex-sync/tests/helper.spec.ts +++ b/packages/oraidex-sync/tests/helper.spec.ts @@ -706,6 +706,61 @@ describe("test-helper", () => { expect(result).toEqual(expectedResult); } ); + + it.each([ + [0n, 0n, 0n, 0n, 0], + [1n, 1n, 2n, 2n, 0.000006] + ])( + "test-getApgPairLiquidity-should-return-correctly-liquidity-by-USDT", + async ( + offerPoolAmount: bigint, + askPoolAmount: bigint, + offerPoolAmount2: bigint, + askPoolAmount2: bigint, + expectedResult: number + ) => { + // setup + jest.spyOn(duckDb, "getLpAmountByTime").mockResolvedValue([ + { + offerPoolAmount, + askPoolAmount, + timestamp: 1, + height: 1, + pairAddr: "oraiUsdtPairAddr", + uniqueKey: "1", + totalShare: "1" + }, + { + offerPoolAmount: offerPoolAmount2, + askPoolAmount: askPoolAmount2, + timestamp: 1, + height: 1, + pairAddr: "oraiUsdtPairAddr", + uniqueKey: "1", + totalShare: "1" + } + ]); + jest.spyOn(poolHelper, "getPriceAssetByUsdt").mockResolvedValue(2); + + // act + const poolInfo: PairInfoData = { + firstAssetInfo: JSON.stringify(oraiInfo), + secondAssetInfo: JSON.stringify(usdtInfo), + commissionRate: "", + pairAddr: "oraiUsdtPairAddr", + liquidityAddr: "", + oracleAddr: "", + symbols: "1", + fromIconUrl: "1", + toIconUrl: "1" + }; + + const result = await helper.getAvgPairLiquidity(poolInfo); + + // assertion + expect(result).toEqual(expectedResult); + } + ); }); describe("test-get-volume-pairs", () => { diff --git a/packages/oraidex-sync/tests/pool-helper.spec.ts b/packages/oraidex-sync/tests/pool-helper.spec.ts index d70a44c5..90d8f401 100644 --- a/packages/oraidex-sync/tests/pool-helper.spec.ts +++ b/packages/oraidex-sync/tests/pool-helper.spec.ts @@ -315,6 +315,37 @@ describe("test-pool-helper", () => { expect(result).toStrictEqual(Array(pairs.length).fill(315360000)); }); + it("test-calculateBoostAprResult-should-return-correctly-APR", async () => { + // setup + jest.spyOn(poolHelper, "getPriceAssetByUsdt").mockResolvedValue(1); + + const avgLiquidities = {}; + pairs.map((p) => { + avgLiquidities[p.lp_token] = 1e6; + return p; + }); + + const fee7Days = pairs.map((p) => { + return { + assetInfos: p.asset_infos, + fee: 1000n + }; + }); + + const expectedResult = {}; + pairs.map((p) => { + expectedResult[p.lp_token] = 0.000005214285714285714; + return p; + }); + + // act + const result = await poolHelper.calculateBoostApr(avgLiquidities, fee7Days); + + // assertion + expect(Object.keys(result).length).toEqual(pairs.length); + expect(result).toStrictEqual(expectedResult); + }); + it.each([ [true, pairs.length, pairs.length], [false, 4, 0] From 7d4c4e9c526b8e280aae6c2851058cd80db9c255 Mon Sep 17 00:00:00 2001 From: quangdz1704 Date: Tue, 6 Feb 2024 14:22:56 +0700 Subject: [PATCH 10/10] fix: update version server --- packages/oraidex-server/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/oraidex-server/package.json b/packages/oraidex-server/package.json index c206f739..69ec1da0 100644 --- a/packages/oraidex-server/package.json +++ b/packages/oraidex-server/package.json @@ -1,6 +1,6 @@ { "name": "@oraichain/oraidex-server", - "version": "1.0.45", + "version": "1.0.46", "main": "dist/index.js", "bin": "dist/index.js", "license": "MIT",