diff --git a/apps/cowswap-frontend/src/modules/swap/pure/banners/TwapSuggestionBanner.tsx b/apps/cowswap-frontend/src/modules/swap/pure/banners/TwapSuggestionBanner.tsx index 53f3c0dfcc..d73d8abe16 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/banners/TwapSuggestionBanner.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/banners/TwapSuggestionBanner.tsx @@ -1,3 +1,4 @@ +import { getIsNativeToken } from '@cowprotocol/common-utils' import { OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk' import { InlineBanner } from '@cowprotocol/ui' import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' @@ -26,7 +27,7 @@ export interface TwapSuggestionBannerProps { priceImpact: Percent | undefined buyingFiatAmount: CurrencyAmount | null tradeUrlParams: TradeUrlParams - sellAmount: string | undefined + sellAmount: CurrencyAmount | undefined } const PRICE_IMPACT_LIMIT = 1 // 1% @@ -47,8 +48,11 @@ export function TwapSuggestionBanner({ }: TwapSuggestionBannerProps) { if (!priceImpact || priceImpact.lessThan(0)) return null - const shouldSuggestTwap = - +priceImpact.toFixed(2) > PRICE_IMPACT_LIMIT && +(buyingFiatAmount?.toExact() || 0) > AMOUNT_LIMIT[chainId] + const isSellNative = !!sellAmount?.currency && getIsNativeToken(sellAmount?.currency) + const priceImpactIsHighEnough = +priceImpact.toFixed(2) > PRICE_IMPACT_LIMIT + const buyAmountIsBigEnough = +(buyingFiatAmount?.toExact() || 0) > AMOUNT_LIMIT[chainId] + + const shouldSuggestTwap = !isSellNative && priceImpactIsHighEnough && buyAmountIsBigEnough if (!shouldSuggestTwap) return null @@ -56,7 +60,7 @@ export function TwapSuggestionBanner({ parameterizeTradeRoute(tradeUrlParams, Routes.ADVANCED_ORDERS) + '?' + parameterizeTradeSearch('', { - amount: sellAmount, + amount: sellAmount?.toExact(), kind: OrderKind.SELL, }) diff --git a/apps/cowswap-frontend/src/modules/swap/pure/warnings.tsx b/apps/cowswap-frontend/src/modules/swap/pure/warnings.tsx index 481c469f17..eb15b33893 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/warnings.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/warnings.tsx @@ -10,6 +10,7 @@ import { SellNativeWarningBanner } from 'modules/trade/containers/SellNativeWarn import { CompatibilityIssuesWarning } from 'modules/trade/pure/CompatibilityIssuesWarning' import { TradeUrlParams } from 'modules/trade/types/TradeRawState' import { BundleTxWrapBanner, HighFeeWarning } from 'modules/tradeWidgetAddons' +import { MetamaskTransactionWarning } from 'modules/tradeWidgetAddons' import { TwapSuggestionBanner } from './banners/TwapSuggestionBanner' @@ -40,9 +41,11 @@ export const SwapWarningsTop = React.memo(function (props: SwapWarningsTopProps) tradeUrlParams, isNativeSellInHooksStore, } = props + const sellToken = trade?.inputAmount.currency return ( <> + {sellToken && !isNativeSellInHooksStore && } {isNativeSellInHooksStore ? ( ) : ( @@ -56,7 +59,7 @@ export const SwapWarningsTop = React.memo(function (props: SwapWarningsTopProps) priceImpact={priceImpact} buyingFiatAmount={buyingFiatAmount} tradeUrlParams={tradeUrlParams} - sellAmount={trade?.inputAmount.toExact()} + sellAmount={trade?.inputAmount} /> )} diff --git a/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/TradeWidgetForm.tsx b/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/TradeWidgetForm.tsx index 6866a903ba..1527a0181a 100644 --- a/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/TradeWidgetForm.tsx +++ b/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/TradeWidgetForm.tsx @@ -91,8 +91,9 @@ export function TradeWidgetForm(props: TradeWidgetProps) { const alternativeOrderModalVisible = useIsAlternativeOrderModalVisible() const primaryFormValidation = useGetTradeFormValidation() - const areCurrenciesLoading = !inputCurrencyInfo.currency && !outputCurrencyInfo.currency - const bothCurrenciesSet = !!inputCurrencyInfo.currency && !!outputCurrencyInfo.currency + const sellToken = inputCurrencyInfo.currency + const areCurrenciesLoading = !sellToken && !outputCurrencyInfo.currency + const bothCurrenciesSet = !!sellToken && !!outputCurrencyInfo.currency const hasRecipientInUrl = !!tradeStateFromUrl?.recipient const withRecipient = !isWrapOrUnwrap && (showRecipient || hasRecipientInUrl) @@ -141,9 +142,9 @@ export function TradeWidgetForm(props: TradeWidgetProps) { const openBuyTokenSelect = useCallback( (selectedToken: string | undefined, field: Field | undefined, onSelectToken: (currency: Currency) => void) => { - openTokenSelectWidget(selectedToken, field, inputCurrencyInfo.currency || undefined, onSelectToken) + openTokenSelectWidget(selectedToken, field, sellToken || undefined, onSelectToken) }, - [openTokenSelectWidget, inputCurrencyInfo.currency], + [openTokenSelectWidget, sellToken], ) const toggleAccountModal = useToggleAccountModal() @@ -198,7 +199,7 @@ export function TradeWidgetForm(props: TradeWidgetProps) { isCollapsed={compactView} hasSeparatorLine={!compactView} onSwitchTokens={isChainIdUnsupported ? () => void 0 : throttledOnSwitchTokens} - isLoading={Boolean(inputCurrencyInfo.currency && outputCurrencyInfo.currency && isTradePriceUpdating)} + isLoading={Boolean(sellToken && outputCurrencyInfo.currency && isTradePriceUpdating)} disabled={isAlternativeOrderModalVisible} /> @@ -223,7 +224,9 @@ export function TradeWidgetForm(props: TradeWidgetProps) { {withRecipient && } {isWrapOrUnwrap ? ( - + sellToken ? ( + + ) : null ) : ( bottomContent?.( hideTradeWarnings ? null : ( diff --git a/apps/cowswap-frontend/src/modules/trade/containers/WrapFlowActionButton/index.tsx b/apps/cowswap-frontend/src/modules/trade/containers/WrapFlowActionButton/index.tsx index 93f06b8bf2..0d6dd0304d 100644 --- a/apps/cowswap-frontend/src/modules/trade/containers/WrapFlowActionButton/index.tsx +++ b/apps/cowswap-frontend/src/modules/trade/containers/WrapFlowActionButton/index.tsx @@ -1,4 +1,9 @@ +import React from 'react' + +import { Currency } from '@uniswap/sdk-core' + import { TradeFormButtons, useGetTradeFormValidation, useTradeFormButtonContext } from 'modules/tradeFormValidation' +import { MetamaskTransactionWarning } from 'modules/tradeWidgetAddons' const doTradeText = '' const confirmText = '' @@ -8,13 +13,16 @@ const confirmTrade = () => void 0 * This component is used only to display a button for Wrap/Unwrap * because of it, we just stub parameters above */ -export function WrapFlowActionButton() { +export function WrapFlowActionButton({ sellToken }: { sellToken: Currency }) { const primaryFormValidation = useGetTradeFormValidation() const tradeFormButtonContext = useTradeFormButtonContext(doTradeText, confirmTrade) if (!tradeFormButtonContext) return null return ( - + <> + + + ) } diff --git a/apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/MetamaskTransactionWarning/index.tsx b/apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/MetamaskTransactionWarning/index.tsx new file mode 100644 index 0000000000..738c5baf2a --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/MetamaskTransactionWarning/index.tsx @@ -0,0 +1,41 @@ +import { CHAIN_INFO } from '@cowprotocol/common-const' +import { getIsNativeToken } from '@cowprotocol/common-utils' +import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { BannerOrientation, InlineBanner } from '@cowprotocol/ui' +import { useWalletProvider } from '@cowprotocol/wallet-provider' +import { Currency } from '@uniswap/sdk-core' + +import SVG from 'react-inlinesvg' +import styled from 'styled-components/macro' + +const Banner = styled(InlineBanner)` + font-size: 14px; + text-align: center; +` + +const NetworkInfo = styled.div` + display: flex; + align-items: center; + gap: 8px; +` + +export function MetamaskTransactionWarning({ sellToken }: { sellToken: Currency }) { + const provider = useWalletProvider() + const ethereumProvider = (provider as unknown as { provider: typeof window.ethereum })?.provider + const isMetamask = !!ethereumProvider?.isMetaMask && !ethereumProvider.isRabby + const isNativeSellToken = getIsNativeToken(sellToken) + + if (!isMetamask || !isNativeSellToken) return null + + const chainInfo = CHAIN_INFO[sellToken.chainId as SupportedChainId] + + return ( + + Issues have been reported with Metamask sending transactions to the wrong chain. + Before you sign, please check in your wallet that the transaction is being sent to the network:{' '} + + {chainInfo.label} + + + ) +} diff --git a/apps/cowswap-frontend/src/modules/tradeWidgetAddons/index.ts b/apps/cowswap-frontend/src/modules/tradeWidgetAddons/index.ts index 5506835feb..2f39b6fc32 100644 --- a/apps/cowswap-frontend/src/modules/tradeWidgetAddons/index.ts +++ b/apps/cowswap-frontend/src/modules/tradeWidgetAddons/index.ts @@ -3,5 +3,6 @@ export { TradeRateDetails } from './containers/TradeRateDetails' export { SettingsTab } from './containers/SettingsTab' export { HighFeeWarning } from './containers/HighFeeWarning' export { BundleTxWrapBanner } from './containers/BundleTxWrapBanner' +export { MetamaskTransactionWarning } from './containers/MetamaskTransactionWarning' export { useHighFeeWarning } from './containers/HighFeeWarning/hooks/useHighFeeWarning' export { NetworkCostsTooltipSuffix } from './pure/NetworkCostsTooltipSuffix'