From 518995f8871f115005bc9fe8ab152d560a497790 Mon Sep 17 00:00:00 2001 From: Hau Nguyen Van Date: Wed, 31 Jan 2024 14:59:46 +0700 Subject: [PATCH 1/3] fix ui relayer fee native evm + friendly msg slippage + fix crash websocket decimals undefined --- src/config/chainInfos.ts | 4 ++- src/helper/index.tsx | 3 +- src/hooks/useTokenFee.ts | 35 +++++++++++-------- src/libs/utils.ts | 4 +-- src/pages/UniversalSwap/SwapV3/index.tsx | 44 ++++++++++-------------- 5 files changed, 46 insertions(+), 44 deletions(-) diff --git a/src/config/chainInfos.ts b/src/config/chainInfos.ts index b0702ee8c..d4e3913af 100644 --- a/src/config/chainInfos.ts +++ b/src/config/chainInfos.ts @@ -835,7 +835,8 @@ export const chainInfos: CustomChainInfo[] = [ coinDecimals: 18, bridgeTo: ['Oraichain'], coinGeckoId: 'ethereum', - Icon: EthIcon + Icon: EthIcon, + prefixToken: ORAI_BRIDGE_EVM_ETH_DENOM_PREFIX }, { coinDenom: 'USDT', @@ -957,6 +958,7 @@ export const chainInfos: CustomChainInfo[] = [ coinDecimals: 18, coinGeckoId: 'binancecoin', bridgeTo: ['Oraichain'], + prefixToken: ORAI_BRIDGE_EVM_DENOM_PREFIX, Icon: BnbIcon } ] diff --git a/src/helper/index.tsx b/src/helper/index.tsx index 6959c8b92..b87d1441a 100644 --- a/src/helper/index.tsx +++ b/src/helper/index.tsx @@ -93,7 +93,7 @@ export const getNetworkGasPrice = async (chainId): Promise => { if (findToken) { return findToken.feeCurrencies[0].gasPriceStep.average; } - } catch {} + } catch { } return 0; }; @@ -161,6 +161,7 @@ export const handleCheckAddress = async (chainId: CosmosChainId): Promise { if (message.includes('invalid hash')) return `Transation was not included to block`; + if (message.includes("Assertion failed; minimum receive amount")) return `Because of high demand, You can increase slippage to increase success rate of the swap!`; if (message.includes("Cannot read properties of undefined (reading 'signed')")) return `User rejected transaction`; if (message.includes('account sequence mismatch')) return `Your previous transaction has not been included in a block. Please wait until it is included before creating a new transaction!`; diff --git a/src/hooks/useTokenFee.ts b/src/hooks/useTokenFee.ts index 2f22317c1..21365ad40 100644 --- a/src/hooks/useTokenFee.ts +++ b/src/hooks/useTokenFee.ts @@ -5,7 +5,9 @@ import { oraichainTokens, toDisplay, toAmount, - BigDecimal + BigDecimal, + ORAI_BRIDGE_EVM_ETH_DENOM_PREFIX, + ORAI_BRIDGE_EVM_DENOM_PREFIX } from '@oraichain/oraidex-common'; import { OraiswapRouterQueryClient } from '@oraichain/oraidex-contracts-sdk'; import { handleSimulateSwap, isEvmNetworkNativeSwapSupported } from '@oraichain/oraidex-universal-swap'; @@ -34,7 +36,15 @@ export default function useTokenFee( if (isEvmNetworkNativeSwapSupported(fromChainId) && fromChainId === toChainId) return; const { token_fees: tokenFees } = feeConfig; - const tokenFee = tokenFees.find((tokenFee) => tokenFee.token_denom === remoteTokenDenom); + const isNativeEth = remoteTokenDenom === 'eth'; + const isNativeBnb = remoteTokenDenom === 'bnb'; + const tokenFee = tokenFees.find( + (tokenFee) => + tokenFee.token_denom === remoteTokenDenom || + // TODO + (isNativeEth && tokenFee.token_denom.includes(ORAI_BRIDGE_EVM_ETH_DENOM_PREFIX)) || + (isNativeBnb && tokenFee.token_denom.includes(ORAI_BRIDGE_EVM_DENOM_PREFIX)) + ); if (tokenFee) fee = (tokenFee.ratio.nominator / tokenFee.ratio.denominator) * 100; setBridgeFee(fee); @@ -47,18 +57,16 @@ 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 routerClient = new OraiswapRouterQueryClient(window.client, network.router); - const oraiToken = oraichainTokens.find((token) => token.coinGeckoId === 'oraichain-token'); - const isWeth = originalToToken?.coinGeckoId === 'weth'; - const CONSTANTS_ORAI_SIMULATE_WETH = 10; 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({ originalFromInfo: oraiToken, originalToInfo: originalToToken, - originalAmount: isWeth ? CONSTANTS_ORAI_SIMULATE_WETH : relayerFeeInOrai, + originalAmount: relayerFeeInOrai, routerClient }); }, @@ -69,19 +77,16 @@ export const useRelayerFeeToken = (originalFromToken: TokenItemType, originalToT // get relayer fee in token, by simulate orai vs to token. useEffect(() => { - if (relayerFeeAmount) - setRelayerFeeAmount( - new BigDecimal(relayerFeeAmount.displayAmount).div(isWeth ? CONSTANTS_ORAI_SIMULATE_WETH : 1).toNumber() - ); + if (relayerFeeAmount) setRelayerFeeAmount(new BigDecimal(relayerFeeAmount.displayAmount).toNumber()); }, [relayerFeeAmount]); // get relayer fee in ORAI useEffect(() => { if (!originalFromToken || !originalToToken || !feeConfig) return; - const isFromChainIdEvm = EVM_CHAIN_ID.includes(originalFromToken.chainId); - const isToChainIdEvm = EVM_CHAIN_ID.includes(originalToToken.chainId); - - if (isToChainIdEvm && isFromChainIdEvm === isToChainIdEvm) { + if ( + isEvmNetworkNativeSwapSupported(originalFromToken.chainId) && + originalFromToken.chainId === originalToToken.chainId + ) { setRelayerFeeAmount(0); setRelayerFeeInOrai(0); return; diff --git a/src/libs/utils.ts b/src/libs/utils.ts index 9330ee5a8..3d594a373 100644 --- a/src/libs/utils.ts +++ b/src/libs/utils.ts @@ -179,8 +179,8 @@ export const processWsResponseMsg = (message: any): string => { // we look for the true denom information with decimals to process // format: {"amount":"100000000000000","denom":"oraib0xA325Ad6D9c92B55A3Fc5aD7e412B1518F96441C0","receiver":"orai...","sender":"oraib..."} const receivedToken = cosmosTokens.find((token) => token.denom === packet.denom); - const displayAmount = toDisplay(packet.amount, receivedToken.decimals); - tokens = tokens.concat(`${displayAmount} ${receivedToken.name}, `); + const displayAmount = toDisplay(packet?.amount, receivedToken?.decimals); + tokens = tokens.concat(`${displayAmount} ${receivedToken?.name}, `); } return tokens.substring(0, tokens.length - 2); // remove , due to concat } diff --git a/src/pages/UniversalSwap/SwapV3/index.tsx b/src/pages/UniversalSwap/SwapV3/index.tsx index 028cd777f..e8b5caae6 100644 --- a/src/pages/UniversalSwap/SwapV3/index.tsx +++ b/src/pages/UniversalSwap/SwapV3/index.tsx @@ -132,13 +132,15 @@ const SwapComponent: React.FC<{ ? tokenMap[toTokenDenom] : getTokenOnOraichain(tokenMap[toTokenDenom].coinGeckoId) ?? tokenMap[toTokenDenom]; + const remoteTokenDenomFrom = originalFromToken.contractAddress ? originalFromToken.prefix + originalFromToken.contractAddress : originalFromToken.denom; + const remoteTokenDenomTo = originalToToken.contractAddress ? originalToToken.prefix + originalToToken.contractAddress : originalToToken.denom; const fromTokenFee = useTokenFee( - originalFromToken.prefix + originalFromToken.contractAddress, + remoteTokenDenomFrom, fromToken.chainId, toToken.chainId ); const toTokenFee = useTokenFee( - originalToToken.prefix + originalToToken.contractAddress, + remoteTokenDenomTo, fromToken.chainId, toToken.chainId ); @@ -188,19 +190,12 @@ const SwapComponent: React.FC<{ // TODO: use this constant so we can temporary simulate for all pair (specifically AIRI/USDC, ORAIX/USDC), update later after migrate contract const isFromAiriToUsdc = originalFromToken.coinGeckoId === 'airight' && originalToToken.coinGeckoId === 'usd-coin'; - const isFromOraixToUsdc = originalFromToken.coinGeckoId === 'oraidex' && originalToToken.coinGeckoId === 'usd-coin'; - const isToWETH = originalToToken.coinGeckoId === 'weth'; - - const isFromUsdc = originalFromToken.coinGeckoId === 'usd-coin'; - const INIT_SIMULATE_THOUNDSAND_AMOUNT = 1000; - const INIT_SIMULATE_TEN_AMOUNT = 10; - const INIT_AMOUNT = - isFromAiriToUsdc || isFromOraixToUsdc || isToWETH - ? INIT_SIMULATE_THOUNDSAND_AMOUNT - : isFromUsdc - ? INIT_SIMULATE_TEN_AMOUNT - : 1; + let INIT_AMOUNT = 1; + + if (isFromAiriToUsdc) { + INIT_AMOUNT = INIT_SIMULATE_THOUNDSAND_AMOUNT; + } const { simulateData: averageRatio } = useSimulate( 'simulate-average-data', @@ -234,12 +229,12 @@ const SwapComponent: React.FC<{ const isSimulateDataDisplay = simulateData && simulateData.displayAmount; const minimumReceive = isAverageRatio ? calculateMinReceive( - // @ts-ignore - Math.trunc(new BigDecimal(averageRatio.amount) / INIT_AMOUNT).toString(), - fromAmountTokenBalance.toString(), - userSlippage, - originalFromToken.decimals - ) + // @ts-ignore + Math.trunc(new BigDecimal(averageRatio.amount) / INIT_AMOUNT).toString(), + fromAmountTokenBalance.toString(), + userSlippage, + originalFromToken.decimals + ) : '0'; const isWarningSlippage = +minimumReceive > +simulateData?.amount; const simulateDisplayAmount = simulateData && simulateData.displayAmount ? simulateData.displayAmount : 0; @@ -250,8 +245,8 @@ const SwapComponent: React.FC<{ const minimumReceiveDisplay = isSimulateDataDisplay ? new BigDecimal( - simulateDisplayAmount - (simulateDisplayAmount * userSlippage) / 100 - relayerFee - bridgeTokenFee - ).toNumber() + simulateDisplayAmount - (simulateDisplayAmount * userSlippage) / 100 - relayerFee - bridgeTokenFee + ).toNumber() : 0; const expectOutputDisplay = isSimulateDataDisplay @@ -442,9 +437,8 @@ const SwapComponent: React.FC<{ />
- {`1 ${originalFromToken.name} ≈ ${ - averageRatio ? Number((averageRatio.displayAmount / INIT_AMOUNT).toFixed(6)) : '0' - } ${originalToToken.name}`} + {`1 ${originalFromToken.name} ≈ ${averageRatio ? Number((averageRatio.displayAmount / INIT_AMOUNT).toFixed(6)) : '0' + } ${originalToToken.name}`}
From d4bdf2d035dea5f25ea7bb305d514e1b8cd1cc7e Mon Sep 17 00:00:00 2001 From: Hau Nguyen Van Date: Wed, 31 Jan 2024 15:03:56 +0700 Subject: [PATCH 2/3] fix: unit test pool --- src/tests/pool.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/pool.spec.ts b/src/tests/pool.spec.ts index d9a16f0cb..1e4ad7591 100644 --- a/src/tests/pool.spec.ts +++ b/src/tests/pool.spec.ts @@ -60,7 +60,7 @@ describe('pool', () => { it('test Pairs getPoolTokens', () => { const poolTokens = getPoolTokens(); expect(Array.isArray(poolTokens)).toBe(true); - expect(poolTokens.length).toBe(14); + expect(poolTokens.length).toBe(15); }); it.each([ From a6084d6aa736db585babe77306d2e0ad4f38e12a Mon Sep 17 00:00:00 2001 From: trungbach Date: Fri, 2 Feb 2024 14:08:11 +0700 Subject: [PATCH 3/3] chore: add try catch --- src/libs/utils.ts | 48 +++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/src/libs/utils.ts b/src/libs/utils.ts index 45a66efae..28a6d81a8 100644 --- a/src/libs/utils.ts +++ b/src/libs/utils.ts @@ -161,30 +161,34 @@ export const buildUnsubscribeMessage = () => { }; export const processWsResponseMsg = (message: any): string => { - if (message === null || message.result === null) { - return null; - } - const { result } = message; - if ( - result && // 👈 null and undefined check - (Object.keys(result).length !== 0 || result.constructor !== Object) - ) { - if (!result.events) return null; - const events = result.events; - const packets = events['recv_packet.packet_data']; - if (!packets) return null; - let tokens = ''; - for (let packetRaw of packets) { - const packet = JSON.parse(packetRaw); - // we look for the true denom information with decimals to process - // format: {"amount":"100000000000000","denom":"oraib0xA325Ad6D9c92B55A3Fc5aD7e412B1518F96441C0","receiver":"orai...","sender":"oraib..."} - const receivedToken = cosmosTokens.find((token) => token.denom === packet.denom); - const displayAmount = toDisplay(packet?.amount, receivedToken?.decimals); - tokens = tokens.concat(`${displayAmount} ${receivedToken?.name}, `); + try { + if (message === null || message.result === null) { + return null; } - return tokens.substring(0, tokens.length - 2); // remove , due to concat + const { result } = message; + if ( + result && // 👈 null and undefined check + (Object.keys(result).length !== 0 || result.constructor !== Object) + ) { + if (!result.events) return null; + const events = result.events; + const packets = events['recv_packet.packet_data']; + if (!packets) return null; + let tokens = ''; + for (let packetRaw of packets) { + const packet = JSON.parse(packetRaw); + // we look for the true denom information with decimals to process + // format: {"amount":"100000000000000","denom":"oraib0xA325Ad6D9c92B55A3Fc5aD7e412B1518F96441C0","receiver":"orai...","sender":"oraib..."} + const receivedToken = cosmosTokens.find((token) => token.denom === packet.denom); + const displayAmount = toDisplay(packet?.amount, receivedToken?.decimals); + tokens = tokens.concat(`${displayAmount} ${receivedToken?.name}, `); + } + return tokens.substring(0, tokens.length - 2); // remove , due to concat + } + return null; + } catch (error) { + console.error({ errorProcessWsResponseMsg: error }); } - return null; }; export const generateError = (message: string) => {