diff --git a/components/DTOs/SwapFormValues.ts b/components/DTOs/SwapFormValues.ts index 492950c42..f023388f8 100644 --- a/components/DTOs/SwapFormValues.ts +++ b/components/DTOs/SwapFormValues.ts @@ -10,12 +10,13 @@ export type SwapFormValues = { refuel?: boolean; from?: RouteNetwork; to?: RouteNetwork; - fromExchange?: Exchange, - toExchange?: Exchange, - currencyGroup?: ExchangeToken + fromExchange?: Exchange; + toExchange?: Exchange; + currencyGroup?: ExchangeToken & { manuallySet?: boolean }; depositMethod?: 'wallet' | 'deposit_address', validatingSource?: boolean; validatingDestination?: boolean; + validatingCurrencyGroup?: boolean; } diff --git a/components/Input/CEXCurrencyFormField.tsx b/components/Input/CEXCurrencyFormField.tsx index aed27822a..5dc0917c0 100644 --- a/components/Input/CEXCurrencyFormField.tsx +++ b/components/Input/CEXCurrencyFormField.tsx @@ -28,6 +28,7 @@ const CurrencyGroupFormField: FC<{ direction: SwapDirection }> = ({ direction }) const apiClient = new LayerSwapApiClient() const { data: exchanges, + isLoading, error } = useSWR>(`${exchangeRoutesURL}`, apiClient.fetcher, { keepPreviousData: true, fallbackData: { data: direction === 'from' ? sourceExchanges : destinationExchanges }, dedupingInterval: 10000 }) @@ -57,14 +58,34 @@ const CurrencyGroupFormField: FC<{ direction: SwapDirection }> = ({ direction }) }, []) useEffect(() => { - const value = availableAssetGroups?.find(r => r.symbol === currencyGroup?.symbol) - if (!value) return - setFieldValue(name, value) + const currency = direction === 'from' ? toCurrency : fromCurrency + const value = availableAssetGroups?.find(r => r.symbol === currency?.symbol && r.status === 'active') + + if (!value || currencyGroup?.manuallySet) + return + + (async () => { + setFieldValue(name, value) + await setFieldValue(direction == "from" ? "validatingSource" : "validatingDestination", true, true) + await setFieldValue("validatingCurrencyGroup", false, true) + })(); }, [fromCurrency, toCurrency, availableAssetGroups]) - const handleSelect = useCallback((item: SelectMenuItem) => { - setFieldValue(name, item.baseObject, true) - }, [name, direction, toCurrency, fromCurrency, from, to]) + const handleSelect = useCallback(async (item: SelectMenuItem) => { + const oppositeCurrency = direction === 'from' ? toCurrency : fromCurrency + if (oppositeCurrency && !oppositeCurrency?.manuallySet) { + const network = direction === 'to' ? from : to + const default_currency = network?.tokens?.find(t => t.symbol === item.baseObject.symbol) || network?.tokens?.find(t => t.symbol.includes(item.baseObject.symbol) || item.baseObject.symbol.includes(t.symbol)) + if (default_currency) { + await setFieldValue("validatingDestination", true, true) + await setFieldValue("validatingSource", true, true) + await setFieldValue(`${direction == "from" ? "to" : "from"}Currency`, default_currency, true) + } + } + + (item.baseObject as any).manuallySet = true + await setFieldValue(name, item.baseObject, true) + }, [name, direction, toCurrency, fromCurrency, from, to, values]) return = { baseObject: c, id: c.symbol, @@ -96,10 +115,10 @@ export function GenerateCurrencyMenuItems( order: ResolveCEXCurrencyOrder(c), imgSrc: c.logo, isAvailable: isAvailable, - leftIcon: + leftIcon: }; return res }); } -export default CurrencyGroupFormField \ No newline at end of file +export default CurrencyGroupFormField diff --git a/components/Input/CurrencyFormField.tsx b/components/Input/CurrencyFormField.tsx index 6fe4dd768..cf95ef89a 100644 --- a/components/Input/CurrencyFormField.tsx +++ b/components/Input/CurrencyFormField.tsx @@ -28,6 +28,7 @@ const CurrencyFormField: FC<{ direction: SwapDirection }> = ({ direction }) => { const { from, to, fromCurrency, toCurrency, fromExchange, toExchange, destination_address, currencyGroup } = values const name = direction === 'from' ? 'fromCurrency' : 'toCurrency'; + const exchangeName = direction === 'from' ? 'fromExchange' : 'toExchange'; const query = useQueryState() const { selectedSourceAccount } = useSwapDataState() const { destinationRoutes, sourceRoutes } = useSettingsState(); @@ -152,12 +153,11 @@ const CurrencyFormField: FC<{ direction: SwapDirection }> = ({ direction }) => { if (!value || value === toCurrency) return (value as any).manuallySet = toCurrency.manuallySet await setFieldValue(name, value) - await setFieldValue("validatingDestination", isLoading, true) + await setFieldValue("validatingDestination", false, true) })() } }, [fromCurrency, currencyGroup, name, to, routes, error, isLoading]) - useEffect(() => { if (name === "fromCurrency" && fromCurrency && !isLoading && routes) { (async () => { @@ -165,15 +165,27 @@ const CurrencyFormField: FC<{ direction: SwapDirection }> = ({ direction }) => { if (!value || value === fromCurrency) return (value as any).manuallySet = fromCurrency.manuallySet await setFieldValue(name, value) - await setFieldValue("validatingSource", isLoading, true) + await setFieldValue("validatingSource", false, true) })() } }, [toCurrency, currencyGroup, name, from, routes, error, isLoading]) const handleSelect = useCallback(async (item: SelectMenuItem) => { const oppositeCurrency = direction === 'from' ? toCurrency : fromCurrency + const exchange = direction === 'from' ? toExchange : fromExchange + + if (currencyGroup && !currencyGroup?.manuallySet) { + const default_currency = exchange?.token_groups?.find(t => t.symbol === item.baseObject.symbol) || exchange?.token_groups?.find(t => t.symbol.includes(item.baseObject.symbol) || item.baseObject.symbol.includes(t.symbol)) + if (default_currency) { + await setFieldValue("validatingCurrencyGroup", true, true) + await setFieldValue(direction == "from" ? "validatingSource" : "validatingDestination", true, true) + await setFieldValue("currencyGroup", default_currency, true) + } + } + if (oppositeCurrency && !oppositeCurrency?.manuallySet) { const network = direction === 'to' ? from : to + const default_currency = network?.tokens?.find(t => t.symbol === item.baseObject.symbol) || network?.tokens?.find(t => t.symbol.includes(item.baseObject.symbol) || item.baseObject.symbol.includes(t.symbol)) if (default_currency) { await setFieldValue("validatingDestination", true, true) diff --git a/context/validationErrorContext.tsx b/context/validationErrorContext.tsx index f1eac6af6..d49c4cf1c 100644 --- a/context/validationErrorContext.tsx +++ b/context/validationErrorContext.tsx @@ -33,7 +33,7 @@ export const ValidationProvider: React.FC<{ children: ReactNode }> = ({ children } = useFormikContext(); const { destinationRoutes: allDestinations, sourceRoutes: allSources } = useSettingsState() const { selectedSourceAccount } = useSwapDataState() - const { to, from, fromCurrency, toCurrency, toExchange, fromExchange, currencyGroup, validatingSource, validatingDestination, destination_address } = values; + const { to, from, fromCurrency, toCurrency, toExchange, fromExchange, currencyGroup, validatingSource, validatingDestination, validatingCurrencyGroup, destination_address } = values; const query = useQueryState(); const fromDisplayName = fromExchange ? fromExchange.display_name : from?.display_name; const toDisplayName = toExchange ? toExchange.display_name : to?.display_name; @@ -88,7 +88,7 @@ export const ValidationProvider: React.FC<{ children: ReactNode }> = ({ children validationDetails = { title: 'Temporarily unavailable.', type: 'warning', icon: }; } } - else if (!validatingSource && !validatingDestination && (currencyGroup?.status === 'not_found' || toCurrency?.status === 'not_found' || fromCurrency?.status === 'not_found')) { + else if (!validatingSource && !validatingDestination && !validatingCurrencyGroup && (currencyGroup?.status === 'not_found' || toCurrency?.status === 'not_found' || fromCurrency?.status === 'not_found')) { validationMessage = 'Please change one of the selected tokens'; validationDetails = { title: 'Route Unavailable', type: 'warning', icon: }; }