From 46df189319113943d12a61b16601d9761ded1902 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Tue, 10 Oct 2023 13:16:53 +0600 Subject: [PATCH] feat(tokens): wire up new tokens lib into app --- .../src/api/gasPrices/index.ts | 4 +- .../src/api/gnosisProtocol/api.ts | 12 --- .../src/api/gnosisProtocol/index.ts | 2 - .../src/common/hooks/useApproveCallback.ts | 5 +- .../src/common/hooks/useApproveState.ts | 6 +- .../src/common/hooks/useCancelOrder/state.ts | 4 +- .../src/common/hooks/useNeedsApproval.ts | 4 +- .../src/common/hooks/useSafeMemo.ts | 5 +- .../useShouldZeroApprove.ts | 7 +- .../src/common/pure/ApproveButton/index.tsx | 5 +- .../RequestCancellationModal.tsx | 5 +- .../CurrencyInputPanel/CurrencyInputPanel.tsx | 38 ++++----- .../defaultCurrencyInputProps.ts | 3 + .../pure/CurrencySelectButton/index.tsx | 5 +- .../src/common/pure/IconSpinner/index.tsx | 9 +-- .../src/common/pure/RateInfo/index.tsx | 2 +- .../common/services/getQuoteCurrency/index.ts | 9 ++- .../src/common/updaters/FeesUpdater.ts | 10 +-- .../common/updaters/orders/GpOrdersUpdater.ts | 2 +- .../updaters/orders/PendingOrdersUpdater.ts | 10 +-- .../src/common/updaters/orders/utils.ts | 4 +- .../src/legacy/components/Header/index.tsx | 8 +- .../Tokens/FavouriteTokenButton.tsx | 6 +- .../legacy/components/Tokens/TokensTable.tsx | 13 +-- .../components/Tokens/TokensTableRow.tsx | 8 +- .../src/legacy/components/Tokens/sorting.ts | 65 +++++++++++++++ .../src/legacy/components/Tokens/styled.ts | 55 +------------ .../TransactionSettingsMod.tsx | 5 +- .../src/legacy/components/Version/index.tsx | 9 +-- .../swap/ConfirmSwapModal/hooks.tsx | 3 +- .../components/swap/SwapModalHeader/index.tsx | 10 ++- .../UnsupportedCurrencyFooterMod.tsx | 12 +-- .../useApproveCallbackMod.ts | 13 +-- .../legacy/hooks/useRefetchPriceCallback.tsx | 50 ++++-------- .../src/legacy/hooks/useTokenLazy.ts | 17 +++- .../src/legacy/hooks/useWrapCallback.ts | 9 ++- .../src/legacy/state/claim/hooks/index.ts | 8 +- .../src/legacy/state/claim/hooks/utils.ts | 16 ++-- .../src/legacy/state/claim/types.ts | 3 +- .../src/legacy/state/gas/actions.ts | 6 +- .../src/legacy/state/global/actions.ts | 8 +- .../src/legacy/state/index.ts | 10 +-- .../src/legacy/state/orders/hooks.ts | 4 +- .../src/legacy/state/orders/reducer.ts | 5 +- .../src/legacy/state/swap/reducer.ts | 2 +- .../src/legacy/state/swap/utils.ts | 12 ++- .../src/legacy/state/user/hooks.tsx | 55 ++----------- .../src/legacy/state/user/reducer.ts | 80 +------------------ .../src/legacy/utils/trade.ts | 8 +- .../src/lib/hooks/useApproval.ts | 10 ++- .../src/lib/hooks/useNativeCurrency.ts | 9 +-- .../Transaction/ActivityDetails.tsx | 17 ++-- .../account/containers/Transaction/styled.ts | 31 ++++--- .../application/containers/App/Updaters.tsx | 10 +-- .../LimitOrdersConfirmModal/index.tsx | 3 +- .../containers/LimitOrdersWidget/index.tsx | 1 - .../limitOrders/hooks/useGetInitialPrice.ts | 4 +- .../orders/hooks/useTokensForOrdersList.ts | 8 +- .../OrdersTableContainer/OrderRow/index.tsx | 4 +- .../OrdersTableContainer/OrderRow/styled.tsx | 4 +- .../utils/getOrderParams.ts | 2 +- .../permit/hooks/useIsTokenPermittable.ts | 5 +- .../hooks/useRemainingNativeTxsAndCosts.ts | 3 +- .../modules/swap/containers/EthFlow/index.tsx | 5 +- .../swap/containers/SwapWidget/index.tsx | 2 +- .../tradeReceiveAmount.test.ts.snap | 25 ++++-- .../hooks/useBaseSafeBundleFlowContext.ts | 3 +- .../modules/swap/hooks/useEthFlowContext.ts | 4 +- .../src/modules/swap/hooks/useFlowContext.ts | 11 +-- .../hooks/useSafeBundleApprovalFlowContext.ts | 3 +- .../swap/hooks/useSwapButtonContext.ts | 7 +- .../modules/swap/hooks/useSwapFlowContext.ts | 3 +- .../src/modules/swap/hooks/useSwapState.tsx | 21 ++--- .../EthFlow/EthFlowBanner/index.cosmos.tsx | 8 +- .../pure/EthFlow/WrappingPreview/WrapCard.tsx | 23 +----- .../WrappingPreview/WrappingPreview.tsx | 7 +- .../pure/EthFlow/WrappingPreview/styled.tsx | 4 +- .../pure/Row/RowFeeContent/index.cosmos.tsx | 3 +- .../modules/swap/pure/SwapButtons/index.tsx | 26 ++++-- .../modules/swap/services/ethFlow/mocks.ts | 4 +- .../tokens/hooks/useCurrencyBalance.ts | 20 +++-- .../modules/tokens/hooks/useEnoughBalance.ts | 10 +-- .../TradeWidget/TradeWidgetModals.tsx | 9 ++- .../trade/containers/TradeWidget/index.tsx | 6 +- .../containers/WrapNativeModal/index.tsx | 3 +- .../useResetStateWithSymbolDuplication.ts | 3 +- .../trade/hooks/useBuildTradeDerivedState.ts | 2 +- .../trade/hooks/useNativeTokenContext.ts | 4 +- .../hooks/useNavigateOnCurrencySelection.ts | 3 +- .../modules/trade/hooks/useWrappedToken.ts | 3 +- .../hooks/useTradeFormValidationContext.ts | 3 +- .../pure/TradeFormButtons/tradeButtonsMap.tsx | 9 ++- .../hooks/useProcessUnsupportedTokenError.ts | 15 +--- .../tradeQuote/hooks/useQuoteParams.ts | 5 +- .../tradeQuote/hooks/useTradeQuotePolling.ts | 3 +- .../twap/hooks/useEmulatedPartOrders.ts | 3 +- .../twap/hooks/useEmulatedTwapOrders.ts | 3 +- .../modules/twap/hooks/useTwapOrdersTokens.ts | 3 +- .../twap/utils/mapPartOrderToStoreOrder.ts | 9 +-- .../twap/utils/mapTwapOrderToStoreOrder.ts | 9 +-- .../modules/twap/utils/twapOrderToStruct.ts | 3 +- .../wallet/containers/AddToMetamask/index.tsx | 9 ++- .../wallet/state/followPendingTxPopupAtom.ts | 4 +- .../pages/Account/Tokens/TokensOverview.tsx | 19 +++-- .../src/pages/Account/Tokens/styled.ts | 71 ++++++++++++++++ .../Claim/InvestmentFlow/InvestOption.tsx | 3 +- .../src/pages/Claim/InvestmentFlow/index.tsx | 3 +- 107 files changed, 552 insertions(+), 606 deletions(-) create mode 100644 apps/cowswap-frontend/src/legacy/components/Tokens/sorting.ts diff --git a/apps/cowswap-frontend/src/api/gasPrices/index.ts b/apps/cowswap-frontend/src/api/gasPrices/index.ts index 6da9ca3898..029e676757 100644 --- a/apps/cowswap-frontend/src/api/gasPrices/index.ts +++ b/apps/cowswap-frontend/src/api/gasPrices/index.ts @@ -1,4 +1,4 @@ -import { DEFAULT_NETWORK_FOR_LISTS, GAS_API_KEYS, GAS_FEE_ENDPOINTS } from '@cowprotocol/common-const' +import { GAS_API_KEYS, GAS_FEE_ENDPOINTS } from '@cowprotocol/common-const' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' import { fetchWithRateLimit } from 'common/utils/fetch' @@ -119,7 +119,7 @@ class GasFeeApi { return response.json() } - async getGasPrices(chainId: ChainId = DEFAULT_NETWORK_FOR_LISTS): Promise { + async getGasPrices(chainId: ChainId = ChainId.MAINNET): Promise { const data = await this.fetchData(chainId) const parsed = this.parseData(data, chainId) diff --git a/apps/cowswap-frontend/src/api/gnosisProtocol/api.ts b/apps/cowswap-frontend/src/api/gnosisProtocol/api.ts index 87646e78ea..2c19b3afc1 100644 --- a/apps/cowswap-frontend/src/api/gnosisProtocol/api.ts +++ b/apps/cowswap-frontend/src/api/gnosisProtocol/api.ts @@ -48,18 +48,6 @@ const DEFAULT_HEADERS = { 'Content-Type': 'application/json', } const API_NAME = 'CoW Protocol' -/** - * Unique identifier for the order, calculated by keccak256(orderDigest, ownerAddress, validTo), - * where orderDigest = keccak256(orderStruct). bytes32. - */ -export type OrderID = string - -export interface UnsupportedToken { - [token: string]: { - address: string - dateAdded: number - } -} function _getProfileApiBaseUrl(chainId: ChainId): string { const baseUrl = PROFILE_API_BASE_URL[chainId] diff --git a/apps/cowswap-frontend/src/api/gnosisProtocol/index.ts b/apps/cowswap-frontend/src/api/gnosisProtocol/index.ts index ede6377c72..a205a8310c 100644 --- a/apps/cowswap-frontend/src/api/gnosisProtocol/index.ts +++ b/apps/cowswap-frontend/src/api/gnosisProtocol/index.ts @@ -1,8 +1,6 @@ import * as realApi from './api' import * as mockApi from './mock' -export type { UnsupportedToken, OrderID } from './api' - const useMock = process.env.REACT_APP_MOCK === 'true' // Re-exporting the result, mocked or not. diff --git a/apps/cowswap-frontend/src/common/hooks/useApproveCallback.ts b/apps/cowswap-frontend/src/common/hooks/useApproveCallback.ts index 8a279423ac..069f3351e0 100644 --- a/apps/cowswap-frontend/src/common/hooks/useApproveCallback.ts +++ b/apps/cowswap-frontend/src/common/hooks/useApproveCallback.ts @@ -2,7 +2,7 @@ import { useCallback } from 'react' import { Erc20 } from '@cowprotocol/abis' import { useTokenContract } from '@cowprotocol/common-hooks' -import { calculateGasMargin } from '@cowprotocol/common-utils' +import { calculateGasMargin, getIsNativeToken } from '@cowprotocol/common-utils' import { useWalletInfo } from '@cowprotocol/wallet' import { BigNumber } from '@ethersproject/bignumber' import { MaxUint256 } from '@ethersproject/constants' @@ -54,7 +54,8 @@ export function useApproveCallback( spender?: string ): (summary?: string) => Promise { const { chainId } = useWalletInfo() - const token = amountToApprove?.currency?.isToken ? amountToApprove.currency : undefined + const currency = amountToApprove?.currency + const token = currency && !getIsNativeToken(currency) ? currency : undefined const tokenContract = useTokenContract(token?.address) const addTransaction = useTransactionAdder() diff --git a/apps/cowswap-frontend/src/common/hooks/useApproveState.ts b/apps/cowswap-frontend/src/common/hooks/useApproveState.ts index d2278e88c6..52818488af 100644 --- a/apps/cowswap-frontend/src/common/hooks/useApproveState.ts +++ b/apps/cowswap-frontend/src/common/hooks/useApproveState.ts @@ -1,7 +1,7 @@ import { useMemo } from 'react' import { usePrevious } from '@cowprotocol/common-hooks' -import { FractionUtils } from '@cowprotocol/common-utils' +import { FractionUtils, getWrappedToken } from '@cowprotocol/common-utils' import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' @@ -16,9 +16,7 @@ import { useSafeMemo } from 'common/hooks/useSafeMemo' function getCurrencyToApprove(amountToApprove: Nullish>): Token | undefined { if (!amountToApprove) return undefined - if (amountToApprove.currency.isNative) return amountToApprove.currency.wrapped - - return amountToApprove.currency + return getWrappedToken(amountToApprove.currency) } export function useApproveState(amountToApprove: Nullish>, spender?: string): ApprovalState { diff --git a/apps/cowswap-frontend/src/common/hooks/useCancelOrder/state.ts b/apps/cowswap-frontend/src/common/hooks/useCancelOrder/state.ts index a7facdd9f8..9c66f22dae 100644 --- a/apps/cowswap-frontend/src/common/hooks/useCancelOrder/state.ts +++ b/apps/cowswap-frontend/src/common/hooks/useCancelOrder/state.ts @@ -1,8 +1,8 @@ import { atom } from 'jotai' import { atomWithReset } from 'jotai/utils' +import { TokenWithLogo } from '@cowprotocol/common-const' import { BigNumber } from '@ethersproject/bignumber' -import { NativeCurrency } from '@uniswap/sdk-core' import { MAINNET_NATIVE_CURRENCY } from 'lib/hooks/useNativeCurrency' @@ -14,7 +14,7 @@ export type CancellationModalContext = { summary: string | undefined | null error: string | null txCost: BigNumber | null - nativeCurrency: NativeCurrency + nativeCurrency: TokenWithLogo isPendingSignature: boolean onDismiss: (() => void) | null triggerCancellation: ((type: CancellationType) => Promise) | null diff --git a/apps/cowswap-frontend/src/common/hooks/useNeedsApproval.ts b/apps/cowswap-frontend/src/common/hooks/useNeedsApproval.ts index d3478d41f1..debf82a764 100644 --- a/apps/cowswap-frontend/src/common/hooks/useNeedsApproval.ts +++ b/apps/cowswap-frontend/src/common/hooks/useNeedsApproval.ts @@ -1,4 +1,4 @@ -import { isEnoughAmount } from '@cowprotocol/common-utils' +import { getWrappedToken, isEnoughAmount } from '@cowprotocol/common-utils' import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' @@ -24,7 +24,7 @@ import { useTradeSpenderAddress } from 'common/hooks/useTradeSpenderAddress' export function useNeedsApproval(amount: Nullish>): boolean { const { account } = useWalletInfo() const spender = useTradeSpenderAddress() - const token = amount?.currency.wrapped + const token = amount ? getWrappedToken(amount.currency) : undefined const tokens = token ? [token] : [] const balancesAndAllowances = useBalancesAndAllowances({ account, spender, tokens }) diff --git a/apps/cowswap-frontend/src/common/hooks/useSafeMemo.ts b/apps/cowswap-frontend/src/common/hooks/useSafeMemo.ts index 7909b3259b..be566a5fcc 100644 --- a/apps/cowswap-frontend/src/common/hooks/useSafeMemo.ts +++ b/apps/cowswap-frontend/src/common/hooks/useSafeMemo.ts @@ -2,14 +2,11 @@ import { EffectCallback, useEffect, useMemo } from 'react' import { CurrencyAmount, NativeCurrency, Percent, Token } from '@uniswap/sdk-core' -import { WrappedTokenInfo } from 'legacy/state/lists/wrappedTokenInfo' - export function useSafeDeps(deps: unknown[]): unknown[] { return deps.map((dep) => { if (dep instanceof NativeCurrency) return dep.symbol if (dep instanceof Token) return dep.address.toLowerCase() - if (dep instanceof CurrencyAmount) return dep.toExact() + dep.currency.symbol + dep.currency.isNative - if (dep instanceof WrappedTokenInfo) return dep.address + if (dep instanceof CurrencyAmount) return dep.toExact() + dep.currency.symbol + dep.currency.chainId if (dep instanceof Percent) return dep.toFixed(6) return dep diff --git a/apps/cowswap-frontend/src/common/hooks/useShouldZeroApprove/useShouldZeroApprove.ts b/apps/cowswap-frontend/src/common/hooks/useShouldZeroApprove/useShouldZeroApprove.ts index 0246824844..3eb4468522 100644 --- a/apps/cowswap-frontend/src/common/hooks/useShouldZeroApprove/useShouldZeroApprove.ts +++ b/apps/cowswap-frontend/src/common/hooks/useShouldZeroApprove/useShouldZeroApprove.ts @@ -1,6 +1,7 @@ import { useEffect, useState } from 'react' import { useTokenContract } from '@cowprotocol/common-hooks' +import { getIsNativeToken } from '@cowprotocol/common-utils' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Nullish } from 'types' @@ -15,9 +16,9 @@ import { useTradeSpenderAddress } from '../useTradeSpenderAddress' export function useShouldZeroApprove(amountToApprove: Nullish>): boolean { const [shouldZeroApprove, setShouldZeroApprove] = useState(false) const spender = useTradeSpenderAddress() - const tokenContract = useTokenContract( - amountToApprove && amountToApprove.currency.isToken ? amountToApprove.currency.address : undefined - ) + const currency = amountToApprove?.currency + const token = currency && !getIsNativeToken(currency) ? currency : undefined + const tokenContract = useTokenContract(token?.address) const approvalState = useApprovalStateForSpender(amountToApprove, spender, () => false) // ignore approval pending state useEffect(() => { diff --git a/apps/cowswap-frontend/src/common/pure/ApproveButton/index.tsx b/apps/cowswap-frontend/src/common/pure/ApproveButton/index.tsx index 7803251226..05a75609be 100644 --- a/apps/cowswap-frontend/src/common/pure/ApproveButton/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/ApproveButton/index.tsx @@ -1,5 +1,6 @@ import { useContext, useMemo } from 'react' +import { TokenLogo } from '@cowprotocol/tokens' import { ButtonSize, Loader, TokenSymbol, AutoRow, ButtonConfirmed } from '@cowprotocol/ui' import { MouseoverTooltip } from '@cowprotocol/ui' import { Currency } from '@uniswap/sdk-core' @@ -10,8 +11,6 @@ import { ThemeContext } from 'styled-components/macro' import { ApprovalState } from 'legacy/hooks/useApproveCallback/useApproveCallbackMod' -import { CurrencyLogo } from 'common/pure/CurrencyLogo' - export interface ApproveButtonProps { currency: Currency | undefined | null state: ApprovalState @@ -81,7 +80,7 @@ export function ApproveButton(props: ApproveButtonProps) { fontSize: '14px', }} > - + {content} diff --git a/apps/cowswap-frontend/src/common/pure/CancellationModal/RequestCancellationModal.tsx b/apps/cowswap-frontend/src/common/pure/CancellationModal/RequestCancellationModal.tsx index 47f7520166..2da1e09fb3 100644 --- a/apps/cowswap-frontend/src/common/pure/CancellationModal/RequestCancellationModal.tsx +++ b/apps/cowswap-frontend/src/common/pure/CancellationModal/RequestCancellationModal.tsx @@ -1,8 +1,9 @@ import React, { useCallback, useState } from 'react' +import { TokenWithLogo } from '@cowprotocol/common-const' import { TokenAmount, ButtonPrimary } from '@cowprotocol/ui' import type { BigNumber } from '@ethersproject/bignumber' -import { CurrencyAmount, NativeCurrency } from '@uniswap/sdk-core' +import { CurrencyAmount } from '@uniswap/sdk-core' import { ArrowRight, ArrowLeft } from 'react-feather' import { NavHashLink } from 'react-router-hash-link' @@ -23,7 +24,7 @@ export type RequestCancellationModalProps = { onDismiss: () => void triggerCancellation: (type: CancellationType) => void txCost: BigNumber | null - nativeCurrency: NativeCurrency + nativeCurrency: TokenWithLogo } const Wrapper = styled.div` diff --git a/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/CurrencyInputPanel.tsx b/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/CurrencyInputPanel.tsx index f38f8fafcb..3b11a29cf9 100644 --- a/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/CurrencyInputPanel.tsx +++ b/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/CurrencyInputPanel.tsx @@ -1,7 +1,8 @@ import React, { useCallback, useEffect, useState } from 'react' import { setMaxSellTokensAnalytics } from '@cowprotocol/analytics' -import { formatInputAmount } from '@cowprotocol/common-utils' +import { NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const' +import { formatInputAmount, getIsNativeToken } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { TokenAmount } from '@cowprotocol/ui' import { MouseoverTooltip } from '@cowprotocol/ui' @@ -9,7 +10,6 @@ import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' -import CurrencySearchModal from 'legacy/components/SearchModal/CurrencySearchModal' import { BalanceAndSubsidy } from 'legacy/hooks/useCowBalanceAndSubsidy' import { PriceImpact } from 'legacy/hooks/usePriceImpact' import { Field } from 'legacy/state/types' @@ -36,13 +36,13 @@ export interface CurrencyInputPanelProps extends Partial { inputTooltip?: string showSetMax?: boolean maxBalance?: CurrencyAmount | undefined - disableNonToken?: boolean allowsOffchainSigning: boolean currencyInfo: CurrencyInfo priceImpactParams?: PriceImpact subsidyAndBalance?: BalanceAndSubsidy onCurrencySelection: (field: Field, currency: Currency) => void onUserInput: (field: Field, typedValue: string) => void + openTokenSelectWidget(selectedToken: string | undefined, onCurrencySelection: (currency: Currency) => void): void topLabel?: string } @@ -53,15 +53,15 @@ export function CurrencyInputPanel(props: CurrencyInputPanelProps) { currencyInfo, className, priceImpactParams, - disableNonToken = false, showSetMax = false, maxBalance, inputDisabled = false, inputTooltip, - onCurrencySelection, onUserInput, allowsOffchainSigning, isChainIdUnsupported, + openTokenSelectWidget, + onCurrencySelection, subsidyAndBalance = { subsidy: { tier: 0, @@ -74,15 +74,8 @@ export function CurrencyInputPanel(props: CurrencyInputPanelProps) { const { field, currency, balance, fiatAmount, amount, isIndependent, receiveAmountInfo } = currencyInfo const disabled = !!props.disabled || isChainIdUnsupported const viewAmount = formatInputAmount(amount, balance, isIndependent) - const [isCurrencySearchModalOpen, setCurrencySearchModalOpen] = useState(false) const [typedValue, setTypedValue] = useState(viewAmount) - const onCurrencySelect = useCallback( - (currency: Currency) => { - onCurrencySelection(field, currency) - }, - [onCurrencySelection, field] - ) const onUserInputDispatch = useCallback( (typedValue: string) => { setTypedValue(typedValue) @@ -113,6 +106,12 @@ export function CurrencyInputPanel(props: CurrencyInputPanelProps) { // eslint-disable-next-line react-hooks/exhaustive-deps }, [viewAmount]) + const selectedTokenAddress = currency + ? getIsNativeToken(currency) + ? NATIVE_CURRENCY_BUY_TOKEN[currency.chainId as SupportedChainId].address + : currency.address + : undefined + const numericalInput = (
setCurrencySearchModalOpen(true)} + onClick={() => + openTokenSelectWidget(selectedTokenAddress, (currency) => onCurrencySelection(field, currency)) + } currency={disabled ? undefined : currency || undefined} loading={areCurrenciesLoading || disabled} /> @@ -175,17 +176,6 @@ export function CurrencyInputPanel(props: CurrencyInputPanelProps) { subsidyAndBalance={subsidyAndBalance} /> )} - - setCurrencySearchModalOpen(false)} - onCurrencySelect={onCurrencySelect} - selectedCurrency={currency} - otherSelectedCurrency={currency} - showCommonBases={true} - showCurrencyAmount={true} - disableNonToken={disableNonToken} - /> ) } diff --git a/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/defaultCurrencyInputProps.ts b/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/defaultCurrencyInputProps.ts index 4729bd4f10..0c922b65a8 100644 --- a/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/defaultCurrencyInputProps.ts +++ b/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/defaultCurrencyInputProps.ts @@ -33,6 +33,9 @@ export const defaultCurrencyInputPanelProps: CurrencyInputPanelProps & { priceIm amount: CurrencyAmount.fromRawAmount(currency, 20 * 10 ** 18), fiatAmount: CurrencyAmount.fromRawAmount(currency, 12 * 10 ** 18), }, + openTokenSelectWidget() { + /**/ + }, onCurrencySelection() { /**/ }, diff --git a/apps/cowswap-frontend/src/common/pure/CurrencySelectButton/index.tsx b/apps/cowswap-frontend/src/common/pure/CurrencySelectButton/index.tsx index aba96807d2..b456b740c3 100644 --- a/apps/cowswap-frontend/src/common/pure/CurrencySelectButton/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/CurrencySelectButton/index.tsx @@ -1,11 +1,10 @@ +import { TokenLogo } from '@cowprotocol/tokens' import { TokenSymbol } from '@cowprotocol/ui' import { Currency } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' import { Nullish } from 'types' -import { CurrencyLogo } from 'common/pure/CurrencyLogo' - import * as styledEl from './styled' export interface CurrencySelectButtonProps { @@ -27,7 +26,7 @@ export function CurrencySelectButton(props: CurrencySelectButtonProps) { isLoading={loading} $stubbed={$stubbed} > - {currency ? :
} + {currency ? :
} {currency ? : Select a token} diff --git a/apps/cowswap-frontend/src/common/pure/IconSpinner/index.tsx b/apps/cowswap-frontend/src/common/pure/IconSpinner/index.tsx index a9b678d3bb..e6800ca65c 100644 --- a/apps/cowswap-frontend/src/common/pure/IconSpinner/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/IconSpinner/index.tsx @@ -1,9 +1,9 @@ +import { TokenLogo } from '@cowprotocol/tokens' import { Currency } from '@uniswap/sdk-core' import styled from 'styled-components/macro' import { UI } from 'common/constants/theme' -import { CurrencyLogo } from 'common/pure/CurrencyLogo' interface IconSpinnerProps { currency?: Currency | null @@ -27,7 +27,7 @@ const Wrapper = styled.div<{ size: number; spinnerWidth: number; bgColor: UI }>` border-radius: ${({ size }) => size}px; &:before { - content: ""; + content: ''; position: absolute; top: calc(-1 * ${({ spinnerWidth }) => spinnerWidth}px); left: calc(-1 * ${({ spinnerWidth }) => spinnerWidth}px); @@ -71,14 +71,13 @@ export function IconSpinner({ size = 24, children, bgColor = UI.COLOR_CONTAINER_BG_01, - spinnerWidth = 2 + spinnerWidth = 2, }: IconSpinnerProps) { - return ( {(() => { if (currency) { - return + return } else if (image) { return Spinning icon } else if (children) { diff --git a/apps/cowswap-frontend/src/common/pure/RateInfo/index.tsx b/apps/cowswap-frontend/src/common/pure/RateInfo/index.tsx index 7ea915715a..09aa77b9cc 100644 --- a/apps/cowswap-frontend/src/common/pure/RateInfo/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/RateInfo/index.tsx @@ -18,7 +18,7 @@ import { getQuoteCurrency } from 'common/services/getQuoteCurrency' const DEFAULT_DECIMALS = 4 export interface RateInfoParams { - chainId: SupportedChainId | undefined + chainId: SupportedChainId inputCurrencyAmount: Nullish> outputCurrencyAmount: Nullish> activeRateFiatAmount: Nullish> diff --git a/apps/cowswap-frontend/src/common/services/getQuoteCurrency/index.ts b/apps/cowswap-frontend/src/common/services/getQuoteCurrency/index.ts index 524e2e4749..1e924447e4 100644 --- a/apps/cowswap-frontend/src/common/services/getQuoteCurrency/index.ts +++ b/apps/cowswap-frontend/src/common/services/getQuoteCurrency/index.ts @@ -2,6 +2,7 @@ import { DAI, USDC_MAINNET, USDT } from '@cowprotocol/common-const' import { NATIVE_CURRENCY_BUY_ADDRESS } from '@cowprotocol/common-const' import { DAI_GOERLI, USDT_GOERLI, USDC_GOERLI } from '@cowprotocol/common-const' import { USDC_GNOSIS_CHAIN, USDT_GNOSIS_CHAIN, WXDAI } from '@cowprotocol/common-const' +import { getIsNativeToken } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' @@ -51,8 +52,12 @@ export function getQuoteCurrencyByStableCoin( const stableCoins = STABLE_COINS[chainId] - const inputAddress = inputCurrency.isNative ? NATIVE_CURRENCY_BUY_ADDRESS : inputCurrency.address.toLowerCase() - const outputAddress = outputCurrency.isNative ? NATIVE_CURRENCY_BUY_ADDRESS : outputCurrency.address.toLowerCase() + const inputAddress = getIsNativeToken(inputCurrency) + ? NATIVE_CURRENCY_BUY_ADDRESS + : inputCurrency.address.toLowerCase() + const outputAddress = getIsNativeToken(outputCurrency) + ? NATIVE_CURRENCY_BUY_ADDRESS + : outputCurrency.address.toLowerCase() const isInputStableCoin = stableCoins.includes(inputAddress) const isOutputStableCoin = stableCoins.includes(outputAddress) diff --git a/apps/cowswap-frontend/src/common/updaters/FeesUpdater.ts b/apps/cowswap-frontend/src/common/updaters/FeesUpdater.ts index dfaf831e1b..2611973837 100644 --- a/apps/cowswap-frontend/src/common/updaters/FeesUpdater.ts +++ b/apps/cowswap-frontend/src/common/updaters/FeesUpdater.ts @@ -2,13 +2,13 @@ import { useEffect, useMemo } from 'react' import { DEFAULT_DECIMALS } from '@cowprotocol/common-const' import { useDebounce, useIsOnline, useIsWindowVisible } from '@cowprotocol/common-hooks' -import { isAddress, tryParseCurrencyAmount } from '@cowprotocol/common-utils' +import { getIsNativeToken, isAddress, tryParseCurrencyAmount } from '@cowprotocol/common-utils' import { OrderKind } from '@cowprotocol/cow-sdk' import { useENSAddress } from '@cowprotocol/ens' +import { useIsUnsupportedToken } from '@cowprotocol/tokens' import { useWalletInfo } from '@cowprotocol/wallet' import { useRefetchQuoteCallback } from 'legacy/hooks/useRefetchPriceCallback' -import { useIsUnsupportedTokenGp } from 'legacy/state/lists/hooks' import { useAllQuotes, useIsBestQuoteLoading, useSetQuoteError } from 'legacy/state/price/hooks' import { QuoteInformationObject } from 'legacy/state/price/reducer' import { LegacyFeeQuoteParams } from 'legacy/state/price/types' @@ -148,7 +148,7 @@ export function FeesUpdater(): null { const isLoading = useIsBestQuoteLoading() const isEthFlow = useIsEoaEthFlow() - const isUnsupportedTokenGp = useIsUnsupportedTokenGp() + const isUnsupportedTokenGp = useIsUnsupportedToken() const appData = useAppData() @@ -160,8 +160,8 @@ export function FeesUpdater(): null { const { validTo } = useOrderValidTo() // prevents things like "USDC" being used as an address - const sellTokenAddressInvalid = sellCurrency && !sellCurrency.isNative && !isAddress(sellCurrencyId) - const buyTokenAddressInvalid = buyCurrency && !buyCurrency.isNative && !isAddress(buyCurrencyId) + const sellTokenAddressInvalid = sellCurrency && !getIsNativeToken(sellCurrency) && !isAddress(sellCurrencyId) + const buyTokenAddressInvalid = buyCurrency && !getIsNativeToken(buyCurrency) && !isAddress(buyCurrencyId) // Update if any parameter is changing useEffect(() => { diff --git a/apps/cowswap-frontend/src/common/updaters/orders/GpOrdersUpdater.ts b/apps/cowswap-frontend/src/common/updaters/orders/GpOrdersUpdater.ts index 88f51d14ca..3c639f51a6 100644 --- a/apps/cowswap-frontend/src/common/updaters/orders/GpOrdersUpdater.ts +++ b/apps/cowswap-frontend/src/common/updaters/orders/GpOrdersUpdater.ts @@ -3,10 +3,10 @@ import { useCallback, useEffect, useMemo, useRef } from 'react' import { NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const' import { EnrichedOrder, EthflowData, OrderClass, SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' +import { useAllTokens } from '@cowprotocol/tokens' import { useWalletInfo } from '@cowprotocol/wallet' import { Token } from '@uniswap/sdk-core' -import { useAllTokens } from 'legacy/hooks/Tokens' import { Order, OrderStatus } from 'legacy/state/orders/actions' import { useAddOrUpdateOrders, useClearOrdersStorage } from 'legacy/state/orders/hooks' import { classifyOrder, OrderTransitionStatus } from 'legacy/state/orders/utils' diff --git a/apps/cowswap-frontend/src/common/updaters/orders/PendingOrdersUpdater.ts b/apps/cowswap-frontend/src/common/updaters/orders/PendingOrdersUpdater.ts index 154a24b889..ded8820af3 100644 --- a/apps/cowswap-frontend/src/common/updaters/orders/PendingOrdersUpdater.ts +++ b/apps/cowswap-frontend/src/common/updaters/orders/PendingOrdersUpdater.ts @@ -32,7 +32,7 @@ import { OrderTransitionStatus } from 'legacy/state/orders/utils' import { useAddOrderToSurplusQueue } from 'modules/swap/state/surplusModal' -import { getOrder, OrderID } from 'api/gnosisProtocol' +import { getOrder } from 'api/gnosisProtocol' import { fetchOrderPopupData, OrderLogPopupMixData } from './utils' @@ -49,7 +49,7 @@ import { useTriggerTotalSurplusUpdateCallback } from '../../state/totalSurplusSt * @param signedOrdersIds ids of orders we know are already pre-signed * @returns ids of the pending orders that were pending for pre-sign, and we now know are pre-signed */ -function _getNewlyPreSignedOrders(allPendingOrders: Order[], signedOrdersIds: OrderID[]) { +function _getNewlyPreSignedOrders(allPendingOrders: Order[], signedOrdersIds: string[]) { return allPendingOrders .filter((order) => order.status === OrderStatus.PRESIGNATURE_PENDING && signedOrdersIds.includes(order.id)) .map((order) => order.id) @@ -200,7 +200,7 @@ async function _updateOrders({ if (presigned.length > 0) { // Only mark as presigned the orders we were not aware of their new state - const presignedOrderIds = presigned as OrderID[] + const presignedOrderIds = presigned as string[] const ordersPresignaturePendingSigned = _getNewlyPreSignedOrders(orders, presignedOrderIds) if (ordersPresignaturePendingSigned.length > 0) { @@ -213,14 +213,14 @@ async function _updateOrders({ if (expired.length > 0) { expireOrdersBatch({ - ids: expired as OrderID[], + ids: expired as string[], chainId, }) } if (cancelled.length > 0) { cancelOrdersBatch({ - ids: cancelled as OrderID[], + ids: cancelled as string[], chainId, }) } diff --git a/apps/cowswap-frontend/src/common/updaters/orders/utils.ts b/apps/cowswap-frontend/src/common/updaters/orders/utils.ts index 7fb3f3a37c..0ca27a6af0 100644 --- a/apps/cowswap-frontend/src/common/updaters/orders/utils.ts +++ b/apps/cowswap-frontend/src/common/updaters/orders/utils.ts @@ -6,10 +6,10 @@ import { Order, OrderFulfillmentData, OrderStatus } from 'legacy/state/orders/ac import { classifyOrder, OrderTransitionStatus } from 'legacy/state/orders/utils' import { stringToCurrency } from 'legacy/state/swap/extension' -import { getOrder, OrderID } from 'api/gnosisProtocol' +import { getOrder } from 'api/gnosisProtocol' import { getIsComposableCowChildOrder } from 'utils/orderUtils/getIsComposableCowChildOrder' -export type OrderLogPopupMixData = OrderFulfillmentData | OrderID +export type OrderLogPopupMixData = OrderFulfillmentData | string export function computeOrderSummary({ orderFromStore, diff --git a/apps/cowswap-frontend/src/legacy/components/Header/index.tsx b/apps/cowswap-frontend/src/legacy/components/Header/index.tsx index ced341809e..6c3ebfce70 100644 --- a/apps/cowswap-frontend/src/legacy/components/Header/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Header/index.tsx @@ -21,7 +21,6 @@ import { useInjectedWidgetParams } from 'modules/injectedWidget' import { MainMenuContext } from 'modules/mainMenu' import { MenuTree } from 'modules/mainMenu/pure/MenuTree' import { useSwapRawState } from 'modules/swap/hooks/useSwapRawState' -import { useNativeCurrencyBalances } from 'modules/tokens/hooks/useCurrencyBalance' import { useTradeState } from 'modules/trade/hooks/useTradeState' import { getDefaultTradeRawState } from 'modules/trade/types/TradeRawState' import { Web3Status } from 'modules/wallet/containers/Web3Status' @@ -29,6 +28,7 @@ import { Web3Status } from 'modules/wallet/containers/Web3Status' import { Routes } from 'common/constants/routes' import { useCategorizeRecentActivity } from 'common/hooks/useCategorizeRecentActivity' import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported' +import { useNativeBalance } from 'common/hooks/useNativeBalance' import MobileMenuIcon from './MobileMenuIcon' import { @@ -57,7 +57,7 @@ export default function Header() { const isChainIdUnsupported = useIsProviderNetworkUnsupported() const { pendingActivity } = useCategorizeRecentActivity() - const userEthBalance = useNativeCurrencyBalances(account ? [account] : [])?.[account ?? ''] + const userEthBalance = useNativeBalance() const nativeToken = CHAIN_CURRENCY_LABELS[chainId] || 'ETH' const [darkMode, toggleDarkModeAux] = useDarkModeManager() const toggleDarkMode = useCallback(() => { @@ -157,9 +157,9 @@ export default function Header() { )} - {account && !isChainIdUnsupported && userEthBalance && chainId && ( + {account && !isChainIdUnsupported && userEthBalance.data && chainId && ( - + )} diff --git a/apps/cowswap-frontend/src/legacy/components/Tokens/FavouriteTokenButton.tsx b/apps/cowswap-frontend/src/legacy/components/Tokens/FavouriteTokenButton.tsx index c87cbaecfb..1c73aa680d 100644 --- a/apps/cowswap-frontend/src/legacy/components/Tokens/FavouriteTokenButton.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Tokens/FavouriteTokenButton.tsx @@ -1,13 +1,13 @@ import { MouseEventHandler, useCallback, useMemo } from 'react' +import { TokenWithLogo } from '@cowprotocol/common-const' import { useTheme } from '@cowprotocol/common-hooks' +import { useFavouriteTokens, useToggleFavouriteToken } from '@cowprotocol/tokens' import { ButtonStar } from '@cowprotocol/ui' import { Token } from '@uniswap/sdk-core' import styled from 'styled-components/macro' -import { useFavouriteTokens, useToggleFavouriteToken } from 'legacy/state/user/hooks' - import { UI } from 'common/constants/theme' export const StyledButtonStar = styled(ButtonStar)` @@ -15,7 +15,7 @@ export const StyledButtonStar = styled(ButtonStar)` ` type FavouriteTokenButtonParams = { - tokenData: Token + tokenData: TokenWithLogo } export default function FavouriteTokenButton({ tokenData }: FavouriteTokenButtonParams) { diff --git a/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTable.tsx b/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTable.tsx index e42ee2aed5..a40539d652 100644 --- a/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTable.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTable.tsx @@ -1,11 +1,10 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { TokenWithLogo } from '@cowprotocol/common-const' import { useFilterTokens, usePrevious } from '@cowprotocol/common-hooks' -import { Token } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' -import { balanceComparator, useTokenComparator } from 'legacy/components/SearchModal/CurrencySearch/sorting' import { useErrorModal } from 'legacy/hooks/useErrorMessageAndModal' import useTransactionConfirmationModal from 'legacy/hooks/useTransactionConfirmationModal' import { useToggleWalletModal } from 'legacy/state/application/hooks' @@ -13,6 +12,7 @@ import { ConfirmOperationType } from 'legacy/state/types' import { TokenAmounts } from 'modules/tokens' +import { balanceComparator, useTokenComparator } from './sorting' import { Arrow, ArrowButton, @@ -39,7 +39,7 @@ enum SORT_FIELD { type BalanceType = [TokenAmounts, boolean] type TokenTableParams = { - tokensData: Token[] | undefined + tokensData: TokenWithLogo[] | undefined maxItems?: number balances?: BalanceType page: number @@ -49,11 +49,6 @@ type TokenTableParams = { debouncedQuery: string } -export enum TableType { - OVERVIEW = 'OVERVIEW', - FAVOURITE = 'FAVOURITE', -} - export default function TokenTable({ tokensData: rawTokensData = [], maxItems = MAX_ITEMS, @@ -64,8 +59,6 @@ export default function TokenTable({ prevQuery, debouncedQuery, }: TokenTableParams) { - // const { account } = useWalletInfo() - const toggleWalletModal = useToggleWalletModal() const tableRef = useRef(null) diff --git a/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTableRow.tsx b/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTableRow.tsx index a633cc108d..b7e6c52b9e 100644 --- a/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTableRow.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTableRow.tsx @@ -1,10 +1,11 @@ import { useCallback, useEffect, useMemo, useState } from 'react' import EtherscanImage from '@cowprotocol/assets/cow-swap/etherscan-icon.svg' -import { GP_VAULT_RELAYER } from '@cowprotocol/common-const' +import { GP_VAULT_RELAYER, TokenWithLogo } from '@cowprotocol/common-const' import { usePrevious, useTheme } from '@cowprotocol/common-hooks' import { getBlockExplorerUrl } from '@cowprotocol/common-utils' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' +import { useAreThereTokensWithSameSymbol } from '@cowprotocol/tokens' import { TokenAmount, TokenSymbol, Loader } from '@cowprotocol/ui' import { useWalletInfo } from '@cowprotocol/wallet' import { CurrencyAmount, MaxUint256, Token } from '@uniswap/sdk-core' @@ -18,7 +19,6 @@ import { useTokenAllowance } from 'legacy/hooks/useTokenAllowance' import { parameterizeTradeRoute } from 'modules/trade/utils/parameterizeTradeRoute' import { Routes } from 'common/constants/routes' -import { useAreThereTokensWithSameSymbol } from 'common/hooks/useAreThereTokensWithSameSymbol' import { CardsSpinner, ExtLink } from 'pages/Account/styled' import BalanceCell from './BalanceCell' @@ -39,7 +39,7 @@ import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallbac import { ConfirmOperationType } from '../../state/types' type DataRowParams = { - tokenData: Token + tokenData: TokenWithLogo index: number balance?: CurrencyAmount | undefined closeModals: () => void @@ -178,7 +178,7 @@ export const TokensTableRow = ({ - + diff --git a/apps/cowswap-frontend/src/legacy/components/Tokens/sorting.ts b/apps/cowswap-frontend/src/legacy/components/Tokens/sorting.ts new file mode 100644 index 0000000000..4a2c468322 --- /dev/null +++ b/apps/cowswap-frontend/src/legacy/components/Tokens/sorting.ts @@ -0,0 +1,65 @@ +import { useMemo } from 'react' + +import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' + +import { TokenAmounts } from 'modules/tokens' +import { useAllTokensBalances } from 'modules/tokensList' + +const PRIORITISED_TOKENS = ['COW', 'GNO'] + +// compare two token amounts with highest one coming first +export function balanceComparator(balanceA?: CurrencyAmount, balanceB?: CurrencyAmount) { + if (balanceA && balanceB) { + return balanceA.greaterThan(balanceB) ? -1 : balanceA.equalTo(balanceB) ? 0 : 1 + } else if (balanceA && balanceA.greaterThan('0')) { + return -1 + } else if (balanceB && balanceB.greaterThan('0')) { + return 1 + } + return 0 +} + +function getTokenComparator(balances: [TokenAmounts, boolean]): (tokenA: Token, tokenB: Token) => number { + return function sortTokens(tokenA: Token, tokenB: Token): number { + // -1 = a is first + // 1 = b is first + + // sort by balances + const balanceA = balances[0][tokenA.address]?.value + const balanceB = balances[0][tokenB.address]?.value + + const balanceComp = balanceComparator(balanceA, balanceB) + if (balanceComp !== 0) return balanceComp + + // Mod: modify tokens list by prioritised list + const indexA = PRIORITISED_TOKENS.indexOf(tokenA.symbol || '') + const indexB = PRIORITISED_TOKENS.indexOf(tokenB.symbol || '') + + if (indexA !== -1 && indexB !== -1) { + return indexB < indexA ? 1 : -1 + } else if (indexA !== -1 || indexB !== -1) { + return indexB !== -1 ? 1 : -1 + } + + if (tokenA.symbol && tokenB.symbol) { + // sort by symbol + return tokenA.symbol.toLowerCase() < tokenB.symbol.toLowerCase() ? -1 : 1 + } else { + return tokenA.symbol ? -1 : tokenB.symbol ? -1 : 0 + } + } +} + +export function useTokenComparator(inverted: boolean): (tokenA: Token, tokenB: Token) => number { + const balances = useAllTokensBalances() + + const comparator = useMemo(() => getTokenComparator(balances), [balances]) + + return useMemo(() => { + if (inverted) { + return (tokenA: Token, tokenB: Token) => comparator(tokenA, tokenB) * -1 + } else { + return comparator + } + }, [inverted, comparator]) +} diff --git a/apps/cowswap-frontend/src/legacy/components/Tokens/styled.ts b/apps/cowswap-frontend/src/legacy/components/Tokens/styled.ts index f0eb8101d0..d87b2aea4c 100644 --- a/apps/cowswap-frontend/src/legacy/components/Tokens/styled.ts +++ b/apps/cowswap-frontend/src/legacy/components/Tokens/styled.ts @@ -1,3 +1,4 @@ +import { TokenLogo } from '@cowprotocol/tokens' import { BaseButton } from '@cowprotocol/ui' import { transparentize } from 'polished' @@ -6,55 +7,6 @@ import { Link } from 'react-router-dom' import styled from 'styled-components/macro' import { UI } from 'common/constants/theme' -import { CurrencyLogo } from 'common/pure/CurrencyLogo' - -export const TokenSearchInput = styled.input` - margin: 0; - font-size: 14px; - max-width: 280px; - width: 100%; - align-self: flex-end; - box-shadow: none; - background: var(${UI.COLOR_GREY}); - border: 1px solid ${({ theme }) => theme.bg1}; - border-radius: 21px; - transition: background 0.2s ease-in-out, max-width 0.2s ease-in-out; - appearance: none; - height: 44px; - padding: 0 16px; - outline: 0; - - &:focus { - max-width: 500px; - background: var(${UI.COLOR_CONTAINER_BG_01}); - outline: 0; - - ${({ theme }) => theme.mediaWidth.upToMedium` - width: 100%; - `}; - } - - &::placeholder { - font-size: 14px !important; - color: ${({ theme }) => transparentize(0.5, theme.darkMode ? theme.white : theme.text1)}; - } - - &:focus::placeholder { - color: ${({ theme }) => transparentize(0.3, theme.darkMode ? theme.white : theme.text1)}; - } - - ${({ theme }) => theme.mediaWidth.upToMedium` - max-width: 100%; - `}; - - ${({ theme }) => theme.mediaWidth.upToSmall` - font-size: 12px !important; - - &::placeholder { - font-size: 12px !important; - } - `}; -` export const Wrapper = styled.div` width: 100%; @@ -77,10 +29,7 @@ export const LinkWrapper = styled(Link)` } ` -export const ResponsiveLogo = styled(CurrencyLogo)` - width: 28px; - height: 28px; - border-radius: 28px; +export const ResponsiveLogo = styled(TokenLogo)` background: var(${UI.COLOR_CONTAINER_BG_01}); color: var(${UI.COLOR_TEXT1}) !important; // TODO: prevent styles override diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionSettings/TransactionSettingsMod.tsx b/apps/cowswap-frontend/src/legacy/components/TransactionSettings/TransactionSettingsMod.tsx index 7b286b19a8..a9c987218f 100644 --- a/apps/cowswap-frontend/src/legacy/components/TransactionSettings/TransactionSettingsMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/TransactionSettings/TransactionSettingsMod.tsx @@ -14,6 +14,7 @@ import { MINIMUM_ETH_FLOW_SLIPPAGE_BIPS, MINIMUM_ORDER_VALID_TO_TIME_SECONDS, } from '@cowprotocol/common-const' +import { getWrappedToken } from '@cowprotocol/common-utils' import { RowBetween, RowFixed } from '@cowprotocol/ui' import { useWalletInfo } from '@cowprotocol/wallet' import { Percent } from '@uniswap/sdk-core' @@ -127,8 +128,6 @@ export interface TransactionSettingsProps { placeholderSlippage: Percent // varies according to the context in which the settings dialog is placed } -// const THREE_DAYS_IN_SECONDS = ms`3 days` / 1000 - export default function TransactionSettings({ placeholderSlippage }: TransactionSettingsProps) { const { chainId } = useWalletInfo() const theme = useContext(ThemeContext) @@ -244,7 +243,7 @@ export default function TransactionSettings({ placeholderSlippage }: Transaction text={ // Your transaction will revert if the price changes unfavorably by more than this percentage. isEoaEthFlow - ? getNativeSlippageTooltip([nativeCurrency.symbol, nativeCurrency.wrapped.symbol]) + ? getNativeSlippageTooltip([nativeCurrency.symbol, getWrappedToken(nativeCurrency).symbol]) : getNonNativeSlippageTooltip() } /> diff --git a/apps/cowswap-frontend/src/legacy/components/Version/index.tsx b/apps/cowswap-frontend/src/legacy/components/Version/index.tsx index ab78ef57e9..72658b24c3 100644 --- a/apps/cowswap-frontend/src/legacy/components/Version/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Version/index.tsx @@ -1,9 +1,4 @@ -import { - CODE_LINK, - DEFAULT_NETWORK_FOR_LISTS, - GP_SETTLEMENT_CONTRACT_ADDRESS, - GP_VAULT_RELAYER, -} from '@cowprotocol/common-const' +import { CODE_LINK, GP_SETTLEMENT_CONTRACT_ADDRESS, GP_VAULT_RELAYER } from '@cowprotocol/common-const' import { getEtherscanLink } from '@cowprotocol/common-utils' import contractsPkg from '@cowprotocol/contracts/package.json' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' @@ -116,7 +111,7 @@ const VersionsLinkWrapper = styled.span` ` export const Version = ({ className }: { className?: string }) => { - const { chainId = DEFAULT_NETWORK_FOR_LISTS } = useWalletInfo() + const { chainId } = useWalletInfo() return ( {/* it's hardcoded anyways */} diff --git a/apps/cowswap-frontend/src/legacy/components/swap/ConfirmSwapModal/hooks.tsx b/apps/cowswap-frontend/src/legacy/components/swap/ConfirmSwapModal/hooks.tsx index 951d0d7237..c40a711599 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/ConfirmSwapModal/hooks.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/ConfirmSwapModal/hooks.tsx @@ -1,5 +1,6 @@ import { useMemo } from 'react' +import { getWrappedToken } from '@cowprotocol/common-utils' import { TokenSymbol } from '@cowprotocol/ui' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' @@ -24,7 +25,7 @@ export function useButtonText(slippageAdjustedSellAmount: Nullish - Confirm (Approve {} + Confirm (Approve {}  and Swap) ) diff --git a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/index.tsx b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/index.tsx index 23524ae1f5..448965061d 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/index.tsx @@ -2,6 +2,7 @@ import React, { useContext, useMemo } from 'react' import { INPUT_OUTPUT_EXPLANATION } from '@cowprotocol/common-const' import { isAddress, shortenAddress } from '@cowprotocol/common-utils' +import { TokenLogo } from '@cowprotocol/tokens' import { RowBetween, RowFixed, TokenAmount, TokenSymbol } from '@cowprotocol/ui' import { useWalletDetails } from '@cowprotocol/wallet' import { Percent, TradeType } from '@uniswap/sdk-core' @@ -24,7 +25,6 @@ import { NoImpactWarning } from 'modules/trade/pure/NoImpactWarning' import { PriceUpdatedBanner } from 'modules/trade/pure/PriceUpdatedBanner' import { useTradeUsdAmounts } from 'modules/usdAmount' -import { CurrencyLogo } from 'common/pure/CurrencyLogo' import { FiatValue } from 'common/pure/FiatValue' import { BannerOrientation, CustomRecipientWarningBanner } from 'common/pure/InlineBanner/banners' import { RateInfoParams } from 'common/pure/RateInfo' @@ -117,7 +117,9 @@ function SwapModalHeaderComponent({ - + + + @@ -164,7 +166,9 @@ function SwapModalHeaderComponent({ - + + + diff --git a/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/UnsupportedCurrencyFooterMod.tsx b/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/UnsupportedCurrencyFooterMod.tsx index 420a3b9338..eaf61425ba 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/UnsupportedCurrencyFooterMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/UnsupportedCurrencyFooterMod.tsx @@ -1,6 +1,8 @@ import { useState } from 'react' -import { getEtherscanLink } from '@cowprotocol/common-utils' +import { getEtherscanLink, getWrappedToken } from '@cowprotocol/common-utils' +import { useIsUnsupportedToken } from '@cowprotocol/tokens' +import { TokenLogo } from '@cowprotocol/tokens' import { ButtonEmpty } from '@cowprotocol/ui' import { AutoRow, RowBetween } from '@cowprotocol/ui' import { ExternalLink } from '@cowprotocol/ui' @@ -12,11 +14,9 @@ import styled from 'styled-components/macro' import Card, { OutlineCard } from 'legacy/components/Card' import { AutoColumn } from 'legacy/components/Column' -import { useIsUnsupportedTokenGp } from 'legacy/state/lists/hooks' import { CloseIcon, ThemedText, Z_INDEX } from 'legacy/theme' import { UI } from 'common/constants/theme' -import { CurrencyLogo } from 'common/pure/CurrencyLogo' import { Modal } from 'common/pure/Modal' export const DetailsFooter = styled.div<{ show: boolean }>` @@ -72,11 +72,11 @@ export default function UnsupportedCurrencyFooter({ const tokens = chainId && currencies ? currencies.map((currency) => { - return currency?.wrapped + return currency && getWrappedToken(currency) }) : [] - const isUnsupportedToken = useIsUnsupportedTokenGp() + const isUnsupportedToken = useIsUnsupportedToken() return ( @@ -96,7 +96,7 @@ export default function UnsupportedCurrencyFooter({ - + {token.symbol} {chainId && ( diff --git a/apps/cowswap-frontend/src/legacy/hooks/useApproveCallback/useApproveCallbackMod.ts b/apps/cowswap-frontend/src/legacy/hooks/useApproveCallback/useApproveCallbackMod.ts index 24d3238d5e..a7a2cb121a 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useApproveCallback/useApproveCallbackMod.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useApproveCallback/useApproveCallbackMod.ts @@ -1,7 +1,8 @@ import { useCallback, useMemo } from 'react' import { useTokenContract, usePrevious } from '@cowprotocol/common-hooks' -import { calculateGasMargin } from '@cowprotocol/common-utils' +import { calculateGasMargin, getIsNativeToken, getWrappedToken } from '@cowprotocol/common-utils' +import { useTokenBySymbolOrAddress } from '@cowprotocol/tokens' import { useWalletInfo } from '@cowprotocol/wallet' import { BigNumber } from '@ethersproject/bignumber' import { MaxUint256 } from '@ethersproject/constants' @@ -12,7 +13,6 @@ import { useTokenAllowance } from 'legacy/hooks/useTokenAllowance' import { useHasPendingApproval, useTransactionAdder } from 'legacy/state/enhancedTransactions/hooks' import { ConfirmOperationType } from '../../state/types' -import { useCurrency } from '../Tokens' import { ApproveCallbackState, OptionalApproveCallbackParams } from './index' @@ -58,15 +58,16 @@ export function useApproveCallback({ amountToCheckAgainstAllowance, }: ApproveCallbackParams): ApproveCallbackState { const { account, chainId } = useWalletInfo() - const token = amountToApprove?.currency?.isToken ? amountToApprove.currency : undefined + const currency = amountToApprove?.currency + const token = currency && !getIsNativeToken(currency) ? currency : undefined const currentAllowance = useTokenAllowance(token, account ?? undefined, spender) const pendingApproval = useHasPendingApproval(token?.address, spender) - const spenderCurrency = useCurrency(spender) + const spenderCurrency = useTokenBySymbolOrAddress(spender) // check the current approval status const approvalStateBase: ApprovalState = useMemo(() => { if (!amountToApprove || !spender) return ApprovalState.UNKNOWN - if (amountToApprove.currency.isNative) return ApprovalState.APPROVED + if (getIsNativeToken(amountToApprove.currency)) return ApprovalState.APPROVED // we might not have enough data to know whether or not we need to approve if (!currentAllowance) return ApprovalState.UNKNOWN @@ -224,7 +225,7 @@ export function useApproveCallback({ addTransaction({ hash: response.hash, summary: optionalParams?.transactionSummary || `Revoke ${token.symbol} approval from ${spender}`, - approval: { tokenAddress: token.wrapped.address, spender }, + approval: { tokenAddress: getWrappedToken(token).address, spender }, }) }) // .catch((error: Error) => { diff --git a/apps/cowswap-frontend/src/legacy/hooks/useRefetchPriceCallback.tsx b/apps/cowswap-frontend/src/legacy/hooks/useRefetchPriceCallback.tsx index 95ff6ea1f0..bb00de1276 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useRefetchPriceCallback.tsx +++ b/apps/cowswap-frontend/src/legacy/hooks/useRefetchPriceCallback.tsx @@ -6,19 +6,13 @@ import { onlyResolvesLast, getPromiseFulfilledValue, isPromiseFulfilled, - registerOnWindow, calculateValidTo, getQuoteUnsupportedToken, } from '@cowprotocol/common-utils' import { PriceQuality } from '@cowprotocol/cow-sdk' +import { useAddUnsupportedToken, useIsUnsupportedToken, useRemoveUnsupportedToken } from '@cowprotocol/tokens' import { useGetGpPriceStrategy } from 'legacy/hooks/useGetGpPriceStrategy' -import { AddGpUnsupportedTokenParams } from 'legacy/state/lists/actions' -import { - useAddGpUnsupportedToken, - useIsUnsupportedTokenGp, - useRemoveGpUnsupportedToken, -} from 'legacy/state/lists/hooks' import { QuoteError } from 'legacy/state/price/actions' import { useQuoteDispatchers } from 'legacy/state/price/hooks' import { QuoteInformationObject } from 'legacy/state/price/reducer' @@ -38,7 +32,7 @@ import GpQuoteError, { interface HandleQuoteErrorParams { quoteData: QuoteInformationObject | LegacyFeeQuoteParams error: unknown - addUnsupportedToken: (params: AddGpUnsupportedTokenParams) => void + addUnsupportedToken: (tokenAddress: string) => void } type QuoteParamsForFetching = Omit @@ -51,11 +45,9 @@ export function handleQuoteError({ quoteData, error, addUnsupportedToken }: Hand console.error(`${error.message}: ${error.description} - disabling.`) // Add token to unsupported token list - addUnsupportedToken({ - chainId: quoteData.chainId, - address: unsupportedTokenAddress || '', - dateAdded: Date.now(), - }) + if (unsupportedTokenAddress) { + addUnsupportedToken(unsupportedTokenAddress) + } return 'unsupported-token' } @@ -90,11 +82,9 @@ export function handleQuoteError({ quoteData, error, addUnsupportedToken }: Hand console.error(`${error.message}: ${error.description} - disabling.`) // Add token to unsupported token list - addUnsupportedToken({ - chainId: quoteData.chainId, - address: unsupportedTokenAddress || '', - dateAdded: Date.now(), - }) + if (unsupportedTokenAddress) { + addUnsupportedToken(unsupportedTokenAddress) + } return 'unsupported-token' } @@ -129,24 +119,15 @@ const getFastQuoteResolveOnlyLastCall = onlyResolvesLast(getFastQuo * @returns callback that fetches a new quote and update the state */ export function useRefetchQuoteCallback() { - const isUnsupportedTokenGp = useIsUnsupportedTokenGp() + const getIsUnsupportedToken = useIsUnsupportedToken() // dispatchers const { getNewQuote, refreshQuote, updateQuote, setQuoteError } = useQuoteDispatchers() - const addUnsupportedToken = useAddGpUnsupportedToken() - const removeGpUnsupportedToken = useRemoveGpUnsupportedToken() + const addUnsupportedToken = useAddUnsupportedToken() + const removeGpUnsupportedToken = useRemoveUnsupportedToken() const strategy = useGetGpPriceStrategy() const [deadline] = useUserTransactionTTL() const isEoaEthFlow = useIsEoaEthFlow() - registerOnWindow({ - getNewQuote, - refreshQuote, - updateQuote, - setQuoteError, - addUnsupportedToken, - removeGpUnsupportedToken, - }) - return useCallback( async (params: QuoteParamsForFetching) => { const { quoteParams, isPriceRefresh } = params @@ -190,16 +171,13 @@ export function useRefetchQuoteCallback() { description: GpQuoteErrorDetails.ZeroPrice, }) - const previouslyUnsupportedToken = isUnsupportedTokenGp(sellToken) || isUnsupportedTokenGp(buyToken) + const previouslyUnsupportedToken = getIsUnsupportedToken(sellToken) || getIsUnsupportedToken(buyToken) // can be a previously unsupported token which is now valid // so we check against map and remove it if (previouslyUnsupportedToken) { console.debug('[useRefetchPriceCallback]::Previously unsupported token now supported - re-enabling.') - removeGpUnsupportedToken({ - chainId, - address: previouslyUnsupportedToken.address.toLowerCase(), - }) + removeGpUnsupportedToken(previouslyUnsupportedToken.address) } // Update quote @@ -264,7 +242,7 @@ export function useRefetchQuoteCallback() { isEoaEthFlow, deadline, strategy, - isUnsupportedTokenGp, + getIsUnsupportedToken, updateQuote, refreshQuote, getNewQuote, diff --git a/apps/cowswap-frontend/src/legacy/hooks/useTokenLazy.ts b/apps/cowswap-frontend/src/legacy/hooks/useTokenLazy.ts index a1978de686..017d38390d 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useTokenLazy.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useTokenLazy.ts @@ -4,15 +4,15 @@ import { Erc20 } from '@cowprotocol/abis' import { getBytes32TokenContract, getTokenContract } from '@cowprotocol/common-hooks' import { retry } from '@cowprotocol/common-utils' import { useWalletInfo } from '@cowprotocol/wallet' +import { arrayify } from '@ethersproject/bytes' import { Contract } from '@ethersproject/contracts' import { JsonRpcProvider } from '@ethersproject/providers' +import { parseBytes32String } from '@ethersproject/strings' import { Token } from '@uniswap/sdk-core' import { useWeb3React } from '@web3-react/core' import { useAddUserToken } from 'legacy/state/user/hooks' -import { parseStringOrBytes32 } from 'lib/hooks/useCurrency' - const contractsCache: Record = {} const bytes32ContractsCache: Record = {} @@ -32,6 +32,18 @@ export interface GetTokenInfoParams { provider: JsonRpcProvider } +// parse a name or symbol from a token response +const BYTES32_REGEX = /^0x[a-fA-F0-9]{64}$/ + +function parseStringOrBytes32(str: string | undefined, bytes32: string | undefined, defaultValue: string): string { + return str && str.length > 0 + ? str + : // need to check for proper bytes string and valid terminator + bytes32 && BYTES32_REGEX.test(bytes32) && arrayify(bytes32)[31] === 0 + ? parseBytes32String(bytes32) + : defaultValue +} + async function _getTokenContract(params: GetTokenInfoParams): Promise { const { address, account, chainId, provider } = params @@ -138,6 +150,7 @@ async function _getTokenInfo(params: GetTokenInfoParams): Promise 0) { - data.price = _getPrice(tokenAndAmount) + if (tokenAndAmount?.amount && Number(tokenAndAmount.amount) > 0 && tokenAndAmount.token) { + data.price = _getPrice({ token: tokenAndAmount.token, amount: tokenAndAmount.amount }) // get the currency amount using the price base currency (remember price was inverted) data.currencyAmount = CurrencyAmount.fromRawAmount(data.price.baseCurrency, claim.amount) @@ -932,7 +932,7 @@ function _enhanceClaimData(claim: UserClaimData, chainId: SupportedChainId, pric return data } -function _getPrice({ token, amount }: { amount: string; token: Token | GpEther }) { +function _getPrice({ token, amount }: { amount: string; token: TokenWithLogo }) { return new Price({ baseAmount: ONE_VCOW, quoteAmount: CurrencyAmount.fromRawAmount(token, amount), diff --git a/apps/cowswap-frontend/src/legacy/state/claim/hooks/utils.ts b/apps/cowswap-frontend/src/legacy/state/claim/hooks/utils.ts index d6cca292b8..859781fc05 100644 --- a/apps/cowswap-frontend/src/legacy/state/claim/hooks/utils.ts +++ b/apps/cowswap-frontend/src/legacy/state/claim/hooks/utils.ts @@ -1,6 +1,6 @@ -import { GpEther, USDC, GNO, ZERO_PERCENT, ONE_HUNDRED_PERCENT } from '@cowprotocol/common-const' +import { USDC, GNO, ZERO_PERCENT, ONE_HUNDRED_PERCENT, NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { Currency, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core' +import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' import { CLAIMS_REPO, FREE_CLAIM_TYPES, PAID_CLAIM_TYPES } from './const' import { ClaimInput, ClaimType, RepoClaims, UserClaims, VCowPrices } from './types' @@ -100,10 +100,6 @@ export function getClaimKey(account: string, chainId: number): string { return `${chainId}:${account}` } -export type PaidClaimTypeToPriceMap = { - [type in ClaimType]: { token: Token; amount: string } | undefined -} - export function claimTypeToToken(type: ClaimType, chainId: SupportedChainId) { switch (type) { case ClaimType.GnoOption: @@ -111,7 +107,7 @@ export function claimTypeToToken(type: ClaimType, chainId: SupportedChainId) { case ClaimType.Investor: return USDC[chainId] case ClaimType.UserOption: - return GpEther.onChain(chainId) + return NATIVE_CURRENCY_BUY_TOKEN[chainId] case ClaimType.Advisor: case ClaimType.Airdrop: case ClaimType.Team: @@ -125,11 +121,11 @@ export function claimTypeToToken(type: ClaimType, chainId: SupportedChainId) { export function claimTypeToTokenAmount(type: ClaimType, chainId: SupportedChainId, prices: VCowPrices) { switch (type) { case ClaimType.GnoOption: - return { token: claimTypeToToken(ClaimType.GnoOption, chainId) as Token, amount: prices.gno as string } + return { token: claimTypeToToken(ClaimType.GnoOption, chainId), amount: prices.gno as string } case ClaimType.Investor: - return { token: claimTypeToToken(ClaimType.Investor, chainId) as Token, amount: prices.usdc as string } + return { token: claimTypeToToken(ClaimType.Investor, chainId), amount: prices.usdc as string } case ClaimType.UserOption: - return { token: claimTypeToToken(ClaimType.UserOption, chainId) as GpEther, amount: prices.native as string } + return { token: claimTypeToToken(ClaimType.UserOption, chainId), amount: prices.native as string } default: return undefined } diff --git a/apps/cowswap-frontend/src/legacy/state/claim/types.ts b/apps/cowswap-frontend/src/legacy/state/claim/types.ts index bba01d01c3..9ca90a5998 100644 --- a/apps/cowswap-frontend/src/legacy/state/claim/types.ts +++ b/apps/cowswap-frontend/src/legacy/state/claim/types.ts @@ -1,6 +1,5 @@ import { SyntheticEvent } from 'react' -import { GpEther } from '@cowprotocol/common-const' import { Currency, CurrencyAmount, Price, Token } from '@uniswap/sdk-core' import { UserClaimData } from './hooks' @@ -19,7 +18,7 @@ export type ClaimCommonTypes = { export type EnhancedUserClaimData = UserClaimData & { claimAmount: CurrencyAmount isFree: boolean - currencyAmount?: CurrencyAmount | undefined + currencyAmount?: CurrencyAmount | undefined price?: Price | undefined cost?: CurrencyAmount | undefined } diff --git a/apps/cowswap-frontend/src/legacy/state/gas/actions.ts b/apps/cowswap-frontend/src/legacy/state/gas/actions.ts index e89e042717..16bf2b8516 100644 --- a/apps/cowswap-frontend/src/legacy/state/gas/actions.ts +++ b/apps/cowswap-frontend/src/legacy/state/gas/actions.ts @@ -1,9 +1,9 @@ +import { SupportedChainId } from '@cowprotocol/cow-sdk' + import { createAction } from '@reduxjs/toolkit' import { GasFeeEndpointResponse } from 'api/gasPrices' -import { WithChainId } from '../lists/actions' - -export type UpdateGasPrices = GasFeeEndpointResponse & WithChainId +export type UpdateGasPrices = GasFeeEndpointResponse & { chainId?: SupportedChainId } export const updateGasPrices = createAction('gas/updateGasPrices') diff --git a/apps/cowswap-frontend/src/legacy/state/global/actions.ts b/apps/cowswap-frontend/src/legacy/state/global/actions.ts index 4094748f77..9bfe30fa2e 100644 --- a/apps/cowswap-frontend/src/legacy/state/global/actions.ts +++ b/apps/cowswap-frontend/src/legacy/state/global/actions.ts @@ -1,9 +1,9 @@ -import { createAction } from '@reduxjs/toolkit' +import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { WithChainId } from '../lists/actions' +import { createAction } from '@reduxjs/toolkit' // fired once when the app reloads but before the app renders // allows any updates to be applied to store data loaded from localStorage // export const updateVersion = createAction('global/updateVersion') -// takes chainId prop to properly set up lists, always defaults to constants/index::DEFAULT_NETWORK_FOR_LISTS -export const updateVersion = createAction('global/updateVersion') +// takes chainId prop to properly set up lists +export const updateVersion = createAction<{ chainId?: SupportedChainId }>('global/updateVersion') diff --git a/apps/cowswap-frontend/src/legacy/state/index.ts b/apps/cowswap-frontend/src/legacy/state/index.ts index d76c9a9fab..278de6c393 100644 --- a/apps/cowswap-frontend/src/legacy/state/index.ts +++ b/apps/cowswap-frontend/src/legacy/state/index.ts @@ -1,10 +1,8 @@ -import { DEFAULT_NETWORK_FOR_LISTS } from '@cowprotocol/common-const' +import { SupportedChainId } from '@cowprotocol/cow-sdk' import { configureStore, StateFromReducersMapObject } from '@reduxjs/toolkit' import { load, save } from 'redux-localstorage-simple' -// import { composableOrdersPopupMiddleware } from 'modules/twap/state/composableOrdersPopupMiddleware' - import application from './application/reducer' import claim from './claim/reducer' import connection from './connection/reducer' @@ -13,7 +11,6 @@ import cowToken from './cowToken/reducer' import enhancedTransactions from './enhancedTransactions/reducer' import gas from './gas/reducer' import { updateVersion } from './global/actions' -import lists from './lists/reducer' import logs from './logs/slice' import { multicall } from './multicall' import { appziMiddleware, popupMiddleware, soundMiddleware } from './orders/middleware' @@ -32,7 +29,6 @@ const reducers = { multicall: multicall.reducer, logs, transactions: enhancedTransactions, // replace transactions state by "enhancedTransactions" - lists, orders, price, gas, @@ -41,7 +37,7 @@ const reducers = { cowToken, } -const PERSISTED_KEYS: string[] = ['user', 'transactions', 'orders', 'lists', 'gas', 'affiliate', 'profile', 'swap'] +const PERSISTED_KEYS: string[] = ['user', 'transactions', 'orders', 'gas', 'affiliate', 'profile', 'swap'] export const cowSwapStore = configureStore({ reducer: reducers, @@ -59,7 +55,7 @@ export const cowSwapStore = configureStore({ }) // this instantiates the app / reducers in several places using the default chainId -cowSwapStore.dispatch(updateVersion({ chainId: DEFAULT_NETWORK_FOR_LISTS })) +cowSwapStore.dispatch(updateVersion({ chainId: SupportedChainId.MAINNET })) // TODO: this is new, should we enable it? // setupListeners(store.dispatch) diff --git a/apps/cowswap-frontend/src/legacy/state/orders/hooks.ts b/apps/cowswap-frontend/src/legacy/state/orders/hooks.ts index e31c65b69d..66510c0b1e 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/hooks.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/hooks.ts @@ -5,8 +5,6 @@ import { OrderClass, SupportedChainId } from '@cowprotocol/cow-sdk' import { useDispatch, useSelector } from 'react-redux' -import { OrderID } from 'api/gnosisProtocol' - import { addOrUpdateOrders, AddOrUpdateOrdersParams, @@ -46,6 +44,8 @@ import { isOrderExpired, partialOrderUpdate } from './utils' import { AppDispatch, AppState } from '../index' import { deserializeToken, serializeToken } from '../user/hooks' +type OrderID = string + export interface AddOrUpdateUnserialisedOrdersParams extends Omit { orders: Order[] } diff --git a/apps/cowswap-frontend/src/legacy/state/orders/reducer.ts b/apps/cowswap-frontend/src/legacy/state/orders/reducer.ts index 26d7908258..8555d811b8 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/reducer.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/reducer.ts @@ -3,7 +3,6 @@ import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' import { createReducer, PayloadAction } from '@reduxjs/toolkit' import { Writable } from 'types' -import { OrderID } from 'api/gnosisProtocol' import { getIsComposableCowDiscreteOrder } from 'utils/orderUtils/getIsComposableCowDiscreteOrder' import { getIsComposableCowParentOrder } from 'utils/orderUtils/getIsComposableCowParentOrder' import { getIsNotComposableCowOrder } from 'utils/orderUtils/getIsNotComposableCowOrder' @@ -36,7 +35,7 @@ import { ContractDeploymentBlocks, MAX_ITEMS_PER_STATUS } from './consts' import { flatOrdersStateNetwork } from './flatOrdersStateNetwork' export interface OrderObject { - id: OrderID + id: string order: SerializedOrder } @@ -50,7 +49,7 @@ export interface V2OrderObject { } // {order uuid => OrderObject} mapping -type OrdersMap = Record +type OrdersMap = Record export type PartialOrdersMap = Partial export type OrderLists = { diff --git a/apps/cowswap-frontend/src/legacy/state/swap/reducer.ts b/apps/cowswap-frontend/src/legacy/state/swap/reducer.ts index 6b7b0fe0a7..d1ff5edd9e 100644 --- a/apps/cowswap-frontend/src/legacy/state/swap/reducer.ts +++ b/apps/cowswap-frontend/src/legacy/state/swap/reducer.ts @@ -199,7 +199,7 @@ function getEthFlowOverridesOnSelect( ): Pick { if ( inputCurrencyId?.toUpperCase() === - NATIVE_CURRENCY_BUY_TOKEN[state.chainId || ChainId.MAINNET]?.symbol?.toUpperCase() + NATIVE_CURRENCY_BUY_TOKEN[(state.chainId as ChainId) || ChainId.MAINNET]?.symbol?.toUpperCase() ) { const independentField = Field.INPUT const formerIndependentField = state.independentField diff --git a/apps/cowswap-frontend/src/legacy/state/swap/utils.ts b/apps/cowswap-frontend/src/legacy/state/swap/utils.ts index 43bdd3004b..d3c9b5d7c6 100644 --- a/apps/cowswap-frontend/src/legacy/state/swap/utils.ts +++ b/apps/cowswap-frontend/src/legacy/state/swap/utils.ts @@ -1,5 +1,5 @@ import { TOKEN_SHORTHANDS, WRAPPED_NATIVE_CURRENCY } from '@cowprotocol/common-const' -import { isAddress } from '@cowprotocol/common-utils' +import { getIsNativeToken, getWrappedToken, isAddress } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Currency } from '@uniswap/sdk-core' @@ -19,8 +19,14 @@ export function isWrappingTrade( const wethByChain = WRAPPED_NATIVE_CURRENCY[chainId] return Boolean( - (sellCurrency?.isNative && buyCurrency?.wrapped.equals(wethByChain)) || - (buyCurrency?.isNative && sellCurrency?.wrapped.equals(wethByChain)) + (sellCurrency && + getIsNativeToken(sellCurrency) && + buyCurrency && + getWrappedToken(buyCurrency).equals(wethByChain)) || + (buyCurrency && + getIsNativeToken(buyCurrency) && + sellCurrency && + getWrappedToken(sellCurrency).equals(wethByChain)) ) } diff --git a/apps/cowswap-frontend/src/legacy/state/user/hooks.tsx b/apps/cowswap-frontend/src/legacy/state/user/hooks.tsx index d4a328ff5a..48d61edd78 100644 --- a/apps/cowswap-frontend/src/legacy/state/user/hooks.tsx +++ b/apps/cowswap-frontend/src/legacy/state/user/hooks.tsx @@ -1,7 +1,8 @@ import { useCallback, useMemo } from 'react' import { L2_DEADLINE_FROM_NOW, NATIVE_CURRENCY_BUY_TOKEN, SupportedLocale } from '@cowprotocol/common-const' -import { calculateValidTo } from '@cowprotocol/common-utils' +import { calculateValidTo, getIsNativeToken } from '@cowprotocol/common-utils' +import { SupportedChainId } from '@cowprotocol/cow-sdk' import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, Percent, Token } from '@uniswap/sdk-core' @@ -10,10 +11,7 @@ import { shallowEqual } from 'react-redux' import { addSerializedToken, - initFavouriteTokens, - removeAllFavouriteTokens, removeSerializedToken, - toggleFavouriteToken, updateRecipientToggleVisible, updateUserDarkMode, updateUserDeadline, @@ -229,57 +227,14 @@ export function useOrderValidTo() { return useMemo(() => ({ validTo: calculateValidTo(deadline), deadline }), [deadline]) } -export function useFavouriteTokens(): Token[] { - const { chainId } = useWalletInfo() - const serializedTokensMap = useAppSelector(({ user: { favouriteTokens } }) => favouriteTokens) - - return useMemo(() => { - if (!chainId) return [] - const tokenMap: Token[] = serializedTokensMap?.[chainId] - ? Object.values(serializedTokensMap[chainId]).map(deserializeToken) - : [] - return tokenMap - }, [serializedTokensMap, chainId]) -} - -export function useToggleFavouriteToken(): (token: Token) => void { - const dispatch = useAppDispatch() - return useCallback( - (token: Token) => { - dispatch(toggleFavouriteToken({ serializedToken: serializeToken(token) })) - }, - [dispatch] - ) -} - -export function useRemoveAllFavouriteTokens(): () => void { - const { chainId } = useWalletInfo() - const dispatch = useAppDispatch() - - return useCallback(() => { - if (chainId) { - dispatch(removeAllFavouriteTokens({ chainId })) - } - }, [dispatch, chainId]) -} - export function useSelectedWallet(): string | undefined { return useAppSelector(({ user: { selectedWallet } }) => selectedWallet) } -export function useInitFavouriteTokens(): void { - const { chainId } = useWalletInfo() - const dispatch = useAppDispatch() - - return useMemo(() => { - if (chainId) { - dispatch(initFavouriteTokens({ chainId })) - } - }, [chainId, dispatch]) -} - export function serializeToken(token: Currency): SerializedToken { - const address = token.isNative ? NATIVE_CURRENCY_BUY_TOKEN[token.chainId].address : token.address + const address = getIsNativeToken(token) + ? NATIVE_CURRENCY_BUY_TOKEN[token.chainId as SupportedChainId].address + : token.address return { chainId: token.chainId, diff --git a/apps/cowswap-frontend/src/legacy/state/user/reducer.ts b/apps/cowswap-frontend/src/legacy/state/user/reducer.ts index 428a2f6d38..611d223883 100644 --- a/apps/cowswap-frontend/src/legacy/state/user/reducer.ts +++ b/apps/cowswap-frontend/src/legacy/state/user/reducer.ts @@ -1,7 +1,5 @@ -import { COMMON_BASES, DEFAULT_DEADLINE_FROM_NOW, SupportedLocale } from '@cowprotocol/common-const' -import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { DEFAULT_DEADLINE_FROM_NOW, SupportedLocale } from '@cowprotocol/common-const' import { ConnectionType } from '@cowprotocol/wallet' -import { Token } from '@uniswap/sdk-core' import { createSlice } from '@reduxjs/toolkit' @@ -9,9 +7,6 @@ import { SerializedPair, SerializedToken } from './types' import { updateVersion } from '../global/actions' -// MOD imports -// import { serializeToken } from './hooks' - const currentTimestamp = () => new Date().getTime() export interface UserState { @@ -67,51 +62,12 @@ export interface UserState { showSurveyPopup: boolean | undefined showDonationLink: boolean - - // mod, favourite tokens - favouriteTokens: { - [chainId: number]: { - [address: string]: SerializedToken - } - } } function pairKey(token0Address: string, token1Address: string) { return `${token0Address};${token1Address}` } -// TODO: replace by the function from state/user/hooks.ts -function serializeToken(token: Token): SerializedToken { - return { - chainId: token.chainId, - address: token.address, - decimals: token.decimals, - symbol: token.symbol, - name: token.name, - } -} - -function _initialStatePerChain(chainId: number) { - return COMMON_BASES[chainId].reduce( - (acc2, curr) => { - acc2[curr.wrapped.address] = serializeToken(curr.wrapped) - return acc2 - }, - {} as { - [address: string]: SerializedToken - } - ) -} - -const ALL_SUPPORTED_CHAIN_IDS = [SupportedChainId.MAINNET, SupportedChainId.GNOSIS_CHAIN, SupportedChainId.GOERLI] - -function _initialSavedTokensState() { - return ALL_SUPPORTED_CHAIN_IDS.reduce((acc, chain) => { - acc[chain] = _initialStatePerChain(chain) - return acc - }, {} as UserState['favouriteTokens']) -} - export const initialState: UserState = { selectedWallet: undefined, selectedWalletBackfilled: false, @@ -132,8 +88,6 @@ export const initialState: UserState = { URLWarningVisible: true, showSurveyPopup: undefined, showDonationLink: true, - // mod, favourite tokens - favouriteTokens: _initialSavedTokensState(), } const userSlice = createSlice({ @@ -223,27 +177,6 @@ const userSlice = createSlice({ state.recipientToggleVisible = action.payload.recipientToggleVisible state.timestamp = currentTimestamp() }, - initFavouriteTokens(state, { payload: { chainId } }) { - if (!state.favouriteTokens?.[chainId]) { - state.favouriteTokens = _initialSavedTokensState() - } - }, - toggleFavouriteToken(state, { payload: { serializedToken } }) { - const { chainId, address } = serializedToken - - if (!state.favouriteTokens?.[chainId]) { - state.favouriteTokens = _initialSavedTokensState() - } - - if (!state.favouriteTokens[chainId][address]) { - state.favouriteTokens[chainId][address] = serializedToken - } else { - delete state.favouriteTokens[chainId][address] - } - }, - removeAllFavouriteTokens(state, { payload: { chainId } }) { - state.favouriteTokens[chainId] = _initialStatePerChain(chainId) - }, }, extraReducers: (builder) => { builder.addCase(updateVersion, (state) => { @@ -284,25 +217,14 @@ const userSlice = createSlice({ export const { updateSelectedWallet, - addSerializedPair, addSerializedToken, - removeSerializedPair, removeSerializedToken, - updateHideClosedPositions, updateMatchesDarkMode, - updateShowDonationLink, - updateShowSurveyPopup, - updateUserClientSideRouter, updateUserDarkMode, updateUserDeadline, updateUserExpertMode, updateUserLocale, updateUserSlippageTolerance, - // MOD - legacy Uni code we want to keep updateRecipientToggleVisible, - toggleURLWarning, - toggleFavouriteToken, - removeAllFavouriteTokens, - initFavouriteTokens, } = userSlice.actions export default userSlice.reducer diff --git a/apps/cowswap-frontend/src/legacy/utils/trade.ts b/apps/cowswap-frontend/src/legacy/utils/trade.ts index 55d856f7cc..e3db90a891 100644 --- a/apps/cowswap-frontend/src/legacy/utils/trade.ts +++ b/apps/cowswap-frontend/src/legacy/utils/trade.ts @@ -1,5 +1,5 @@ import { RADIX_DECIMAL, NATIVE_CURRENCY_BUY_ADDRESS } from '@cowprotocol/common-const' -import { isAddress, shortenAddress, formatTokenAmount, formatSymbol } from '@cowprotocol/common-utils' +import { isAddress, shortenAddress, formatTokenAmount, formatSymbol, getIsNativeToken } from '@cowprotocol/common-utils' import { EcdsaSigningScheme, OrderClass, @@ -19,7 +19,7 @@ import { AddUnserialisedPendingOrderParams } from 'legacy/state/orders/hooks' import { AppDataInfo } from 'modules/appData' -import { getTrades, OrderID } from 'api/gnosisProtocol' +import { getTrades } from 'api/gnosisProtocol' import { getProfileData } from 'api/gnosisProtocol/api' export type PostOrderParams = { @@ -125,7 +125,7 @@ export function getSignOrderParams(params: PostOrderParams): SignOrderParams { quoteId, order: { sellToken: sellTokenAddress, - buyToken: buyToken.isNative ? NATIVE_CURRENCY_BUY_ADDRESS : buyToken.address, + buyToken: getIsNativeToken(buyToken) ? NATIVE_CURRENCY_BUY_ADDRESS : buyToken.address, sellAmount, buyAmount, validTo, @@ -250,7 +250,7 @@ export async function signAndPostOrder(params: PostOrderParams): Promise boolean ): ApprovalStateForSpenderResult { const { account } = useWalletInfo() - const token = amountToApprove?.currency?.isToken ? amountToApprove.currency : undefined + const currency = amountToApprove?.currency + const token = currency && !getIsNativeToken(currency) ? currency : undefined const currentAllowance = useTokenAllowance(token, account ?? undefined, spender) const pendingApproval = useIsPendingApproval(token, spender) @@ -78,7 +79,8 @@ export function useApproval( () => Promise<{ response: TransactionResponse; tokenAddress: string; spenderAddress: string } | undefined> ] { const { chainId } = useWalletInfo() - const token = amountToApprove?.currency?.isToken ? amountToApprove.currency : undefined + const currency = amountToApprove?.currency + const token = currency && !getIsNativeToken(currency) ? currency : undefined // check the current approval status const approvalState = useApprovalStateForSpender(amountToApprove, spender, useIsPendingApproval).approvalState diff --git a/apps/cowswap-frontend/src/lib/hooks/useNativeCurrency.ts b/apps/cowswap-frontend/src/lib/hooks/useNativeCurrency.ts index 2104ea7478..0687399819 100644 --- a/apps/cowswap-frontend/src/lib/hooks/useNativeCurrency.ts +++ b/apps/cowswap-frontend/src/lib/hooks/useNativeCurrency.ts @@ -1,14 +1,13 @@ import { useMemo } from 'react' -import { nativeOnChain } from '@cowprotocol/common-const' +import { NATIVE_CURRENCY_BUY_TOKEN, TokenWithLogo } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { useWalletInfo } from '@cowprotocol/wallet' -import { NativeCurrency } from '@uniswap/sdk-core' -export const MAINNET_NATIVE_CURRENCY = nativeOnChain(SupportedChainId.MAINNET) +export const MAINNET_NATIVE_CURRENCY = NATIVE_CURRENCY_BUY_TOKEN[SupportedChainId.MAINNET] -export default function useNativeCurrency(): NativeCurrency { +export default function useNativeCurrency(): TokenWithLogo { const { chainId } = useWalletInfo() - return useMemo(() => nativeOnChain(chainId), [chainId]) + return useMemo(() => NATIVE_CURRENCY_BUY_TOKEN[chainId], [chainId]) } diff --git a/apps/cowswap-frontend/src/modules/account/containers/Transaction/ActivityDetails.tsx b/apps/cowswap-frontend/src/modules/account/containers/Transaction/ActivityDetails.tsx index 8c84e3f393..67fdbfc189 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/Transaction/ActivityDetails.tsx +++ b/apps/cowswap-frontend/src/modules/account/containers/Transaction/ActivityDetails.tsx @@ -2,12 +2,14 @@ import { ReactNode } from 'react' import { V_COW_CONTRACT_ADDRESS, V_COW, COW } from '@cowprotocol/common-const' import { ExplorerDataType, getExplorerLink, shortenAddress } from '@cowprotocol/common-utils' +import { SupportedChainId } from '@cowprotocol/cow-sdk' import { useENS } from '@cowprotocol/ens' +import { useTokenBySymbolOrAddress } from '@cowprotocol/tokens' +import { TokenLogo } from '@cowprotocol/tokens' import { ExternalLink, TokenAmount } from '@cowprotocol/ui' import { CurrencyAmount } from '@uniswap/sdk-core' import { OrderProgressBar } from 'legacy/components/OrderProgressBar' -import { useToken } from 'legacy/hooks/Tokens' import { getActivityState } from 'legacy/hooks/useActivityDerivedState' import { ActivityStatus } from 'legacy/hooks/useRecentActivity' import { OrderStatus } from 'legacy/state/orders/actions' @@ -18,7 +20,6 @@ import { UI } from 'common/constants/theme' import { useCancelOrder } from 'common/hooks/useCancelOrder' import { isPending } from 'common/hooks/useCategorizeRecentActivity' import { useGetSurplusData } from 'common/hooks/useGetSurplusFiatValue' -import { CurrencyLogo } from 'common/pure/CurrencyLogo' import { Icon } from 'common/pure/Icon' import { BannerOrientation, CustomRecipientWarningBanner } from 'common/pure/InlineBanner/banners' import { RateInfoParams, RateInfo } from 'common/pure/RateInfo' @@ -172,7 +173,7 @@ export function ActivityDetails(props: { const activityState = getActivityState(activityDerivedState) const tokenAddress = enhancedTransaction?.approval?.tokenAddress || (enhancedTransaction?.claim && V_COW_CONTRACT_ADDRESS[chainId]) - const singleToken = useToken(tokenAddress) || null + const singleToken = useTokenBySymbolOrAddress(tokenAddress) || null const getShowCancellationModal = useCancelOrder() @@ -259,8 +260,8 @@ export function ActivityDetails(props: { let outputToken = activityDerivedState?.order?.outputToken || null if (enhancedTransaction?.swapVCow || enhancedTransaction?.swapLockedGNOvCow) { - inputToken = V_COW[chainId] - outputToken = COW[chainId] + inputToken = V_COW[chainId as SupportedChainId] + outputToken = COW[chainId as SupportedChainId] } const isCustomRecipient = Boolean(order?.receiver && order.owner !== order.receiver) @@ -283,15 +284,15 @@ export function ActivityDetails(props: { {/* Token Approval Currency Logo */} {!isOrder && singleToken && ( - + )} {/* Order Currency Logo */} {inputToken && outputToken && ( - - + + )} diff --git a/apps/cowswap-frontend/src/modules/account/containers/Transaction/styled.ts b/apps/cowswap-frontend/src/modules/account/containers/Transaction/styled.ts index 7a12e05aff..732373472d 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/Transaction/styled.ts +++ b/apps/cowswap-frontend/src/modules/account/containers/Transaction/styled.ts @@ -7,7 +7,6 @@ import styled, { css, keyframes } from 'styled-components/macro' import { LinkStyledButton } from 'legacy/theme' import { UI } from 'common/constants/theme' -import { StyledLogo } from 'common/pure/CurrencyLogo' import { RateWrapper } from 'common/pure/RateInfo' export const TransactionWrapper = styled.div` @@ -270,8 +269,8 @@ export const StatusLabel = styled.div<{ isPending || isPresignaturePending || isCreating ? theme.text1 : color === 'success' - ? theme.success - : theme.attention}; + ? theme.success + : theme.attention}; position: relative; border-radius: 4px; display: flex; @@ -291,13 +290,13 @@ export const StatusLabel = styled.div<{ &::before { content: ''; background: ${({ color, isTransaction, isPending, isPresignaturePending, isCancelling, isCreating, theme }) => - !isCancelling && (isPending || isCreating) - ? 'transparent' - : isPresignaturePending || (isPending && isTransaction) + !isCancelling && (isPending || isCreating) + ? 'transparent' + : isPresignaturePending || (isPending && isTransaction) ? theme.pending : color === 'success' - ? theme.success - : theme.attention}; + ? theme.success + : theme.attention}; position: absolute; left: 0; top: 0; @@ -331,9 +330,9 @@ export const StatusLabel = styled.div<{ > svg > path { fill: ${({ theme, color, isPending, isPresignaturePending, isCreating }) => - isPending || isPresignaturePending || isCreating - ? theme.text1 - : color === 'success' + isPending || isPresignaturePending || isCreating + ? theme.text1 + : color === 'success' ? theme.success : theme.attention}; } @@ -356,7 +355,7 @@ export const StatusLabelBelow = styled.div<{ isCancelling?: boolean }>` } ` -export const OldTransactionState = styled(ExternalLink) <{ pending: boolean; success?: boolean }>` +export const OldTransactionState = styled(ExternalLink)<{ pending: boolean; success?: boolean }>` display: flex; justify-content: space-between; align-items: center; @@ -477,21 +476,21 @@ export const ActivityVisual = styled.div` display: flex; margin: 0 0 6px; - ${StyledLogo} { + div { padding: 2px; box-sizing: content-box; box-shadow: none; background: ${({ theme }) => theme.white}; color: ${({ theme }) => - theme.transaction.tokenColor}!important; // TODO: Fix MOD file to not require this !important property value. + theme.transaction.tokenColor}!important; // TODO: Fix MOD file to not require this !important property value. border: 2px solid ${({ theme }) => theme.bg1}; } - ${StyledLogo}:not(:first-child):last-child { + div:not(:first-child):last-child { margin: 0 0 0 -9px; } - &:hover ${StyledLogo} { + &:hover div { animation: ${rotate360} 1s cubic-bezier(0.83, 0, 0.17, 1) infinite; transform: translateZ(0); } diff --git a/apps/cowswap-frontend/src/modules/application/containers/App/Updaters.tsx b/apps/cowswap-frontend/src/modules/application/containers/App/Updaters.tsx index 557ee7d30d..acb3a12eae 100644 --- a/apps/cowswap-frontend/src/modules/application/containers/App/Updaters.tsx +++ b/apps/cowswap-frontend/src/modules/application/containers/App/Updaters.tsx @@ -1,4 +1,5 @@ -import { WalletUpdater } from '@cowprotocol/wallet' +import { TokensListsUpdater } from '@cowprotocol/tokens' +import { useWalletInfo, WalletUpdater } from '@cowprotocol/wallet' import { GasPriceStrategyUpdater } from 'legacy/state/gas/gas-price-strategy-updater' import { MulticallUpdater } from 'legacy/state/multicall' @@ -6,7 +7,6 @@ import { MulticallUpdater } from 'legacy/state/multicall' import { UploadToIpfsUpdater } from 'modules/appData/updater/UploadToIpfsUpdater' import { InjectedWidgetUpdater } from 'modules/injectedWidget' import { EthFlowDeadlineUpdater, EthFlowSlippageUpdater } from 'modules/swap/state/EthFlow/updaters' -import { TokensListUpdater } from 'modules/tokensList/updaters/TokensListUpdater' import { UsdPricesUpdater } from 'modules/usdAmount' import { TotalSurplusUpdater } from 'common/state/totalSurplusState' @@ -16,7 +16,6 @@ import { FeesUpdater } from 'common/updaters/FeesUpdater' import { FinalizeTxUpdater } from 'common/updaters/FinalizeTxUpdater' import { GasUpdater } from 'common/updaters/GasUpdater' import { HwAccountIndexUpdater } from 'common/updaters/HwAccountIndexUpdater' -import { ListsUpdater } from 'common/updaters/ListsUpdater' import { LogsUpdater } from 'common/updaters/LogsUpdater' import { CancelledOrdersUpdater, @@ -31,12 +30,12 @@ import { ThemeFromUrlUpdater } from 'common/updaters/ThemeFromUrlUpdater' import { UserUpdater } from 'common/updaters/UserUpdater' export function Updaters() { + const { chainId } = useWalletInfo() + return ( <> - - @@ -60,6 +59,7 @@ export function Updaters() { + ) } diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersConfirmModal/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersConfirmModal/index.tsx index 7c8fa13f95..479a48af3a 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersConfirmModal/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersConfirmModal/index.tsx @@ -1,6 +1,7 @@ import { useAtom, useAtomValue } from 'jotai' import React from 'react' +import { getWrappedToken } from '@cowprotocol/common-utils' import { TokenSymbol } from '@cowprotocol/ui' import { PriceImpact } from 'legacy/hooks/usePriceImpact' @@ -54,7 +55,7 @@ export function LimitOrdersConfirmModal(props: LimitOrdersConfirmModalProps) { const buttonText = isSafeApprovalBundle ? ( <> Confirm (Approve  - +  & Limit order) ) : ( diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx index a416b9bbb4..ad624603fb 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx @@ -236,7 +236,6 @@ const LimitOrders = React.memo((props: LimitOrdersProps) => { primaryFormValidation === TradeFormValidation.WrapUnwrapFlow const params = { - disableNonToken: false, compactView: false, disableNativeSelling: true, isExpertMode, diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useGetInitialPrice.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useGetInitialPrice.ts index cee5622916..c45ce39b44 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useGetInitialPrice.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useGetInitialPrice.ts @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react' import { useIsWindowVisible } from '@cowprotocol/common-hooks' -import { getAddress } from '@cowprotocol/common-utils' +import { getAddress, getIsNativeToken } from '@cowprotocol/common-utils' import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, Fraction } from '@uniswap/sdk-core' @@ -26,7 +26,7 @@ async function requestPriceForCurrency(chainId: number | undefined, currency: Cu } try { - if (currency.isNative || !currencyAddress) { + if (getIsNativeToken(currency) || !currencyAddress) { return parsePrice(1, currency) } diff --git a/apps/cowswap-frontend/src/modules/orders/hooks/useTokensForOrdersList.ts b/apps/cowswap-frontend/src/modules/orders/hooks/useTokensForOrdersList.ts index 5d1174e575..0609c8ad91 100644 --- a/apps/cowswap-frontend/src/modules/orders/hooks/useTokensForOrdersList.ts +++ b/apps/cowswap-frontend/src/modules/orders/hooks/useTokensForOrdersList.ts @@ -1,19 +1,17 @@ import { useCallback, useRef } from 'react' +import { TokenWithLogo } from '@cowprotocol/common-const' +import { TokensByAddress, useTokensByAddressMap } from '@cowprotocol/tokens' import { useWalletInfo } from '@cowprotocol/wallet' import { Token } from '@uniswap/sdk-core' -import { useAllTokens } from 'legacy/hooks/Tokens' import { useTokenLazy } from 'legacy/hooks/useTokenLazy' -import { TokensByAddress } from 'modules/tokensList/state/tokensListAtom' -import { TokenWithLogo } from 'modules/tokensList/types' - import { getTokenFromMapping } from 'utils/orderUtils/getTokenFromMapping' export function useTokensForOrdersList(): (tokensToFetch: string[]) => Promise { const { chainId } = useWalletInfo() - const allTokens = useAllTokens() + const allTokens = useTokensByAddressMap() const getToken = useTokenLazy() // Using a ref to store allTokens to avoid re-fetching when new tokens are added diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx index 21f8a63541..04ad3f09e0 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx @@ -5,6 +5,7 @@ import { ZERO_FRACTION } from '@cowprotocol/common-const' import { useTimeAgo } from '@cowprotocol/common-hooks' import { getAddress, getEtherscanLink } from '@cowprotocol/common-utils' import { OrderClass, SupportedChainId } from '@cowprotocol/cow-sdk' +import { TokenLogo } from '@cowprotocol/tokens' import { Loader, TokenAmount, TokenSymbol } from '@cowprotocol/ui' import { Currency, CurrencyAmount, Percent, Price } from '@uniswap/sdk-core' @@ -28,7 +29,6 @@ import { getIsEthFlowOrder } from 'modules/swap/containers/EthFlowStepper' import { useSafeMemo } from 'common/hooks/useSafeMemo' import { ButtonSecondary } from 'common/pure/ButtonSecondary' -import { CurrencyLogo } from 'common/pure/CurrencyLogo' import { RateInfo } from 'common/pure/RateInfo' import { getQuoteCurrency } from 'common/services/getQuoteCurrency' import { isOrderCancellable } from 'common/utils/isOrderCancellable' @@ -53,7 +53,7 @@ function CurrencyAmountItem({ amount }: { amount: CurrencyAmount }) { } function CurrencySymbolItem({ amount }: { amount: CurrencyAmount }) { - return + return } function BalanceWarning(params: { symbol: string; isScheduled: boolean }) { diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/styled.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/styled.tsx index a335e391df..fe69cc2ae7 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/styled.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/styled.tsx @@ -146,12 +146,12 @@ export const CurrencyLogoPair = styled.div<{ clickable?: boolean }>` display: flex; cursor: ${({ clickable }) => (clickable ? 'pointer' : 'initial')}; - > img, + > div, > svg { border: 2px solid ${({ theme }) => theme.grey1}; } - > img:last-child, + > div:last-child, > svg:last-child { margin: 0 0 0 -14px; } diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/utils/getOrderParams.ts b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/utils/getOrderParams.ts index c7e0077ed9..395a170252 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/utils/getOrderParams.ts +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/utils/getOrderParams.ts @@ -19,7 +19,7 @@ export interface OrderParams { const PERCENTAGE_FOR_PARTIAL_FILLS = new Percent(5, 10000) // 0.05% export function getOrderParams( - chainId: SupportedChainId | undefined, + chainId: SupportedChainId, balancesAndAllowances: BalancesAndAllowances, order: ParsedOrder ): OrderParams { diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts index b804d3aaf5..e8019ce7ed 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts @@ -1,6 +1,7 @@ import { useAtomValue, useSetAtom } from 'jotai' import { useEffect, useMemo } from 'react' +import { getIsNativeToken, getWrappedToken } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { useWalletInfo } from '@cowprotocol/wallet' import { Currency } from '@uniswap/sdk-core' @@ -32,8 +33,8 @@ export function useIsTokenPermittable( const { chainId } = useWalletInfo() const { provider } = useWeb3React() - const lowerCaseAddress = token?.wrapped?.address?.toLowerCase() - const isNative = token?.isNative + const lowerCaseAddress = token ? getWrappedToken(token).address?.toLowerCase() : undefined + const isNative = !!token && getIsNativeToken(token) const tokenName = token?.name || lowerCaseAddress || '' // Avoid building permit info in the first place if order type is not supported diff --git a/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useRemainingNativeTxsAndCosts.ts b/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useRemainingNativeTxsAndCosts.ts index 58376d2694..5576cd2b30 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useRemainingNativeTxsAndCosts.ts +++ b/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useRemainingNativeTxsAndCosts.ts @@ -1,6 +1,7 @@ import { useMemo } from 'react' import { AVG_APPROVE_COST_GWEI } from '@cowprotocol/common-const' +import { getIsNativeToken } from '@cowprotocol/common-utils' import { useWalletInfo } from '@cowprotocol/wallet' import { BigNumber } from '@ethersproject/bignumber' import { CurrencyAmount, Currency } from '@uniswap/sdk-core' @@ -83,7 +84,7 @@ export default function useRemainingNativeTxsAndCosts({ // does the user have a lower than set threshold balance? show error const balanceChecks: BalanceChecks = useMemo(() => { // we only check this for native currencies, otherwise stop - if (!nativeInput?.currency.isNative) return undefined + if (nativeInput?.currency && !getIsNativeToken(nativeInput.currency)) return undefined const { multiTxCost, singleTxCost } = txCosts return { diff --git a/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/index.tsx index 09af53c8e8..e0d507ecc3 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/index.tsx @@ -1,6 +1,7 @@ import { useAtomValue } from 'jotai' import { useMemo } from 'react' +import { currencyAmountToTokenAmount } from '@cowprotocol/common-utils' import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' @@ -46,7 +47,9 @@ function EthFlow({ const approvalState = useTradeApproveState(nativeInput || null) const ethFlowContext = useAtomValue(ethFlowContextAtom) - const approveCallback = useTradeApproveCallback(nativeInput?.wrapped) + const approveCallback = useTradeApproveCallback( + (nativeInput && currencyAmountToTokenAmount(nativeInput)) || undefined + ) const ethFlowActions = useEthFlowActions({ wrap: wrapCallback, approve: approveCallback, diff --git a/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx index 07a12bff92..8dab3406f2 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx @@ -1,6 +1,7 @@ import React, { useMemo, useState } from 'react' import { isFractionFalsy } from '@cowprotocol/common-utils' +import { useIsTradeUnsupported } from '@cowprotocol/tokens' import { useIsSafeViaWc, useWalletDetails, useWalletInfo } from '@cowprotocol/wallet' import { NetworkAlert } from 'legacy/components/NetworkAlert/NetworkAlert' @@ -8,7 +9,6 @@ import SettingsTab from 'legacy/components/Settings' import useCowBalanceAndSubsidy from 'legacy/hooks/useCowBalanceAndSubsidy' import { useModalIsOpen } from 'legacy/state/application/hooks' import { ApplicationModal } from 'legacy/state/application/reducer' -import { useIsTradeUnsupported } from 'legacy/state/lists/hooks' import { Field } from 'legacy/state/types' import { useExpertModeManager, useUserSlippageTolerance } from 'legacy/state/user/hooks' diff --git a/apps/cowswap-frontend/src/modules/swap/helpers/__snapshots__/tradeReceiveAmount.test.ts.snap b/apps/cowswap-frontend/src/modules/swap/helpers/__snapshots__/tradeReceiveAmount.test.ts.snap index 2aea16f68f..663406db74 100644 --- a/apps/cowswap-frontend/src/modules/swap/helpers/__snapshots__/tradeReceiveAmount.test.ts.snap +++ b/apps/cowswap-frontend/src/modules/swap/helpers/__snapshots__/tradeReceiveAmount.test.ts.snap @@ -3,12 +3,15 @@ exports[`Helpers to build ReceiveAmountInfo getInputReceiveAmountInfo() When selling, if the fee is bigger than the traded amount Then amountBeforeFees should be zero 1`] = ` { "amount": CurrencyAmount { - "currency": Token { + "currency": TokenWithLogo { "address": "0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB", "chainId": 1, "decimals": 18, "isNative": false, "isToken": true, + "logoURI": { + "ReactComponent": "IconMock", + }, "name": "CoW Protocol Token", "symbol": "COW", }, @@ -35,12 +38,15 @@ exports[`Helpers to build ReceiveAmountInfo getInputReceiveAmountInfo() When sel exports[`Helpers to build ReceiveAmountInfo getInputReceiveAmountInfo() When selling, if the fee is bigger than the traded amount Then amountBeforeFees should be zero 3`] = ` { "amount": CurrencyAmount { - "currency": Token { + "currency": TokenWithLogo { "address": "0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB", "chainId": 1, "decimals": 18, "isNative": false, "isToken": true, + "logoURI": { + "ReactComponent": "IconMock", + }, "name": "CoW Protocol Token", "symbol": "COW", }, @@ -64,12 +70,15 @@ exports[`Helpers to build ReceiveAmountInfo getInputReceiveAmountInfo() When sel exports[`Helpers to build ReceiveAmountInfo getOutputReceiveAmountInfo() Should match a snapshot 1`] = ` { "amount": CurrencyAmount { - "currency": Token { + "currency": TokenWithLogo { "address": "0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB", "chainId": 1, "decimals": 18, "isNative": false, "isToken": true, + "logoURI": { + "ReactComponent": "IconMock", + }, "name": "CoW Protocol Token", "symbol": "COW", }, @@ -93,12 +102,15 @@ exports[`Helpers to build ReceiveAmountInfo getOutputReceiveAmountInfo() Should exports[`Helpers to build ReceiveAmountInfo getOutputReceiveAmountInfo() Should match a snapshot 2`] = ` { "amount": CurrencyAmount { - "currency": Token { + "currency": TokenWithLogo { "address": "0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB", "chainId": 1, "decimals": 18, "isNative": false, "isToken": true, + "logoURI": { + "ReactComponent": "IconMock", + }, "name": "CoW Protocol Token", "symbol": "COW", }, @@ -122,12 +134,15 @@ exports[`Helpers to build ReceiveAmountInfo getOutputReceiveAmountInfo() Should exports[`Helpers to build ReceiveAmountInfo getOutputReceiveAmountInfo() Should match a snapshot 3`] = ` { "amount": CurrencyAmount { - "currency": Token { + "currency": TokenWithLogo { "address": "0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB", "chainId": 1, "decimals": 18, "isNative": false, "isToken": true, + "logoURI": { + "ReactComponent": "IconMock", + }, "name": "CoW Protocol Token", "symbol": "COW", }, diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useBaseSafeBundleFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useBaseSafeBundleFlowContext.ts index a1369547a6..1513afbd2b 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useBaseSafeBundleFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useBaseSafeBundleFlowContext.ts @@ -1,4 +1,5 @@ import { useGP2SettlementContract } from '@cowprotocol/common-hooks' +import { getWrappedToken } from '@cowprotocol/common-utils' import { OrderKind } from '@cowprotocol/cow-sdk' import { useSafeAppsSdk } from '@cowprotocol/wallet' import { TradeType } from '@uniswap/sdk-core' @@ -11,7 +12,7 @@ import { useTradeSpenderAddress } from 'common/hooks/useTradeSpenderAddress' export function useBaseSafeBundleFlowContext(): BaseSafeFlowContext | null { const baseProps = useBaseFlowContextSetup() - const sellToken = baseProps.trade ? baseProps.trade.inputAmount.currency.wrapped : undefined + const sellToken = baseProps.trade ? getWrappedToken(baseProps.trade.inputAmount.currency) : undefined const settlementContract = useGP2SettlementContract() const spender = useTradeSpenderAddress() const safeAppsSdk = useSafeAppsSdk() diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useEthFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useEthFlowContext.ts index 7cd8122b69..ae9192c860 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useEthFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useEthFlowContext.ts @@ -2,7 +2,7 @@ import { useSetAtom } from 'jotai' import { NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const' import { useEthFlowContract } from '@cowprotocol/common-hooks' -import { OrderKind } from '@cowprotocol/cow-sdk' +import { OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk' import { useTransactionAdder } from 'legacy/state/enhancedTransactions/hooks' @@ -23,7 +23,7 @@ export function useEthFlowContext(): EthFlowContext | null { const baseContext = getFlowContext({ baseProps, - sellToken: baseProps.chainId ? NATIVE_CURRENCY_BUY_TOKEN[baseProps.chainId] : undefined, + sellToken: baseProps.chainId ? NATIVE_CURRENCY_BUY_TOKEN[baseProps.chainId as SupportedChainId] : undefined, kind: OrderKind.SELL, }) diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useFlowContext.ts index 5b4f2fd8e0..165cb299d1 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useFlowContext.ts @@ -1,8 +1,8 @@ import { Erc20, Weth } from '@cowprotocol/abis' -import { GpEther as ETHER, NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const' +import { NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const' import { useTokenContract, useWETHContract } from '@cowprotocol/common-hooks' -import { calculateValidTo, getAddress } from '@cowprotocol/common-utils' -import { OrderClass, OrderKind } from '@cowprotocol/cow-sdk' +import { calculateValidTo, getAddress, getIsNativeToken } from '@cowprotocol/common-utils' +import { OrderClass, OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk' import { useENSAddress } from '@cowprotocol/ens' import { useGnosisSafeInfo, useWalletDetails, useWalletInfo } from '@cowprotocol/wallet' import { Web3Provider } from '@ethersproject/providers' @@ -196,10 +196,11 @@ export function getFlowContext({ baseProps, sellToken, kind }: BaseGetFlowContex return null } - const isBuyEth = ETHER.onChain(chainId).equals(trade.outputAmount.currency) const isGnosisSafeWallet = !!gnosisSafeInfo - const buyToken = isBuyEth ? NATIVE_CURRENCY_BUY_TOKEN[chainId] : trade.outputAmount.currency.wrapped + const buyToken = getIsNativeToken(trade.outputAmount.currency) + ? NATIVE_CURRENCY_BUY_TOKEN[chainId as SupportedChainId] + : trade.outputAmount.currency const marketLabel = [sellToken?.symbol, buyToken.symbol].join(',') if (!sellToken || !buyToken) { diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSafeBundleApprovalFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSafeBundleApprovalFlowContext.ts index 7fc8ee6a35..15f731cfa1 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSafeBundleApprovalFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSafeBundleApprovalFlowContext.ts @@ -1,4 +1,5 @@ import { useTokenContract } from '@cowprotocol/common-hooks' +import { getWrappedToken } from '@cowprotocol/common-utils' import { FlowType } from 'modules/swap/hooks/useFlowContext' import { SafeBundleApprovalFlowContext } from 'modules/swap/services/types' @@ -9,7 +10,7 @@ export function useSafeBundleApprovalFlowContext(): SafeBundleApprovalFlowContex const baseContext = useBaseSafeBundleFlowContext() const trade = baseContext?.context.trade - const sellToken = trade ? trade.inputAmount.currency.wrapped : undefined + const sellToken = trade ? getWrappedToken(trade.inputAmount.currency) : undefined const erc20Contract = useTokenContract(sellToken?.address) if (!trade || !erc20Contract) return null diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts index e76de08d48..a95c5937d5 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts @@ -1,3 +1,5 @@ +import { currencyAmountToTokenAmount, getWrappedToken } from '@cowprotocol/common-utils' +import { useIsTradeUnsupported } from '@cowprotocol/tokens' import { useGnosisSafeInfo, useIsBundlingSupported, @@ -9,7 +11,6 @@ import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { PriceImpact } from 'legacy/hooks/usePriceImpact' import { useToggleWalletModal } from 'legacy/state/application/hooks' -import { useIsTradeUnsupported } from 'legacy/state/lists/hooks' import { useGetQuoteAndStatus, useIsBestQuoteLoading } from 'legacy/state/price/hooks' import { Field } from 'legacy/state/types' import { useExpertModeManager } from 'legacy/state/user/hooks' @@ -77,7 +78,7 @@ export function useSwapButtonContext(input: SwapButtonInput): SwapButtonsContext const isNativeInSwap = isNativeIn && !isWrappedOut const inputAmount = slippageAdjustedSellAmount || parsedAmount - const wrapUnwrapAmount = isNativeInSwap ? inputAmount?.wrapped : inputAmount + const wrapUnwrapAmount = isNativeInSwap ? currencyAmountToTokenAmount(inputAmount) || undefined : inputAmount const hasEnoughWrappedBalanceForSwap = useHasEnoughWrappedBalanceForSwap(wrapUnwrapAmount) const wrapCallback = useWrapNativeFlow() const approvalState = useTradeApproveState(slippageAdjustedSellAmount || null) @@ -139,7 +140,7 @@ export function useSwapButtonContext(input: SwapButtonInput): SwapButtonsContext function useHasEnoughWrappedBalanceForSwap(inputAmount?: CurrencyAmount): boolean { const { currencies } = useDerivedSwapInfo() const { account } = useWalletInfo() - const wrappedBalance = useCurrencyBalance(account ?? undefined, currencies.INPUT?.wrapped) + const wrappedBalance = useCurrencyBalance(account ?? undefined, currencies.INPUT && getWrappedToken(currencies.INPUT)) // is an native currency trade but wrapped token has enough balance return !!(wrappedBalance && inputAmount && !wrappedBalance.lessThan(inputAmount)) diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts index 086e4329ba..13bc3ef6b6 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts @@ -1,5 +1,6 @@ import { GP_VAULT_RELAYER } from '@cowprotocol/common-const' import { useGP2SettlementContract } from '@cowprotocol/common-hooks' +import { getWrappedToken } from '@cowprotocol/common-utils' import { OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk' import { TradeType as UniTradeType } from '@uniswap/sdk-core' @@ -27,7 +28,7 @@ export function useSwapFlowContext(): SwapFlowContext | null { const baseContext = getFlowContext({ baseProps, - sellToken: baseProps.trade.inputAmount.currency.wrapped, + sellToken: getWrappedToken(baseProps.trade.inputAmount.currency), kind: baseProps.trade.tradeType === UniTradeType.EXACT_INPUT ? OrderKind.SELL : OrderKind.BUY, }) diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapState.tsx b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapState.tsx index c0de1c1112..6e7a82e992 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapState.tsx +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapState.tsx @@ -2,15 +2,16 @@ import { useCallback, useEffect, useMemo, useState } from 'react' import { changeSwapAmountAnalytics, switchTokensAnalytics } from '@cowprotocol/analytics' import { FEE_SIZE_THRESHOLD } from '@cowprotocol/common-const' -import { formatSymbol, isAddress, tryParseCurrencyAmount } from '@cowprotocol/common-utils' +import { formatSymbol, getIsNativeToken, isAddress, tryParseCurrencyAmount } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { useENS } from '@cowprotocol/ens' +import { useTokenBySymbolOrAddress } from '@cowprotocol/tokens' +import { useAreThereTokensWithSameSymbol } from '@cowprotocol/tokens' import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' import { t } from '@lingui/macro' -import { useCurrency } from 'legacy/hooks/Tokens' import { PriceImpact } from 'legacy/hooks/usePriceImpact' import { AppState } from 'legacy/state' import { useAppDispatch, useAppSelector } from 'legacy/state/hooks' @@ -26,9 +27,7 @@ import { useCurrencyBalances } from 'modules/tokens/hooks/useCurrencyBalance' import { useNavigateOnCurrencySelection } from 'modules/trade/hooks/useNavigateOnCurrencySelection' import { useTradeNavigate } from 'modules/trade/hooks/useTradeNavigate' -import { useAreThereTokensWithSameSymbol } from 'common/hooks/useAreThereTokensWithSameSymbol' import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported' -import { useTokenBySymbolOrAddress } from 'common/hooks/useTokenBySymbolOrAddress' import { useSwapSlippage } from './useSwapSlippage' @@ -243,10 +242,14 @@ export function useDerivedSwapInfo(): DerivedSwapInfo { // TODO: be careful! For native tokens we use symbol instead of address const currenciesIds: { [field in Field]?: string | null } = useMemo( () => ({ - [Field.INPUT]: currencies.INPUT?.isNative ? currencies.INPUT.symbol : currencies.INPUT?.address?.toLowerCase(), - [Field.OUTPUT]: currencies.OUTPUT?.isNative - ? currencies.OUTPUT.symbol - : currencies.OUTPUT?.address?.toLowerCase(), + [Field.INPUT]: + currencies.INPUT && getIsNativeToken(currencies.INPUT) + ? currencies.INPUT.symbol + : currencies.INPUT?.address?.toLowerCase(), + [Field.OUTPUT]: + currencies.OUTPUT && getIsNativeToken(currencies.OUTPUT) + ? currencies.OUTPUT.symbol + : currencies.OUTPUT?.address?.toLowerCase(), }), [currencies] ) @@ -374,7 +377,7 @@ export function useIsFeeGreaterThanInput({ fee: CurrencyAmount | null } { const quote = useQuote({ chainId, token: address }) - const feeToken = useCurrency(address) + const feeToken = useTokenBySymbolOrAddress(address) if (!quote || !feeToken) return { isFeeGreater: false, fee: null } diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/index.cosmos.tsx index 4745047b58..eaa91def2e 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/index.cosmos.tsx @@ -1,13 +1,13 @@ -import { GpEther } from '@cowprotocol/common-const' +import { NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const' +import { getWrappedToken } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { Token } from '@uniswap/sdk-core' import { EthFlowBannerContent, EthFlowBannerContentProps } from '.' const defaultProps: EthFlowBannerContentProps = { - native: GpEther.onChain(SupportedChainId.MAINNET), + native: NATIVE_CURRENCY_BUY_TOKEN[SupportedChainId.MAINNET], get wrapped() { - return this.native.wrapped as Token & { logoURI: string } + return getWrappedToken(this.native) }, showBanner: true, hasEnoughWrappedBalance: false, diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/WrapCard.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/WrapCard.tsx index ec22db099c..d0bc338d25 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/WrapCard.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/WrapCard.tsx @@ -1,39 +1,22 @@ -import { CHAIN_INFO, WRAPPED_NATIVE_CURRENCY } from '@cowprotocol/common-const' -import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { TokenLogo } from '@cowprotocol/tokens' import { TokenAmount } from '@cowprotocol/ui' import { CurrencyAmount, Currency } from '@uniswap/sdk-core' -import styled from 'styled-components/macro' - -import { WrappedTokenInfo } from 'legacy/state/lists/wrappedTokenInfo' - import * as styledEl from 'modules/swap/pure/EthFlow/WrappingPreview/styled' -import { CurrencyLogo } from 'common/pure/CurrencyLogo' - -const BackupTokenImg = styled.img.attrs((attrs) => ({ ...attrs, width: '24px' }))` - filter: invert(1); -` - interface WrapCardProps { currency: Currency balance?: CurrencyAmount amountToWrap?: CurrencyAmount - chainId?: SupportedChainId } export function WrapCard(props: WrapCardProps) { - const { balance, amountToWrap, currency, chainId } = props - const hasLogoUri = currency.isNative || Boolean(currency instanceof WrappedTokenInfo && currency.logoURI) + const { balance, amountToWrap, currency } = props return ( {/* logo */} - {!hasLogoUri && chainId && currency.equals(WRAPPED_NATIVE_CURRENCY[chainId]) ? ( - - ) : ( - - )} + {/* amount to wrap/unwrap */} diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/WrappingPreview.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/WrappingPreview.tsx index 77ead3c51e..f9d1f1ac32 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/WrappingPreview.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/WrappingPreview.tsx @@ -15,21 +15,20 @@ export type WrappingPreviewProps = { wrapped: Currency wrappedBalance: CurrencyAmount | undefined amount: CurrencyAmount | undefined - chainId?: number } export const WrappingPreview = (props: WrappingPreviewProps) => { - const { nativeBalance, native, wrapped, wrappedBalance, amount, chainId } = props + const { nativeBalance, native, wrapped, wrappedBalance, amount } = props return ( {/* To Wrap */} - + {/* Wrap Outcome */} - + ) } diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/styled.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/styled.tsx index e85f4b6ab5..0beee256d8 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/styled.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/styled.tsx @@ -9,9 +9,7 @@ export const WrapCardWrapper = styled.div` flex: 1; padding: 16px; - > img { - width: 42px; - height: 42px; + > div { margin: 0 0 14px; box-shadow: none; } diff --git a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowFeeContent/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowFeeContent/index.cosmos.tsx index e843ec7148..af5d129e00 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowFeeContent/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowFeeContent/index.cosmos.tsx @@ -1,4 +1,5 @@ import { COW, GNO } from '@cowprotocol/common-const' +import { currencyAmountToTokenAmount } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { CurrencyAmount, TradeType, Price } from '@uniswap/sdk-core' @@ -30,7 +31,7 @@ const defaultProps: RowFeeProps & RowFeeContentProps = { feeUsd: '(≈$42.93)', feeCurrencySymbol: 'GNO', get feeFiatValue() { - return this.fee?.multiply('100').wrapped || null + return currencyAmountToTokenAmount(this.fee?.multiply('100')) || null }, get feeToken() { return (this.fee?.toExact() || '-') + ' ' + this.feeCurrencySymbol diff --git a/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.tsx index 8605cc9de6..13f31c7ec3 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.tsx @@ -1,7 +1,7 @@ import React, { ReactNode } from 'react' -import { GpEther } from '@cowprotocol/common-const' -import { genericPropsChecker } from '@cowprotocol/common-utils' +import { NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const' +import { genericPropsChecker, getWrappedToken } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { AutoRow, ButtonError, ButtonPrimary, ButtonSize, TokenSymbol } from '@cowprotocol/ui' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' @@ -72,8 +72,8 @@ const swapButtonStateMap: { [key in SwapButtonState]: (props: SwapButtonsContext [SwapButtonState.TransferToSmartContract]: (props: SwapButtonsContext) => ( - Buying {GpEther.onChain(props.chainId || SupportedChainId.MAINNET).symbol} with smart contract wallets is not - currently supported + Buying {NATIVE_CURRENCY_BUY_TOKEN[(props.chainId as SupportedChainId) || SupportedChainId.MAINNET].symbol} with + smart contract wallets is not currently supported ), @@ -150,7 +150,14 @@ const swapButtonStateMap: { [key in SwapButtonState]: (props: SwapButtonsContext - Approve {} and Swap + Approve  + { + + } +  and Swap @@ -159,7 +166,14 @@ const swapButtonStateMap: { [key in SwapButtonState]: (props: SwapButtonsContext - Confirm (Approve {} and Swap) + Confirm (Approve  + { + + } +  and Swap) diff --git a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/mocks.ts b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/mocks.ts index 669903f979..2bc0d19c6a 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/mocks.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/mocks.ts @@ -1,4 +1,4 @@ -import { nativeOnChain, WRAPPED_NATIVE_CURRENCY as WETH } from '@cowprotocol/common-const' +import { NATIVE_CURRENCY_BUY_TOKEN, WRAPPED_NATIVE_CURRENCY as WETH } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { CurrencyAmount } from '@uniswap/sdk-core' @@ -9,7 +9,7 @@ import { WrappingPreviewProps } from 'modules/swap/pure/EthFlow/WrappingPreview' import { EthFlowState } from 'modules/swap/services/ethFlow/types' import { defaultEthFlowContext, EthFlowActionContext } from 'modules/swap/state/EthFlow/ethFlowContextAtom' -const native = nativeOnChain(SupportedChainId.GOERLI) +const native = NATIVE_CURRENCY_BUY_TOKEN[SupportedChainId.GOERLI] const wrapped = WETH[SupportedChainId.GOERLI] const nativeInput = CurrencyAmount.fromRawAmount(native, 5.987654 * 10 ** 18) const nativeBalance = CurrencyAmount.fromRawAmount(native, 15.12123 * 10 ** 18) diff --git a/apps/cowswap-frontend/src/modules/tokens/hooks/useCurrencyBalance.ts b/apps/cowswap-frontend/src/modules/tokens/hooks/useCurrencyBalance.ts index f2a4d6ad19..2e5df074c4 100644 --- a/apps/cowswap-frontend/src/modules/tokens/hooks/useCurrencyBalance.ts +++ b/apps/cowswap-frontend/src/modules/tokens/hooks/useCurrencyBalance.ts @@ -2,9 +2,9 @@ import { useMemo } from 'react' -import { nativeOnChain } from '@cowprotocol/common-const' +import { NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const' import { useInterfaceMulticall } from '@cowprotocol/common-hooks' -import { isAddress } from '@cowprotocol/common-utils' +import { getIsNativeToken, isAddress } from '@cowprotocol/common-utils' import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' @@ -17,6 +17,7 @@ import { useSingleContractMultipleData } from 'lib/hooks/multicall' // TODO: Move this hooks to some other module. It doens't belong with the tokens /** + * @deprecated Use useNativeBalance instead * Returns a map of the given addresses to their eventually consistent ETH balances. */ export function useNativeCurrencyBalances( @@ -48,7 +49,7 @@ export function useNativeCurrencyBalances( const value = results?.[i]?.result?.[0] if (value && chainId) memo[lowerCaseAddress ? address.toLowerCase() : address] = CurrencyAmount.fromRawAmount( - nativeOnChain(chainId), + NATIVE_CURRENCY_BUY_TOKEN[chainId], JSBI.BigInt(value.toString()) ) return memo @@ -88,21 +89,24 @@ export function useCurrencyBalances( currencies?: (Currency | undefined | null)[] ): (CurrencyAmount | undefined)[] { const tokens = useMemo( - () => currencies?.filter((currency): currency is Token => currency?.isToken ?? false) ?? [], + () => currencies?.filter((currency): currency is Token => (currency && !getIsNativeToken(currency)) ?? false) ?? [], [currencies] ) const tokenBalances = useTokenBalances(account, tokens) - const containsETH: boolean = useMemo(() => currencies?.some((currency) => currency?.isNative) ?? false, [currencies]) + const containsETH: boolean = useMemo( + () => currencies?.some((currency) => currency && getIsNativeToken(currency)) ?? false, + [currencies] + ) const ethBalance = useNativeCurrencyBalances(useMemo(() => (containsETH ? [account] : []), [containsETH, account])) return useMemo( () => currencies?.map((currency) => { if (!account || !currency) return undefined - if (currency.isToken) return tokenBalances[currency.address]?.value - if (currency.isNative) return ethBalance[account] - return undefined + if (getIsNativeToken(currency)) return ethBalance[account] + + return tokenBalances[currency.address]?.value }) ?? [], [account, currencies, ethBalance, tokenBalances] ) diff --git a/apps/cowswap-frontend/src/modules/tokens/hooks/useEnoughBalance.ts b/apps/cowswap-frontend/src/modules/tokens/hooks/useEnoughBalance.ts index e3fb3eeb8e..170c9a44e7 100644 --- a/apps/cowswap-frontend/src/modules/tokens/hooks/useEnoughBalance.ts +++ b/apps/cowswap-frontend/src/modules/tokens/hooks/useEnoughBalance.ts @@ -1,4 +1,4 @@ -import { isEnoughAmount, getAddress } from '@cowprotocol/common-utils' +import { isEnoughAmount, getAddress, getIsNativeToken, getWrappedToken } from '@cowprotocol/common-utils' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' import useNativeCurrency from 'lib/hooks/useNativeCurrency' @@ -39,8 +39,8 @@ const DEFAULT_BALANCE_AND_ALLOWANCE = { enoughBalance: undefined, enoughAllowanc */ export function useEnoughBalanceAndAllowance(params: UseEnoughBalanceParams): UseEnoughBalanceAndAllowanceResult { const { account, amount, checkAllowanceAddress } = params - const isNativeCurrency = amount?.currency.isNative - const token = amount?.currency.wrapped + const isNativeCurrency = !!amount?.currency && getIsNativeToken(amount?.currency) + const token = amount?.currency && getWrappedToken(amount.currency) const { balances, allowances } = useBalancesAndAllowances({ account, @@ -88,8 +88,8 @@ export function hasEnoughBalanceAndAllowance(params: EnoughBalanceParams): UseEn return DEFAULT_BALANCE_AND_ALLOWANCE } - const isNativeCurrency = amount?.currency.isNative - const token = amount?.currency.wrapped + const isNativeCurrency = !!amount?.currency && getIsNativeToken(amount?.currency) + const token = amount?.currency && getWrappedToken(amount.currency) const tokenAddress = getAddress(token) const enoughBalance = _enoughBalance(tokenAddress, amount, balances, isNativeCurrency, nativeBalance) diff --git a/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/TradeWidgetModals.tsx b/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/TradeWidgetModals.tsx index 930b93fc6b..dcb6caa78e 100644 --- a/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/TradeWidgetModals.tsx +++ b/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/TradeWidgetModals.tsx @@ -1,24 +1,25 @@ import React from 'react' -import { useWalletInfo } from '@cowprotocol/wallet' +import { AutoImportTokens, SelectTokenWidget } from 'modules/tokensList' -import { ImportTokenModal } from 'common/containers/ImportTokenModal' import { TradeApproveModal } from 'common/containers/TradeApprove' import { ZeroApprovalModal } from 'common/containers/ZeroApprovalModal' import { useShouldZeroApprove } from 'common/hooks/useShouldZeroApprove' import { useDerivedTradeState } from '../../hooks/useDerivedTradeState' +import { useTradeState } from '../../hooks/useTradeState' export function TradeWidgetModals() { - const { chainId } = useWalletInfo() + const { state: rawState } = useTradeState() const { state } = useDerivedTradeState() const shouldZeroApprove = useShouldZeroApprove(state?.slippageAdjustedSellAmount) return ( <> - {chainId && } + {shouldZeroApprove && } + ) } diff --git a/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/index.tsx b/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/index.tsx index bb5f1d3dcc..33d2df29b6 100644 --- a/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/index.tsx @@ -9,6 +9,7 @@ import { PriceImpact } from 'legacy/hooks/usePriceImpact' import { TradeWidgetLinks } from 'modules/application/containers/TradeWidgetLinks' import { SetRecipientProps } from 'modules/swap/containers/SetRecipient' +import { useOpenTokenSelectWidget } from 'modules/tokensList' import { useIsWrapOrUnwrap } from 'modules/trade/hooks/useIsWrapOrUnwrap' import { RecipientAddressUpdater } from 'modules/trade/updaters/RecipientAddressUpdater' import { TradeFormValidationUpdater } from 'modules/tradeFormValidation' @@ -38,7 +39,6 @@ export interface TradeWidgetActions { interface TradeWidgetParams { recipient: string | null - disableNonToken?: boolean isEoaEthFlow?: boolean compactView: boolean showRecipient: boolean @@ -80,7 +80,6 @@ export function TradeWidget(props: TradeWidgetProps) { showRecipient, isTradePriceUpdating, isEoaEthFlow = false, - disableNonToken = false, priceImpact, recipient, disableQuotePolling = false, @@ -94,6 +93,7 @@ export function TradeWidget(props: TradeWidgetProps) { const { allowsOffchainSigning } = useWalletDetails() const isChainIdUnsupported = useIsProviderNetworkUnsupported() const isSafeWallet = useIsSafeWallet() + const openTokenSelectWidget = useOpenTokenSelectWidget() const currenciesLoadingInProgress = !inputCurrencyInfo.currency && !outputCurrencyInfo.currency @@ -106,12 +106,12 @@ export function TradeWidget(props: TradeWidgetProps) { const currencyInputCommonProps = { isChainIdUnsupported, - disableNonToken, chainId, areCurrenciesLoading: currenciesLoadingInProgress, onCurrencySelection, onUserInput, allowsOffchainSigning, + openTokenSelectWidget, } /** diff --git a/apps/cowswap-frontend/src/modules/trade/containers/WrapNativeModal/index.tsx b/apps/cowswap-frontend/src/modules/trade/containers/WrapNativeModal/index.tsx index cdafbb4479..fd9ac2d692 100644 --- a/apps/cowswap-frontend/src/modules/trade/containers/WrapNativeModal/index.tsx +++ b/apps/cowswap-frontend/src/modules/trade/containers/WrapNativeModal/index.tsx @@ -1,6 +1,7 @@ import { useAtom } from 'jotai' import { useCallback } from 'react' +import { getIsNativeToken } from '@cowprotocol/common-utils' import { TokenAmount, TokenSymbol } from '@cowprotocol/ui' import { useWalletDisplayedAddress } from '@cowprotocol/wallet' @@ -25,7 +26,7 @@ export function WrapNativeModal() { }, [setWrapNativeState]) const inputCurrency = inputCurrencyAmount?.currency - const isNativeIn = !!inputCurrency?.isNative + const isNativeIn = !!inputCurrency && getIsNativeToken(inputCurrency) const title = isNativeIn ? ( diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useResetStateWithSymbolDuplication.ts b/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useResetStateWithSymbolDuplication.ts index db2c485178..5fcf2dfbb8 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useResetStateWithSymbolDuplication.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useResetStateWithSymbolDuplication.ts @@ -1,11 +1,10 @@ import { useEffect } from 'react' +import { useAreThereTokensWithSameSymbol } from '@cowprotocol/tokens' import { useWalletInfo } from '@cowprotocol/wallet' import { t } from '@lingui/macro' -import { useAreThereTokensWithSameSymbol } from 'common/hooks/useAreThereTokensWithSameSymbol' - import { getDefaultTradeRawState, TradeRawState } from '../../types/TradeRawState' import { useTradeNavigate } from '../useTradeNavigate' diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useBuildTradeDerivedState.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useBuildTradeDerivedState.ts index 27140cdd8d..641be06795 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/useBuildTradeDerivedState.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/useBuildTradeDerivedState.ts @@ -1,6 +1,7 @@ import { Atom, useAtomValue } from 'jotai' import { tryParseFractionalAmount } from '@cowprotocol/common-utils' +import { useTokenBySymbolOrAddress } from '@cowprotocol/tokens' import { useWalletInfo } from '@cowprotocol/wallet' import useCurrencyBalance from 'modules/tokens/hooks/useCurrencyBalance' @@ -8,7 +9,6 @@ import { ExtendedTradeRawState } from 'modules/trade/types/TradeRawState' import { useTradeUsdAmounts } from 'modules/usdAmount' import { useSafeMemoObject } from 'common/hooks/useSafeMemo' -import { useTokenBySymbolOrAddress } from 'common/hooks/useTokenBySymbolOrAddress' export function useBuildTradeDerivedState(stateAtom: Atom) { const { account } = useWalletInfo() diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useNativeTokenContext.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useNativeTokenContext.ts index e34e2bedbe..1db1aed8fe 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/useNativeTokenContext.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/useNativeTokenContext.ts @@ -1,5 +1,7 @@ import { useMemo } from 'react' +import { getWrappedToken } from '@cowprotocol/common-utils' + import useNativeCurrency from 'lib/hooks/useNativeCurrency' import { useIsNativeIn, useIsNativeOut } from './useIsNativeInOrOut' @@ -7,7 +9,7 @@ import { useIsWrappedIn, useIsWrappedOut } from './useIsWrappedInOrOut' export function useNativeTokenContext() { const native = useNativeCurrency() - const wrappedToken = native.wrapped + const wrappedToken = getWrappedToken(native) const isNativeIn = useIsNativeIn() const isNativeOut = useIsNativeOut() diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useNavigateOnCurrencySelection.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useNavigateOnCurrencySelection.ts index 1df5d47bd7..6edad21866 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/useNavigateOnCurrencySelection.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/useNavigateOnCurrencySelection.ts @@ -1,5 +1,6 @@ import { useCallback } from 'react' +import { useAreThereTokensWithSameSymbol } from '@cowprotocol/tokens' import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, Token } from '@uniswap/sdk-core' @@ -8,8 +9,6 @@ import { Field } from 'legacy/state/types' import { useTradeNavigate } from 'modules/trade/hooks/useTradeNavigate' import { useTradeState } from 'modules/trade/hooks/useTradeState' -import { useAreThereTokensWithSameSymbol } from 'common/hooks/useAreThereTokensWithSameSymbol' - export type CurrencySelectionCallback = ( field: Field, currency: Currency | null, diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useWrappedToken.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useWrappedToken.ts index 6cf2cc53cc..3a3b9bc84a 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/useWrappedToken.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/useWrappedToken.ts @@ -1,7 +1,8 @@ +import { getWrappedToken } from '@cowprotocol/common-utils' import { Token } from '@uniswap/sdk-core' import useNativeCurrency from 'lib/hooks/useNativeCurrency' export function useWrappedToken(): Token { - return useNativeCurrency().wrapped + return getWrappedToken(useNativeCurrency()) } diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts index 1c1d9ce845..003bd0cc33 100644 --- a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts +++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts @@ -1,10 +1,9 @@ import { useMemo } from 'react' import { useENSAddress } from '@cowprotocol/ens' +import { useIsTradeUnsupported } from '@cowprotocol/tokens' import { useGnosisSafeInfo, useIsBundlingSupported, useWalletDetails, useWalletInfo } from '@cowprotocol/wallet' -import { useIsTradeUnsupported } from 'legacy/state/lists/hooks' - import { isUnsupportedTokenInQuote } from 'modules/limitOrders/utils/isUnsupportedTokenInQuote' import { useIsTokenPermittable } from 'modules/permit' import { useDerivedTradeState } from 'modules/trade/hooks/useDerivedTradeState' diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/pure/TradeFormButtons/tradeButtonsMap.tsx b/apps/cowswap-frontend/src/modules/tradeFormValidation/pure/TradeFormButtons/tradeButtonsMap.tsx index af472af4f5..5c917f3495 100644 --- a/apps/cowswap-frontend/src/modules/tradeFormValidation/pure/TradeFormButtons/tradeButtonsMap.tsx +++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/pure/TradeFormButtons/tradeButtonsMap.tsx @@ -1,5 +1,6 @@ import React from 'react' +import { getIsNativeToken, getWrappedToken } from '@cowprotocol/common-utils' import { TokenSymbol } from '@cowprotocol/ui' import { Trans } from '@lingui/macro' @@ -60,7 +61,7 @@ const unsupportedTokenButton = (context: TradeFormButtonContext) => { export const tradeButtonsMap: Record = { [TradeFormValidation.WrapUnwrapFlow]: (context) => { - const isNativeIn = !!context.derivedState.inputCurrency?.isNative + const isNativeIn = !!context.derivedState.inputCurrency && getIsNativeToken(context.derivedState.inputCurrency) return ( context.wrapNativeFlow()}> @@ -121,7 +122,8 @@ export const tradeButtonsMap: Record { - const tokenToApprove = context.derivedState.slippageAdjustedSellAmount?.currency.wrapped + const currency = context.derivedState.slippageAdjustedSellAmount?.currency + const tokenToApprove = currency && getWrappedToken(currency) return ( @@ -132,7 +134,8 @@ export const tradeButtonsMap: Record { - const tokenToApprove = context.derivedState.slippageAdjustedSellAmount?.currency.wrapped + const currency = context.derivedState.slippageAdjustedSellAmount?.currency + const tokenToApprove = currency && getWrappedToken(currency) return ( diff --git a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useProcessUnsupportedTokenError.ts b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useProcessUnsupportedTokenError.ts index 6bd3d9a61e..3759bbf63a 100644 --- a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useProcessUnsupportedTokenError.ts +++ b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useProcessUnsupportedTokenError.ts @@ -1,28 +1,21 @@ import { useCallback } from 'react' import { getQuoteUnsupportedToken } from '@cowprotocol/common-utils' -import { useWalletInfo } from '@cowprotocol/wallet' - -import { useAddGpUnsupportedToken } from 'legacy/state/lists/hooks' +import { useAddUnsupportedToken } from '@cowprotocol/tokens' import GpQuoteError from 'api/gnosisProtocol/errors/QuoteError' export function useProcessUnsupportedTokenError() { - const { chainId } = useWalletInfo() - const addGpUnsupportedToken = useAddGpUnsupportedToken() + const addGpUnsupportedToken = useAddUnsupportedToken() return useCallback( (error: GpQuoteError, quoteParams: { sellToken: string; buyToken: string }) => { const unsupportedTokenAddress = getQuoteUnsupportedToken(error, quoteParams) if (unsupportedTokenAddress) { - addGpUnsupportedToken({ - chainId, - dateAdded: Date.now(), - address: unsupportedTokenAddress || '', - }) + addGpUnsupportedToken(unsupportedTokenAddress) } }, - [chainId, addGpUnsupportedToken] + [addGpUnsupportedToken] ) } diff --git a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useQuoteParams.ts b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useQuoteParams.ts index bec2b7f889..993b8bf68c 100644 --- a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useQuoteParams.ts +++ b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useQuoteParams.ts @@ -1,7 +1,7 @@ import { useMemo } from 'react' import { NATIVE_CURRENCY_BUY_ADDRESS } from '@cowprotocol/common-const' -import { getAddress } from '@cowprotocol/common-utils' +import { getAddress, getIsNativeToken } from '@cowprotocol/common-utils' import { useWalletInfo } from '@cowprotocol/wallet' import { CurrencyAmount } from '@uniswap/sdk-core' @@ -24,7 +24,8 @@ export function useQuoteParams(amount: string | null): LegacyFeeQuoteParams | un const { inputCurrency, outputCurrency, orderKind } = state || {} const sellToken = getAddress(inputCurrency) - const buyToken = outputCurrency?.isNative ? NATIVE_CURRENCY_BUY_ADDRESS : getAddress(outputCurrency) + const buyToken = + outputCurrency && getIsNativeToken(outputCurrency) ? NATIVE_CURRENCY_BUY_ADDRESS : getAddress(outputCurrency) const fromDecimals = inputCurrency?.decimals const toDecimals = outputCurrency?.decimals diff --git a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.ts b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.ts index baf4ce96e2..cf884e138f 100644 --- a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.ts +++ b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.ts @@ -4,11 +4,10 @@ import { useLayoutEffect, useMemo } from 'react' import { useDebounce } from '@cowprotocol/common-hooks' import { onlyResolvesLast } from '@cowprotocol/common-utils' import { OrderQuoteResponse } from '@cowprotocol/cow-sdk' +import { useIsUnsupportedTokens } from '@cowprotocol/tokens' import ms from 'ms.macro' -import { useIsUnsupportedTokens } from 'legacy/state/lists/hooks' - import { useUpdateCurrencyAmount } from 'modules/trade/hooks/useUpdateCurrencyAmount' import { updateTradeQuoteAtom } from 'modules/tradeQuote/state/tradeQuoteAtom' diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedPartOrders.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedPartOrders.ts index a8736ee5f8..6293084099 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedPartOrders.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedPartOrders.ts @@ -2,13 +2,12 @@ import { useAtomValue } from 'jotai' import { useMemo } from 'react' import { useMachineTimeMs } from '@cowprotocol/common-hooks' +import { TokensByAddress } from '@cowprotocol/tokens' import ms from 'ms.macro' import { Order } from 'legacy/state/orders/actions' -import { TokensByAddress } from 'modules/tokensList/state/tokensListAtom' - import { twapOrdersAtom, TwapOrdersList } from '../state/twapOrdersListAtom' import { TwapPartOrderItem, twapPartOrdersListAtom } from '../state/twapPartOrdersAtom' import { emulatePartAsOrder } from '../utils/emulatePartAsOrder' diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedTwapOrders.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedTwapOrders.ts index 17dc8e82f9..210fc69db8 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedTwapOrders.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedTwapOrders.ts @@ -2,14 +2,13 @@ import { useAtomValue } from 'jotai' import { useMemo } from 'react' import { useMachineTimeMs } from '@cowprotocol/common-hooks' +import { TokensByAddress } from '@cowprotocol/tokens' import { useWalletInfo } from '@cowprotocol/wallet' import ms from 'ms.macro' import { Order } from 'legacy/state/orders/actions' -import { TokensByAddress } from 'modules/tokensList/state/tokensListAtom' - import { twapOrdersListAtom } from '../state/twapOrdersListAtom' import { mapTwapOrderToStoreOrder } from '../utils/mapTwapOrderToStoreOrder' diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersTokens.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersTokens.ts index 97a1c901f7..733af5b5b5 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersTokens.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersTokens.ts @@ -1,10 +1,11 @@ import { useAtomValue } from 'jotai/index' import { useMemo } from 'react' +import { TokensByAddress } from '@cowprotocol/tokens' + import { useAsyncMemo } from 'use-async-memo' import { useTokensForOrdersList, getTokensListFromOrders } from 'modules/orders' -import { TokensByAddress } from 'modules/tokensList/state/tokensListAtom' import { twapOrdersListAtom } from '../state/twapOrdersListAtom' import { twapPartOrdersListAtom } from '../state/twapPartOrdersAtom' diff --git a/apps/cowswap-frontend/src/modules/twap/utils/mapPartOrderToStoreOrder.ts b/apps/cowswap-frontend/src/modules/twap/utils/mapPartOrderToStoreOrder.ts index 3cfbea976b..1a5989c00a 100644 --- a/apps/cowswap-frontend/src/modules/twap/utils/mapPartOrderToStoreOrder.ts +++ b/apps/cowswap-frontend/src/modules/twap/utils/mapPartOrderToStoreOrder.ts @@ -1,10 +1,8 @@ import { EnrichedOrder } from '@cowprotocol/cow-sdk' +import { TokensByAddress } from '@cowprotocol/tokens' import { Order } from 'legacy/state/orders/actions' -import { TokensByAddress } from 'modules/tokensList/state/tokensListAtom' -import { getTokensByAddress } from 'modules/tokensList/utils/getTokensByAddress' - import { computeOrderSummary } from 'common/updaters/orders/utils' import { getIsLastPartOrder } from './getIsLastPartOrder' @@ -20,7 +18,6 @@ export function mapPartOrderToStoreOrder( parent: TwapOrderItem, tokensByAddress: TokensByAddress ): Order { - const chainId = item.chainId const isCancelling = item.isCancelling || parent.status === TwapOrderStatus.Cancelling const status = getPartOrderStatus(enrichedOrder, parent, isVirtualPart) @@ -33,8 +30,8 @@ export function mapPartOrderToStoreOrder( parentId: parent.id, }, sellAmountBeforeFee: enrichedOrder.sellAmount, - inputToken: getTokensByAddress(chainId, enrichedOrder.sellToken, tokensByAddress), - outputToken: getTokensByAddress(chainId, enrichedOrder.buyToken, tokensByAddress), + inputToken: tokensByAddress[enrichedOrder.sellToken.toLowerCase()], + outputToken: tokensByAddress[enrichedOrder.buyToken.toLowerCase()], creationTime: enrichedOrder.creationDate, summary: '', status, diff --git a/apps/cowswap-frontend/src/modules/twap/utils/mapTwapOrderToStoreOrder.ts b/apps/cowswap-frontend/src/modules/twap/utils/mapTwapOrderToStoreOrder.ts index 76f943c32e..d9d04035ae 100644 --- a/apps/cowswap-frontend/src/modules/twap/utils/mapTwapOrderToStoreOrder.ts +++ b/apps/cowswap-frontend/src/modules/twap/utils/mapTwapOrderToStoreOrder.ts @@ -1,7 +1,6 @@ -import { Order, OrderStatus } from 'legacy/state/orders/actions' +import { TokensByAddress } from '@cowprotocol/tokens' -import { TokensByAddress } from 'modules/tokensList/state/tokensListAtom' -import { getTokensByAddress } from 'modules/tokensList/utils/getTokensByAddress' +import { Order, OrderStatus } from 'legacy/state/orders/actions' import { computeOrderSummary } from 'common/updaters/orders/utils' @@ -29,8 +28,8 @@ export function mapTwapOrderToStoreOrder(order: TwapOrderItem, tokensByAddress: id: order.id, }, sellAmountBeforeFee: enrichedOrder.sellAmount, - inputToken: getTokensByAddress(order.chainId, enrichedOrder.sellToken, tokensByAddress), - outputToken: getTokensByAddress(order.chainId, enrichedOrder.buyToken, tokensByAddress), + inputToken: tokensByAddress[enrichedOrder.sellToken.toLowerCase()], + outputToken: tokensByAddress[enrichedOrder.buyToken.toLowerCase()], creationTime: enrichedOrder.creationDate, summary: '', status, diff --git a/apps/cowswap-frontend/src/modules/twap/utils/twapOrderToStruct.ts b/apps/cowswap-frontend/src/modules/twap/utils/twapOrderToStruct.ts index 8e33c2ed95..944d9d9f4f 100644 --- a/apps/cowswap-frontend/src/modules/twap/utils/twapOrderToStruct.ts +++ b/apps/cowswap-frontend/src/modules/twap/utils/twapOrderToStruct.ts @@ -1,4 +1,5 @@ import { NATIVE_CURRENCY_BUY_ADDRESS } from '@cowprotocol/common-const' +import { getIsNativeToken } from '@cowprotocol/common-utils' import { TWAPOrder, TWAPOrderStruct } from '../types' @@ -7,7 +8,7 @@ export function twapOrderToStruct(order: TWAPOrder): TWAPOrderStruct { return { sellToken: order.sellAmount.currency.address, - buyToken: buyToken.isNative ? NATIVE_CURRENCY_BUY_ADDRESS : buyToken.address, + buyToken: getIsNativeToken(buyToken) ? NATIVE_CURRENCY_BUY_ADDRESS : buyToken.address, receiver: order.receiver, partSellAmount: order.sellAmount.divide(order.numOfParts).quotient.toString(), minPartLimit: order.buyAmount.divide(order.numOfParts).quotient.toString(), diff --git a/apps/cowswap-frontend/src/modules/wallet/containers/AddToMetamask/index.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/AddToMetamask/index.tsx index fc8aa550e9..153b3d40b4 100644 --- a/apps/cowswap-frontend/src/modules/wallet/containers/AddToMetamask/index.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/containers/AddToMetamask/index.tsx @@ -1,12 +1,13 @@ import React, { useCallback, useState } from 'react' import { addTokenToMetamaskAnalytics } from '@cowprotocol/analytics' +import { TokenWithLogo } from '@cowprotocol/common-const' +import { getWrappedToken } from '@cowprotocol/common-utils' +import { getTokenLogoUrls } from '@cowprotocol/tokens' import { getIsMetaMask } from '@cowprotocol/wallet' import { Currency } from '@uniswap/sdk-core' import { useWeb3React } from '@web3-react/core' -import useCurrencyLogoURIs from 'common/pure/CurrencyLogo/hooks/useCurrencyLogoURIs' - import { AddToMetamask as AddToMetamaskPure } from '../../pure/AddToMetamask' export type AddToMetamaskProps = { @@ -22,8 +23,8 @@ export function AddToMetamask(props: AddToMetamaskProps) { const [success, setSuccess] = useState() - const token = currency?.wrapped - const logoURL = useCurrencyLogoURIs(token)[0] + const token = currency && getWrappedToken(currency) + const logoURL = getTokenLogoUrls(token as TokenWithLogo)[0] const addToken = useCallback(() => { if (!token?.symbol || !connector.watchAsset) return diff --git a/apps/cowswap-frontend/src/modules/wallet/state/followPendingTxPopupAtom.ts b/apps/cowswap-frontend/src/modules/wallet/state/followPendingTxPopupAtom.ts index 58be234eb6..8920fd994f 100644 --- a/apps/cowswap-frontend/src/modules/wallet/state/followPendingTxPopupAtom.ts +++ b/apps/cowswap-frontend/src/modules/wallet/state/followPendingTxPopupAtom.ts @@ -1,8 +1,6 @@ import { atom } from 'jotai' import { atomWithStorage, selectAtom } from 'jotai/utils' -import { OrderID } from 'api/gnosisProtocol' - type FollowPendingTxPopup = { showPopup: boolean lastOrderPopupClosed: string | undefined @@ -26,7 +24,7 @@ export const handleHidePopupPermanentlyAtom = atom(null, (_get, set, hidePopupPe set(followPendingTxPopupAtom, (prev) => ({ ...prev, hidePopupPermanently })) }) -export const handleCloseOrderPopupAtom = atom(null, (_get, set, orderIdClosed: OrderID) => { +export const handleCloseOrderPopupAtom = atom(null, (_get, set, orderIdClosed: string) => { set(followPendingTxPopupAtom, (prev) => ({ ...prev, lastOrderPopupClosed: orderIdClosed })) }) diff --git a/apps/cowswap-frontend/src/pages/Account/Tokens/TokensOverview.tsx b/apps/cowswap-frontend/src/pages/Account/Tokens/TokensOverview.tsx index cdcfa8efb1..5d4b04e347 100644 --- a/apps/cowswap-frontend/src/pages/Account/Tokens/TokensOverview.tsx +++ b/apps/cowswap-frontend/src/pages/Account/Tokens/TokensOverview.tsx @@ -1,22 +1,20 @@ import { useEffect, useMemo, useState, useCallback, useRef, ChangeEventHandler } from 'react' +import { TokenWithLogo } from '@cowprotocol/common-const' import { useDebounce, useOnClickOutside, usePrevious, useTheme } from '@cowprotocol/common-hooks' import { isAddress, isTruthy } from '@cowprotocol/common-utils' +import { useTokensByAddressMap, useFavouriteTokens, useResetFavouriteTokens } from '@cowprotocol/tokens' import { useWalletInfo } from '@cowprotocol/wallet' -import { Token } from '@uniswap/sdk-core' import { useWeb3React } from '@web3-react/core' import { Trans, t } from '@lingui/macro' import { Check } from 'react-feather' -import { ContentWrapper as SearchInputFormatter } from 'legacy/components/SearchModal/CurrencySearch' -import { TokenSearchInput } from 'legacy/components/Tokens/styled' import TokensTable from 'legacy/components/Tokens/TokensTable' -import { useAllTokenBalances, useAllTokens } from 'legacy/hooks/Tokens' -import { useFavouriteTokens, useRemoveAllFavouriteTokens, useInitFavouriteTokens } from 'legacy/state/user/hooks' import { CloseIcon } from 'legacy/theme' import { PageTitle } from 'modules/application/containers/PageTitle' +import { useAllTokensBalances } from 'modules/tokensList' import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported' @@ -31,6 +29,8 @@ import { LeftSection, ClearSearchInput, Overview, + SearchInputFormatter, + TokenSearchInput, } from './styled' import { CardsLoader, CardsSpinner } from '../styled' @@ -50,7 +50,6 @@ const PageView = { } export default function TokensOverview() { - useInitFavouriteTokens() const { chainId, account } = useWalletInfo() const { provider } = useWeb3React() @@ -67,16 +66,16 @@ export default function TokensOverview() { }, []) const theme = useTheme() - const allTokens = useAllTokens() + const allTokens = useTokensByAddressMap() const favouriteTokens = useFavouriteTokens() - const balances = useAllTokenBalances() + const balances = useAllTokensBalances() // search - takes precedence re:filtering const [query, setQuery] = useState('') const debouncedQuery = useDebounce(query, 300) const prevQuery = usePrevious(debouncedQuery) - const removeAllFavouriteTokens = useRemoveAllFavouriteTokens() + const removeAllFavouriteTokens = useResetFavouriteTokens() const isProviderNetworkUnsupported = useIsProviderNetworkUnsupported() const handleRestoreTokens = useCallback(() => { @@ -98,7 +97,7 @@ export default function TokensOverview() { useOnClickOutside(node, isMenuOpen ? toggleMenu : undefined) const renderTableContent = useCallback(() => { - let tokensData: Token[] = [] + let tokensData: TokenWithLogo[] = [] if (selectedView === PageViewKeys.ALL_TOKENS) { tokensData = formattedTokens diff --git a/apps/cowswap-frontend/src/pages/Account/Tokens/styled.ts b/apps/cowswap-frontend/src/pages/Account/Tokens/styled.ts index d4f614d7b0..a5ba67954c 100644 --- a/apps/cowswap-frontend/src/pages/Account/Tokens/styled.ts +++ b/apps/cowswap-frontend/src/pages/Account/Tokens/styled.ts @@ -2,6 +2,7 @@ import { transparentize, darken } from 'polished' import { ChevronDown } from 'react-feather' import styled from 'styled-components/macro' +import Column from 'legacy/components/Column' import { ThemedText } from 'legacy/theme' import { UI } from 'common/constants/theme' @@ -163,3 +164,73 @@ export const Overview = styled.div` } `}; ` + +export const SearchInputFormatter = styled(Column)` + width: 100%; + flex: 1 1 fit-content; + position: relative; + + > input { + border: none; + transition: background 0.3s ease-in-out; + background: var(${UI.COLOR_CONTAINER_BG_01}); + color: var(${UI.COLOR_TEXT1}); + } + + > input::placeholder { + font-size: 16px; + color: ${({ theme }) => transparentize(0.4, theme.text1)}; + } + + > input:focus::placeholder { + color: ${({ theme }) => transparentize(0.9, theme.text1)}; + } +` + +export const TokenSearchInput = styled.input` + margin: 0; + font-size: 14px; + max-width: 280px; + width: 100%; + align-self: flex-end; + box-shadow: none; + background: var(${UI.COLOR_GREY}); + border: 1px solid ${({ theme }) => theme.bg1}; + border-radius: 21px; + transition: background 0.2s ease-in-out, max-width 0.2s ease-in-out; + appearance: none; + height: 44px; + padding: 0 16px; + outline: 0; + + &:focus { + max-width: 500px; + background: var(${UI.COLOR_CONTAINER_BG_01}); + outline: 0; + + ${({ theme }) => theme.mediaWidth.upToMedium` + width: 100%; + `}; + } + + &::placeholder { + font-size: 14px !important; + color: ${({ theme }) => transparentize(0.5, theme.darkMode ? theme.white : theme.text1)}; + } + + &:focus::placeholder { + color: ${({ theme }) => transparentize(0.3, theme.darkMode ? theme.white : theme.text1)}; + } + + ${({ theme }) => theme.mediaWidth.upToMedium` + max-width: 100%; + `}; + + ${({ theme }) => theme.mediaWidth.upToSmall` + font-size: 12px !important; + + &::placeholder { + font-size: 12px !important; + } + `}; +` diff --git a/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/InvestOption.tsx b/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/InvestOption.tsx index aba0b53bd0..31100f06f6 100644 --- a/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/InvestOption.tsx +++ b/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/InvestOption.tsx @@ -9,6 +9,7 @@ import { tryParseCurrencyAmount, formatTokenAmount, formatSymbol, + getIsNativeToken, } from '@cowprotocol/common-utils' import { Loader, loadingOpacityMixin, ButtonSize, TokenAmount, ButtonConfirmed, Row } from '@cowprotocol/ui' import { useWalletInfo } from '@cowprotocol/wallet' @@ -122,7 +123,7 @@ export default function InvestOption({ claim, openModal, closeModal }: InvestOpt ) const token = currencyAmount?.currency - const isNative = token?.isNative + const isNative = !!token && getIsNativeToken(token) const balance = useCurrencyBalance(account || undefined, token) const gasPrice = useGasPrices(isNative ? chainId : undefined) diff --git a/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/index.tsx b/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/index.tsx index 0b48baa463..7cf6f14cc2 100644 --- a/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/index.tsx +++ b/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/index.tsx @@ -3,6 +3,7 @@ import { useEffect, useMemo } from 'react' import CowProtocolImage from '@cowprotocol/assets/cow-swap/cowprotocol.svg' import ImportantIcon from '@cowprotocol/assets/cow-swap/important.svg' import RoundArrow from '@cowprotocol/assets/cow-swap/round-arrow.svg' +import { currencyAmountToTokenAmount } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { ExternalLink } from '@cowprotocol/ui' import { useWalletInfo } from '@cowprotocol/wallet' @@ -109,7 +110,7 @@ function _calculateTotalVCow(allClaims: ClaimWithInvestmentData[]) { // Sum up all the vCowAmount being claimed return allClaims.reduce( - (total, { vCowAmount }) => total.add(vCowAmount?.wrapped || zeroVCow), + (total, { vCowAmount }) => total.add(currencyAmountToTokenAmount(vCowAmount) || zeroVCow), zeroVCow ) }