Skip to content

Commit

Permalink
[GSW-551] feat: Integrate pool data with RPC
Browse files Browse the repository at this point in the history
  • Loading branch information
jinoosss committed Nov 8, 2023
1 parent ed6c1c5 commit a43e68e
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ import React, { useCallback, useMemo } from "react";
import { SelectFeeTierItemWrapper, SelectFeeTierWrapper } from "./SelectFeeTier.styles";
import { SwapFeeTierInfoMap, SwapFeeTierType } from "@constants/option.constant";
import { PoolModel } from "@models/pool/pool-model";
import BigNumber from "bignumber.js";

interface SelectFeeTierProps {
feetierOfLiquidityMap: { [key in string]: number };
feeTiers: SwapFeeTierType[];
feeTier: SwapFeeTierType | null;
pools: PoolModel[],
selectFeeTier: (feeTier: SwapFeeTierType) => void;
}

const SelectFeeTier: React.FC<SelectFeeTierProps> = ({
feetierOfLiquidityMap,
feeTiers,
feeTier,
pools,
Expand All @@ -30,6 +31,7 @@ const SelectFeeTier: React.FC<SelectFeeTierProps> = ({
selected={feeTier === item}
feeTier={item}
pools={pools}
liquidityRange={feetierOfLiquidityMap[SwapFeeTierInfoMap[item].fee] || null}
onClick={() => onClickFeeTierItem(item)}
/>
))}
Expand All @@ -41,32 +43,26 @@ interface SelectFeeTierItemProps {
selected: boolean;
feeTier: SwapFeeTierType;
pools: PoolModel[];
liquidityRange: number | null;
onClick: () => void;
}

const SelectFeeTierItem: React.FC<SelectFeeTierItemProps> = ({
selected,
feeTier,
pools,
liquidityRange,
onClick,
}) => {
const feeRateStr = useMemo(() => {
return SwapFeeTierInfoMap[feeTier].rateStr;
}, [feeTier]);

const rangeStr = useMemo(() => {
const pool = pools.find(pool => pool.fee === feeTier);
if (!pool || pool.bins.length < 2) {
if (liquidityRange === null) {
return "Not created";
}
const sortedBins = pool.bins.sort((p1, p2) => p1.currentTick - p2.currentTick);
const fullTickRange = 1774545;
const currentTickGap = sortedBins[0].currentTick - sortedBins[sortedBins.length - 1].currentTick;
return BigNumber(currentTickGap)
.dividedBy(fullTickRange)
.multipliedBy(100)
.toFixed();
}, [feeTier, pools]);
return `${liquidityRange}% Select`;
}, [liquidityRange]);

const description = useMemo(() => {
return SwapFeeTierInfoMap[feeTier].description;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ interface EarnAddLiquidityProps {
changeTokenB: (token: TokenModel) => void;
tokenAInput: TokenAmountInputModel;
tokenBInput: TokenAmountInputModel;
feetierOfLiquidityMap: { [key in string]: number };
feeTiers: SwapFeeTierType[];
feeTier: SwapFeeTierType | null;
pools: PoolModel[];
Expand All @@ -44,6 +45,7 @@ const EarnAddLiquidity: React.FC<EarnAddLiquidityProps> = ({
changeTokenB,
tokenAInput,
tokenBInput,
feetierOfLiquidityMap,
feeTiers,
feeTier,
pools,
Expand Down Expand Up @@ -169,6 +171,7 @@ const EarnAddLiquidity: React.FC<EarnAddLiquidityProps> = ({

{openedFeeTier && (
<SelectFeeTier
feetierOfLiquidityMap={feetierOfLiquidityMap}
feeTiers={feeTiers}
feeTier={feeTier}
pools={pools}
Expand Down
2 changes: 2 additions & 0 deletions packages/web/src/constants/swap.constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ export const MAX_PRICE_X96 =

export const MIN_TICK = -887272 as const;
export const MAX_TICK = 887272 as const;

export const X96 = 7.9228163e28 as const;
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
} from "@constants/option.constant";
import { useTokenAmountInput } from "@hooks/token/use-token-amount-input";
import { TokenModel } from "@models/token/token-model";
import { PoolModel } from "@models/pool/pool-model";
import { useWallet } from "@hooks/wallet/use-wallet";
import BigNumber from "bignumber.js";
import { useSlippage } from "@hooks/common/use-slippage";
Expand All @@ -16,6 +15,7 @@ import { useEarnAddLiquidityConfirmModal } from "@hooks/token/use-earn-add-liqui
import { useAtom } from "jotai";
import { SwapState } from "@states/index";
import { useRouter } from "next/router";
import { usePool } from "@hooks/pool/use-pool";

export interface AddLiquidityPriceRage {
type: PriceRangeType;
Expand Down Expand Up @@ -73,7 +73,7 @@ const EarnAddLiquidityContainer: React.FC = () => {
const [priceRange, setPriceRange] = useState<AddLiquidityPriceRage | null>(
null
);
const [pools] = useState<PoolModel[]>([]);

const {
connected: connectedWallet,
account,
Expand All @@ -83,6 +83,7 @@ const EarnAddLiquidityContainer: React.FC = () => {
} = useWallet();
const { slippage } = useSlippage();
const { updateTokenPrices } = useTokenData();
const { pools, feetierOfLiquidityMap, createPool } = usePool({ tokenA, tokenB });
const { openModal: openConfirmModal } = useEarnAddLiquidityConfirmModal({
tokenA,
tokenB,
Expand All @@ -92,8 +93,13 @@ const EarnAddLiquidityContainer: React.FC = () => {
priceRange,
slippage,
swapFeeTier,
createPool
});

useEffect(() => {
console.log(feetierOfLiquidityMap);
}, [feetierOfLiquidityMap]);

useEffect(() => {
if (query?.feeTier) {
setSwapFeeTier(query?.feeTier as SwapFeeTierType);
Expand Down Expand Up @@ -209,6 +215,7 @@ const EarnAddLiquidityContainer: React.FC = () => {
changeTokenA={changeTokenA}
changeTokenB={changeTokenB}
feeTiers={SWAP_FEE_TIERS}
feetierOfLiquidityMap={feetierOfLiquidityMap}
feeTier={swapFeeTier}
selectFeeTier={selectSwapFeeTier}
priceRanges={priceRanges}
Expand Down
61 changes: 53 additions & 8 deletions packages/web/src/hooks/pool/use-pool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,55 @@ import { SwapFeeTierType } from "@constants/option.constant";
import { AddLiquidityPriceRage } from "@containers/earn-add-liquidity-container/EarnAddLiquidityContainer";
import { useGnoswapContext } from "@hooks/common/use-gnoswap-context";
import { useWallet } from "@hooks/wallet/use-wallet";
import { PoolModel } from "@models/pool/pool-model";
import { TokenModel } from "@models/token/token-model";
import { useCallback } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
import { usePoolData } from "./use-pool-data";

export const usePool = () => {
interface Props {
tokenA: TokenModel | null;
tokenB: TokenModel | null;
}

export const usePool = ({
tokenA,
tokenB
}: Props) => {
const { account } = useWallet();
const { poolRepository } = useGnoswapContext();
const { pools, updatePools } = usePoolData();
const [feetierOfLiquidityMap, setFeetierOfLiquidityMap] = useState<{ [key in string]: number }>({});

const currentPools: PoolModel[] = useMemo(() => {
if (!tokenA || !tokenB) {
return [];
}

const tokenPairOfPaths = [tokenA.path, tokenB.path]; // [tokenA.path, tokenB.path];
return pools.filter(pool => tokenPairOfPaths.includes(pool.tokenA.path) && tokenPairOfPaths.includes(pool.tokenB.path));
}, [pools, tokenA, tokenB]);

async function fetchPoolInfos(pools: PoolModel[]) {
const poolInfos = await (await Promise.all(pools.map(pool => poolRepository.getPoolInfoByPoolPath(pool.id).catch(null)))).filter(info => info !== null);
return poolInfos;
}

const createPool = useCallback(async ({
tokenA,
tokenB,
tokenAAmount,
tokenBAmount,
swapFeeTier,
startPrice,
priceRange,
slippage,
}: {
tokenA: TokenModel;
tokenB: TokenModel;
tokenAAmount: string;
tokenBAmount: string;
swapFeeTier: SwapFeeTierType;
startPrice: string;
priceRange: AddLiquidityPriceRage;
slippage: number;
}) => {
if (!account) {
if (!tokenA || !tokenB || !account) {
return null;
}
const hash = await poolRepository.createPool({
Expand All @@ -47,9 +69,32 @@ export const usePool = () => {
return null;
});
return hash;
}, [account, poolRepository]);
}, [account, poolRepository, tokenA, tokenB]);

useEffect(() => {
updatePools();
}, []);

useEffect(() => {
fetchPoolInfos(currentPools)
.then(infos => {
const feetierOfLiquidityMap: { [key in string]: number } = {};
const totalLiquidities = infos.map(info => info.liquidity).reduce((total, cur) => total + cur, 0);
for (const info of infos) {
const liquidityRate = Math.round((info.liquidity / totalLiquidities) * 100);
const feeTier = currentPools.find(pool => pool.id === info.poolPath)?.fee;
if (feeTier) {
feetierOfLiquidityMap[`${feeTier}`] = liquidityRate;
}
}
return feetierOfLiquidityMap;
})
.then(setFeetierOfLiquidityMap);
}, [currentPools]);

return {
pools: currentPools,
feetierOfLiquidityMap,
createPool
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import EarnAddConfirm from "@components/earn-add/earn-add-confirm/EarnAddConfirm
import { SwapFeeTierInfoMap, SwapFeeTierType } from "@constants/option.constant";
import { AddLiquidityPriceRage } from "@containers/earn-add-liquidity-container/EarnAddLiquidityContainer";
import useNavigate from "@hooks/common/use-navigate";
import { usePool } from "@hooks/pool/use-pool";
import { TokenModel } from "@models/token/token-model";
import { CommonState } from "@states/index";
import { useAtom } from "jotai";
Expand All @@ -19,6 +18,16 @@ export interface EarnAddLiquidityConfirmModalProps {
priceRange: AddLiquidityPriceRage | null;
slippage: number;
swapFeeTier: SwapFeeTierType | null;
createPool: (
params: {
tokenAAmount: string;
tokenBAmount: string;
swapFeeTier: SwapFeeTierType;
startPrice: string;
priceRange: AddLiquidityPriceRage;
slippage: number;
}
) => Promise<string | null>;
}
export interface SelectTokenModalModel {
openModal: () => void;
Expand All @@ -33,10 +42,10 @@ export const useEarnAddLiquidityConfirmModal = ({
currentPrice,
slippage,
swapFeeTier,
createPool,
}: EarnAddLiquidityConfirmModalProps): SelectTokenModalModel => {
const [, setOpenedModal] = useAtom(CommonState.openedModal);
const [, setModalContent] = useAtom(CommonState.modalContent);
const { createPool } = usePool();
const navigator = useNavigate();

const amountInfo = useMemo(() => {
Expand Down Expand Up @@ -106,8 +115,6 @@ export const useEarnAddLiquidityConfirmModal = ({
return;
}
createPool({
tokenA,
tokenB,
tokenAAmount: tokenAAmountInput.amount,
tokenBAmount: tokenBAmountInput.amount,
priceRange,
Expand Down
11 changes: 10 additions & 1 deletion packages/web/src/utils/swap-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
SwapFeeTierInfoMap,
SwapFeeTierType,
} from "@constants/option.constant";
import { MAX_TICK, MIN_TICK } from "@constants/swap.constant";
import { MAX_TICK, MIN_TICK, X96 } from "@constants/swap.constant";
import BigNumber from "bignumber.js";

export function getCurrentPriceByRaw(raw: string) {
Expand Down Expand Up @@ -40,6 +40,15 @@ export function priceToNearTick(price: number, tickSpacing: number) {
return tickRaw - mod;
}

export function rawByX96(value: number) {
return BigNumber(value).dividedBy(X96).toNumber();
}

export function priceX96ToNearTick(priceX96: number, tickSpacing: number) {
const price = rawByX96(priceX96);
return priceToNearTick(price, tickSpacing);
}

export function tickToPriceStr(tick: number, decimals?: number) {
if (tick === MIN_TICK + 1) {
return "0.00";
Expand Down

0 comments on commit a43e68e

Please sign in to comment.