Skip to content

Commit

Permalink
Merge pull request #26 from oraichain/update/swap
Browse files Browse the repository at this point in the history
update universal swap
  • Loading branch information
haunv3 authored Oct 28, 2024
2 parents c97625f + afa517c commit 142fccc
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 132 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"@oraichain/oraidex-common": "^1.1.23",
"@oraichain/oraidex-common-ui": "1.0.11",
"@oraichain/oraidex-contracts-sdk": "^1.0.26",
"@oraichain/oraidex-universal-swap": "1.1.14",
"@oraichain/oraidex-universal-swap": "1.1.15",
"@reduxjs/toolkit": "^1.9.3",
"@sentry/react": "^7.47.0",
"@tanstack/react-query": "^4.32.6",
Expand Down
63 changes: 32 additions & 31 deletions src/hooks/useTokenFee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@ import {
toAmount,
BigDecimal,
ORAI_BRIDGE_EVM_ETH_DENOM_PREFIX,
ORAI_BRIDGE_EVM_DENOM_PREFIX
ORAI_BRIDGE_EVM_DENOM_PREFIX,
PEPE_BSC_CONTRACT,
PEPE_ETH_CONTRACT
} from '@oraichain/oraidex-common';
import { OraiswapRouterQueryClient } from '@oraichain/oraidex-contracts-sdk';
import { handleSimulateSwap, isEvmNetworkNativeSwapSupported } from '@oraichain/oraidex-universal-swap';
import { handleSimulateSwap, UniversalSwapHelper } from '@oraichain/oraidex-universal-swap';
import { useQuery } from '@tanstack/react-query';
import { EVM_CHAIN_ID } from 'helper';
import { getProtocolsSmartRoute, isAllowAlphaIbcWasm, isAllowIBCWasm } from 'pages/UniversalSwap/helpers';
import { getRouterConfig } from 'pages/UniversalSwap/Swap/hooks';
import { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { updateFeeConfig } from 'reducer/token';
Expand All @@ -33,7 +37,7 @@ export default function useTokenFee(

// since we have supported evm swap, tokens that are on the same supported evm chain id
// don't have any token fees (because they are not bridged to Oraichain)
if (isEvmNetworkNativeSwapSupported(fromChainId) && fromChainId === toChainId) return;
if (UniversalSwapHelper.isEvmNetworkNativeSwapSupported(fromChainId) && fromChainId === toChainId) return;

const { token_fees: tokenFees } = feeConfig;
const isNativeEth = remoteTokenDenom === 'eth';
Expand All @@ -58,34 +62,55 @@ export const useRelayerFeeToken = (originalFromToken: TokenItemType, originalToT
const [relayerFeeInOrai, setRelayerFeeInOrai] = useState(0);
const [relayerFee, setRelayerFeeAmount] = useState(0);
const feeConfig = useSelector((state: RootState) => state.token.feeConfigs);
const isFromPepeToken =
originalFromToken?.contractAddress &&
[PEPE_BSC_CONTRACT, PEPE_ETH_CONTRACT].includes(originalFromToken?.contractAddress);

const useAlphaIbcWasm = isAllowAlphaIbcWasm(originalFromToken, originalToToken);
const useIbcWasm = isAllowIBCWasm(originalFromToken, originalToToken);
const protocols = getProtocolsSmartRoute(originalFromToken, originalToToken, { useIbcWasm, useAlphaIbcWasm });
const simulateOption = {
useAlphaIbcWasm,
useIbcWasm,
protocols,
maxSplits: useAlphaIbcWasm ? 1 : 10,
dontAllowSwapAfter: useAlphaIbcWasm ? [''] : undefined,
ignoreFee: true
};

const { data: relayerFeeAmount } = useQuery(
['simulate-relayer-data', originalFromToken, originalToToken, relayerFeeInOrai],
() => {
const routerClient = new OraiswapRouterQueryClient(window.client, network.router);
const oraiToken = oraichainTokens.find((token) => token.coinGeckoId === 'oraichain-token');
return handleSimulateSwap({
return UniversalSwapHelper.handleSimulateSwap({
originalFromInfo: oraiToken,
originalToInfo: originalToToken,
originalAmount: relayerFeeInOrai,
routerClient
routerClient,
routerOption: {
useIbcWasm,
useAlphaIbcWasm
},
routerConfig: getRouterConfig(simulateOption)
});
},
{
enabled: !!originalFromToken && !!originalToToken && relayerFeeInOrai > 0
enabled: !!originalFromToken && !!originalToToken && relayerFeeInOrai > 0 && !isFromPepeToken
}
);

// get relayer fee in token, by simulate orai vs to token.
useEffect(() => {
if (isFromPepeToken) return setRelayerFeeAmount(0);
if (relayerFeeAmount) setRelayerFeeAmount(new BigDecimal(relayerFeeAmount?.displayAmount || 0).toNumber());
}, [relayerFeeAmount]);

// get relayer fee in ORAI
useEffect(() => {
if (!originalFromToken || !originalToToken || !feeConfig) return;
if (
isEvmNetworkNativeSwapSupported(originalFromToken.chainId) &&
UniversalSwapHelper.isEvmNetworkNativeSwapSupported(originalFromToken.chainId) &&
originalFromToken.chainId === originalToToken.chainId
) {
setRelayerFeeAmount(0);
Expand All @@ -112,30 +137,6 @@ export const useRelayerFeeToken = (originalFromToken: TokenItemType, originalToT
relayerFeeInOraiToAmount: toAmount(relayerFeeInOrai)
};
};
export const useUsdtToBtc = (amount) => {
const routerClient = new OraiswapRouterQueryClient(window.client, network.router);
const originalFromToken = oraichainTokens.find((token) => token.coinGeckoId === 'tether');
const originalToToken = oraichainTokens.find((token) => token.coinGeckoId === 'bitcoin');
const { data } = useQuery(
['convert-btc-to-usdt', originalFromToken, originalToToken],
() => {
return handleSimulateSwap({
originalFromInfo: originalToToken,
originalToInfo: originalFromToken,
originalAmount: amount,
routerClient
});
},
{
enabled: !!originalFromToken && !!originalToToken && !!amount,
placeholderData: {
displayAmount: 0,
amount: '0'
}
}
);
return data;
};

export const useGetFeeConfig = () => {
const dispatch = useDispatch();
Expand Down
6 changes: 3 additions & 3 deletions src/pages/UniversalSwap/Swap/hooks/useCalculateDataSwap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
getProtocolsSmartRoute,
getRemoteDenom,
isAllowAlphaIbcWasm,
isAllowAlphaSmartRouter,
isAllowIBCWasm
} from 'pages/UniversalSwap/helpers';
import { fetchTokenInfos } from 'rest/api';
Expand Down Expand Up @@ -74,7 +73,7 @@ const useCalculateDataSwap = ({ originalFromToken, originalToToken, fromToken, t
}
);

const { simulateData: averageSimulateData } = useSimulate(
const { simulateData: averageSimulateData, isPreviousSimulate: isAveragePreviousSimulate } = useSimulate(
'average-simulate-data',
fromTokenInfoData,
toTokenInfoData,
Expand Down Expand Up @@ -185,7 +184,8 @@ const useCalculateDataSwap = ({ originalFromToken, originalToToken, fromToken, t

averageSimulateDatas: {
averageRatio,
averageSimulateData
averageSimulateData,
isAveragePreviousSimulate
},

simulateDatas: {
Expand Down
17 changes: 17 additions & 0 deletions src/pages/UniversalSwap/Swap/index.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,23 @@
}
}

.swap-ai-dot {
display: flex;
flex-direction: column;
align-items: end;
gap: 8px;
.noRoutes {
color: $warning-color;
text-align: right;
font-family: 'IBM Plex Sans';
font-size: 12px;
font-style: normal;
font-weight: 700;
line-height: 150%;
letter-spacing: 0.013px;
}
}

.ratio {
@include theme() {
color: theme-get('colors-neutral-text-text-token-name');
Expand Down
125 changes: 59 additions & 66 deletions src/pages/UniversalSwap/Swap/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ import {
getTokenBalance,
getTokenInfo,
isAllowAlphaIbcWasm,
isAllowAlphaSmartRouter,
isAllowIBCWasm,
refreshBalances
} from 'pages/UniversalSwap/helpers';
Expand Down Expand Up @@ -171,7 +170,7 @@ const SwapComponent: React.FC<{
} = fees;
const { expectOutputDisplay, minimumReceiveDisplay, isWarningSlippage } = outputs;
const { fromAmountTokenBalance, usdPriceShowFrom, usdPriceShowTo } = tokenInfos;
const { averageRatio, averageSimulateData } = averageSimulateDatas;
const { averageRatio, averageSimulateData, isAveragePreviousSimulate } = averageSimulateDatas;
const { simulateData, setSwapAmount, fromAmountToken, toAmountToken, debouncedFromAmount, isPreviousSimulate } =
simulateDatas;

Expand Down Expand Up @@ -563,7 +562,7 @@ const SwapComponent: React.FC<{
}
${originalToToken.name}`}
</span>
{!!isRoutersSwapData && !isPreviousSimulate && (
{!!isRoutersSwapData && !isPreviousSimulate && !!routersSwapData?.routes.length && (
<img src={!openRoutes ? DownArrowIcon : UpArrowIcon} alt="arrow" />
)}
</div>
Expand All @@ -572,6 +571,56 @@ const SwapComponent: React.FC<{

const getSwitchIcon = () => (isLightMode ? SwitchLightImg : SwitchDarkImg);

const noRoutesFound =
!isAveragePreviousSimulate &&
(!averageSimulateData?.displayAmount ||
(averageSimulateData?.displayAmount &&
!averageSimulateData?.routes.routes.length &&
originalToToken.coinGeckoId !== originalFromToken.coinGeckoId));

const hasRoutesData =
!!isRoutersSwapData &&
!!averageSimulateData?.displayAmount &&
!isPreviousSimulate &&
Array.isArray(routersSwapData?.routes) &&
routersSwapData.routes.length > 0;

const volumnPercentage = (amount, returnAmount) =>
Math.round(new BigDecimal(returnAmount).div(amount).mul(100).toNumber());

const renderRoutes = (routes) => {
return routes.map((route, ind) => {
const volumn = volumnPercentage(routersSwapData.amount, route.returnAmount);
return (
<div key={ind} className={cx('smart-router-item')}>
<div className={cx('smart-router-item-volumn')}>{volumn.toFixed(0)}%</div>
{route.paths.map((path, i, acc) => {
const { NetworkFromIcon, NetworkToIcon } = getPathInfo(path, chainIcons, assets);
return (
<React.Fragment key={i}>
<div className={cx('smart-router-item-line')}>
<div className={cx('smart-router-item-line-detail')} />
</div>
<div className={cx('smart-router-item-pool')} onClick={() => setOpenSmartRoute(!openSmartRoute)}>
<div className={cx('smart-router-item-pool-wrap')} onClick={() => setIndSmartRoute([ind, i])}>
<div className={cx('smart-router-item-pool-wrap-img')}>{<NetworkFromIcon />}</div>
<div className={cx('smart-router-item-pool-wrap-img')}>{<NetworkToIcon />}</div>
</div>
</div>
{i === acc.length - 1 && (
<div className={cx('smart-router-item-line')}>
<div className={cx('smart-router-item-line-detail')} />
</div>
)}
</React.Fragment>
);
})}
<div className={cx('smart-router-item-volumn')}>{volumn.toFixed(0)}%</div>
</div>
);
});
};

return (
<div className={cx('swap-box-wrapper')}>
<LoadingBox loading={loadingRefresh} className={cx('custom-loader-root')}>
Expand Down Expand Up @@ -637,71 +686,15 @@ const SwapComponent: React.FC<{
<AIRouteSwitch isLoading={isPreviousSimulate} />
)} */}
{generateRatioComp()}
{noRoutesFound && <div className={styles.noRoutes}>NO ROUTES FOUND</div>}
</div>
</div>
{!!isRoutersSwapData &&
!!averageSimulateData?.displayAmount &&
!isPreviousSimulate &&
!!routersSwapData?.routes.length && (
<div className={cx('smart', !openRoutes ? 'hidden' : '')}>
<div className={cx('smart-router')}>
{routersSwapData?.routes.map((route, ind) => {
const volumn = Math.round(
new BigDecimal(route.returnAmount).div(routersSwapData.amount).mul(100).toNumber()
);
return (
<div key={ind} className={cx('smart-router-item')}>
<div className={cx('smart-router-item-volumn')}>{volumn.toFixed(0)}%</div>
{route.paths.map((path, i, acc) => {
const { NetworkFromIcon, NetworkToIcon } = getPathInfo(path, chainIcons, assets);
return (
<React.Fragment key={i}>
<div className={cx('smart-router-item-line')}>
<div className={cx('smart-router-item-line-detail')} />
</div>
<div
className={cx('smart-router-item-pool')}
onClick={() => setOpenSmartRoute(!openSmartRoute)}
>
<div
className={cx('smart-router-item-pool-wrap')}
onClick={() => setIndSmartRoute([ind, i])}
>
<div className={cx('smart-router-item-pool-wrap-img')}>{<NetworkFromIcon />}</div>
<div className={cx('smart-router-item-pool-wrap-img')}>{<NetworkToIcon />}</div>
</div>
</div>
{i === acc.length - 1 && (
<div className={cx('smart-router-item-line')}>
<div className={cx('smart-router-item-line-detail')} />
</div>
)}
</React.Fragment>
);
})}
<div className={cx('smart-router-item-volumn')}>{volumn.toFixed(0)}%</div>
</div>
);
})}
{/* <div className={cx('smart-router-price-impact')}>
<div className={cx('smart-router-price-impact-title')}>Price Impact:</div>
<div
className={cx(
'smart-router-price-impact-warning',
waringImpactBiggerTen
? 'smart-router-price-impact-warning-ten'
: waringImpactBiggerFive && 'smart-router-price-impact-warning-five'
)}
>
<span>
{waringImpactBiggerFive && <WarningIcon />} ≈{' '}
{numberWithCommas(impactWarning, undefined, { minimumFractionDigits: 2 })}%
</span>
</div>
</div> */}
</div>
</div>
)}
{hasRoutesData && (
<div className={cx('smart', !openRoutes ? 'hidden' : '')}>
<div className={cx('smart-router')}>{renderRoutes(routersSwapData.routes)}</div>
</div>
)}

<div className={cx('to')}>
<div className={cx('input-wrapper')}>
<InputSwap
Expand Down
Loading

0 comments on commit 142fccc

Please sign in to comment.