From f3af65e42cd4fca8ae9f11edf4d361becb29f271 Mon Sep 17 00:00:00 2001 From: trungbach Date: Wed, 22 Nov 2023 18:30:33 +0700 Subject: [PATCH 1/6] update: calculate earned reward with transfer attributes --- packages/oraidex-sync/src/tx-parsing.ts | 108 ++++++++++++------ .../oraidex-sync/tests/tx-parsing.spec.ts | 10 ++ 2 files changed, 83 insertions(+), 35 deletions(-) diff --git a/packages/oraidex-sync/src/tx-parsing.ts b/packages/oraidex-sync/src/tx-parsing.ts index 77fc7186..321a3b7a 100644 --- a/packages/oraidex-sync/src/tx-parsing.ts +++ b/packages/oraidex-sync/src/tx-parsing.ts @@ -1,6 +1,9 @@ +/* eslint-disable security/detect-object-injection */ import { Attribute, Event } from "@cosmjs/stargate"; import { Log } from "@cosmjs/stargate/build/logs"; import { Tx } from "@oraichain/cosmos-rpc-sync"; +import { AssetInfo } from "@oraichain/oraidex-contracts-sdk"; +import { PoolResponse } from "@oraichain/oraidex-contracts-sdk/build/OraiswapPair.types"; import { Tx as CosmosTx } from "cosmjs-types/cosmos/tx/v1beta1/tx"; import { MsgExecuteContract } from "cosmjs-types/cosmwasm/wasm/v1/tx"; import { isEqual } from "lodash"; @@ -22,6 +25,7 @@ import { parseAssetInfoOnlyDenom, parseCw20DenomToAssetInfo } from "./parse"; import { accumulatePoolAmount, calculateLiquidityFee, + getOraiPrice, getPoolInfos, getPriceAssetByUsdt, isPoolHasFee @@ -42,13 +46,16 @@ import { TxAnlysisResult, WithdrawLiquidityOperationData } from "./types"; -import { AssetInfo } from "@oraichain/oraidex-contracts-sdk"; -import { PoolResponse } from "@oraichain/oraidex-contracts-sdk/build/OraiswapPair.types"; function parseWasmEvents(events: readonly Event[]): (readonly Attribute[])[] { return events.filter((event) => event.type === "wasm").map((event) => event.attributes); } +// use for extract claim reward +function parseTransferEvents(events: readonly Event[]): (readonly Attribute[])[] { + return events.filter((event) => event.type === "transfer").map((event) => event.attributes); +} + function parseTxLog(rawLog: string): Log[] { return JSON.parse(rawLog); } @@ -71,17 +78,17 @@ function parseTxToMsgExecuteContractMsgs(tx: Tx): MsgExecuteContractWithLogs[] { } function extractSwapOperations(txData: BasicTxData, wasmAttributes: (readonly Attribute[])[]): SwapOperationData[] { - let swapData: SwapOperationData[] = []; - let offerDenoms: string[] = []; - let askDenoms: string[] = []; - let commissionAmounts: string[] = []; - let offerAmounts: string[] = []; - let returnAmounts: string[] = []; - let taxAmounts: string[] = []; - let spreadAmounts: string[] = []; - for (let attrs of wasmAttributes) { + const swapData: SwapOperationData[] = []; + const offerDenoms: string[] = []; + const askDenoms: string[] = []; + const commissionAmounts: string[] = []; + const offerAmounts: string[] = []; + const returnAmounts: string[] = []; + const taxAmounts: string[] = []; + const spreadAmounts: string[] = []; + for (const attrs of wasmAttributes) { if (!attrs.find((attr) => attr.key === "action" && attr.value === "swap")) continue; - for (let attr of attrs) { + for (const attr of attrs) { if (attr.key === "offer_asset") { offerDenoms.push(attr.value); } else if (attr.key === "ask_asset") { @@ -165,16 +172,16 @@ export const calculateSwapOpsWithPoolAmount = async (swapOps: SwapOperationData[ pairInfos.map((pair) => pair.pairAddr), minTxHeight - 1 // assume data is sorted by height and timestamp ); - let accumulatePoolAmount: { + const accumulatePoolAmount: { [key: string]: PoolInfo; } = {}; - let updatedSwapOps = JSON.parse(JSON.stringify(swapOps)) as SwapOperationData[]; + const updatedSwapOps = JSON.parse(JSON.stringify(swapOps)) as SwapOperationData[]; for (const swapOp of updatedSwapOps) { const pool = getPoolFromSwapDenom(swapOp, poolInfos); // get pair addr to combine by address - let assetInfos = pool.assets.map((asset) => asset.info) as [AssetInfo, AssetInfo]; + const assetInfos = pool.assets.map((asset) => asset.info) as [AssetInfo, AssetInfo]; if (isAssetInfoPairReverse(assetInfos)) assetInfos.reverse(); const pairInfo = await duckDb.getPoolByAssetInfos(assetInfos); if (!pairInfo) throw new Error("cannot find pair info when collectAccumulateLpAndSwapData"); @@ -183,11 +190,11 @@ export const calculateSwapOpsWithPoolAmount = async (swapOps: SwapOperationData[ const [baseAmount, quoteAmount] = getBaseQuoteAmountFromSwapOps(swapOp); // accumulate pool amount by pair addr if (!accumulatePoolAmount[pairAddr]) { - let initialFirstTokenAmount = BigInt( + const initialFirstTokenAmount = BigInt( pool.assets.find((asset) => parseAssetInfoOnlyDenom(asset.info) === parseAssetInfoOnlyDenom(assetInfos[0])) .amount ); - let initialSecondTokenAmount = BigInt( + const initialSecondTokenAmount = BigInt( pool.assets.find((asset) => parseAssetInfoOnlyDenom(asset.info) === parseAssetInfoOnlyDenom(assetInfos[1])) .amount ); @@ -212,13 +219,29 @@ export const calculateSwapOpsWithPoolAmount = async (swapOps: SwapOperationData[ async function extractClaimOperations( txData: BasicTxData, wasmAttributes: (readonly Attribute[])[], - msg: MsgType + msg: MsgType, + transferAttributes: (readonly Attribute[])[] ): Promise { const claimData: EarningOperationData[] = []; const stakerAddresses: string[] = []; const rewardAssetDenoms: string[] = []; const earnAmounts: number[] = []; let stakingToken: string; + + // transfer attribute for claim native ORAI + let oraiEarnedAmount = 0; + for (const attrs of transferAttributes) { + for (const attr of attrs) { + if (attr.key === "amount") { + const asset = parseClaimNativeAsset(attr.value); + oraiEarnedAmount = parseInt(asset[0]); + break; + } + } + } + let oraiPrice = 0; + if (oraiEarnedAmount) oraiPrice = await getOraiPrice(); + for (const attrs of wasmAttributes) { const stakingAction = attrs.find((attr) => attr.key === "action" && attr.value === "withdraw_reward"); if (!stakingAction) continue; @@ -251,7 +274,7 @@ async function extractClaimOperations( rewardAssetPrice = await getPriceAssetByUsdt(rewardAssetInfo); } - const earnAmountInUsdt = rewardAssetPrice * earnAmounts[i]; + const earnAmountInUsdt = rewardAssetPrice * earnAmounts[i] + oraiPrice * oraiEarnedAmount; claimData.push({ uniqueKey: concatEarnedHistoryToUniqueKey({ txheight: txData.txheight, @@ -301,7 +324,7 @@ async function getFeeLiquidity( let fee = 0n; const isHasFee = isPoolHasFee(findedPair.asset_infos); if (isHasFee) { - let lpShare = + const lpShare = opType === "provide" ? attrs.find((attr) => attr.key === "share").value : attrs.find((attr) => attr.key === "withdrawn_share").value; @@ -320,7 +343,7 @@ async function extractMsgProvideLiquidity( wasmAttributes: (readonly Attribute[])[] ): Promise { if ("provide_liquidity" in msg) { - for (let attrs of wasmAttributes) { + for (const attrs of wasmAttributes) { const assetInfos = msg.provide_liquidity.assets.map((asset) => asset.info); let baseAsset = msg.provide_liquidity.assets[0]; @@ -373,6 +396,14 @@ function parseWithdrawLiquidityAssets(assets: string): string[] { return matches.slice(1, 5); } +function parseClaimNativeAsset(assets: string): string[] { + // format: "2591orai" + const regex = /^(\d+)([a-zA-Z\/0-9]+)$/; + const matches = assets.match(regex); + if (!matches || matches.length < 2) return []; + return matches.slice(1, 5); +} + async function extractMsgWithdrawLiquidity( txData: BasicTxData, wasmAttributes: (readonly Attribute[])[], @@ -380,7 +411,7 @@ async function extractMsgWithdrawLiquidity( ): Promise { const withdrawData: WithdrawLiquidityOperationData[] = []; - for (let attrs of wasmAttributes) { + for (const attrs of wasmAttributes) { if (!attrs.find((attr) => attr.key === "action" && attr.value === "withdraw_liquidity")) continue; const assetAttr = attrs.find((attr) => attr.key === "refund_assets"); if (!assetAttr) continue; @@ -391,7 +422,7 @@ async function extractMsgWithdrawLiquidity( let quoteAsset = assets[3]; let quoteAssetAmount = parseInt(assets[2]); // we only have one pair order. If the order is reversed then we also reverse the order - let findedPair = pairs.find((pair) => + const findedPair = pairs.find((pair) => isEqual( pair.asset_infos.map((info) => parseAssetInfoOnlyDenom(info)), [quoteAsset, baseAsset] @@ -430,8 +461,8 @@ async function extractMsgWithdrawLiquidity( } function parseExecuteContractToOraidexMsgs(msgs: MsgExecuteContractWithLogs[]): ModifiedMsgExecuteContract[] { - let objs: ModifiedMsgExecuteContract[] = []; - for (let msg of msgs) { + const objs: ModifiedMsgExecuteContract[] = []; + for (const msg of msgs) { try { const obj: ModifiedMsgExecuteContract = { ...msg, @@ -478,13 +509,13 @@ function parseExecuteContractToOraidexMsgs(msgs: MsgExecuteContractWithLogs[]): } async function parseTxs(txs: Tx[]): Promise { - let transactions: Tx[] = []; + const transactions: Tx[] = []; let swapOpsData: SwapOperationData[] = []; let claimOpsData: EarningOperationData[] = []; - let accountTxs: AccountTx[] = []; + const accountTxs: AccountTx[] = []; let provideLiquidityOpsData: ProvideLiquidityOperationData[] = []; let withdrawLiquidityOpsData: WithdrawLiquidityOperationData[] = []; - for (let tx of txs) { + for (const tx of txs) { transactions.push(tx); const msgExecuteContracts = parseTxToMsgExecuteContractMsgs(tx); const msgs = parseExecuteContractToOraidexMsgs(msgExecuteContracts); @@ -494,12 +525,12 @@ async function parseTxs(txs: Tx[]): Promise { txheight: tx.height }; - for (let msg of msgs) { + for (const msg of msgs) { const sender = msg.sender; const wasmAttributes = parseWasmEvents(msg.logs.events); - + const transferAttributes = parseTransferEvents(msg.logs.events); swapOpsData.push(...extractSwapOperations(basicTxData, wasmAttributes)); - claimOpsData.push(...(await extractClaimOperations(basicTxData, wasmAttributes, msg.msg))); + claimOpsData.push(...(await extractClaimOperations(basicTxData, wasmAttributes, msg.msg, transferAttributes))); const provideLiquidityData = await extractMsgProvideLiquidity(basicTxData, msg.msg, sender, wasmAttributes); if (provideLiquidityData) provideLiquidityOpsData.push(provideLiquidityData); withdrawLiquidityOpsData.push(...(await extractMsgWithdrawLiquidity(basicTxData, wasmAttributes, sender))); @@ -539,15 +570,15 @@ export const processEventApr = (txs: Tx[]) => { infoTokenAssetPools: new Set(), isTriggerRewardPerSec: false }; - for (let tx of txs) { + for (const tx of txs) { // guard code. Should refetch all token info if match event update_rewards_per_sec or length of staking asset equal to pairs length. if (assets.isTriggerRewardPerSec || assets.infoTokenAssetPools.size === pairs.length) break; const msgExecuteContracts = parseTxToMsgExecuteContractMsgs(tx); const msgs = parseExecuteContractToOraidexMsgs(msgExecuteContracts); - for (let msg of msgs) { + for (const msg of msgs) { const wasmAttributes = parseWasmEvents(msg.logs.events); - for (let attrs of wasmAttributes) { + for (const attrs of wasmAttributes) { if (attrs.find((attr) => attr.key === "action" && (attr.value === "bond" || attr.value === "unbond"))) { const stakingAssetDenom = attrs.find((attr) => attr.key === "staking_token")?.value; assets.infoTokenAssetPools.add(stakingAssetDenom); @@ -563,4 +594,11 @@ export const processEventApr = (txs: Tx[]) => { return assets; }; -export { parseTxToMsgExecuteContractMsgs, parseTxs, parseWasmEvents, parseWithdrawLiquidityAssets }; +export { + parseClaimNativeAsset, + parseTransferEvents, + parseTxToMsgExecuteContractMsgs, + parseTxs, + parseWasmEvents, + parseWithdrawLiquidityAssets +}; diff --git a/packages/oraidex-sync/tests/tx-parsing.spec.ts b/packages/oraidex-sync/tests/tx-parsing.spec.ts index c20f826c..343a8585 100644 --- a/packages/oraidex-sync/tests/tx-parsing.spec.ts +++ b/packages/oraidex-sync/tests/tx-parsing.spec.ts @@ -22,6 +22,16 @@ describe("test-tx-parsing", () => { expect(result).toEqual(expectedParsing); }); + it.each<[string, string[]]>([ + ["foo", []], + ["2591orai", ["2591", "orai"]] + ])("test-parseClaimNativeAsset", (assets, expectedParsing) => { + // act + const result = parse.parseClaimNativeAsset(assets); + // assert + expect(result).toEqual(expectedParsing); + }); + it.each<[number, number]>([ [1, 0], [0, 1] From 9589edc575592759560119d4227c609282fad9b6 Mon Sep 17 00:00:00 2001 From: trungbach Date: Sun, 3 Dec 2023 16:11:41 +0700 Subject: [PATCH 2/6] chore: add .env.example --- .env.example | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..00ce0a54 --- /dev/null +++ b/.env.example @@ -0,0 +1,12 @@ +PORT=2024 +RPC_URL=https://rpc.orai.io +FACTORY_CONTACT_ADDRESS_V1="orai1hemdkz4xx9kukgrunxu3yw0nvpyxf34v82d2c8" +FACTORY_CONTACT_ADDRESS_V2="orai167r4ut7avvgpp3rlzksz6vw5spmykluzagvmj3ht845fjschwugqjsqhst" +ROUTER_CONTRACT_ADDRESS="orai1j0r67r9k8t34pnhy00x3ftuxuwg0r6r4p8p6rrc8az0ednzr8y9s3sj2sf" +MULTICALL_CONTRACT_ADDRESS="orai1q7x644gmf7h8u8y6y8t9z9nnwl8djkmspypr6mxavsk9ual7dj0sxpmgwd" +STAKING_CONTRACT="orai19p43y0tqnr5qlhfwnxft2u5unph5yn60y7tuvu" +LIMIT=1000 +MAX_THREAD_LEVEL=3 +DUCKDB_PROD_FILENAME="db_name" +DUCKDB_FILENAME="db_name_only_sync" +INITIAL_SYNC_HEIGHT=14612180 \ No newline at end of file From e0d1c780c78252153394e64ef9414d9f3ddce7b1 Mon Sep 17 00:00:00 2001 From: trungbach Date: Mon, 4 Dec 2023 11:16:44 +0700 Subject: [PATCH 3/6] ci: pumb oraidex-server --- packages/oraidex-server/package.json | 2 +- packages/oraidex-server/package.staging.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/oraidex-server/package.json b/packages/oraidex-server/package.json index 7db31590..bf31a846 100644 --- a/packages/oraidex-server/package.json +++ b/packages/oraidex-server/package.json @@ -1,6 +1,6 @@ { "name": "@oraichain/oraidex-server", - "version": "1.0.29", + "version": "1.0.30", "main": "dist/index.js", "bin": "dist/index.js", "license": "MIT", diff --git a/packages/oraidex-server/package.staging.json b/packages/oraidex-server/package.staging.json index 3d8867d4..2963605d 100644 --- a/packages/oraidex-server/package.staging.json +++ b/packages/oraidex-server/package.staging.json @@ -1,6 +1,6 @@ { "name": "@oraichain/oraidex-server-staging", - "version": "1.0.39", + "version": "1.0.40", "main": "dist/index.js", "bin": "dist/index.js", "license": "MIT", From 4801612fd727c677c759f49ed8aae1fa55d00035 Mon Sep 17 00:00:00 2001 From: trungbach Date: Tue, 5 Dec 2023 11:05:39 +0700 Subject: [PATCH 4/6] chore: pumb oraidex-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 bf31a846..ab65f5ec 100644 --- a/packages/oraidex-server/package.json +++ b/packages/oraidex-server/package.json @@ -1,6 +1,6 @@ { "name": "@oraichain/oraidex-server", - "version": "1.0.30", + "version": "1.0.31", "main": "dist/index.js", "bin": "dist/index.js", "license": "MIT", From 1bea6cfbc8315b5e4b95900834312a4ea1b2f168 Mon Sep 17 00:00:00 2001 From: trungbach Date: Wed, 6 Dec 2023 14:57:41 +0700 Subject: [PATCH 5/6] chore: use constant from common instead of env --- .env.example | 5 ----- packages/oraidex-server/package.json | 2 +- packages/oraidex-sync/src/constants.ts | 17 ++++++++++++----- packages/oraidex-sync/src/types.ts | 4 ---- 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/.env.example b/.env.example index 00ce0a54..cf9589e3 100644 --- a/.env.example +++ b/.env.example @@ -1,10 +1,5 @@ PORT=2024 RPC_URL=https://rpc.orai.io -FACTORY_CONTACT_ADDRESS_V1="orai1hemdkz4xx9kukgrunxu3yw0nvpyxf34v82d2c8" -FACTORY_CONTACT_ADDRESS_V2="orai167r4ut7avvgpp3rlzksz6vw5spmykluzagvmj3ht845fjschwugqjsqhst" -ROUTER_CONTRACT_ADDRESS="orai1j0r67r9k8t34pnhy00x3ftuxuwg0r6r4p8p6rrc8az0ednzr8y9s3sj2sf" -MULTICALL_CONTRACT_ADDRESS="orai1q7x644gmf7h8u8y6y8t9z9nnwl8djkmspypr6mxavsk9ual7dj0sxpmgwd" -STAKING_CONTRACT="orai19p43y0tqnr5qlhfwnxft2u5unph5yn60y7tuvu" LIMIT=1000 MAX_THREAD_LEVEL=3 DUCKDB_PROD_FILENAME="db_name" diff --git a/packages/oraidex-server/package.json b/packages/oraidex-server/package.json index ab65f5ec..ff5c08da 100644 --- a/packages/oraidex-server/package.json +++ b/packages/oraidex-server/package.json @@ -1,6 +1,6 @@ { "name": "@oraichain/oraidex-server", - "version": "1.0.31", + "version": "1.0.32", "main": "dist/index.js", "bin": "dist/index.js", "license": "MIT", diff --git a/packages/oraidex-sync/src/constants.ts b/packages/oraidex-sync/src/constants.ts index f592b865..cfd097e9 100644 --- a/packages/oraidex-sync/src/constants.ts +++ b/packages/oraidex-sync/src/constants.ts @@ -1,3 +1,10 @@ +import { + FACTORY_CONTRACT, + FACTORY_V2_CONTRACT, + MULTICALL_CONTRACT, + ROUTER_V2_CONTRACT, + STAKING_CONTRACT +} from "@oraichain/oraidex-common"; import { AssetInfo } from "@oraichain/oraidex-contracts-sdk"; export const ORAI = "orai"; @@ -27,9 +34,9 @@ export const OCH_PRICE = 0.4; // usdt export const SEC_PER_YEAR = 60 * 60 * 24 * 365; export const network = { - factory: process.env.FACTORY_CONTACT_ADDRESS_V1, - factory_v2: process.env.FACTORY_CONTACT_ADDRESS_V2, - router: process.env.ROUTER_CONTRACT_ADDRESS, - staking: process.env.STAKING_CONTRACT, - multicall: process.env.MULTICALL_CONTRACT_ADDRESS + factory: FACTORY_CONTRACT, + factory_v2: FACTORY_V2_CONTRACT, + router: ROUTER_V2_CONTRACT, + staking: STAKING_CONTRACT, + multicall: MULTICALL_CONTRACT }; diff --git a/packages/oraidex-sync/src/types.ts b/packages/oraidex-sync/src/types.ts index 667aabac..6ee15b6b 100644 --- a/packages/oraidex-sync/src/types.ts +++ b/packages/oraidex-sync/src/types.ts @@ -195,10 +195,6 @@ export type TotalLiquidity = { export type Env = { PORT: number; RPC_URL: string; - FACTORY_CONTACT_ADDRESS_V1: string; - FACTORY_CONTACT_ADDRESS_V2: string; - ROUTER_CONTRACT_ADDRESS: string; - MULTICALL_CONTRACT_ADDRESS: string; LIMIT: number; MAX_THREAD_LEVEL: number; DUCKDB_PROD_FILENAME: string; From 50a583eb63ed367ba19372f939161044ec553930 Mon Sep 17 00:00:00 2001 From: trungbach Date: Thu, 7 Dec 2023 12:04:47 +0700 Subject: [PATCH 6/6] chore: seperate func to test --- packages/oraidex-server/package.staging.json | 2 +- packages/oraidex-sync/src/tx-parsing.ts | 30 ++++++++++++------ .../oraidex-sync/tests/tx-parsing.spec.ts | 31 ++++++++++++++++++- 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/packages/oraidex-server/package.staging.json b/packages/oraidex-server/package.staging.json index aa5b8b4d..2db91d05 100644 --- a/packages/oraidex-server/package.staging.json +++ b/packages/oraidex-server/package.staging.json @@ -1,6 +1,6 @@ { "name": "@oraichain/oraidex-server-staging", - "version": "1.0.41", + "version": "1.0.42", "main": "dist/index.js", "bin": "dist/index.js", "license": "MIT", diff --git a/packages/oraidex-sync/src/tx-parsing.ts b/packages/oraidex-sync/src/tx-parsing.ts index 321a3b7a..089a5249 100644 --- a/packages/oraidex-sync/src/tx-parsing.ts +++ b/packages/oraidex-sync/src/tx-parsing.ts @@ -216,6 +216,25 @@ export const calculateSwapOpsWithPoolAmount = async (swapOps: SwapOperationData[ } }; +export async function calculateRewardAssetPrice(rewardAssetDenom: string): Promise { + // hardcode price for reward OCH + if (rewardAssetDenom === ORAIXOCH_INFO.token.contract_addr) { + return OCH_PRICE; + } else { + const rewardAssetInfo = parseCw20DenomToAssetInfo(rewardAssetDenom); + return await getPriceAssetByUsdt(rewardAssetInfo); + } +} + +export function calculateEarnAmountInUsdt( + rewardAssetPrice: number, + earnAmount: number, + oraiEarnedAmount: number, + oraiPrice: number +): number { + return rewardAssetPrice * earnAmount + oraiPrice * oraiEarnedAmount; +} + async function extractClaimOperations( txData: BasicTxData, wasmAttributes: (readonly Attribute[])[], @@ -266,15 +285,8 @@ async function extractClaimOperations( } for (let i = 0; i < stakerAddresses.length; i++) { - let rewardAssetPrice = 0; - // hardcode price for reward OCH - if (rewardAssetDenoms[i] === ORAIXOCH_INFO.token.contract_addr) rewardAssetPrice = OCH_PRICE; - else { - const rewardAssetInfo = parseCw20DenomToAssetInfo(rewardAssetDenoms[i]); - rewardAssetPrice = await getPriceAssetByUsdt(rewardAssetInfo); - } - - const earnAmountInUsdt = rewardAssetPrice * earnAmounts[i] + oraiPrice * oraiEarnedAmount; + const rewardAssetPrice = await calculateRewardAssetPrice(rewardAssetDenoms[i]); + const earnAmountInUsdt = calculateEarnAmountInUsdt(rewardAssetPrice, earnAmounts[i], oraiEarnedAmount, oraiPrice); claimData.push({ uniqueKey: concatEarnedHistoryToUniqueKey({ txheight: txData.txheight, diff --git a/packages/oraidex-sync/tests/tx-parsing.spec.ts b/packages/oraidex-sync/tests/tx-parsing.spec.ts index 343a8585..26b33768 100644 --- a/packages/oraidex-sync/tests/tx-parsing.spec.ts +++ b/packages/oraidex-sync/tests/tx-parsing.spec.ts @@ -2,10 +2,11 @@ import * as parse from "../src/tx-parsing"; import { Tx } from "@oraichain/cosmos-rpc-sync"; import { parseTxToMsgExecuteContractMsgs } from "../src/tx-parsing"; import { Tx as CosmosTx } from "cosmjs-types/cosmos/tx/v1beta1/tx"; -import { DuckDb, ORAI, SwapDirection, SwapOperationData, oraiInfo, usdtCw20Address, usdtInfo } from "../src"; +import { DuckDb, OCH_PRICE, ORAI, SwapDirection, SwapOperationData, oraiInfo, usdtCw20Address, usdtInfo } from "../src"; import * as poolHelper from "../src/pool-helper"; import { PoolResponse } from "@oraichain/oraidex-contracts-sdk/build/OraiswapPair.types"; import { AssetInfo } from "@oraichain/oraidex-contracts-sdk"; +import { ORAIXOCH_INFO } from "@oraichain/oraidex-common"; describe("test-tx-parsing", () => { it.each<[string, string[]]>([ @@ -249,4 +250,32 @@ describe("test-tx-parsing", () => { expect(updatedSwapOps[0].basePoolAmount).toEqual(99n); // 100n - 1n expect(updatedSwapOps[0].quotePoolAmount).toEqual(202n); // 200n + 2n }); + + it.each([ + [ORAIXOCH_INFO.token.contract_addr, OCH_PRICE], + ["other_denom", 1] + ])("should-calculate-reward-asset-price", async (denom: string, expectedPrice: number) => { + // setup + jest.spyOn(poolHelper, "getPriceAssetByUsdt").mockResolvedValue(expectedPrice); + + // act + const price = await parse.calculateRewardAssetPrice(denom); + + // assertion + expect(price).toBe(expectedPrice); + }); + + it("test-calculateEarnAmountInUsdt-should-calculate-earn-amount-in-USDT", async () => { + // setup + const earnAmount = 100; + const rewardAssetPrice = 0.5; + const oraiEarnedAmount = 50; + const oraiPrice = 4; + + // act + const result = parse.calculateEarnAmountInUsdt(rewardAssetPrice, earnAmount, oraiEarnedAmount, oraiPrice); + + // assertion + expect(result).toBe(250); + }); });