From 346c93e52e8b6fdaa26a22c1a3c501c68d84c116 Mon Sep 17 00:00:00 2001 From: mikasackermn Date: Wed, 13 Nov 2024 12:11:29 +0000 Subject: [PATCH 1/4] feat: display same source and destination token warning on widget --- .../components/NoResult/NoResult.helpers.ts | 18 ++++++++++++------ .../src/components/NoResult/NoResult.types.ts | 8 ++++++-- .../QuoteWarningsAndErrors.helpers.ts | 6 ++++++ .../QuoteWarningsAndErrors.tsx | 17 +++++++++++++---- widget/embedded/src/hooks/useSwapInput.ts | 13 ++++++++----- widget/embedded/src/types/quote.ts | 8 +++++++- 6 files changed, 52 insertions(+), 18 deletions(-) diff --git a/widget/embedded/src/components/NoResult/NoResult.helpers.ts b/widget/embedded/src/components/NoResult/NoResult.helpers.ts index 679e117873..2415707114 100644 --- a/widget/embedded/src/components/NoResult/NoResult.helpers.ts +++ b/widget/embedded/src/components/NoResult/NoResult.helpers.ts @@ -1,19 +1,20 @@ import type { Info } from './NoResult.types'; +import type { + NoResultError, + QuoteRequestFailed, + SameTokensWarning, +} from '../../types'; import { i18n } from '@lingui/core'; import { errorMessages } from '../../constants/errors'; -import { - type NoResultError, - QuoteErrorType, - type QuoteRequestFailed, -} from '../../types'; +import { QuoteErrorType, QuoteWarningType } from '../../types'; const SMALL_NO_ROUTE__ICON_SIZE = 24; const LARGE_NO_ROUTE_ICON_SIZE = 60; export function makeInfo( - error: NoResultError | QuoteRequestFailed | null, + error: NoResultError | QuoteRequestFailed | SameTokensWarning | null, disabledLiquiditySources: string[], toggleAllLiquiditySources: (shouldReset: boolean) => void, refetchQuote: () => void @@ -30,6 +31,11 @@ export function makeInfo( }, description: '', }; + } else if (error?.type === QuoteWarningType.SAME_TOKENS) { + return { + alert: null, + description: '', + }; } else if (disabledLiquiditySources.length) { return { alert: { diff --git a/widget/embedded/src/components/NoResult/NoResult.types.ts b/widget/embedded/src/components/NoResult/NoResult.types.ts index 8821114652..7e12d0e43b 100644 --- a/widget/embedded/src/components/NoResult/NoResult.types.ts +++ b/widget/embedded/src/components/NoResult/NoResult.types.ts @@ -1,8 +1,12 @@ -import type { NoResultError, QuoteRequestFailed } from '../../types'; +import type { + NoResultError, + QuoteRequestFailed, + SameTokensWarning, +} from '../../types'; export interface PropTypes { fetch: () => void; - error: NoResultError | QuoteRequestFailed | null; + error: NoResultError | QuoteRequestFailed | SameTokensWarning | null; size?: 'small' | 'large'; } diff --git a/widget/embedded/src/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.helpers.ts b/widget/embedded/src/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.helpers.ts index 367dc68149..d71610bb03 100644 --- a/widget/embedded/src/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.helpers.ts +++ b/widget/embedded/src/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.helpers.ts @@ -68,6 +68,12 @@ export function makeAlerts( alertInfo.title = i18n.t('Caution, your slippage is high.'); alertInfo.action = 'change-settings'; } + if (warning.type === QuoteWarningType.SAME_TOKENS) { + alertInfo.title = i18n.t( + 'You cannot use the same token for From and To.' + ); + } + return alertInfo; } return null; diff --git a/widget/embedded/src/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.tsx b/widget/embedded/src/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.tsx index b1874144c7..f9007a3ec8 100644 --- a/widget/embedded/src/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.tsx +++ b/widget/embedded/src/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.tsx @@ -33,10 +33,18 @@ export function QuoteWarningsAndErrors(props: PropTypes) { onClose: onCloseWarningModal, onConfirm: onConfirmWarningModal, }; + const isNoResultError = error?.type === QuoteErrorType.NO_RESULT; + const isRequestFailedError = error?.type === QuoteErrorType.REQUEST_FAILED; + const isSameTokensWarning = warning?.type === QuoteWarningType.SAME_TOKENS; const showNoResultMessage = - error?.type === QuoteErrorType.NO_RESULT || - error?.type === QuoteErrorType.REQUEST_FAILED; + isNoResultError || isRequestFailedError || isSameTokensWarning; + + const displayedError = isSameTokensWarning + ? warning + : isNoResultError || isRequestFailedError + ? error + : null; const alertInfo = makeAlerts( warning, @@ -53,8 +61,9 @@ export function QuoteWarningsAndErrors(props: PropTypes) { return ( <> - {showNoResultMessage && } - + {showNoResultMessage && ( + + )} {showAlerts && ( { setLoading(loading); @@ -107,7 +105,12 @@ export function useSwapInput({ affiliatePercent, affiliateWallets, } = params; - + if (areTokensEqual(fromToken, toToken)) { + updateQuotePartialState('warning', { + type: QuoteWarningType.SAME_TOKENS, + }); + return; + } if (!loading) { resetState(true); } diff --git a/widget/embedded/src/types/quote.ts b/widget/embedded/src/types/quote.ts index 7072c576c7..8e1ea43b79 100644 --- a/widget/embedded/src/types/quote.ts +++ b/widget/embedded/src/types/quote.ts @@ -51,6 +51,7 @@ export enum QuoteWarningType { UNKNOWN_PRICE, INSUFFICIENT_SLIPPAGE, HIGH_SLIPPAGE, + SAME_TOKENS, } export enum QuoteUpdateType { @@ -100,11 +101,16 @@ export type UnknownPriceWarning = { type: QuoteWarningType.UNKNOWN_PRICE; }; +export type SameTokensWarning = { + type: QuoteWarningType.SAME_TOKENS; +}; + export type QuoteWarning = | HighValueLossWarning | InsufficientSlippageWarning | HighSlippageWarning - | UnknownPriceWarning; + | UnknownPriceWarning + | SameTokensWarning; export type ConfirmSwapWarnings = { quote: QuoteWarning | null; From de5524d8747c8d57bdb5432233031f8501501e20 Mon Sep 17 00:00:00 2001 From: mikasackermn Date: Wed, 13 Nov 2024 13:30:10 +0000 Subject: [PATCH 2/4] fix: display same tokens warning --- widget/embedded/src/hooks/useSwapInput.ts | 12 ++++-------- widget/embedded/src/pages/Home.tsx | 17 +++++++++++++---- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/widget/embedded/src/hooks/useSwapInput.ts b/widget/embedded/src/hooks/useSwapInput.ts index ce74fb9226..aa51bba5e5 100644 --- a/widget/embedded/src/hooks/useSwapInput.ts +++ b/widget/embedded/src/hooks/useSwapInput.ts @@ -5,7 +5,7 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import { useAppStore } from '../store/AppStore'; import { useQuoteStore } from '../store/quote'; import { useWalletsStore } from '../store/wallets'; -import { QuoteErrorType, QuoteWarningType } from '../types'; +import { QuoteErrorType } from '../types'; import { debounce } from '../utils/common'; import { isPositiveNumber } from '../utils/numbers'; import { @@ -86,7 +86,9 @@ export function useSwapInput({ const userSlippage = customSlippage ?? slippage; const tokensValueInvalid = !fromToken || !toToken; const shouldSkipRequest = - tokensValueInvalid || !isPositiveNumber(inputAmount); + tokensValueInvalid || + areTokensEqual(fromToken, toToken) || + !isPositiveNumber(inputAmount); const resetState = (loading: boolean) => { setLoading(loading); @@ -105,12 +107,6 @@ export function useSwapInput({ affiliatePercent, affiliateWallets, } = params; - if (areTokensEqual(fromToken, toToken)) { - updateQuotePartialState('warning', { - type: QuoteWarningType.SAME_TOKENS, - }); - return; - } if (!loading) { resetState(true); } diff --git a/widget/embedded/src/pages/Home.tsx b/widget/embedded/src/pages/Home.tsx index a59ca27e44..585d4a26fc 100644 --- a/widget/embedded/src/pages/Home.tsx +++ b/widget/embedded/src/pages/Home.tsx @@ -1,4 +1,4 @@ -import type { SelectedQuote } from '../types'; +import type { SameTokensWarning, SelectedQuote } from '../types'; import { i18n } from '@lingui/core'; import { Button, Divider, styled, WarningIcon } from '@rango-dev/ui'; @@ -19,10 +19,11 @@ import { useAppStore } from '../store/AppStore'; import { useQuoteStore } from '../store/quote'; import { useUiStore } from '../store/ui'; import { useWalletsStore } from '../store/wallets'; -import { UiEventTypes } from '../types'; +import { QuoteWarningType, UiEventTypes } from '../types'; import { isVariantExpandable } from '../utils/configs'; import { emitPreventableEvent } from '../utils/events'; import { getSwapButtonState, isTokensIdentical } from '../utils/swap'; +import { areTokensEqual } from '../utils/wallets'; const MainContainer = styled('div', { display: 'flex', @@ -88,9 +89,16 @@ export function Home() { const fetchingQuote = hasInputs && fetchMetaStatus === 'success' && loading; + const sameTokensWarning: SameTokensWarning | null = + areTokensEqual(fromToken, toToken) && fetchMetaStatus === 'success' + ? { + type: QuoteWarningType.SAME_TOKENS, + } + : null; + const hasValidQuotes = !isExpandable || (isExpandable && quotes?.results.length); - const hasWarningOrError = quoteWarning || quoteError; + const hasWarningOrError = quoteWarning || quoteError || sameTokensWarning; const showMessages = hasValidQuotes && hasWarningOrError; useEffect(() => { @@ -123,6 +131,7 @@ export function Home() { setSelectedQuote(quote); } }; + return ( Date: Sun, 17 Nov 2024 10:11:24 +0000 Subject: [PATCH 3/4] fix: delete SameTokensWarning type --- .../components/NoResult/NoResult.helpers.ts | 15 ++-------- .../src/components/NoResult/NoResult.types.ts | 8 ++--- .../QuoteWarningsAndErrors.helpers.ts | 6 ---- .../QuoteWarningsAndErrors.tsx | 17 +++-------- .../SameTokensWarning.styles.ts | 7 +++++ .../SameTokensWarning/SameTokensWarning.tsx | 30 +++++++++++++++++++ .../src/components/SameTokensWarning/index.ts | 1 + widget/embedded/src/hooks/useSwapInput.ts | 1 + widget/embedded/src/pages/Home.tsx | 18 ++++------- widget/embedded/src/types/quote.ts | 8 +---- 10 files changed, 55 insertions(+), 56 deletions(-) create mode 100644 widget/embedded/src/components/SameTokensWarning/SameTokensWarning.styles.ts create mode 100644 widget/embedded/src/components/SameTokensWarning/SameTokensWarning.tsx create mode 100644 widget/embedded/src/components/SameTokensWarning/index.ts diff --git a/widget/embedded/src/components/NoResult/NoResult.helpers.ts b/widget/embedded/src/components/NoResult/NoResult.helpers.ts index 2415707114..f0bfb1cce0 100644 --- a/widget/embedded/src/components/NoResult/NoResult.helpers.ts +++ b/widget/embedded/src/components/NoResult/NoResult.helpers.ts @@ -1,20 +1,16 @@ import type { Info } from './NoResult.types'; -import type { - NoResultError, - QuoteRequestFailed, - SameTokensWarning, -} from '../../types'; +import type { NoResultError, QuoteRequestFailed } from '../../types'; import { i18n } from '@lingui/core'; import { errorMessages } from '../../constants/errors'; -import { QuoteErrorType, QuoteWarningType } from '../../types'; +import { QuoteErrorType } from '../../types'; const SMALL_NO_ROUTE__ICON_SIZE = 24; const LARGE_NO_ROUTE_ICON_SIZE = 60; export function makeInfo( - error: NoResultError | QuoteRequestFailed | SameTokensWarning | null, + error: NoResultError | QuoteRequestFailed | null, disabledLiquiditySources: string[], toggleAllLiquiditySources: (shouldReset: boolean) => void, refetchQuote: () => void @@ -31,11 +27,6 @@ export function makeInfo( }, description: '', }; - } else if (error?.type === QuoteWarningType.SAME_TOKENS) { - return { - alert: null, - description: '', - }; } else if (disabledLiquiditySources.length) { return { alert: { diff --git a/widget/embedded/src/components/NoResult/NoResult.types.ts b/widget/embedded/src/components/NoResult/NoResult.types.ts index 7e12d0e43b..8821114652 100644 --- a/widget/embedded/src/components/NoResult/NoResult.types.ts +++ b/widget/embedded/src/components/NoResult/NoResult.types.ts @@ -1,12 +1,8 @@ -import type { - NoResultError, - QuoteRequestFailed, - SameTokensWarning, -} from '../../types'; +import type { NoResultError, QuoteRequestFailed } from '../../types'; export interface PropTypes { fetch: () => void; - error: NoResultError | QuoteRequestFailed | SameTokensWarning | null; + error: NoResultError | QuoteRequestFailed | null; size?: 'small' | 'large'; } diff --git a/widget/embedded/src/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.helpers.ts b/widget/embedded/src/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.helpers.ts index d71610bb03..367dc68149 100644 --- a/widget/embedded/src/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.helpers.ts +++ b/widget/embedded/src/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.helpers.ts @@ -68,12 +68,6 @@ export function makeAlerts( alertInfo.title = i18n.t('Caution, your slippage is high.'); alertInfo.action = 'change-settings'; } - if (warning.type === QuoteWarningType.SAME_TOKENS) { - alertInfo.title = i18n.t( - 'You cannot use the same token for From and To.' - ); - } - return alertInfo; } return null; diff --git a/widget/embedded/src/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.tsx b/widget/embedded/src/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.tsx index f9007a3ec8..b1874144c7 100644 --- a/widget/embedded/src/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.tsx +++ b/widget/embedded/src/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.tsx @@ -33,18 +33,10 @@ export function QuoteWarningsAndErrors(props: PropTypes) { onClose: onCloseWarningModal, onConfirm: onConfirmWarningModal, }; - const isNoResultError = error?.type === QuoteErrorType.NO_RESULT; - const isRequestFailedError = error?.type === QuoteErrorType.REQUEST_FAILED; - const isSameTokensWarning = warning?.type === QuoteWarningType.SAME_TOKENS; const showNoResultMessage = - isNoResultError || isRequestFailedError || isSameTokensWarning; - - const displayedError = isSameTokensWarning - ? warning - : isNoResultError || isRequestFailedError - ? error - : null; + error?.type === QuoteErrorType.NO_RESULT || + error?.type === QuoteErrorType.REQUEST_FAILED; const alertInfo = makeAlerts( warning, @@ -61,9 +53,8 @@ export function QuoteWarningsAndErrors(props: PropTypes) { return ( <> - {showNoResultMessage && ( - - )} + {showNoResultMessage && } + {showAlerts && ( + + + + {i18n.t('No Routes Found')} + + + + + ) : null; +} diff --git a/widget/embedded/src/components/SameTokensWarning/index.ts b/widget/embedded/src/components/SameTokensWarning/index.ts new file mode 100644 index 0000000000..997e76f388 --- /dev/null +++ b/widget/embedded/src/components/SameTokensWarning/index.ts @@ -0,0 +1 @@ +export { SameTokensWarning } from './SameTokensWarning'; diff --git a/widget/embedded/src/hooks/useSwapInput.ts b/widget/embedded/src/hooks/useSwapInput.ts index aa51bba5e5..5bca482537 100644 --- a/widget/embedded/src/hooks/useSwapInput.ts +++ b/widget/embedded/src/hooks/useSwapInput.ts @@ -107,6 +107,7 @@ export function useSwapInput({ affiliatePercent, affiliateWallets, } = params; + if (!loading) { resetState(true); } diff --git a/widget/embedded/src/pages/Home.tsx b/widget/embedded/src/pages/Home.tsx index 585d4a26fc..eb539c0172 100644 --- a/widget/embedded/src/pages/Home.tsx +++ b/widget/embedded/src/pages/Home.tsx @@ -1,4 +1,4 @@ -import type { SameTokensWarning, SelectedQuote } from '../types'; +import type { SelectedQuote } from '../types'; import { i18n } from '@lingui/core'; import { Button, Divider, styled, WarningIcon } from '@rango-dev/ui'; @@ -9,6 +9,7 @@ import { useNavigate } from 'react-router-dom'; import { HeaderButtons } from '../components/HeaderButtons'; import { Layout, PageContainer } from '../components/Layout'; import { QuoteWarningsAndErrors } from '../components/QuoteWarningsAndErrors'; +import { SameTokensWarning } from '../components/SameTokensWarning'; import { navigationRoutes } from '../constants/navigationRoutes'; import { ExpandedQuotes } from '../containers/ExpandedQuotes'; import { Inputs } from '../containers/Inputs'; @@ -19,11 +20,10 @@ import { useAppStore } from '../store/AppStore'; import { useQuoteStore } from '../store/quote'; import { useUiStore } from '../store/ui'; import { useWalletsStore } from '../store/wallets'; -import { QuoteWarningType, UiEventTypes } from '../types'; +import { UiEventTypes } from '../types'; import { isVariantExpandable } from '../utils/configs'; import { emitPreventableEvent } from '../utils/events'; import { getSwapButtonState, isTokensIdentical } from '../utils/swap'; -import { areTokensEqual } from '../utils/wallets'; const MainContainer = styled('div', { display: 'flex', @@ -89,16 +89,9 @@ export function Home() { const fetchingQuote = hasInputs && fetchMetaStatus === 'success' && loading; - const sameTokensWarning: SameTokensWarning | null = - areTokensEqual(fromToken, toToken) && fetchMetaStatus === 'success' - ? { - type: QuoteWarningType.SAME_TOKENS, - } - : null; - const hasValidQuotes = !isExpandable || (isExpandable && quotes?.results.length); - const hasWarningOrError = quoteWarning || quoteError || sameTokensWarning; + const hasWarningOrError = quoteWarning || quoteError; const showMessages = hasValidQuotes && hasWarningOrError; useEffect(() => { @@ -216,7 +209,7 @@ export function Home() { <> ) : null} + {isExpandable ? ( diff --git a/widget/embedded/src/types/quote.ts b/widget/embedded/src/types/quote.ts index 8e1ea43b79..7072c576c7 100644 --- a/widget/embedded/src/types/quote.ts +++ b/widget/embedded/src/types/quote.ts @@ -51,7 +51,6 @@ export enum QuoteWarningType { UNKNOWN_PRICE, INSUFFICIENT_SLIPPAGE, HIGH_SLIPPAGE, - SAME_TOKENS, } export enum QuoteUpdateType { @@ -101,16 +100,11 @@ export type UnknownPriceWarning = { type: QuoteWarningType.UNKNOWN_PRICE; }; -export type SameTokensWarning = { - type: QuoteWarningType.SAME_TOKENS; -}; - export type QuoteWarning = | HighValueLossWarning | InsufficientSlippageWarning | HighSlippageWarning - | UnknownPriceWarning - | SameTokensWarning; + | UnknownPriceWarning; export type ConfirmSwapWarnings = { quote: QuoteWarning | null; From 8c043d38f35f96b8f5dd994593c51cfcbc9bfd04 Mon Sep 17 00:00:00 2001 From: mikasackermn Date: Mon, 18 Nov 2024 11:09:38 +0000 Subject: [PATCH 4/4] fix: spacing around the SameTokensWarning component --- .../src/components/SameTokensWarning/SameTokensWarning.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/widget/embedded/src/components/SameTokensWarning/SameTokensWarning.tsx b/widget/embedded/src/components/SameTokensWarning/SameTokensWarning.tsx index 1f2c859384..7774230b31 100644 --- a/widget/embedded/src/components/SameTokensWarning/SameTokensWarning.tsx +++ b/widget/embedded/src/components/SameTokensWarning/SameTokensWarning.tsx @@ -10,21 +10,22 @@ import { Container } from './SameTokensWarning.styles'; export function SameTokensWarning() { const { fromToken, toToken } = useQuoteStore(); const showWarningMessage = - fromToken && toToken && areTokensEqual(fromToken, toToken); + !!fromToken && !!toToken && areTokensEqual(fromToken, toToken); return showWarningMessage ? ( + {i18n.t('No Routes Found')} - + ) : null; }