diff --git a/.husky/pre-commit b/.husky/pre-commit index a4c85981..7e6341b2 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -2,4 +2,4 @@ . "$(dirname -- "$0")/_/husky.sh" # use lerna isntead of yarn in windows -./node_modules/.bin/lerna run test && ./node_modules/.bin/lerna run test:e2e +./node_modules/.bin/lerna run test diff --git a/packages/dodoex-widgets/package.json b/packages/dodoex-widgets/package.json index 1452b211..787fb2c4 100644 --- a/packages/dodoex-widgets/package.json +++ b/packages/dodoex-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@dodoex/widgets", - "version": "2.6.12-beta.6", + "version": "2.6.12-beta.11", "description": "DODO Widgets", "source": "src/index.tsx", "types": "dist/src/index.d.ts", diff --git a/packages/dodoex-widgets/src/components/Bridge/BridgeSummaryDialog/BridgeSummaryDetail.tsx b/packages/dodoex-widgets/src/components/Bridge/BridgeSummaryDialog/BridgeSummaryDetail.tsx index 530bf460..b666edb1 100644 --- a/packages/dodoex-widgets/src/components/Bridge/BridgeSummaryDialog/BridgeSummaryDetail.tsx +++ b/packages/dodoex-widgets/src/components/Bridge/BridgeSummaryDialog/BridgeSummaryDetail.tsx @@ -194,35 +194,41 @@ export default function BridgeSummaryDetail({ /> )} */} - - {truncatePoolAddress(route.fromAddress)} - - - - + {route.fromAddress ? ( + <> + + {truncatePoolAddress(route.fromAddress)} + + + + + + ) : ( + '-' + )} {route.feeUSD ? ( diff --git a/packages/dodoex-widgets/src/components/Swap/components/ConnectWallet/index.tsx b/packages/dodoex-widgets/src/components/Swap/components/ConnectWallet/index.tsx index 22134235..41495990 100644 --- a/packages/dodoex-widgets/src/components/Swap/components/ConnectWallet/index.tsx +++ b/packages/dodoex-widgets/src/components/Swap/components/ConnectWallet/index.tsx @@ -44,7 +44,7 @@ export default function ConnectWallet({ size={Button.Size.middle} fullWidth onClick={async () => { - if (onConnectWalletClick) { + if (onConnectWalletClick && needConnectChainId !== ChainId.TON) { // switch chain if ( !needEvmChainId && diff --git a/packages/dodoex-widgets/src/components/Swap/index.tsx b/packages/dodoex-widgets/src/components/Swap/index.tsx index ff862bf6..d3291c54 100644 --- a/packages/dodoex-widgets/src/components/Swap/index.tsx +++ b/packages/dodoex-widgets/src/components/Swap/index.tsx @@ -7,8 +7,9 @@ import { useTheme, RotatingIcon, Tooltip, + Input, } from '@dodoex/components'; -import { formatTokenAmountNumber } from '../../utils'; +import { formatTokenAmountNumber, isAddress } from '../../utils'; import { useMemo, useState, useEffect, useCallback } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { Setting, Dodo, Warn, DoubleRight } from '@dodoex/icons'; @@ -71,16 +72,20 @@ import { import { useWalletState } from '../../hooks/ConnectWallet/useWalletState'; import { useWeb3React } from '@web3-react/core'; import useTonConnectStore from '../../hooks/ConnectWallet/TonConnect'; +import { isAndroid, isIOS } from '../../utils/device'; +import WebApp from '@twa-dev/sdk'; export interface SwapProps { /** Higher priority setting slippage */ getAutoSlippage?: GetAutoSlippage; onConnectWalletClick?: ConnectWalletProps['onConnectWalletClick']; + bridgeToTonUrl?: string; } export function Swap({ getAutoSlippage, onConnectWalletClick, + bridgeToTonUrl, }: SwapProps = {}) { const theme = useTheme(); const { isInflight } = useInflights(); @@ -158,9 +163,17 @@ export function Swap({ const insufficientBalance = useMemo(() => { const token = isReverseRouting ? toToken : fromToken; const balance = new BigNumber(token ? getBalance(token) || 0 : 0); + if ( + !(token && getBalance(token)) && + fromToken?.chainId !== ChainId.TON && + toToken?.chainId === ChainId.TON + ) { + return false; + } return balance.lt(isReverseRouting ? toAmt ?? 0 : fromAmt); }, [isReverseRouting, fromToken, toToken, fromAmt, toAmt, getBalance]); + const [receiveAddress, setReceiveAddress] = useState(''); const { bridgeRouteList, status: bridgeRouteStatus, @@ -170,6 +183,7 @@ export function Swap({ fromToken, fromAmount: fromAmt, fromFiatPrice, + toAddress: receiveAddress ? receiveAddress : undefined, }); const [switchBridgeRouteShow, setSwitchBridgeRouteShow] = useState(false); const [selectedRouteIdOrigin, setSelectRouteId] = useState(''); @@ -183,7 +197,8 @@ export function Swap({ () => bridgeRouteList.find( (route) => - route.id === selectedRouteId && route.fromAddress === account, + route.id === selectedRouteId && + (route.fromAddress === account || !account), ), [bridgeRouteList, selectedRouteId, account], ); @@ -703,18 +718,29 @@ export function Swap({ let needEvmChainId = undefined as undefined | ChainId; const isFromTon = fromToken?.chainId === ChainId.TON; const isToTon = toToken?.chainId === ChainId.TON; - if (!(isFromTon && isToTon) && (isFromTon || isToTon)) { - needEvmChainId = isFromTon ? toToken?.chainId : fromToken?.chainId; + let isNeedConnect = false; + let needSwitchChain = fromToken?.chainId; + if (isFromTon || isToTon) { + // if (window.ethereum) { + // if (!(isFromTon && isToTon)) { + // needEvmChainId = isFromTon ? toToken?.chainId : fromToken?.chainId; + // } + // isNeedConnect = + // !web3React.account || + // (fromToken?.chainId && chainId !== fromToken.chainId) || + // !tonConnect.connected; + // } else { + needSwitchChain = ChainId.TON; + isNeedConnect = !tonConnect.connected; + // } + } else { + isNeedConnect = + !account || (!!fromToken?.chainId && chainId !== fromToken.chainId); } - if ( - !account || - (fromToken?.chainId && chainId !== fromToken.chainId) || - (needEvmChainId && !tonConnect.connected) || - !web3React.account - ) + if (isNeedConnect) return ( @@ -809,22 +835,75 @@ export function Swap({ ); if (isBridge) { + const needReceiveAddress = + !web3React.account && + fromToken.chainId === ChainId.TON && + toToken.chainId !== ChainId.TON; return ( - + <> + {needReceiveAddress && ( + setReceiveAddress(e.target.value)} + errorMsg={ + !receiveAddress || isAddress(receiveAddress) + ? undefined + : 'Invalid address' + } + sx={{ + height: 48, + border: 'none', + }} + placeholder="Receive address" + /> + )} + + ); } return ( diff --git a/packages/dodoex-widgets/src/components/TokenPicker/TokenItem.tsx b/packages/dodoex-widgets/src/components/TokenPicker/TokenItem.tsx index 545a2076..0c6f706d 100644 --- a/packages/dodoex-widgets/src/components/TokenPicker/TokenItem.tsx +++ b/packages/dodoex-widgets/src/components/TokenPicker/TokenItem.tsx @@ -10,6 +10,7 @@ import { tokenPickerItem } from '../../constants/testId'; import { useTheme } from '@dodoex/components'; import { ChainId } from '../../constants/chains'; import { useWeb3React } from '@web3-react/core'; +import useTonConnectStore from '../../hooks/ConnectWallet/TonConnect'; export default function TokenItem({ token, @@ -24,7 +25,8 @@ export default function TokenItem({ }) { const theme = useTheme(); const getBalance = useGetBalance(); - const { account } = useWeb3React(); + const { account: evmAccount } = useWeb3React(); + const tonAccount = useTonConnectStore((state) => state.connected?.account); const balanceBigNumber = getBalance(token); const balance = balanceBigNumber ? formatReadableNumber({ @@ -71,7 +73,7 @@ export default function TokenItem({ > {token.symbol} - {account && ( + {(token.chainId === ChainId.TON ? tonAccount : evmAccount) && ( (); + const tokenList = useSelector(getTokenList); + const fromToken = React.useMemo(() => { + const token = [...defaultTokens, ...tokenList].find( + (token) => + token.chainId === fromChainId && token.address === fromTokenAddress, + ); + if (!token) throw new Error('Could not find from token'); + return token; + }, [tokenList, fromTokenAddress, fromChainId]); + const toToken = React.useMemo(() => { + const token = [...defaultTokens, ...tokenList].find( + (token) => + token.chainId === toChainId && token.address === toTokenAddress, + ); + if (!token) throw new Error('Could not find from token'); + return token; + }, [tokenList, toTokenAddress, toChainId]); + + const { fromFiatPrice } = useFetchFiatPrice({ + toToken, + fromToken, + }); + const { account, chainId } = useWalletState(); + const balanceLoadings = useSelector(getBalanceLoadings); + const balanceLoading = + !account || balanceLoadings[fromToken.address.toLocaleLowerCase()]; + + const fetchFromTokenQuery = useFetchTokens({ + tokenList: [fromToken], + skip: chainId !== fromToken.chainId, + }); + const fromTokenBalance = fetchFromTokenQuery.data?.[0]?.balance; + let insufficientBalance = false; + if (fromTokenBalance) { + insufficientBalance = fromTokenBalance.lt(fromAmt); + } + + React.useEffect(() => { + if (!slippage) return; + dispatch(setSlippage(String(slippage))); + }, [slippage]); + + const { bridgeRouteList } = useFetchRoutePriceBridge({ + toToken, + fromToken, + fromAmount: fromAmt, + fromFiatPrice, + fromAddress: account, + toAddress: tonAccount, + }); + const route = React.useMemo(() => { + if (!bridgeRouteList?.length) return undefined; + return { + ...bridgeRouteList[0], + fromAddress: account ?? '', + }; + }, [bridgeRouteList, account]); + const { contractStatus } = useSelector(getGlobalProps); + const { bridgeOrderTxRequest } = useSendRoute(); + const handleExecuteRoute = useExecuteBridgeRoute({ + route, + bridgeOrderTxRequest, + sendData: route?.sendData, + }); + + return ( + Cross Chain Summary} + open + onClose={() => { + window.open(redirectLink); + }} + > + <> + {route ? ( + + + + + {!!route.step && ( + + + + + + )} + + + + + + + ) : ( + + + + + + )} + + {insufficientBalance ? ( + + ) : account && chainId === fromToken.chainId ? ( + + ) : ( + + )} + + + + ); +} diff --git a/packages/dodoex-widgets/src/components/Widget/index.tsx b/packages/dodoex-widgets/src/components/Widget/index.tsx index 217c6d60..449763c7 100644 --- a/packages/dodoex-widgets/src/components/Widget/index.tsx +++ b/packages/dodoex-widgets/src/components/Widget/index.tsx @@ -41,6 +41,7 @@ import { import { useWalletState } from '../../hooks/ConnectWallet/useWalletState'; import WebApp from '@twa-dev/sdk'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { isBrowser } from '../../utils/device'; export const WIDGET_CLASS_NAME = 'dodo-widget-container'; export const queryClient = new QueryClient(); @@ -121,7 +122,7 @@ function InitStatus(props: PropsWithChildren) { }, [provider]); useEffect(() => { - if (props.tonConnect) { + if (props.tonConnect && isBrowser) { WebApp.ready(); } }, [props.tonConnect]); diff --git a/packages/dodoex-widgets/src/hooks/Bridge/useFetchRoutePriceBridge.ts b/packages/dodoex-widgets/src/hooks/Bridge/useFetchRoutePriceBridge.ts index ad03b93a..d465d33b 100644 --- a/packages/dodoex-widgets/src/hooks/Bridge/useFetchRoutePriceBridge.ts +++ b/packages/dodoex-widgets/src/hooks/Bridge/useFetchRoutePriceBridge.ts @@ -161,12 +161,16 @@ export interface FetchRoutePrice { toToken: TokenInfo | null; fromAmount: string; fromFiatPrice: string; + fromAddress?: string; + toAddress?: string; } export function useFetchRoutePriceBridge({ toToken, fromToken, fromAmount, fromFiatPrice, + fromAddress: fromAddressProps, + toAddress: toAddressProps, }: FetchRoutePrice) { const { account, provider } = useWalletState(); const { defaultSlippage, loading: slippageLoading } = @@ -211,8 +215,16 @@ export function useFetchRoutePriceBridge({ toToken, fromToken, fromAmount, - evmAccount: web3React.account, - tonAccount: tonConnect.connected?.account, + fromAddress: + fromAddressProps ?? + (fromToken?.chainId === ChainId.TON + ? tonConnect.connected?.account + : web3React.account), + toAddress: + toAddressProps ?? + (toToken?.chainId === ChainId.TON + ? tonConnect.connected?.account + : web3React.account), slippage: Number(slippage), }, }); @@ -238,8 +250,8 @@ export function useFetchRoutePriceBridge({ const fromTokenAddress = fromToken.address; const toTokenAddress = toToken.address; - const fromAddress = account || EmptyAddress; - const toAddress = account || EmptyAddress; + const fromAddress = fromAddressProps ?? (account || EmptyAddress); + const toAddress = toAddressProps ?? (account || EmptyAddress); const slippageNum = Number(slippage) / 100; const data: any = { @@ -433,6 +445,8 @@ export function useFetchRoutePriceBridge({ bridgeRoutePriceAPI, slippageLoading, needOrbiterQuery, + fromAddressProps, + toAddressProps, ]); usePriceTimer({ refetch }); @@ -446,6 +460,12 @@ export function useFetchRoutePriceBridge({ fromAddress = tonConnect.connected?.account; toAddress = web3React.account; } + if (fromAddressProps !== undefined) { + fromAddress = fromAddressProps; + } + if (toAddressProps !== undefined) { + toAddress = toAddressProps; + } if ( !needOrbiterQuery || !orbiterQuery.data || @@ -537,6 +557,8 @@ export function useFetchRoutePriceBridge({ web3React.account, tonConnect.connected?.account, orbiterContractMapQuery, + fromAddressProps, + toAddressProps, ]); const bridgeRouteListRes = useMemo(() => { diff --git a/packages/dodoex-widgets/src/hooks/ConnectWallet/useWalletState.ts b/packages/dodoex-widgets/src/hooks/ConnectWallet/useWalletState.ts index 42094e8c..d22c9f13 100644 --- a/packages/dodoex-widgets/src/hooks/ConnectWallet/useWalletState.ts +++ b/packages/dodoex-widgets/src/hooks/ConnectWallet/useWalletState.ts @@ -46,7 +46,10 @@ export function useWalletState({ isMetamask: false, autoConnect, connect: tonConnect.connect, - getLastBlockNumber: tonConnect.getBlockNumber, + getLastBlockNumber: async () => { + const result = await tonConnect.getBlockNumber(); + return result; + }, getBalance: async (account: string) => { const balance = await tonConnect.getBalance(account); return balance; @@ -67,7 +70,10 @@ export function useWalletState({ : web3React.connector.resetState(); }, provider: web3React.provider, - getLastBlockNumber: web3React.provider?.getBlockNumber, + getLastBlockNumber: async () => { + const result = await web3React.provider?.getBlockNumber(); + return result; + }, getBalance: web3React.provider ? async (account: string) => { const balance = await web3React.provider?.getBalance(account); diff --git a/packages/dodoex-widgets/src/hooks/Swap/useFetchFiatPrice.ts b/packages/dodoex-widgets/src/hooks/Swap/useFetchFiatPrice.ts index f98a224d..05e68aef 100644 --- a/packages/dodoex-widgets/src/hooks/Swap/useFetchFiatPrice.ts +++ b/packages/dodoex-widgets/src/hooks/Swap/useFetchFiatPrice.ts @@ -10,7 +10,7 @@ import { useGetAPIService } from '../setting/useGetAPIService'; import { APIServiceKey } from '../../constants/api'; export interface FetchFiatPriceProps { - chainId: ChainId | undefined; + chainId?: ChainId; fromToken: TokenInfo | null; toToken: TokenInfo | null; } @@ -26,7 +26,7 @@ export function useFetchFiatPrice({ const fiatPriceAPI = useGetAPIService(APIServiceKey.fiatPrice); const refetch = useCallback(() => { - if (!chainId || !fromToken || !toToken) return; + if (!fromToken || !toToken) return; const tokens = [] as TokenInfo[]; if (fromToken.chainId !== ChainId.TON) { tokens.push(fromToken); diff --git a/packages/dodoex-widgets/src/hooks/Token/useGetBalance.test.ts b/packages/dodoex-widgets/src/hooks/Token/useGetBalance.test.ts index 8673d5b4..513db0eb 100644 --- a/packages/dodoex-widgets/src/hooks/Token/useGetBalance.test.ts +++ b/packages/dodoex-widgets/src/hooks/Token/useGetBalance.test.ts @@ -27,6 +27,7 @@ jest.mock('../ConnectWallet/useWalletState', () => ({ useWalletState: () => ({ chainId: 1, account: '0x2Ba1633338dDD2Ab37fbc95ea615BA98f0445380', + evmAccount: '0x2Ba1633338dDD2Ab37fbc95ea615BA98f0445380', }), })); describe('useGetBalance', () => { diff --git a/packages/dodoex-widgets/src/hooks/Token/useGetBalance.ts b/packages/dodoex-widgets/src/hooks/Token/useGetBalance.ts index ac4fc347..d2022b00 100644 --- a/packages/dodoex-widgets/src/hooks/Token/useGetBalance.ts +++ b/packages/dodoex-widgets/src/hooks/Token/useGetBalance.ts @@ -11,16 +11,17 @@ import { isSameAddress } from '../../utils'; import { useWalletState } from '../ConnectWallet/useWalletState'; export default function useGetBalance() { - const { account, chainId } = useWalletState(); + const { chainId, evmAccount, tonAccount } = useWalletState(); const accountBalances = useSelector(getAccountBalances); const ethBalance = useSelector(getEthBalance); const getBalance = useCallback( (token: TokenInfo) => { + const tokenChainId = token.chainId ?? chainId ?? 1; + const account = tokenChainId === ChainId.TON ? tonAccount : evmAccount; if (!account || !token) return null; // cross-chain basic token if (isSameAddress(token.address, etherTokenAddress)) { - const currentChainIdEthBalance = - ethBalance[token.chainId ?? chainId ?? 1]; + const currentChainIdEthBalance = ethBalance[tokenChainId]; return !currentChainIdEthBalance || currentChainIdEthBalance?.isNaN() ? null : currentChainIdEthBalance; @@ -29,7 +30,7 @@ export default function useGetBalance() { accountBalances[token.address.toLocaleLowerCase()]?.tokenBalances; return !balance || balance?.isNaN() ? null : balance; }, - [accountBalances, ethBalance, account], + [accountBalances, ethBalance, evmAccount, tonAccount], ); return getBalance; diff --git a/packages/dodoex-widgets/src/hooks/Token/useGetTokenStatus.test.ts b/packages/dodoex-widgets/src/hooks/Token/useGetTokenStatus.test.ts index 1b505d0f..cb632ec1 100644 --- a/packages/dodoex-widgets/src/hooks/Token/useGetTokenStatus.test.ts +++ b/packages/dodoex-widgets/src/hooks/Token/useGetTokenStatus.test.ts @@ -35,6 +35,7 @@ jest.mock('react-redux', () => ({ jest.mock('../ConnectWallet/useWalletState', () => ({ useWalletState: () => ({ account: '0x2Ba1633338dDD2Ab37fbc95ea615BA98f0445380', + evmAccount: '0x2Ba1633338dDD2Ab37fbc95ea615BA98f0445380', }), })); diff --git a/packages/dodoex-widgets/src/hooks/contract/layerswap/data.ts b/packages/dodoex-widgets/src/hooks/contract/layerswap/data.ts index f92fe6ed..4284427e 100644 --- a/packages/dodoex-widgets/src/hooks/contract/layerswap/data.ts +++ b/packages/dodoex-widgets/src/hooks/contract/layerswap/data.ts @@ -1,10 +1,19 @@ +import { Interface } from '@ethersproject/abi'; +import { Web3Provider } from '@ethersproject/providers'; +import { useWeb3React } from '@web3-react/core'; +import BigNumber from 'bignumber.js'; import { Address, beginCell, JettonMaster, toNano } from 'ton'; +import { ChainId } from '../../../constants/chains'; +import { isETHAddress } from '../../../utils/address'; import useTonConnectStore from '../../ConnectWallet/TonConnect'; import { getHashByBoc, waitForTransaction, } from '../../ConnectWallet/TonConnect/contract'; +import { WatchResult } from '../../Submission/types'; import { TokenInfo } from '../../Token'; +import erc20ABI from '../abis/erc20ABI'; +import { sendTransaction } from '../wallet'; import { LAYERSWAP_API_KEY, LAYERSWAP_LIMITS_URL, @@ -167,6 +176,7 @@ export async function submitTonWalletWithdraw({ toNetworkName, fromAmount, slippage, + provider, params, }: { fromAddress: string | undefined; @@ -177,6 +187,7 @@ export async function submitTonWalletWithdraw({ toNetworkName: string | undefined | null; fromAmount: string; slippage?: number; + provider?: Web3Provider; params: { onSubmit?: (tx: string, reportInfo?: Record) => void; onSuccess?: (tx: string, reportInfo?: Record) => Promise; @@ -228,35 +239,81 @@ export async function submitTonWalletWithdraw({ if (!callData || !depositAddress) { throw new Error('No deposit action found in the swap response'); } - const transaction = await transactionBuilder( - amount, - sourceToken, - depositAddress, - fromAddress, - callData, - ); + if (fromToken.chainId === ChainId.TON) { + const transaction = await transactionBuilder( + amount, + sourceToken, + depositAddress, + fromAddress, + callData, + ); - const { tonConnectUI, client } = useTonConnectStore.getState(); - if (!tonConnectUI || !client) { - throw new Error('No tonConnectUI or client available'); - } - const res = await tonConnectUI.sendTransaction(transaction); - const bocHash = getHashByBoc(res.boc); - if (params.onSubmit) { - params.onSubmit(bocHash); - } + const { tonConnectUI, client } = useTonConnectStore.getState(); + if (!tonConnectUI || !client) { + throw new Error('No tonConnectUI or client available'); + } + const res = await tonConnectUI.sendTransaction(transaction); + const bocHash = getHashByBoc(res.boc); + if (params.onSubmit) { + params.onSubmit(bocHash); + } - const data = await waitForTransaction( - { - boc: res.boc, - address: fromAddress, - }, - client, - ); - if (params.onSuccess) { - params.onSuccess(data?.hash()?.toString('base64') ?? bocHash, { - tonTransaction: data, - }); + const data = await waitForTransaction( + { + boc: res.boc, + address: fromAddress, + }, + client, + ); + if (params.onSuccess) { + params.onSuccess(data?.hash()?.toString('base64') ?? bocHash, { + tonTransaction: data, + }); + } + return data; + } else { + if (!provider) throw new Error('Invalid provider'); + const sendAmountWei = new BigNumber(amount) + .times(10 ** fromToken.decimals) + .toString(); + let value = '0x0'; + let data = '0x'; + if (isETHAddress(fromToken.address)) { + value = sendAmountWei; + } else { + data = callData; + } + const executePrams = { + value, + data: data, + to: fromToken.address, + from: fromAddress, + chainId: fromToken.chainId, + }; + try { + const transaction = await sendTransaction(executePrams, provider); + const tx = transaction.hash; + if (params.onSubmit) { + params.onSubmit(tx); + } + const receipt = await transaction.wait(1); + if (receipt.status === WatchResult.Success) { + if (params.onSuccess) { + params.onSuccess(tx, { + receipt, + }); + } + } else if (receipt.status === WatchResult.Failed) { + if (params.onError) { + params.onError(new Error('Transaction failed')); + } + } + return receipt; + } catch (error) { + if (params.onError) { + params.onError(error); + return null; + } + } } - return data; } diff --git a/packages/dodoex-widgets/src/hooks/contract/layerswap/useLayerswapRouters.ts b/packages/dodoex-widgets/src/hooks/contract/layerswap/useLayerswapRouters.ts index 954f5c61..da8533bf 100644 --- a/packages/dodoex-widgets/src/hooks/contract/layerswap/useLayerswapRouters.ts +++ b/packages/dodoex-widgets/src/hooks/contract/layerswap/useLayerswapRouters.ts @@ -1,4 +1,5 @@ import { useQuery } from '@tanstack/react-query'; +import { useWeb3React } from '@web3-react/core'; import BigNumber from 'bignumber.js'; import React from 'react'; import { ChainId } from '../../../constants/chains'; @@ -9,12 +10,6 @@ import { import { refreshTime } from '../../Swap/usePriceTimer'; import { TokenInfo } from '../../Token'; import { - LAYERSWAP_QUOTE_URL, - LAYERSWAP_API_KEY, - LAYERSWAP_SWAPS_URL, -} from './constants'; -import { - getLayerSwapData, getLimits, getNetworks, getQuote, @@ -32,18 +27,19 @@ function convertAvgCompletionTime(completionTime: string) { export function useLayerswapRouters({ skip, - data: { fromToken, toToken, fromAmount, evmAccount, tonAccount, slippage }, + data: { fromToken, toToken, fromAmount, fromAddress, toAddress, slippage }, }: { skip?: boolean; data: { fromToken: TokenInfo | null; toToken: TokenInfo | null; fromAmount: string; - evmAccount: string | undefined; - tonAccount: string | undefined; + fromAddress: string | undefined; + toAddress: string | undefined; slippage?: number; }; }) { + const { provider: evmProvider } = useWeb3React(); const networkQuery = useQuery({ queryKey: ['layerSwap', 'networkQuery'], enabled: !skip, @@ -120,11 +116,8 @@ export function useLayerswapRouters({ if (!data) { throw new Error('Failed to get quote'); } - - const fromAddress = tonAccount; - const toAddress = evmAccount; - const product = 'layerswap'; const { quote } = data; + const product = 'layerswap'; const logoURI = 'https://images.dodoex.io/PI0Kb_gccJbkOIpRNof2CUmeiyiPof28wrEH86RAlIE/rs:fit:160:160:0/g:no/aHR0cHM6Ly9zdG9yYWdlLmdvb2dsZWFwaXMuY29tL2RvZG8tbWVkaWEtc3RhZ2luZy91cGxvYWRfaW1nXzQwMTA2NzFfMjAyMzExMTYxMTE1MTM5ODAud2VicA.webp'; const name = product.charAt(0).toUpperCase() + product.slice(1); @@ -156,18 +149,7 @@ export function useLayerswapRouters({ name, }, }, - sendData: (params) => - submitTonWalletWithdraw({ - fromAddress, - toAddress, - fromToken, - toToken, - fromNetworkName, - toNetworkName, - fromAmount, - params, - }), - } as BridgeRouteI; + }; }, }); @@ -185,10 +167,33 @@ export function useLayerswapRouters({ if (!quoteQuery.data) return null; return { ...quoteQuery.data, + sendData: (params) => + submitTonWalletWithdraw({ + fromAddress, + toAddress, + fromToken, + toToken, + fromNetworkName, + toNetworkName, + fromAmount, + provider: evmProvider, + params, + }), minAmt: limitQuery.data?.min_amount, maxAmt: limitQuery.data?.max_amount, } as BridgeRouteI; - }, [limitQuery.data, quoteQuery.data]); + }, [ + limitQuery.data, + quoteQuery.data, + fromAddress, + toAddress, + fromToken, + toToken, + fromNetworkName, + toNetworkName, + fromAmount, + evmProvider, + ]); return { status, diff --git a/packages/dodoex-widgets/src/hooks/contract/useFetchBlockNumber.ts b/packages/dodoex-widgets/src/hooks/contract/useFetchBlockNumber.ts index 867b555d..f5933434 100644 --- a/packages/dodoex-widgets/src/hooks/contract/useFetchBlockNumber.ts +++ b/packages/dodoex-widgets/src/hooks/contract/useFetchBlockNumber.ts @@ -11,7 +11,7 @@ export default function useFetchBlockNumber() { const updateBlockNumber = useCallback(async () => { if (!getLastBlockNumber || !chainId) return; const blockNumber = await getLastBlockNumber(); - dispatch(setBlockNumber(blockNumber)); + dispatch(setBlockNumber(blockNumber ?? 0)); }, [getLastBlockNumber, chainId]); return { updateBlockNumber, diff --git a/packages/dodoex-widgets/src/hooks/contract/useFetchTokens.ts b/packages/dodoex-widgets/src/hooks/contract/useFetchTokens.ts index 358625ee..94d3709a 100644 --- a/packages/dodoex-widgets/src/hooks/contract/useFetchTokens.ts +++ b/packages/dodoex-widgets/src/hooks/contract/useFetchTokens.ts @@ -16,7 +16,6 @@ import { useWalletState } from '../ConnectWallet/useWalletState'; import { ChainId } from '../../constants/chains'; import useTonConnectStore from '../ConnectWallet/TonConnect'; import { BIG_ALLOWANCE } from '../../constants/token'; -import { useWeb3React } from '@web3-react/core'; type TokenResult = { address: string; @@ -39,8 +38,7 @@ export default function useFetchTokens({ chainId?: number; skip?: boolean; }) { - const { account } = useWeb3React(); - const tonConnect = useTonConnectStore(); + const { evmAccount, tonAccount } = useWalletState(); const dispatch = useDispatch(); const [addresses, tonTokenList] = useMemo(() => { const evmList = [] as TokenList; @@ -61,7 +59,7 @@ export default function useFetchTokens({ const [data, setData] = useState(); const thunk = useMemo(() => { - if (!account || !addresses.length || !contractConfig) return undefined; + if (!evmAccount || !addresses.length || !contractConfig) return undefined; const { DODO_APPROVE: proxyAddress, ERC20_HELPER: erc20HelperAddress } = contractConfig; const contract = getContract(erc20HelperAddress, erc20Helper); @@ -69,7 +67,7 @@ export default function useFetchTokens({ const res = addresses.map((tokenAddress) => { const encoded = contract.interface.encodeFunctionData('isERC20', [ tokenAddress, - account, + evmAccount, proxyAddress, ]); const callData = { @@ -109,7 +107,7 @@ export default function useFetchTokens({ }; }); return res; - }, [account, getContract, JSON.stringify(addresses)]); + }, [evmAccount, getContract, JSON.stringify(addresses)]); // query addresses useEffect(() => { @@ -181,15 +179,10 @@ export default function useFetchTokens({ } }; - if (tonTokenList.length && !!tonConnect.connected?.account) { + if (tonTokenList.length && !!tonAccount) { computed(); } - }, [ - JSON.stringify(tonTokenList), - blockNumber, - skip, - tonConnect.connected?.account, - ]); + }, [JSON.stringify(tonTokenList), blockNumber, skip, tonAccount]); return { data, diff --git a/packages/dodoex-widgets/src/index.tsx b/packages/dodoex-widgets/src/index.tsx index 25a207e0..071ed5d4 100644 --- a/packages/dodoex-widgets/src/index.tsx +++ b/packages/dodoex-widgets/src/index.tsx @@ -5,12 +5,16 @@ import { Widget, WidgetProps } from './components/Widget'; export type SwapWidgetProps = WidgetProps; export type { TokenInfo } from './hooks/Token/type'; +export { default as BridgeTonSummaryDialog } from './components/Widget/BridgeTonSummaryDialog'; +export { Widget } from './components/Widget'; + export function SwapWidget(props: SwapWidgetProps) { return ( ); @@ -25,6 +29,7 @@ export function InitSwapWidget(props: SwapWidgetProps) { , ); diff --git a/packages/dodoex-widgets/src/locales/en-US.po b/packages/dodoex-widgets/src/locales/en-US.po index 05e73cc3..602069df 100644 --- a/packages/dodoex-widgets/src/locales/en-US.po +++ b/packages/dodoex-widgets/src/locales/en-US.po @@ -22,7 +22,7 @@ msgstr "Transaction Time:" msgid "Cross Chain" msgstr "Cross Chain" -#: src/components/Swap/index.tsx:520 +#: src/components/Swap/index.tsx:535 msgid "The current slippage protection coefficient set exceeds {maxSlippageWarning}%, which may result in losses." msgstr "The current slippage protection coefficient set exceeds {maxSlippageWarning}%, which may result in losses." @@ -48,7 +48,7 @@ msgid "Dismiss" msgstr "Dismiss" #: src/components/Swap/components/ReviewDialog.tsx:342 -#: src/components/Swap/index.tsx:445 +#: src/components/Swap/index.tsx:460 msgid "Due to the market condition, market price and estimated price may have a slight difference" msgstr "Due to the market condition, market price and estimated price may have a slight difference" @@ -56,11 +56,11 @@ msgstr "Due to the market condition, market price and estimated price may have a msgid "{0} confirmed" msgstr "{0} confirmed" -#: src/components/Swap/index.tsx:552 +#: src/components/Swap/index.tsx:567 msgid "The current network is inconsistent with the wallet - please switch in wallet" msgstr "The current network is inconsistent with the wallet - please switch in wallet" -#: src/components/Swap/index.tsx:453 +#: src/components/Swap/index.tsx:468 msgid "Current price impact" msgstr "Current price impact" @@ -85,7 +85,7 @@ msgstr "Fee includes: Cross Chain fees + Swap fees. Gas fee not included." msgid "Confirm" msgstr "Confirm" -#: src/components/Swap/index.tsx:1076 +#: src/components/Swap/index.tsx:1155 msgid "Powered by DODO protocol" msgstr "Powered by DODO protocol" @@ -117,7 +117,7 @@ msgstr "This CP has been settled by other addrs" msgid "Max" msgstr "Max" -#: src/components/Bridge/BridgeSummaryDialog/BridgeSummaryDetail.tsx:277 +#: src/components/Bridge/BridgeSummaryDialog/BridgeSummaryDetail.tsx:283 #: src/components/Swap/components/ReviewDialog.tsx:362 msgid "Slippage" msgstr "Slippage" @@ -142,7 +142,7 @@ msgstr "Unapproved" msgid "Insufficient cross-chain fees, need at least {0} {1}" msgstr "Insufficient cross-chain fees, need at least {0} {1}" -#: src/components/Swap/index.tsx:725 +#: src/components/Swap/index.tsx:751 msgid "Transaction Pending" msgstr "Transaction Pending" @@ -174,11 +174,11 @@ msgid "Additional Fee" msgstr "Additional Fee" #: src/components/Swap/components/TokenPairPriceWithToggle.tsx:52 -#: src/components/Swap/index.tsx:573 +#: src/components/Swap/index.tsx:588 msgid "Fetching best price..." msgstr "Fetching best price..." -#: src/components/Swap/index.tsx:836 +#: src/components/Swap/index.tsx:915 msgid "Review Swap" msgstr "Review Swap" @@ -186,26 +186,26 @@ msgstr "Review Swap" msgid "Select Cross Chain" msgstr "Select Cross Chain" -#: src/components/Bridge/BridgeSummaryDialog/BridgeSummaryDetail.tsx:281 +#: src/components/Bridge/BridgeSummaryDialog/BridgeSummaryDetail.tsx:287 #: src/components/Swap/components/SettingsDialog/index.tsx:53 msgid "Attention: High slippage tolerance will increase the success rate of transaction, but might not get the best quote." msgstr "Attention: High slippage tolerance will increase the success rate of transaction, but might not get the best quote." -#: src/components/Swap/index.tsx:732 +#: src/components/Swap/index.tsx:758 msgid "Select Tokens" msgstr "Select Tokens" -#: src/components/Swap/index.tsx:931 +#: src/components/Swap/index.tsx:1010 msgid "The setting has been switched to swap mode" msgstr "The setting has been switched to swap mode" #: src/components/Swap/components/TokenPairPriceWithToggle.tsx:61 -#: src/components/Swap/index.tsx:628 -#: src/components/Swap/index.tsx:807 +#: src/components/Swap/index.tsx:643 +#: src/components/Swap/index.tsx:833 msgid "Quote not available" msgstr "Quote not available" -#: src/components/Swap/index.tsx:792 +#: src/components/Swap/index.tsx:818 msgid "Fetching Price..." msgstr "Fetching Price..." @@ -219,6 +219,7 @@ msgstr "Best offer" #: src/components/Bridge/BridgeSummaryDialog/index.tsx:157 #: src/components/Swap/components/ReviewDialog.tsx:452 +#: src/components/Widget/BridgeTonSummaryDialog/index.tsx:224 msgid "Confirming" msgstr "Confirming" @@ -226,11 +227,12 @@ msgstr "Confirming" msgid "{DEFAULT_SWAP_DDL} minutes" msgstr "{DEFAULT_SWAP_DDL} minutes" -#: src/components/Bridge/BridgeSummaryDialog/BridgeSummaryDetail.tsx:246 +#: src/components/Bridge/BridgeSummaryDialog/BridgeSummaryDetail.tsx:252 msgid "Fee" msgstr "Fee" #: src/components/Bridge/BridgeSummaryDialog/index.tsx:159 +#: src/components/Widget/BridgeTonSummaryDialog/index.tsx:226 msgid "Confirm Cross Chain" msgstr "Confirm Cross Chain" @@ -239,7 +241,7 @@ msgstr "Confirm Cross Chain" msgid "Price impact reaches <0>{priceImpact}%, accept the quote" msgstr "Price impact reaches <0>{priceImpact}%, accept the quote" -#: src/components/Bridge/BridgeSummaryDialog/BridgeSummaryDetail.tsx:342 +#: src/components/Bridge/BridgeSummaryDialog/BridgeSummaryDetail.tsx:348 msgid "Estimated Time" msgstr "Estimated Time" @@ -252,7 +254,7 @@ msgstr "Swap summary" msgid "Tx" msgstr "Tx" -#: src/components/Swap/index.tsx:826 +#: src/components/Swap/index.tsx:904 msgid "Review Cross Chain" msgstr "Review Cross Chain" @@ -301,7 +303,7 @@ msgstr "For" msgid "On" msgstr "On" -#: src/components/Swap/index.tsx:742 +#: src/components/Swap/index.tsx:768 #: src/hooks/Token/useGetTokenStatus.ts:142 msgid "Approve" msgstr "Approve" @@ -334,7 +336,7 @@ msgstr "Min" msgid "Transaction rejected." msgstr "Transaction rejected." -#: src/components/Swap/index.tsx:778 +#: src/components/Swap/index.tsx:804 msgid "cannot be greater than {maxAmt}" msgstr "cannot be greater than {maxAmt}" @@ -359,15 +361,15 @@ msgstr "Estimated transaction time" msgid "Connect to your wallet" msgstr "Connect to your wallet" -#: src/components/Swap/index.tsx:748 +#: src/components/Swap/index.tsx:774 msgid "Enter an amount" msgstr "Enter an amount" -#: src/components/Swap/index.tsx:776 +#: src/components/Swap/index.tsx:802 msgid "cannot be lower than {minAmt}" msgstr "cannot be lower than {minAmt}" -#: src/components/Swap/index.tsx:742 +#: src/components/Swap/index.tsx:768 msgid "Approving" msgstr "Approving" @@ -396,7 +398,7 @@ msgstr "Send to:" msgid "Unable to SETTLE during the cooling-off period" msgstr "Unable to SETTLE during the cooling-off period" -#: src/components/Swap/index.tsx:929 +#: src/components/Swap/index.tsx:1008 msgid "The setting has been switched to cross chain mode" msgstr "The setting has been switched to cross chain mode" @@ -421,6 +423,7 @@ msgid "SELECT TOKEN" msgstr "SELECT TOKEN" #: src/components/Bridge/BridgeSummaryDialog/index.tsx:63 +#: src/components/Widget/BridgeTonSummaryDialog/index.tsx:117 msgid "Cross Chain Summary" msgstr "Cross Chain Summary" @@ -428,11 +431,11 @@ msgstr "Cross Chain Summary" msgid "SafeERC20: low-level call failed. Please contact the DODO team." msgstr "SafeERC20: low-level call failed. Please contact the DODO team." -#: src/components/Swap/index.tsx:589 +#: src/components/Swap/index.tsx:604 msgid "Unsupported network - switch to trade" msgstr "Unsupported network - switch to trade" -#: src/components/Swap/index.tsx:924 +#: src/components/Swap/index.tsx:1003 #: src/hooks/Swap/useExecuteSwap.ts:56 msgid "Swap" msgstr "Swap" @@ -461,6 +464,7 @@ msgstr "Close" msgid "Transaction Deadline" msgstr "Transaction Deadline" -#: src/components/Swap/index.tsx:760 +#: src/components/Swap/index.tsx:786 +#: src/components/Widget/BridgeTonSummaryDialog/index.tsx:207 msgid "Insufficient balance" msgstr "Insufficient balance" diff --git a/packages/dodoex-widgets/src/locales/zh-CN.po b/packages/dodoex-widgets/src/locales/zh-CN.po index 2e9f31aa..c61c5468 100644 --- a/packages/dodoex-widgets/src/locales/zh-CN.po +++ b/packages/dodoex-widgets/src/locales/zh-CN.po @@ -22,7 +22,7 @@ msgstr "交易时长:" msgid "Cross Chain" msgstr "跨链桥" -#: src/components/Swap/index.tsx:520 +#: src/components/Swap/index.tsx:535 msgid "The current slippage protection coefficient set exceeds {maxSlippageWarning}%, which may result in losses." msgstr "当前滑点保护系数设置超过{maxSlippageWarning}%,可能会造成损失。" @@ -48,7 +48,7 @@ msgid "Dismiss" msgstr "忽略" #: src/components/Swap/components/ReviewDialog.tsx:342 -#: src/components/Swap/index.tsx:445 +#: src/components/Swap/index.tsx:460 msgid "Due to the market condition, market price and estimated price may have a slight difference" msgstr "由于市场情况不同,市场价格与估算价格可能略有差异。" @@ -56,11 +56,11 @@ msgstr "由于市场情况不同,市场价格与估算价格可能略有差异 msgid "{0} confirmed" msgstr "{0} 已确认" -#: src/components/Swap/index.tsx:552 +#: src/components/Swap/index.tsx:567 msgid "The current network is inconsistent with the wallet - please switch in wallet" msgstr "当前网络与钱包不一致,请在钱包中切换" -#: src/components/Swap/index.tsx:453 +#: src/components/Swap/index.tsx:468 msgid "Current price impact" msgstr "当前价格冲击" @@ -85,7 +85,7 @@ msgstr "费用包括过跨链桥和交易的手续费,不包括 gas 费。" msgid "Confirm" msgstr "确认" -#: src/components/Swap/index.tsx:1076 +#: src/components/Swap/index.tsx:1155 msgid "Powered by DODO protocol" msgstr "Powered by DODO protocol" @@ -117,7 +117,7 @@ msgstr "此众筹池已被其他地址结算" msgid "Max" msgstr "全部" -#: src/components/Bridge/BridgeSummaryDialog/BridgeSummaryDetail.tsx:277 +#: src/components/Bridge/BridgeSummaryDialog/BridgeSummaryDetail.tsx:283 #: src/components/Swap/components/ReviewDialog.tsx:362 msgid "Slippage" msgstr "滑点" @@ -142,7 +142,7 @@ msgstr "未授权" msgid "Insufficient cross-chain fees, need at least {0} {1}" msgstr "跨链费用不足,至少需要 {0} {1} " -#: src/components/Swap/index.tsx:725 +#: src/components/Swap/index.tsx:751 msgid "Transaction Pending" msgstr "交易进行中" @@ -174,11 +174,11 @@ msgid "Additional Fee" msgstr "额外手续费" #: src/components/Swap/components/TokenPairPriceWithToggle.tsx:52 -#: src/components/Swap/index.tsx:573 +#: src/components/Swap/index.tsx:588 msgid "Fetching best price..." msgstr "获取最优价格中..." -#: src/components/Swap/index.tsx:836 +#: src/components/Swap/index.tsx:915 msgid "Review Swap" msgstr "预览交易" @@ -186,26 +186,26 @@ msgstr "预览交易" msgid "Select Cross Chain" msgstr "选择跨链桥" -#: src/components/Bridge/BridgeSummaryDialog/BridgeSummaryDetail.tsx:281 +#: src/components/Bridge/BridgeSummaryDialog/BridgeSummaryDetail.tsx:287 #: src/components/Swap/components/SettingsDialog/index.tsx:53 msgid "Attention: High slippage tolerance will increase the success rate of transaction, but might not get the best quote." msgstr "注意:滑点越高,交易的成功率越高,但是交易的价格可能不会是最好的市场价格。请谨慎调整滑点。" -#: src/components/Swap/index.tsx:732 +#: src/components/Swap/index.tsx:758 msgid "Select Tokens" msgstr "选择代币" -#: src/components/Swap/index.tsx:931 +#: src/components/Swap/index.tsx:1010 msgid "The setting has been switched to swap mode" msgstr "设置已切换至闪兑模式" #: src/components/Swap/components/TokenPairPriceWithToggle.tsx:61 -#: src/components/Swap/index.tsx:628 -#: src/components/Swap/index.tsx:807 +#: src/components/Swap/index.tsx:643 +#: src/components/Swap/index.tsx:833 msgid "Quote not available" msgstr "没有报价" -#: src/components/Swap/index.tsx:792 +#: src/components/Swap/index.tsx:818 msgid "Fetching Price..." msgstr "获取价格中..." @@ -219,6 +219,7 @@ msgstr "最优价格" #: src/components/Bridge/BridgeSummaryDialog/index.tsx:157 #: src/components/Swap/components/ReviewDialog.tsx:452 +#: src/components/Widget/BridgeTonSummaryDialog/index.tsx:224 msgid "Confirming" msgstr "确认中" @@ -226,11 +227,12 @@ msgstr "确认中" msgid "{DEFAULT_SWAP_DDL} minutes" msgstr "{DEFAULT_SWAP_DDL} 分钟" -#: src/components/Bridge/BridgeSummaryDialog/BridgeSummaryDetail.tsx:246 +#: src/components/Bridge/BridgeSummaryDialog/BridgeSummaryDetail.tsx:252 msgid "Fee" msgstr "手续费" #: src/components/Bridge/BridgeSummaryDialog/index.tsx:159 +#: src/components/Widget/BridgeTonSummaryDialog/index.tsx:226 msgid "Confirm Cross Chain" msgstr "确认跨链交易" @@ -239,7 +241,7 @@ msgstr "确认跨链交易" msgid "Price impact reaches <0>{priceImpact}%, accept the quote" msgstr "价格冲击为<0>{priceImpact}%, 仍接受此报价" -#: src/components/Bridge/BridgeSummaryDialog/BridgeSummaryDetail.tsx:342 +#: src/components/Bridge/BridgeSummaryDialog/BridgeSummaryDetail.tsx:348 msgid "Estimated Time" msgstr "预计时间" @@ -252,7 +254,7 @@ msgstr "交易预览" msgid "Tx" msgstr "交易哈希:" -#: src/components/Swap/index.tsx:826 +#: src/components/Swap/index.tsx:904 msgid "Review Cross Chain" msgstr "预览跨链交易" @@ -301,7 +303,7 @@ msgstr "对于" msgid "On" msgstr "在" -#: src/components/Swap/index.tsx:742 +#: src/components/Swap/index.tsx:768 #: src/hooks/Token/useGetTokenStatus.ts:142 msgid "Approve" msgstr "代币授权" @@ -334,7 +336,7 @@ msgstr "分钟" msgid "Transaction rejected." msgstr "交易被拒绝." -#: src/components/Swap/index.tsx:778 +#: src/components/Swap/index.tsx:804 msgid "cannot be greater than {maxAmt}" msgstr "" @@ -359,15 +361,15 @@ msgstr "预计交易时长" msgid "Connect to your wallet" msgstr "连接钱包" -#: src/components/Swap/index.tsx:748 +#: src/components/Swap/index.tsx:774 msgid "Enter an amount" msgstr "输入代币数量" -#: src/components/Swap/index.tsx:776 +#: src/components/Swap/index.tsx:802 msgid "cannot be lower than {minAmt}" msgstr "" -#: src/components/Swap/index.tsx:742 +#: src/components/Swap/index.tsx:768 msgid "Approving" msgstr "授权中" @@ -396,7 +398,7 @@ msgstr "发送至:" msgid "Unable to SETTLE during the cooling-off period" msgstr "在冷静期无法进行清算" -#: src/components/Swap/index.tsx:929 +#: src/components/Swap/index.tsx:1008 msgid "The setting has been switched to cross chain mode" msgstr "设置已切换到跨链桥交易模式" @@ -421,6 +423,7 @@ msgid "SELECT TOKEN" msgstr "选择代币" #: src/components/Bridge/BridgeSummaryDialog/index.tsx:63 +#: src/components/Widget/BridgeTonSummaryDialog/index.tsx:117 msgid "Cross Chain Summary" msgstr "跨链桥概览" @@ -428,11 +431,11 @@ msgstr "跨链桥概览" msgid "SafeERC20: low-level call failed. Please contact the DODO team." msgstr "SafeERC20:low-level call failed,请联系DODO团队解决。" -#: src/components/Swap/index.tsx:589 +#: src/components/Swap/index.tsx:604 msgid "Unsupported network - switch to trade" msgstr "未支持网络 - 请切换后进行交易" -#: src/components/Swap/index.tsx:924 +#: src/components/Swap/index.tsx:1003 #: src/hooks/Swap/useExecuteSwap.ts:56 msgid "Swap" msgstr "交易" @@ -461,6 +464,7 @@ msgstr "关闭" msgid "Transaction Deadline" msgstr "交易截止时间" -#: src/components/Swap/index.tsx:760 +#: src/components/Swap/index.tsx:786 +#: src/components/Widget/BridgeTonSummaryDialog/index.tsx:207 msgid "Insufficient balance" msgstr "余额不足" diff --git a/packages/dodoex-widgets/src/utils/address.ts b/packages/dodoex-widgets/src/utils/address.ts index 9c5e498f..abe71dea 100644 --- a/packages/dodoex-widgets/src/utils/address.ts +++ b/packages/dodoex-widgets/src/utils/address.ts @@ -49,7 +49,7 @@ export default function isZero(hexNumberString: string) { * @param address pool address */ export function truncatePoolAddress(address: string): string { - if (address.length <= 10) { + if (!address || address.length <= 10) { return address; } return `${address.slice(0, 6)}...${address.slice( diff --git a/packages/dodoex-widgets/src/utils/device.ts b/packages/dodoex-widgets/src/utils/device.ts new file mode 100644 index 00000000..8254481b --- /dev/null +++ b/packages/dodoex-widgets/src/utils/device.ts @@ -0,0 +1,10 @@ +export const isBrowser = typeof document !== 'undefined'; + +export const isAndroid = + isBrowser && + window.navigator?.userAgent && + /(Android)/i.test(navigator.userAgent); + +export const isIOS = isBrowser + ? /(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent) + : false;