Skip to content

Commit

Permalink
Merge pull request #55 from oraichain/task/FOU-634
Browse files Browse the repository at this point in the history
Fix OHLCV price
  • Loading branch information
trungbach authored Nov 21, 2023
2 parents 4482773 + b73c08f commit 4813f78
Show file tree
Hide file tree
Showing 11 changed files with 277 additions and 39 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/publish_package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
if: steps.yarn-cache.outputs.cache-hit != 'true'
run: yarn
- name: Build
run: yarn build
run: yarn build && yarn build-tsc packages/oraidex-sync && yarn --cwd packages/oraidex-server/ build
- name: Authenticate with private NPM package
run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc
- name: Publish Oraidex Server
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish_staging_package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
if: steps.yarn-cache.outputs.cache-hit != 'true'
run: yarn
- name: Build
run: yarn build
run: yarn build-tsc packages/contracts-sdk && yarn build-tsc packages/oraidex-sync && yarn --cwd packages/oraidex-server-staging/ build
- name: Authenticate with private NPM package
run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc
- name: Publish
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
"docs": "typedoc --entryPointStrategy expand --name 'Oraidex SDK' --readme none --tsconfig packages/contracts-sdk/tsconfig.json packages/contracts-sdk/src",
"clean": "lerna clean --yes && lerna exec -- rimraf build/ dist/ cache/",
"build": "lerna run build --concurrency 1",
"build-tsc": "tsc -p",
"postbuild": "mkdir -p packages/oraidex-common/build/tronweb && cp -r packages/oraidex-common/src/tronweb/* packages/oraidex-common/build/tronweb",
"deploy": "yarn publish --access public",
"start:server": "yarn build packages/oraidex-sync/ && npx ts-node-dev packages/oraidex-server/src/index.ts",
"start:server": "yarn build-tsc packages/oraidex-sync/ && npx ts-node-dev packages/oraidex-server/src/index.ts",
"start:sync": "npx ts-node packages/oraidex-sync/src/sync-cmd.ts",
"prepare": "husky install"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/oraidex-server/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@oraichain/oraidex-server",
"version": "1.0.18",
"version": "1.0.19",
"main": "dist/index.js",
"bin": "dist/index.js",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion packages/oraidex-server/package.staging.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@oraichain/oraidex-server-staging",
"version": "1.0.17",
"version": "1.0.20",
"main": "dist/index.js",
"bin": "dist/index.js",
"license": "MIT",
Expand Down
3 changes: 2 additions & 1 deletion packages/oraidex-server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ app
oraidexSync.sync();
console.log(`[server]: oraiDEX info server is running at http://${hostname}:${port}`);
})
.on("error", () => {
.on("error", (err) => {
console.log("error when start oraiDEX server", err);
process.exit(1);
});
8 changes: 2 additions & 6 deletions packages/oraidex-sync/src/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,12 +311,8 @@ export function buildOhlcv(ops: SwapOperationData[]): Ohlcv[] {
}

export const calculateBasePriceFromSwapOp = (op: SwapOperationData): number => {
if (!op || !op.offerAmount || !op.returnAmount) {
return 0;
}
const offerAmount = op.offerAmount;
const askAmount = op.returnAmount;
return op.direction === "Buy" ? Number(offerAmount) / Number(askAmount) : Number(askAmount) / Number(offerAmount);
if (!op || !op.quotePoolAmount || !op.basePoolAmount) return 0;
return Number(op.quotePoolAmount) / Number(op.basePoolAmount);
};

export function getSwapDirection(offerDenom: string, askDenom: string): SwapDirection {
Expand Down
92 changes: 90 additions & 2 deletions packages/oraidex-sync/src/tx-parsing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@ import {
} from "./helper";
import { pairWithStakingAsset, pairs } from "./pairs";
import { parseAssetInfoOnlyDenom, parseCw20DenomToAssetInfo } from "./parse";
import { accumulatePoolAmount, calculateLiquidityFee, getPriceAssetByUsdt, isPoolHasFee } from "./pool-helper";
import {
accumulatePoolAmount,
calculateLiquidityFee,
getPoolInfos,
getPriceAssetByUsdt,
isPoolHasFee
} from "./pool-helper";
import { fetchAllRewardInfo } from "./query";
import {
AccountTx,
Expand All @@ -34,12 +40,15 @@ import {
MsgType,
OraiswapPairCw20HookMsg,
OraiswapRouterCw20HookMsg,
PoolInfo,
ProvideLiquidityOperationData,
StakingOperationData,
SwapOperationData,
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);
Expand Down Expand Up @@ -151,6 +160,84 @@ async function calculateLpPrice(stakingAssetDenom: string): Promise<number> {
}
}

export const getBaseQuoteAmountFromSwapOps = (swapOp: SwapOperationData) => {
// Sell: offer is ORAI, return is USDT
// Buy: offer is USDT, return is ORAI
let baseAmount = swapOp.direction === "Sell" ? swapOp.offerAmount : swapOp.returnAmount;
let quoteAmount = -(swapOp.direction === "Sell" ? swapOp.returnAmount : swapOp.offerAmount);
if (swapOp.direction === "Buy") {
baseAmount = -baseAmount;
quoteAmount = -quoteAmount;
}
return [BigInt(baseAmount), BigInt(quoteAmount)];
};

export const getPoolFromSwapDenom = (swapOp: SwapOperationData, poolInfos: PoolResponse[]) => {
const baseDenom = swapOp.direction === "Sell" ? swapOp.offerDenom : swapOp.askDenom;
const quoteDenom = swapOp.direction === "Sell" ? swapOp.askDenom : swapOp.offerDenom;
const pool = poolInfos.find(
(info) =>
info.assets.some((assetInfo) => parseAssetInfoOnlyDenom(assetInfo.info) === baseDenom) &&
info.assets.some((assetInfo) => parseAssetInfoOnlyDenom(assetInfo.info) === quoteDenom)
);
return pool;
};

export const calculateSwapOpsWithPoolAmount = async (swapOps: SwapOperationData[]): Promise<SwapOperationData[]> => {
try {
if (swapOps.length === 0) return [];
const duckDb = DuckDb.instances;
const pairInfos = await duckDb.queryPairInfos();

const minTxHeight = swapOps[0].txheight;
const poolInfos = await getPoolInfos(
pairInfos.map((pair) => pair.pairAddr),
minTxHeight - 1 // assume data is sorted by height and timestamp
);
let accumulatePoolAmount: {
[key: string]: PoolInfo;
} = {};

let 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];
if (isAssetInfoPairReverse(assetInfos)) assetInfos.reverse();
const pairInfo = await duckDb.getPoolByAssetInfos(assetInfos);
if (!pairInfo) throw new Error("cannot find pair info when collectAccumulateLpAndSwapData");
const { pairAddr } = pairInfo;

const [baseAmount, quoteAmount] = getBaseQuoteAmountFromSwapOps(swapOp);
// accumulate pool amount by pair addr
if (!accumulatePoolAmount[pairAddr]) {
let initialFirstTokenAmount = BigInt(
pool.assets.find((asset) => parseAssetInfoOnlyDenom(asset.info) === parseAssetInfoOnlyDenom(assetInfos[0]))
.amount
);
let initialSecondTokenAmount = BigInt(
pool.assets.find((asset) => parseAssetInfoOnlyDenom(asset.info) === parseAssetInfoOnlyDenom(assetInfos[1]))
.amount
);
accumulatePoolAmount[pairAddr] = {
offerPoolAmount: initialFirstTokenAmount + baseAmount,
askPoolAmount: initialSecondTokenAmount + quoteAmount
};
} else {
accumulatePoolAmount[pairAddr].offerPoolAmount += baseAmount;
accumulatePoolAmount[pairAddr].askPoolAmount += quoteAmount;
}
// update pool amount for swap ops
swapOp.basePoolAmount = accumulatePoolAmount[pairAddr].offerPoolAmount;
swapOp.quotePoolAmount = accumulatePoolAmount[pairAddr].askPoolAmount;
}
return updatedSwapOps;
} catch (error) {
console.log("error in calculateSwapOpsWithPoolAmount: ", error.message);
}
};

async function extractStakingOperations(
txData: BasicTxData,
wasmAttributes: (readonly Attribute[])[]
Expand Down Expand Up @@ -550,9 +637,10 @@ async function parseTxs(txs: Tx[]): Promise<TxAnlysisResult> {
// accumulate liquidity pool amount via provide/withdraw liquidity and swap ops
const poolAmountHistories = await accumulatePoolAmount(lpOpsData, [...swapOpsData]);

const swapOpsWithPoolAmount = await calculateSwapOpsWithPoolAmount(swapOpsData);
return {
swapOpsData: groupByTime(swapOpsData) as SwapOperationData[],
ohlcv: buildOhlcv(swapOpsData),
ohlcv: buildOhlcv(swapOpsWithPoolAmount),
accountTxs,
provideLiquidityOpsData,
withdrawLiquidityOpsData,
Expand Down
2 changes: 2 additions & 0 deletions packages/oraidex-sync/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export type SwapOperationData = {
returnAmount: number | bigint;
spreadAmount: number;
taxAmount: number;
basePoolAmount?: number | bigint;
quotePoolAmount?: number | bigint;
} & BasicTxData;

export type StakingOperationData = {
Expand Down
53 changes: 29 additions & 24 deletions packages/oraidex-sync/tests/helper.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -582,30 +582,35 @@ describe("test-helper", () => {
});

it.each([
["Buy" as SwapDirection, 2],
["Sell" as SwapDirection, 0.5]
])("test-calculateBasePriceFromSwapOp", (direction: SwapDirection, expectedPrice: number) => {
const swapOp = {
offerAmount: 2,
offerDenom: ORAI,
returnAmount: 1,
askDenom: usdtCw20Address,
direction,
uniqueKey: "1",
timestamp: 1,
txCreator: "a",
txhash: "a",
txheight: 1,
spreadAmount: 1,
taxAmount: 1,
commissionAmount: 1
} as SwapOperationData;
// first case undefined, return 0
expect(calculateBasePriceFromSwapOp(undefined as any)).toEqual(0);
// other cases
const price = calculateBasePriceFromSwapOp(swapOp);
expect(price).toEqual(expectedPrice);
});
["Buy" as SwapDirection, 100n, 200n, 2],
["Sell" as SwapDirection, 105n, 214n, 2.038095238095238]
])(
"test-calculateBasePriceFromSwapOp",
(direction: SwapDirection, basePoolAmount, quotePoolAmount, expectedPrice: number) => {
const swapOp = {
offerAmount: 2,
offerDenom: ORAI,
returnAmount: 1,
askDenom: usdtCw20Address,
direction,
uniqueKey: "1",
timestamp: 1,
txCreator: "a",
txhash: "a",
txheight: 1,
spreadAmount: 1,
taxAmount: 1,
commissionAmount: 1,
basePoolAmount,
quotePoolAmount
} as SwapOperationData;
// first case undefined, return 0
expect(calculateBasePriceFromSwapOp(undefined as any)).toEqual(0);
// other cases
const price = calculateBasePriceFromSwapOp(swapOp);
expect(price).toEqual(expectedPrice);
}
);

it.each([
[usdtCw20Address, "orai", "Buy" as SwapDirection],
Expand Down
Loading

0 comments on commit 4813f78

Please sign in to comment.