Skip to content

Commit

Permalink
Feat/price service (#1152)
Browse files Browse the repository at this point in the history
* feat: integrate token pool prices into wallet management and pool creation

* chore: update persistence version to 3.2

* refactor: remove debug logging for pricesViaPool in getTotalUsd function
  • Loading branch information
trungbach authored Feb 12, 2025
1 parent 62c73bf commit 943febf
Show file tree
Hide file tree
Showing 19 changed files with 153 additions and 59 deletions.
4 changes: 3 additions & 1 deletion src/components/WalletManagement/Connected/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ const Connected: React.FC<{ setIsShowMyWallet: (isShow: boolean) => void }> = ({
const [theme] = useConfigReducer('theme');
const amounts = useSelector((state: RootState) => state.token.amounts);
const { data: prices } = useCoinGeckoPrices();
const totalUsd = getTotalUsd(amounts, prices);
const [tokenPoolPrices] = useConfigReducer('tokenPoolPrices');

const totalUsd = getTotalUsd(amounts, prices, tokenPoolPrices);
const [walletsByNetwork] = useWalletReducer('walletsByNetwork');

const renderConnectedWalletLogo = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ export const ConnectedMobile: React.FC<{ setIsShowMyWallet: (isShow: boolean) =>
const [theme] = useConfigReducer('theme');
const amounts = useSelector((state: RootState) => state.token.amounts);
const { data: prices } = useCoinGeckoPrices();
const totalUsd = getTotalUsd(amounts, prices);
const [tokenPoolPrices] = useConfigReducer('tokenPoolPrices');
const totalUsd = getTotalUsd(amounts, prices, tokenPoolPrices);

return (
<div className={cx('connected_container', theme)} onClick={() => setIsShowMyWallet(true)}>
Expand Down
3 changes: 2 additions & 1 deletion src/components/WalletManagement/MyWallet/MyWallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export const MyWallet: React.FC<{
const [tonAddress] = useConfigReducer('tonAddress');

const [metamaskAddress] = useConfigReducer('metamaskAddress');
const [tokenPoolPrices] = useConfigReducer('tokenPoolPrices');
const [cosmosAddresses, setCosmosAddress] = useConfigReducer('cosmosAddress');
const [walletByNetworks] = useWalletReducer('walletsByNetwork');

Expand All @@ -62,7 +63,7 @@ export const MyWallet: React.FC<{

const amounts = useSelector((state: RootState) => state.token.amounts);
const { data: prices } = useCoinGeckoPrices();
const totalUsd = getTotalUsd(amounts, prices);
const totalUsd = getTotalUsd(amounts, prices, tokenPoolPrices);
const { isCopied, copiedValue, handleCopy } = useCopyClipboard();

useEffect(() => {
Expand Down
31 changes: 31 additions & 0 deletions src/hooks/useGetTokenPoolPrices.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { useQuery } from '@tanstack/react-query';
import useConfigReducer from './useConfigReducer';
import axios from 'rest/request';

/**
* Fetches prices of tokens from pools oraiDEX backend.
* @returns The pool prices.
*/
export const useGetTokenPoolPrices = () => {
// use cached first then update by query, if is limited then return cached version
const [tokenPoolPrices, setTokenPoolPrices] = useConfigReducer('tokenPoolPrices');

return useQuery({
initialData: tokenPoolPrices,
// make unique
queryKey: ['tokenPoolPrices'],
queryFn: async () => {
const prices = await getTokenPrices();
if (Object.keys(prices).length === 0) return tokenPoolPrices;
setTokenPoolPrices(prices);
return prices;
}
});
};

export const getTokenPrices = async () => {
const res = await axios.get('/prices/pool-tokens');
return res.data;
};

getTokenPrices();
2 changes: 2 additions & 0 deletions src/layouts/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import './index.scss';
import Menu from './Menu';
import { NoticeBanner } from './NoticeBanner';
import Sidebar from './Sidebar';
import { useGetTokenPoolPrices } from 'hooks/useGetTokenPoolPrices';

const App = () => {
const [address, setOraiAddress] = useConfigReducer('address');
Expand All @@ -56,6 +57,7 @@ const App = () => {
const solanaWallet = useWallet();

useTronEventListener();
useGetTokenPoolPrices();

// init TON
useEffect(() => {
Expand Down
5 changes: 3 additions & 2 deletions src/libs/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
COSMOS_CHAIN_ID_COMMON,
TokenItemType,
getSubAmountDetails,
parseTokenInfoRawDenom,
toAmount,
toDisplay
} from '@oraichain/oraidex-common';
Expand Down Expand Up @@ -41,13 +42,13 @@ export const getUsd = (
return toDisplay(amount, tokenInfo.decimals) * (prices[tokenInfo.coinGeckoId] ?? 0);
};

export const getTotalUsd = (amounts: AmountDetails, prices: CoinGeckoPrices<string>): number => {
export const getTotalUsd = (amounts: AmountDetails, prices: CoinGeckoPrices<string>, pricesViaPool = {}): number => {
let usd = 0;
for (const denom in amounts) {
const tokenInfo = tokenMap[denom];
if (!tokenInfo) continue;
const amount = toDisplay(amounts[denom], tokenInfo.decimals);
usd += amount * (prices[tokenInfo.coinGeckoId] ?? 0);
usd += amount * (prices[tokenInfo.coinGeckoId] ?? pricesViaPool?.[parseTokenInfoRawDenom(tokenInfo)] ?? 0);
}
return usd;
};
Expand Down
6 changes: 4 additions & 2 deletions src/pages/Balance/TransferConvertToken/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NetworkChainId } from '@oraichain/common';
import { BigDecimal, BTC_CONTRACT, toDisplay, TokenItemType } from '@oraichain/oraidex-common';
import { BigDecimal, BTC_CONTRACT, parseTokenInfoRawDenom, toDisplay, TokenItemType } from '@oraichain/oraidex-common';
import loadingGif from 'assets/gif/loading.gif';
import ArrowDownIcon from 'assets/icons/arrow.svg?react';
import ArrowDownIconLight from 'assets/icons/arrow_light.svg?react';
Expand Down Expand Up @@ -72,6 +72,7 @@ const TransferConvertToken: FC<TransferConvertProps> = ({
const { data: prices } = useCoinGeckoPrices();
const [walletByNetworks] = useWalletReducer('walletsByNetwork');
const contractConfig = useGetContractConfig();
const [tokenPoolPrices] = useConfigReducer('tokenPoolPrices');

useEffect(() => {
if (chainInfo) setConvertAmount([undefined, 0]);
Expand Down Expand Up @@ -417,7 +418,8 @@ const TransferConvertToken: FC<TransferConvertProps> = ({
}}
onValueChange={({ floatValue }) => {
if (!floatValue) return setConvertAmount([undefined, 0]);
const usdValue = floatValue * (prices[token.coinGeckoId] ?? 0);
const usdValue =
floatValue * (prices[token.coinGeckoId] ?? tokenPoolPrices[parseTokenInfoRawDenom(token)] ?? 0);
setConvertAmount([floatValue!, usdValue]);
}}
className={classNames(styles.amount, styles[theme])}
Expand Down
8 changes: 6 additions & 2 deletions src/pages/Balance/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
getTokenOnOraichain,
ORAI,
ORAI_SOL_CONTRACT_ADDRESS,
parseTokenInfoRawDenom,
solChainId,
toAmount,
toDisplay,
Expand Down Expand Up @@ -147,6 +148,7 @@ const Balance: React.FC<BalanceProps> = () => {

const [filterNetworkUI, setFilterNetworkUI] = useConfigReducer('filterNetwork');
const [hideOtherSmallAmount, setHideOtherSmallAmount] = useConfigReducer('hideOtherSmallAmount');
const [tokenPoolPrices] = useConfigReducer('tokenPoolPrices');

const {
metamaskAddress,
Expand Down Expand Up @@ -771,7 +773,7 @@ const Balance: React.FC<BalanceProps> = () => {
return getFilterTokens(filterNetworkUI);
}, [filterNetworkUI, otherChainTokens, oraichainTokens]);

const totalUsd = getTotalUsd(amounts, prices);
const totalUsd = getTotalUsd(amounts, prices, tokenPoolPrices);

// Move oraib2oraichain
const [moveOraib2OraiLoading, setMoveOraib2OraiLoading] = useState(false);
Expand Down Expand Up @@ -895,7 +897,9 @@ const Balance: React.FC<BalanceProps> = () => {
listTokens.map((t: TokenItemType) => {
// check balance cw20
let amount = BigInt(amounts[t.denom] ?? 0);
let usd = getUsd(amount, t, prices);

const tokenPrice = prices[t.coinGeckoId] ?? tokenPoolPrices[parseTokenInfoRawDenom(t)] ?? 0;
let usd = getUsd(amount, t, prices, tokenPrice);
let subAmounts: AmountDetails;
if (t.contractAddress && t.evmDenoms) {
subAmounts = getSubAmountDetails(amounts, t);
Expand Down
19 changes: 16 additions & 3 deletions src/pages/Pool-V3/components/CreatePoolForm/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { BigDecimal, toAmount, toDisplay, TokenItemType, CW20_DECIMALS } from '@oraichain/oraidex-common';
import {
BigDecimal,
toAmount,
toDisplay,
TokenItemType,
CW20_DECIMALS,
parseTokenInfoRawDenom
} from '@oraichain/oraidex-common';
import {
FeeTier,
PoolKey,
Expand Down Expand Up @@ -147,8 +154,14 @@ const CreatePoolForm: FC<CreatePoolFormProps> = ({ tokenFrom, tokenTo, feeTier,

const [amountTo, setAmountTo] = useState<number | string>();
const [amountFrom, setAmountFrom] = useState<number | string>();
const fromUsd = (prices?.[tokenFrom?.coinGeckoId] * Number(amountFrom || 0)).toFixed(6);
const toUsd = (prices?.[tokenTo?.coinGeckoId] * Number(amountTo || 0)).toFixed(6);
const [tokenPoolPrices] = useConfigReducer('tokenPoolPrices');

const fromUsd = (
prices?.[tokenFrom?.coinGeckoId] ?? tokenPoolPrices?.[parseTokenInfoRawDenom(tokenFrom)] * Number(amountFrom || 0)
).toFixed(6);
const toUsd = (
prices?.[tokenTo?.coinGeckoId] ?? tokenPoolPrices?.[parseTokenInfoRawDenom(tokenTo)] * Number(amountTo || 0)
).toFixed(6);

const isLightTheme = theme === 'light';
const TokenFromIcon =
Expand Down
7 changes: 4 additions & 3 deletions src/pages/Pool-V3/components/SelectToken/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TokenItemType, truncDecimals } from '@oraichain/oraidex-common';
import { parseTokenInfoRawDenom, TokenItemType, truncDecimals } from '@oraichain/oraidex-common';
import CloseIcon from 'assets/icons/close-icon.svg?react';
import ArrowIcon from 'assets/icons/ic_arrow_down.svg?react';
import NoResultDark from 'assets/images/no-result-dark.svg?react';
Expand Down Expand Up @@ -41,6 +41,7 @@ const SelectToken = ({

const dispatch = useDispatch();
const allOraichainTokens = useSelector((state: RootState) => state.token.allOraichainTokens || []);
const [tokenPoolPrices] = useConfigReducer('tokenPoolPrices');

// useEffect(() => {
// if (listItems.length === 0 && textSearch) {
Expand Down Expand Up @@ -152,8 +153,8 @@ const SelectToken = ({
sumAmount = toSumDisplay(sumAmountDetails);
}
const balance = sumAmount > 0 ? sumAmount.toFixed(truncDecimals) : '0';
const usd =
sumAmount > 0 && token && prices[token.coinGeckoId] ? sumAmount * prices[token.coinGeckoId] : '0';
const tokenPrice = prices[token.coinGeckoId] ?? tokenPoolPrices[parseTokenInfoRawDenom(token)] ?? 0;
const usd = sumAmount > 0 && token ? sumAmount * tokenPrice : '0';

return {
...token,
Expand Down
11 changes: 7 additions & 4 deletions src/pages/Pool-V3/components/TransactionHistory/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,8 @@ const TransactionHistory = ({
quoteToken: TokenItemType;
poolKey: string;
}) => {

const [theme] = useConfigReducer('theme');
const mobileMode = isMobile();
const { data: prices } = useCoinGeckoPrices();

let [BaseTokenIcon, QuoteTokenIcon] = [OraiIcon, OraiIcon];

Expand Down Expand Up @@ -57,7 +55,6 @@ const TransactionHistory = ({
const offerToken = item.offerDenom === baseDenom ? baseToken : quoteToken;
const returnToken = item.askDenom === quoteDenom ? quoteToken : baseToken;


if (offerToken) BaseTokenIcon = theme === 'light' ? offerToken.iconLight : offerToken.icon;
if (returnToken) QuoteTokenIcon = theme === 'light' ? returnToken.iconLight : returnToken.icon;

Expand Down Expand Up @@ -190,7 +187,13 @@ const TransactionHistory = ({
</td>
<td className={`${styles.receive}`}>
<div className={styles.amount}>
<img style={{ borderRadius: '100%' }} src={QuoteTokenIcon} width={20} height={20} alt="" />
<img
style={{ borderRadius: '100%' }}
src={QuoteTokenIcon}
width={20}
height={20}
alt=""
/>
<span>
{numberWithCommas(toDisplay(item.returnAmount), undefined, {
maximumFractionDigits: 6
Expand Down
22 changes: 17 additions & 5 deletions src/pages/Pools/NewPoolModal/NewPoolModal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FACTORY_V2_CONTRACT, toDisplay, TokenItemType } from '@oraichain/oraidex-common';
import { FACTORY_V2_CONTRACT, parseTokenInfoRawDenom, toDisplay, TokenItemType } from '@oraichain/oraidex-common';
import { Asset, AssetInfo } from '@oraichain/oraidex-contracts-sdk';
import { useQuery } from '@tanstack/react-query';
import IcBack from 'assets/icons/ic_back.svg?react';
Expand Down Expand Up @@ -52,6 +52,7 @@ const NewPoolModal: FC<ModalProps> = ({ isOpen, close, open }) => {
const amounts = useSelector((state: RootState) => state.token.amounts);
const theme = useTheme();
const [walletAddress] = useConfigReducer('address');
const [tokenPoolPrices] = useConfigReducer('tokenPoolPrices');

const tokenObj1 = (allOraichainTokens || []).find((token) => token?.denom === token1);
const tokenObj2 = (allOraichainTokens || []).find((token) => token?.denom === token2);
Expand Down Expand Up @@ -230,6 +231,15 @@ const NewPoolModal: FC<ModalProps> = ({ isOpen, close, open }) => {
}
};

const token1Price = tokenObj1
? prices[tokenObj1?.coinGeckoId] ?? tokenPoolPrices[parseTokenInfoRawDenom(tokenObj1)] ?? 0
: 0;
const token2Price = tokenObj2
? prices[tokenObj2?.coinGeckoId] ?? tokenPoolPrices[parseTokenInfoRawDenom(tokenObj2)] ?? 0
: 0;

console.log({ amountToken1 });

const step1Component = (
<>
<div className={cx('supply', theme)}>
Expand Down Expand Up @@ -307,7 +317,7 @@ const NewPoolModal: FC<ModalProps> = ({ isOpen, close, open }) => {
MAX
</div>
<TokenBalance
balance={getBalanceValue(token1InfoData?.symbol ?? '', amountToken1)}
balance={amountToken1 * token1Price}
style={{ flexGrow: 1, textAlign: 'right' }}
decimalScale={2}
/>
Expand Down Expand Up @@ -390,7 +400,7 @@ const NewPoolModal: FC<ModalProps> = ({ isOpen, close, open }) => {
MAX
</div>
<TokenBalance
balance={getBalanceValue(token2InfoData?.symbol ?? '', amountToken2)}
balance={amountToken2 * token2Price}
style={{ flexGrow: 1, textAlign: 'right' }}
decimalScale={2}
/>
Expand Down Expand Up @@ -432,7 +442,8 @@ const NewPoolModal: FC<ModalProps> = ({ isOpen, close, open }) => {
<span className={cx('stats_info_name', theme)}>{token1InfoData?.symbol}</span>
<div>
<TokenBalance
balance={getBalanceValue(token1InfoData?.symbol ?? '', +amountToken1)}
balance={amountToken1 * token1Price}
// balance={getBalanceValue(token1InfoData?.symbol ?? '', +amountToken1)}
className={cx('stats_info_value_usd', theme)}
decimalScale={2}
/>
Expand All @@ -452,7 +463,8 @@ const NewPoolModal: FC<ModalProps> = ({ isOpen, close, open }) => {
<span className={cx('stats_info_name', theme)}>{token2InfoData?.symbol}</span>
<div>
<TokenBalance
balance={getBalanceValue(token2InfoData?.symbol ?? '', +amountToken2)}
balance={amountToken2 * token2Price}
// balance={getBalanceValue(token2InfoData?.symbol ?? '', +amountToken2)}
className={cx('stats_info_value_usd', theme)}
decimalScale={2}
/>
Expand Down
3 changes: 1 addition & 2 deletions src/pages/Pools/NewTokenModal/NewTokenModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import {

import { inspectToken, optimisticUpdateToken } from 'reducer/onchainTokens';
import { GasPrice } from '@cosmjs/stargate';
import { OraichainNetworkConfig } from '@oraichain/orai-token-inspector';

const cx = cn.bind(styles);
// const TOKEN_FACTORY_CONTRACT = 'orai1ytjgzxvtsq3ukhzmt39cp85j27zzqf5y706y9qrffrnpn3vd3uds957ydu';
Expand Down Expand Up @@ -206,7 +205,7 @@ const NewTokenModal: FC<ModalProps> = ({ isOpen, close, open }) => {
chainId: network.chainId,
cosmosBased: true,
contractAddress: '',
coinType: OraichainNetworkConfig.coinType,
coinType: network.coinType,
description: description,
feeCurrencies: network.feeCurrencies,
gasPriceStep: network.feeCurrencies[0].gasPriceStep,
Expand Down
Loading

0 comments on commit 943febf

Please sign in to comment.