Token approval bundling
For your convenience, token approval and order placement will be bundled into a single transaction, streamlining
@@ -27,7 +32,7 @@ export type BundleTxWrapBannerProps = {
export function BundleTxWrapBanner({ nativeCurrencySymbol, wrappedCurrencySymbol }: BundleTxWrapBannerProps) {
return (
-
+
Token wrapping bundling
For your convenience, CoW Swap will bundle all the necessary actions for this trade into a single transaction.
@@ -49,7 +54,7 @@ export function BundleTxSafeWcBanner({ nativeCurrencySymbol, supportsWrapping }:
const supportsWrappingText = supportsWrapping ? `${nativeCurrencySymbol} wrapping, ` : ''
return (
-
+
Use Safe web app
Use the Safe web app for streamlined trading: {supportsWrappingText}token approval and orders bundled in one go!
@@ -82,3 +87,37 @@ export function SmallVolumeWarningBanner({ feePercentage, feeAmount }: SmallVolu
)
}
+
+type CustomRecipientBannerProps = InlineBannerProps & { onDismiss?: () => void }
+
+export function CustomRecipientWarningBanner({
+ bannerType,
+ borderRadius,
+ orientation,
+ iconSize = 21,
+ iconPadding = '0',
+ padding = '10px 16px',
+ onDismiss,
+}: CustomRecipientBannerProps) {
+ const handleDismiss = () => onDismiss?.()
+
+ return (
+
+
+ Caution: Order recipient address differs from order owner!
+
+ {onDismiss && (
+
+ Dismiss
+
+ )}
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/common/pure/InlineBanner/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/InlineBanner/index.cosmos.tsx
index f1ea3565a3..76693c91e5 100644
--- a/apps/cowswap-frontend/src/common/pure/InlineBanner/index.cosmos.tsx
+++ b/apps/cowswap-frontend/src/common/pure/InlineBanner/index.cosmos.tsx
@@ -12,14 +12,14 @@ const Fixtures = {
),
alert: (
-
- This is an alert banner (explicitly passed type).
+
+ This is an alert banner (explicitly passed bannerType).
),
information: (
-
+
Token approval bundling
For your convenience, token approval and order placement will be bundled into a single transaction,
@@ -30,14 +30,14 @@ const Fixtures = {
),
success: (
-
+
Operation completed successfully!
),
danger: (
-
+
Something went wrong! Please try again.
diff --git a/apps/cowswap-frontend/src/common/pure/InlineBanner/index.tsx b/apps/cowswap-frontend/src/common/pure/InlineBanner/index.tsx
index 64bc0f1cc4..816b5e2f4d 100644
--- a/apps/cowswap-frontend/src/common/pure/InlineBanner/index.tsx
+++ b/apps/cowswap-frontend/src/common/pure/InlineBanner/index.tsx
@@ -1,55 +1,74 @@
import { ReactNode } from 'react'
-import { lighten, darken, transparentize } from 'polished'
-import SVG from 'react-inlinesvg'
-import styled, { useTheme } from 'styled-components/macro' // import useTheme
+import styled from 'styled-components/macro'
-import iconInformation from 'legacy/assets/cow-swap/alert-circle.svg'
-import iconAlert from 'legacy/assets/cow-swap/alert.svg'
-import iconDanger from 'legacy/assets/cow-swap/alert.svg'
-import iconSuccess from 'legacy/assets/cow-swap/check.svg'
+import { UI } from 'common/constants/theme'
+import { Icon, IconType } from 'common/pure/Icon'
+import { BannerOrientation } from 'common/pure/InlineBanner/banners'
-type BannerType = 'alert' | 'information' | 'success' | 'danger' | 'savings'
+export type BannerType = 'alert' | 'information' | 'success' | 'danger' | 'savings'
-interface BannerConfig {
- colorKey: Exclude
- icon?: string
+interface ColorEnums {
+ icon?: IconType
iconText?: string
+ color: UI
+ bg: string
+ text: string
}
-const BANNER_CONFIG: Record = {
+const colorEnumsMap: Record = {
alert: {
- icon: iconAlert,
- colorKey: 'alert',
+ icon: IconType.ALERT,
+ color: UI.COLOR_ALERT,
+ bg: UI.COLOR_ALERT_BG,
+ text: UI.COLOR_ALERT_TEXT,
},
information: {
- icon: iconInformation,
- colorKey: 'information',
+ icon: IconType.INFORMATION,
+ color: UI.COLOR_INFORMATION,
+ bg: UI.COLOR_INFORMATION_BG,
+ text: UI.COLOR_INFORMATION_TEXT,
},
success: {
- icon: iconSuccess,
- colorKey: 'success',
+ icon: IconType.SUCCESS,
+ color: UI.COLOR_SUCCESS,
+ bg: UI.COLOR_SUCCESS_BG,
+ text: UI.COLOR_SUCCESS_TEXT,
+ },
+ danger: {
+ icon: IconType.DANGER,
+ color: UI.COLOR_DANGER,
+ bg: UI.COLOR_DANGER_BG,
+ text: UI.COLOR_DANGER_TEXT,
},
savings: {
iconText: '💸',
- colorKey: 'success',
- },
- danger: {
- icon: iconDanger,
- colorKey: 'danger',
+ color: UI.COLOR_SUCCESS,
+ bg: UI.COLOR_SUCCESS_BG,
+ text: UI.COLOR_SUCCESS_TEXT,
},
}
-const Wrapper = styled.span<{ color: string }>`
+function getColorEnums(bannerType: BannerType): ColorEnums {
+ return colorEnumsMap[bannerType] || colorEnumsMap.alert
+}
+
+const Wrapper = styled.span<{
+ colorEnums: ColorEnums
+ borderRadius?: string
+ orientation?: BannerOrientation
+ iconSize?: number
+ padding?: string
+}>`
display: flex;
align-items: center;
justify-content: center;
- background: ${({ theme, color }) => (theme.darkMode ? transparentize(0.9, color) : transparentize(0.85, color))};
- color: ${({ theme, color }) => (theme.darkMode ? lighten(0.1, color) : darken(0.2, color))};
+ background: ${({ colorEnums }) => `var(${colorEnums.bg})`};
+ color: ${({ colorEnums }) => `var(${colorEnums.text})`};
gap: 24px 10px;
- border-radius: 16px;
+ border-radius: ${({ borderRadius = '16px' }) => borderRadius};
margin: auto;
- padding: 16px;
+ padding: ${({ padding = '16px' }) => padding};
font-size: 14px;
font-weight: 400;
line-height: 1.2;
@@ -59,29 +78,10 @@ const Wrapper = styled.span<{ color: string }>`
display: flex;
justify-content: center;
align-items: center;
- flex-flow: column wrap;
+ flex-flow: ${({ orientation = BannerOrientation.Vertical }) =>
+ orientation === BannerOrientation.Horizontal ? 'row' : 'column wrap'};
gap: 10px;
width: 100%;
- }
-
- > span > svg {
- --size: 32px;
- display: block;
- min-width: var(--size);
- min-height: var(--size);
- width: var(--size);
- height: var(--size);
- object-fit: contain;
- stroke: none !important;
- }
-
- > span > svg > path {
- fill: ${({ color }) => color};
- }
-
- > span {
- display: flex;
- flex-flow: row wrap;
${({ theme }) => theme.mediaWidth.upToSmall`
flex-flow: column wrap;
@@ -93,7 +93,7 @@ const Wrapper = styled.span<{ color: string }>`
display: flex;
align-items: center;
gap: 6px;
- color: ${({ theme, color }) => (theme.darkMode ? lighten(0.2, color) : darken(0.2, color))};
+ color: ${({ colorEnums }) => `var(${colorEnums.text})`};
}
> span > p {
@@ -101,7 +101,8 @@ const Wrapper = styled.span<{ color: string }>`
margin: auto;
padding: 0;
width: 100%;
- text-align: center;
+ text-align: ${({ orientation = BannerOrientation.Vertical }) =>
+ orientation === BannerOrientation.Horizontal ? 'left' : 'center'};
}
> span > i {
@@ -115,19 +116,46 @@ export type InlineBannerProps = {
children?: ReactNode
className?: string
hideIcon?: boolean
- type?: BannerType
+ bannerType?: BannerType
+ borderRadius?: string
+ orientation?: BannerOrientation
+ iconSize?: number
+ iconPadding?: string
+ padding?: string
}
-export function InlineBanner({ children, className, hideIcon, type = 'alert' }: InlineBannerProps) {
- const theme = useTheme()
- const config = BANNER_CONFIG[type]
- const color = theme[config.colorKey]
+export function InlineBanner({
+ children,
+ className,
+ hideIcon,
+ bannerType = 'alert',
+ borderRadius,
+ orientation,
+ iconSize,
+ iconPadding,
+ padding,
+}: InlineBannerProps) {
+ const colorEnums = getColorEnums(bannerType)
return (
-
+
- {!hideIcon && config.icon && }
- {!hideIcon && config.iconText && {config.iconText} }
+ {!hideIcon && colorEnums.icon && (
+
+ )}
+ {!hideIcon && colorEnums.iconText && {colorEnums.iconText} }
{children}
diff --git a/apps/cowswap-frontend/src/common/pure/Modal/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/Modal/index.cosmos.tsx
new file mode 100644
index 0000000000..f07e58e4a5
--- /dev/null
+++ b/apps/cowswap-frontend/src/common/pure/Modal/index.cosmos.tsx
@@ -0,0 +1,46 @@
+import styled from 'styled-components/macro'
+
+import { CowModal, Modal } from './index'
+
+const Wrapper = styled.div`
+ width: 100vw;
+ height: 100vh;
+`
+
+const ModalFixtures = {
+ 'default modal': (
+
+ console.log('Dismissed')}>
+ Default modal content here
+
+
+ ),
+ 'modal with minHeight and maxHeight': (
+
+ console.log('Dismissed')} minHeight={50} maxHeight={80}>
+ Modal with minHeight and maxHeight
+
+
+ ),
+ 'cow modal': (
+
+ console.log('Cow Modal Dismissed')} maxWidth={400}>
+ Cow Modal Content
+
+
+ ),
+ 'cow modal with background color': (
+
+ console.log('Cow Modal Dismissed')}
+ maxWidth={400}
+ backgroundColor="pink"
+ >
+ Cow Modal with Pink Background
+
+
+ ),
+}
+
+export default ModalFixtures
diff --git a/apps/cowswap-frontend/src/common/pure/Modal/index.tsx b/apps/cowswap-frontend/src/common/pure/Modal/index.tsx
index b0aec21d42..bc01d75991 100644
--- a/apps/cowswap-frontend/src/common/pure/Modal/index.tsx
+++ b/apps/cowswap-frontend/src/common/pure/Modal/index.tsx
@@ -1,10 +1,12 @@
import React from 'react'
+import { isMobile } from '@cowprotocol/common-utils'
+
import { useSpringValue, useTransition } from '@react-spring/web'
import { useGesture } from '@use-gesture/react'
import styled from 'styled-components/macro'
-import { isMobile } from 'legacy/utils/userAgent'
+import { UI } from 'common/constants/theme'
import { CloseIcon, ContentWrapper, HeaderRow, HoverText, StyledDialogContent, StyledDialogOverlay } from './styled'
@@ -20,6 +22,9 @@ interface ModalProps {
children?: React.ReactNode
}
+/**
+ * @deprecated use common/pure/NewModal instead
+ */
export function Modal({
isOpen,
onDismiss,
@@ -90,7 +95,7 @@ export const CowModal = styled(Modal)<{
padding?: string
}>`
> [data-reach-dialog-content] {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
width: 100%;
max-width: ${({ maxWidth = 500 }) => `${maxWidth}px`};
border: ${({ border = 'inherit' }) => `${border}`};
@@ -98,8 +103,9 @@ export const CowModal = styled(Modal)<{
padding: ${({ padding = '0px' }) => `${padding}`};
margin: auto;
transition: max-width 0.4s ease;
- background-color: ${({ theme }) => theme.bg1};
+ background-color: var(${UI.COLOR_CONTAINER_BG_01});
overflow: hidden;
+ border-radius: var(${UI.BORDER_RADIUS_NORMAL});
${({ theme }) => theme.mediaWidth.upToSmall`
max-height: 100vh;
@@ -116,7 +122,7 @@ export const CowModal = styled(Modal)<{
left: 0;
width: 100%;
padding: 16px;
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
z-index: 20;
`}
}
@@ -141,3 +147,8 @@ export const CowModal = styled(Modal)<{
}
}
`
+
+export const NewCowModal = styled(Modal)`
+ width: 100vw;
+ height: 100vh;
+`
\ No newline at end of file
diff --git a/apps/cowswap-frontend/src/common/pure/Modal/styled.tsx b/apps/cowswap-frontend/src/common/pure/Modal/styled.tsx
index 29ef71105b..a6e8b4e8e7 100644
--- a/apps/cowswap-frontend/src/common/pure/Modal/styled.tsx
+++ b/apps/cowswap-frontend/src/common/pure/Modal/styled.tsx
@@ -5,6 +5,8 @@ import { animated } from '@react-spring/web'
import { transparentize } from 'polished'
import styled, { css } from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
export const HeaderRow = styled.div`
${({ theme }) => theme.flexRowNoWrap};
padding: 1rem 1rem;
@@ -27,7 +29,7 @@ export const CloseIcon = styled.div`
export const HoverText = styled.div`
text-decoration: none;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
display: flex;
align-items: center;
@@ -38,7 +40,7 @@ export const HoverText = styled.div`
export const ContentWrapper = styled.div`
/* background-color: ${({ theme }) => theme.bg0}; */
- background-color: ${({ theme }) => theme.bg1};
+ background-color: var(${UI.COLOR_CONTAINER_BG_01});
padding: 0 1rem 1rem 1rem;
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
@@ -57,6 +59,7 @@ export const StyledDialogOverlay = styled(AnimatedDialogOverlay)`
justify-content: center;
background-color: ${({ theme }) => theme.modalBG};
+ backdrop-filter: blur(5px);
}
`
diff --git a/apps/cowswap-frontend/src/common/pure/NetworksList/index.tsx b/apps/cowswap-frontend/src/common/pure/NetworksList/index.tsx
index a2ae882e45..04880fef18 100644
--- a/apps/cowswap-frontend/src/common/pure/NetworksList/index.tsx
+++ b/apps/cowswap-frontend/src/common/pure/NetworksList/index.tsx
@@ -1,12 +1,11 @@
+import { getChainInfo } from '@cowprotocol/common-const'
+import { getExplorerBaseUrl } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { ALL_SUPPORTED_CHAIN_IDS } from '@cowprotocol/cow-sdk'
+import { ExternalLink } from '@cowprotocol/ui'
import { Trans } from '@lingui/macro'
-import { getChainInfo } from 'legacy/constants/chainInfo'
-import { ALL_SUPPORTED_CHAIN_IDS } from 'legacy/constants/chains'
-import { ExternalLink } from 'legacy/theme'
-import { getExplorerBaseUrl } from 'legacy/utils/explorer'
-
import * as styledEl from './styled'
export interface NetworksListProps {
diff --git a/apps/cowswap-frontend/src/common/pure/NetworksList/styled.tsx b/apps/cowswap-frontend/src/common/pure/NetworksList/styled.tsx
index 9b85e9d168..e79310176b 100644
--- a/apps/cowswap-frontend/src/common/pure/NetworksList/styled.tsx
+++ b/apps/cowswap-frontend/src/common/pure/NetworksList/styled.tsx
@@ -2,6 +2,8 @@ import { transparentize } from 'polished'
import { ArrowDownCircle } from 'react-feather'
import styled from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
export const ActiveRowWrapper = styled.div`
background-color: ${({ theme }) => transparentize(0.4, theme.bg4)};
border-radius: 8px;
@@ -17,7 +19,7 @@ export const ActiveRowLinkList = styled.div`
& > a {
align-items: center;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
display: flex;
flex-direction: row;
font-size: 14px;
diff --git a/apps/cowswap-frontend/src/common/pure/NewModal/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/NewModal/index.cosmos.tsx
new file mode 100644
index 0000000000..72d1966d76
--- /dev/null
+++ b/apps/cowswap-frontend/src/common/pure/NewModal/index.cosmos.tsx
@@ -0,0 +1,85 @@
+import ICON_ARROW from 'assets/icon/arrow.svg'
+import SVG from 'react-inlinesvg'
+import styled from 'styled-components/macro'
+
+import { IMAGE_ACCOUNT, MOCK_TOKEN } from 'common/constants/cosmos'
+import { UI } from 'common/constants/theme'
+import { IconSpinner } from 'common/pure/IconSpinner'
+import { Stepper } from 'common/pure/Stepper'
+
+import { NewModal, NewModalContentBottom, NewModalContentTop } from './index'
+
+const Wrapper = styled.div`
+ width: 100vw;
+ height: 100vh;
+`
+
+const ArrowRight = styled(SVG)`
+ --size: 12px;
+ width: var(--size);
+ height: var(--size);
+ margin: auto;
+
+ > path {
+ fill: var(${UI.COLOR_TEXT2});
+ }
+`
+
+const ModalFixtures = {
+ 'new modal + content top/bottom': (
+
+
+
+
+
+ Approve spending AAVE on CoW Swap
+
+
+
+
+ Sign (gas-free!) in your wallet...
+
+
+
+
+ ),
+ 'new modal + content top/bottom 2': (
+
+
+
+
+
+ Confirm Swap
+
+ 10 AAVE 564.7202 DAI
+
+
+
+
+
+ Sign (gas-free!) in your wallet...
+
+
+
+
+ ),
+ 'new modal + heading title': (
+
+ - New Modal -
+
+ ),
+}
+
+export default ModalFixtures
diff --git a/apps/cowswap-frontend/src/common/pure/NewModal/index.tsx b/apps/cowswap-frontend/src/common/pure/NewModal/index.tsx
new file mode 100644
index 0000000000..090f5b9e5d
--- /dev/null
+++ b/apps/cowswap-frontend/src/common/pure/NewModal/index.tsx
@@ -0,0 +1,163 @@
+import React from 'react'
+
+import CLOSE_ICON from 'assets/icon/x.svg'
+import SVG from 'react-inlinesvg'
+import styled from 'styled-components/macro'
+
+import { UI } from 'common/constants/theme'
+
+const ModalInner = styled.div`
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ height: auto;
+ margin: auto;
+ background: transparent;
+ padding: 0;
+ position: relative;
+`
+
+const Wrapper = styled.div<{ maxWidth?: number | string; minHeight?: number | string }>`
+ display: flex;
+ width: 100%;
+ height: 100%;
+ margin: auto;
+ overflow-y: auto;
+ background: var(${UI.COLOR_CONTAINER_BG_01});
+ border-radius: var(${UI.BORDER_RADIUS_NORMAL});
+ box-shadow: var(${UI.BOX_SHADOW_NORMAL});
+
+ ${({ theme }) => theme.mediaWidth.upToSmall`
+ margin: 0;
+ border-radius: 0;
+ border-top-left-radius: var(${UI.BORDER_RADIUS_NORMAL});
+ border-top-right-radius: var(${UI.BORDER_RADIUS_NORMAL});
+ box-shadow: none;
+ `}
+
+ ${ModalInner} {
+ max-width: ${({ maxWidth }) => (maxWidth ? `${maxWidth}px` : '100%')};
+ min-height: ${({ minHeight }) => (minHeight ? `${minHeight}px` : '100%')};
+
+ ${({ theme }) => theme.mediaWidth.upToSmall`
+ max-width: 100%;
+ height: 100%;
+ `}
+ }
+`
+
+const Heading = styled.h2`
+ display: flex;
+ justify-content: space-between;
+ width: 100%;
+ height: auto;
+ padding: 18px;
+ margin: 0;
+ font-size: var(${UI.FONT_SIZE_MEDIUM});
+
+ ${({ theme }) => theme.mediaWidth.upToSmall`
+ position: sticky;
+ top: 0;
+ `}
+`
+
+const IconX = styled.div`
+ position: absolute;
+ top: 16px;
+ right: 10px;
+ cursor: pointer;
+ opacity: 0.7;
+ transition: opacity 0.2s ease-in-out;
+ margin: 0 0 0 auto;
+
+ > svg {
+ width: var(${UI.ICON_SIZE_NORMAL});
+ height: var(${UI.ICON_SIZE_NORMAL});
+ color: var(${UI.ICON_COLOR_NORMAL});
+ }
+
+ &:hover {
+ opacity: 1;
+ }
+`
+
+const NewModalContent = styled.div<{ paddingTop?: number }>`
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-flow: column wrap;
+ flex: 1;
+ width: 100%;
+ height: 100%;
+ padding: 0 var(${UI.PADDING_NORMAL}) var(${UI.PADDING_NORMAL});
+
+ h1,
+ h2,
+ h3 {
+ width: 100%;
+ font-size: var(${UI.FONT_SIZE_LARGER});
+ font-weight: var(${UI.FONT_WEIGHT_BOLD});
+ text-align: center;
+ line-height: 1.4;
+ margin: 0 auto;
+ }
+
+ p {
+ font-size: var(${UI.FONT_SIZE_NORMAL});
+ font-weight: var(${UI.FONT_WEIGHT_NORMAL});
+ color: var(${UI.COLOR_TEXT2});
+ margin: 0 auto;
+ padding: 0;
+ }
+`
+
+export const NewModalContentTop = styled.div<{ paddingTop?: number }>`
+ display: flex;
+ flex-flow: column wrap;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ margin: 0 0 auto;
+ padding: ${({ paddingTop = 0 }) => `${paddingTop}px`} 0 0;
+ gap: 24px;
+
+ > span {
+ gap: 6px;
+ display: flex;
+ flex-flow: column wrap;
+ }
+
+ p {
+ font-size: var(${UI.FONT_SIZE_MEDIUM});
+ }
+`
+
+export const NewModalContentBottom = styled(NewModalContentTop)`
+ margin: auto 0 0;
+
+ p {
+ font-size: var(${UI.FONT_SIZE_NORMAL});
+ }
+`
+export interface NewModalProps {
+ maxWidth?: number
+ minHeight?: number
+ title?: string
+ onDismiss?: () => void
+ children?: React.ReactNode
+}
+
+export function NewModal({ maxWidth = 450, minHeight = 450, title, children, onDismiss }: NewModalProps) {
+ return (
+
+
+ {title && {title} }
+ onDismiss && onDismiss()}>
+
+
+
+ {children}
+
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/common/pure/OrderExecutionStatusList/RateTooltipHeader.tsx b/apps/cowswap-frontend/src/common/pure/OrderExecutionStatusList/RateTooltipHeader.tsx
index bd2ee27daf..6da6a4630e 100644
--- a/apps/cowswap-frontend/src/common/pure/OrderExecutionStatusList/RateTooltipHeader.tsx
+++ b/apps/cowswap-frontend/src/common/pure/OrderExecutionStatusList/RateTooltipHeader.tsx
@@ -1,5 +1,7 @@
import styled from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
import { OrderExecutionStatusList } from './index'
const Content = styled.div`
@@ -16,7 +18,7 @@ const Content = styled.div`
line-height: 1.5;
padding: 0;
margin: 0;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
> h3 {
diff --git a/apps/cowswap-frontend/src/common/pure/OrderSubmittedContent/index.tsx b/apps/cowswap-frontend/src/common/pure/OrderSubmittedContent/index.tsx
index 371e4e54d3..d8551b7e69 100644
--- a/apps/cowswap-frontend/src/common/pure/OrderSubmittedContent/index.tsx
+++ b/apps/cowswap-frontend/src/common/pure/OrderSubmittedContent/index.tsx
@@ -1,12 +1,12 @@
+import { isCowOrder } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { ButtonPrimary } from '@cowprotocol/ui'
import { Trans } from '@lingui/macro'
import styled from 'styled-components/macro'
-import { ButtonPrimary } from 'legacy/components/Button'
import { EnhancedTransactionLink } from 'legacy/components/EnhancedTransactionLink'
import { HashType } from 'legacy/state/enhancedTransactions/reducer'
-import { isCowOrder } from 'legacy/utils'
import AnimatedConfirmation from 'common/pure/AnimatedConfirmation'
diff --git a/apps/cowswap-frontend/src/common/pure/PermitModal/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/PermitModal/index.cosmos.tsx
new file mode 100644
index 0000000000..c209c2aea0
--- /dev/null
+++ b/apps/cowswap-frontend/src/common/pure/PermitModal/index.cosmos.tsx
@@ -0,0 +1,83 @@
+import { USDC_MAINNET, WBTC } from '@cowprotocol/common-const'
+import { Identicon } from '@cowprotocol/wallet'
+import { CurrencyAmount } from '@uniswap/sdk-core'
+
+import styled from 'styled-components/macro'
+
+import { IconSpinner } from '../IconSpinner'
+
+import { PermitModal } from './index'
+
+const Wrapper = styled.div`
+ width: 100vw;
+ height: 100vh;
+`
+
+const INPUT_AMOUNT = CurrencyAmount.fromRawAmount(USDC_MAINNET, 500_000 * 10 ** USDC_MAINNET.decimals)
+const OUTPUT_AMOUNT = CurrencyAmount.fromRawAmount(WBTC, 1.2 * 10 ** WBTC.decimals)
+
+const WALLET_ICON = (
+
+
+
+)
+
+const PermitModalFixtures = {
+ 'SWAP: Pending permit signature': (
+
+
+
+ ),
+ 'SWAP: Pending order signature': (
+
+
+
+ ),
+ 'LIMIT: Pending permit signature': (
+
+
+
+ ),
+ 'LIMIT: Pending order signature': (
+
+
+
+ ),
+ // These two cases should happen, but including for completeness as the parameters allow it
+ 'Missing amounts on approve': (
+
+
+
+ ),
+ 'Missing amounts on submit': (
+
+
+
+ ),
+}
+
+export default PermitModalFixtures
diff --git a/apps/cowswap-frontend/src/common/pure/PermitModal/index.tsx b/apps/cowswap-frontend/src/common/pure/PermitModal/index.tsx
new file mode 100644
index 0000000000..0157dacdc9
--- /dev/null
+++ b/apps/cowswap-frontend/src/common/pure/PermitModal/index.tsx
@@ -0,0 +1,103 @@
+import { useMemo } from 'react'
+
+import { TokenAmount, TokenSymbol } from '@cowprotocol/ui'
+import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
+
+import ICON_ARROW from 'assets/icon/arrow.svg'
+import SVG from 'react-inlinesvg'
+import styled from 'styled-components/macro'
+import { Nullish } from 'types'
+
+import { UI } from '../../constants/theme'
+import { IconSpinner } from '../IconSpinner'
+import { NewModal, NewModalContentBottom, NewModalContentTop, NewModalProps } from '../NewModal'
+import { Stepper, StepProps } from '../Stepper'
+
+export type PermitModalProps = NewModalProps & {
+ inputAmount: Nullish>
+ outputAmount: Nullish>
+ step: 'approve' | 'submit'
+ orderType: 'Swap' | 'Limit Order'
+ icon?: React.ReactNode
+}
+
+/**
+ * You probably want to use containers/PermitModal instead
+ * This is the pure component for cosmos
+ */
+export function PermitModal(props: PermitModalProps) {
+ const { inputAmount, outputAmount, step, icon: inputIcon, orderType, ...rest } = props
+
+ const steps: StepProps[] = useMemo(
+ () => [
+ {
+ stepState: step === 'approve' ? 'loading' : 'finished',
+ stepNumber: 1,
+ label: 'Approve' + (step === 'approve' ? '' : 'd'),
+ },
+ { stepState: step === 'submit' ? 'loading' : 'active', stepNumber: 2, label: 'Submit' },
+ ],
+ [step]
+ )
+ const icon = useMemo(
+ () =>
+ step === 'approve' ? (
+
+ ) : (
+ {inputIcon}
+ ),
+ [inputAmount?.currency, inputIcon, step]
+ )
+
+ const title = useMemo(
+ () =>
+ step === 'approve' ? (
+ <>
+ Approve spending
+ on CoW Swap
+ >
+ ) : (
+ `Confirm ${orderType}`
+ ),
+ [inputAmount?.currency, orderType, step]
+ )
+
+ const body = useMemo(
+ () =>
+ step === 'approve' ? null : (
+
+ {' '}
+
+
+ ),
+ [inputAmount, outputAmount, step]
+ )
+
+ return (
+
+
+ {icon}
+
+ {title}
+ {body}
+
+
+
+
+ Sign (gas-free!) in your wallet...
+
+
+
+ )
+}
+
+const ArrowRight = styled(SVG)`
+ --size: 12px;
+ width: var(--size);
+ height: var(--size);
+ margin: auto;
+
+ > path {
+ fill: var(${UI.COLOR_TEXT2});
+ }
+`
diff --git a/apps/cowswap-frontend/src/common/pure/PriceImpactIndicator/index.tsx b/apps/cowswap-frontend/src/common/pure/PriceImpactIndicator/index.tsx
index 0fe2fc1de7..4d18915b0d 100644
--- a/apps/cowswap-frontend/src/common/pure/PriceImpactIndicator/index.tsx
+++ b/apps/cowswap-frontend/src/common/pure/PriceImpactIndicator/index.tsx
@@ -1,15 +1,14 @@
+import { formatPercent } from '@cowprotocol/common-utils'
+import { Loader } from '@cowprotocol/ui'
+import { MouseoverTooltip } from '@cowprotocol/ui'
import { Percent } from '@uniswap/sdk-core'
import { t } from '@lingui/macro'
import styled, { DefaultTheme } from 'styled-components/macro'
-import Loader from 'legacy/components/Loader'
-import { MouseoverTooltip } from 'legacy/components/Tooltip'
import { PriceImpact } from 'legacy/hooks/usePriceImpact'
import { warningSeverity } from 'legacy/utils/prices'
-import { formatPercent } from 'utils/amountFormat'
-
export interface PriceImpactIndicatorProps {
priceImpactParams?: PriceImpact
}
diff --git a/apps/cowswap-frontend/src/common/pure/RateInfo/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/RateInfo/index.cosmos.tsx
index b21ff58f99..8d54cde44c 100644
--- a/apps/cowswap-frontend/src/common/pure/RateInfo/index.cosmos.tsx
+++ b/apps/cowswap-frontend/src/common/pure/RateInfo/index.cosmos.tsx
@@ -1,13 +1,10 @@
+import { COW, GNO, DAI_GOERLI, USDT_GOERLI, WETH_GOERLI } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { TokenSymbol } from '@cowprotocol/ui'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import styled from 'styled-components/macro'
-import { COW, GNO } from 'legacy/constants/tokens'
-import { DAI_GOERLI, USDT_GOERLI, WETH_GOERLI } from 'legacy/utils/goerli/constants'
-
-import { TokenSymbol } from 'common/pure/TokenSymbol'
-
import { RateInfoParams, RateInfo } from './index'
const inputCurrency = WETH_GOERLI
diff --git a/apps/cowswap-frontend/src/common/pure/RateInfo/index.tsx b/apps/cowswap-frontend/src/common/pure/RateInfo/index.tsx
index 9f84c1d116..7ea915715a 100644
--- a/apps/cowswap-frontend/src/common/pure/RateInfo/index.tsx
+++ b/apps/cowswap-frontend/src/common/pure/RateInfo/index.tsx
@@ -1,6 +1,8 @@
import React, { Dispatch, SetStateAction, useEffect, useMemo, useState } from 'react'
+import { getAddress } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { FiatAmount, TokenAmount, TokenSymbol } from '@cowprotocol/ui'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import { Trans } from '@lingui/macro'
@@ -9,12 +11,9 @@ import { Repeat } from 'react-feather'
import styled from 'styled-components/macro'
import { Nullish } from 'types'
+import { UI } from 'common/constants/theme'
import { usePrice } from 'common/hooks/usePrice'
-import { FiatAmount } from 'common/pure/FiatAmount'
-import { TokenAmount } from 'common/pure/TokenAmount'
-import { TokenSymbol } from 'common/pure/TokenSymbol'
import { getQuoteCurrency } from 'common/services/getQuoteCurrency'
-import { getAddress } from 'utils/getAddress'
const DEFAULT_DECIMALS = 4
@@ -60,7 +59,7 @@ const RateLabel = styled.div`
color: ${({ theme }) => transparentize(0.2, theme.text1)};
&:hover {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
`
@@ -68,7 +67,7 @@ const InvertIcon = styled.div`
--size: 17px;
cursor: pointer;
background: ${({ theme }) => transparentize(0.9, theme.text1)};
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
width: var(--size);
height: var(--size);
min-width: var(--size);
diff --git a/apps/cowswap-frontend/src/common/pure/SafeWalletLink/index.tsx b/apps/cowswap-frontend/src/common/pure/SafeWalletLink/index.tsx
index 864694ae96..2df9622fa3 100644
--- a/apps/cowswap-frontend/src/common/pure/SafeWalletLink/index.tsx
+++ b/apps/cowswap-frontend/src/common/pure/SafeWalletLink/index.tsx
@@ -1,6 +1,5 @@
-import { ExternalLink } from 'legacy/theme'
-
-import { getSafeWebUrl } from 'api/gnosisSafe'
+import { getSafeWebUrl } from '@cowprotocol/core'
+import { ExternalLink } from '@cowprotocol/ui'
export function SafeWalletLink(props: {
chainId: number
diff --git a/apps/cowswap-frontend/src/common/pure/Stepper/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/Stepper/index.cosmos.tsx
new file mode 100644
index 0000000000..9b62a26e3f
--- /dev/null
+++ b/apps/cowswap-frontend/src/common/pure/Stepper/index.cosmos.tsx
@@ -0,0 +1,62 @@
+import styled from 'styled-components/macro';
+
+import { UI } from 'common/constants/theme'
+
+import { Stepper } from './index';
+
+const Wrapper = styled.div`
+ width: 90%;
+ height: 120px;
+ background: var(${UI.COLOR_CONTAINER_BG_01});
+ border-radius: var(${UI.BORDER_RADIUS_NORMAL});
+ display: flex;
+ align-items: center;
+ justify-content: center;
+`;
+
+const StepperFixtures = {
+ 'Stepper start': (
+
+
+
+ ),
+ '2 Stepper with active step': (
+
+
+
+ ),
+ 'Stepper with error state': (
+
+
+
+ ),
+ 'Stepper with loading state': (
+
+
+
+ ),
+};
+
+export default StepperFixtures;
diff --git a/apps/cowswap-frontend/src/common/pure/Stepper/index.tsx b/apps/cowswap-frontend/src/common/pure/Stepper/index.tsx
new file mode 100644
index 0000000000..b1673895b8
--- /dev/null
+++ b/apps/cowswap-frontend/src/common/pure/Stepper/index.tsx
@@ -0,0 +1,142 @@
+import ICON_CHECK from 'assets/icon/check.svg'
+import SVG from 'react-inlinesvg'
+import styled from 'styled-components/macro'
+
+import { UI } from 'common/constants/theme'
+import { IconSpinner } from 'common/pure/IconSpinner'
+
+type StepState = 'active' | 'finished' | 'disabled' | 'error' | 'loading' | 'open'
+
+export interface StepProps {
+ stepState: StepState
+ stepNumber: number
+ label: string
+ dotSize?: number
+ dotBorderColor?: UI
+}
+
+interface StepStyles {
+ dotBackground: UI
+ dotColor: UI
+ labelColor: UI
+}
+
+const stateStyles: Record = {
+ active: { dotBackground: UI.COLOR_LINK, dotColor: UI.COLOR_CONTAINER_BG_01, labelColor: UI.COLOR_TEXT1 },
+ finished: { dotBackground: UI.COLOR_LINK_OPACITY_10, dotColor: UI.COLOR_LINK, labelColor: UI.COLOR_TEXT1 },
+ disabled: {
+ dotBackground: UI.COLOR_TEXT1_OPACITY_25,
+ dotColor: UI.COLOR_TEXT1_OPACITY_25,
+ labelColor: UI.COLOR_TEXT1_OPACITY_25,
+ },
+ error: { dotBackground: UI.COLOR_DANGER_BG, dotColor: UI.COLOR_DANGER, labelColor: UI.COLOR_DANGER },
+ loading: { dotBackground: UI.COLOR_LINK, dotColor: UI.COLOR_CONTAINER_BG_01, labelColor: UI.COLOR_LINK },
+ open: { dotBackground: UI.COLOR_TEXT1_OPACITY_10, dotColor: UI.COLOR_TEXT2, labelColor: UI.COLOR_TEXT2 },
+}
+
+const Step = styled.div`
+ display: flex;
+ position: relative;
+ align-items: center;
+ margin: 0;
+ padding: 0;
+ font-size: var(${UI.FONT_SIZE_SMALL});
+ background: transparent;
+ color: ${({ stepState }) => `var(${stateStyles[stepState].labelColor})`};
+ gap: 8px;
+ flex: 1 0 auto;
+
+ i {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: var(--dotSize);
+ height: var(--dotSize);
+ max-width: var(--dotSize);
+ max-height: var(--dotSize);
+ border-radius: var(--dotSize);
+ border: 1px solid ${({ dotBorderColor = UI.COLOR_CONTAINER_BG_01 }) => `var(${dotBorderColor})`};
+ background: ${({ stepState }) => `var(${stateStyles[stepState].dotBackground})`};
+ color: ${({ stepState }) => `var(${stateStyles[stepState].dotColor})`};
+ flex: 0 0 auto;
+ z-index: 1;
+ position: relative;
+ font-style: normal;
+ font-size: inherit;
+ line-height: 1;
+
+ > svg {
+ width: 50%;
+ height: 50%;
+ margin: auto;
+ }
+
+ > svg > path {
+ fill: var(${UI.COLOR_LINK});
+ }
+ }
+
+ > small {
+ flex: 0 0 auto;
+ font-size: inherit;
+ }
+
+ > hr {
+ width: 100%;
+ height: 1px;
+ border: 0;
+ background: ${({ stepState }) =>
+ stepState === 'error'
+ ? `var(${stateStyles['error'].dotBackground})`
+ : stepState === 'finished'
+ ? `var(${stateStyles['finished'].dotBackground})`
+ : `var(${UI.COLOR_TEXT1_OPACITY_25})`};
+ border-radius: var(${UI.BORDER_RADIUS_NORMAL});
+ }
+
+ &&:last-child {
+ flex: 0;
+ }
+
+ &:last-child > hr {
+ display: none;
+ }
+`
+
+const Wrapper = styled.div<{ maxWidth?: string; dotSize?: number }>`
+ --dotSize: ${({ dotSize }) => `${dotSize}px`};
+ width: ${({ maxWidth }) => (maxWidth ? maxWidth : '100%')};
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ position: relative;
+ gap: 10px;
+ padding: 24px;
+ margin: 0 auto;
+`
+
+interface StepperProps {
+ steps: StepProps[]
+ maxWidth?: string
+ dotSize?: number
+}
+
+export function Stepper({ steps, maxWidth, dotSize = 21 }: StepperProps) {
+ return (
+
+ {steps.map((step, index) => (
+
+ {step.stepState === 'loading' ? (
+
+ {step.stepNumber}
+
+ ) : (
+ {step.stepState === 'finished' ? : step.stepNumber}
+ )}
+ {step.label}
+
+
+ ))}
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/common/pure/TradeLoadingButton/index.tsx b/apps/cowswap-frontend/src/common/pure/TradeLoadingButton/index.tsx
index 790066f67a..0ef6a6110e 100644
--- a/apps/cowswap-frontend/src/common/pure/TradeLoadingButton/index.tsx
+++ b/apps/cowswap-frontend/src/common/pure/TradeLoadingButton/index.tsx
@@ -1,10 +1,11 @@
import { useEffect, useState } from 'react'
+import { LONG_LOAD_THRESHOLD } from '@cowprotocol/common-const'
+
import { Text } from 'rebass'
import styled from 'styled-components/macro'
import { Dots } from 'legacy/components/swap/styleds'
-import { LONG_LOAD_THRESHOLD } from 'legacy/constants'
import { ThemedText } from 'legacy/theme'
const fadeIn = `
diff --git a/apps/cowswap-frontend/src/common/pure/TransactionErrorContent/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/TransactionErrorContent/index.cosmos.tsx
index 990d8e3e55..1d221cf1a3 100644
--- a/apps/cowswap-frontend/src/common/pure/TransactionErrorContent/index.cosmos.tsx
+++ b/apps/cowswap-frontend/src/common/pure/TransactionErrorContent/index.cosmos.tsx
@@ -1,11 +1,13 @@
import styled from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
import { TransactionErrorContent } from './index'
const Wrapper = styled.div`
width: 560px;
margin: 0 auto;
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
`
const fixtures = {
diff --git a/apps/cowswap-frontend/src/common/pure/TransactionErrorContent/index.tsx b/apps/cowswap-frontend/src/common/pure/TransactionErrorContent/index.tsx
index 44491b0cc3..63aeeb57c7 100644
--- a/apps/cowswap-frontend/src/common/pure/TransactionErrorContent/index.tsx
+++ b/apps/cowswap-frontend/src/common/pure/TransactionErrorContent/index.tsx
@@ -1,8 +1,9 @@
+import { ButtonPrimary } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import { AlertTriangle } from 'react-feather'
import styled from 'styled-components/macro'
-import { ButtonPrimary } from 'legacy/components/Button'
import { CloseIcon } from 'legacy/theme'
const Wrapper = styled.div`
diff --git a/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/SurplusModal.tsx b/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/SurplusModal.tsx
index 487ecf1fe9..a0bf0e18cf 100644
--- a/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/SurplusModal.tsx
+++ b/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/SurplusModal.tsx
@@ -1,22 +1,21 @@
import React, { useCallback } from 'react'
+import { sendEvent } from '@cowprotocol/analytics'
+import CheckSingular from '@cowprotocol/assets/cow-swap/check-singular.svg'
+import SurplusCow from '@cowprotocol/assets/cow-swap/surplus-cow.svg'
+import twitterImage from '@cowprotocol/assets/cow-swap/twitter.svg'
import { OrderKind } from '@cowprotocol/cow-sdk'
+import { FiatAmount, TokenAmount, SymbolElement } from '@cowprotocol/ui'
+import { ExternalLink } from '@cowprotocol/ui'
import { transparentize } from 'polished'
import SVG from 'react-inlinesvg'
import styled from 'styled-components/macro'
-import CheckSingular from 'legacy/assets/cow-swap/check-singular.svg'
-import SurplusCow from 'legacy/assets/cow-swap/surplus-cow.svg'
-import twitterImage from 'legacy/assets/cow-swap/twitter.svg'
import { Order } from 'legacy/state/orders/actions'
-import { ExternalLink } from 'legacy/theme'
+import { UI } from 'common/constants/theme'
import { useGetSurplusData } from 'common/hooks/useGetSurplusFiatValue'
-import { FiatAmount } from 'common/pure/FiatAmount'
-import { TokenAmount, SymbolElement } from 'common/pure/TokenAmount'
-
-import { sendEvent } from '../../../legacy/components/analytics/googleAnalytics'
const SELL_SURPLUS_WORD = 'got'
const BUY_SURPLUS_WORD = 'saved'
@@ -59,7 +58,7 @@ export const Wrapper = styled.div`
--size: 28px;
width: var(--size);
height: var(--size);
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
border-radius: 50%;
width: var(--size);
height: var(--size);
@@ -121,7 +120,7 @@ export const Wrapper = styled.div`
width: 70%;
margin: 34px auto;
padding: 0;
- color: ${({ theme }) => theme.text2};
+ color: var(${UI.COLOR_TEXT2});
}
`
diff --git a/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/index.tsx b/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/index.tsx
index e234c0603d..a39747a3d9 100644
--- a/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/index.tsx
+++ b/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/index.tsx
@@ -1,5 +1,6 @@
import React from 'react'
+import GameIcon from '@cowprotocol/assets/cow-swap/game.gif'
import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
import { Currency } from '@uniswap/sdk-core'
@@ -7,7 +8,6 @@ import { Link } from 'react-router-dom'
import { Text } from 'rebass'
import { Nullish } from 'types'
-import GameIcon from 'legacy/assets/cow-swap/game.gif'
import { OrderProgressBar } from 'legacy/components/OrderProgressBar'
import { DisplayLink } from 'legacy/components/TransactionConfirmationModal/DisplayLink'
import { getActivityState } from 'legacy/hooks/useActivityDerivedState'
@@ -15,7 +15,7 @@ import { ActivityStatus } from 'legacy/hooks/useRecentActivity'
import { ActivityDerivedState } from 'modules/account/containers/Transaction'
import { EthFlowStepper } from 'modules/swap/containers/EthFlowStepper'
-import AddToMetamask from 'modules/wallet/web3-react/containers/AddToMetamask'
+import { AddToMetamask } from 'modules/wallet/containers/AddToMetamask'
import { Routes } from 'common/constants/routes'
diff --git a/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/styled.tsx b/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/styled.tsx
index 6e0fedede7..ac318fc56c 100644
--- a/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/styled.tsx
+++ b/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/styled.tsx
@@ -2,6 +2,8 @@ import styled from 'styled-components/macro'
import { CloseIcon } from 'legacy/theme'
+import { UI } from 'common/constants/theme'
+
export const ButtonCustom = styled.button`
display: flex;
flex: 1 1 auto;
@@ -11,7 +13,7 @@ export const ButtonCustom = styled.button`
border-radius: 16px;
min-height: 52px;
border: 1px solid ${({ theme }) => theme.border2};
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
background: transparent;
outline: 0;
padding: 8px 16px;
diff --git a/apps/cowswap-frontend/src/common/services/getQuoteCurrency/index.ts b/apps/cowswap-frontend/src/common/services/getQuoteCurrency/index.ts
index 4f528f1a19..524e2e4749 100644
--- a/apps/cowswap-frontend/src/common/services/getQuoteCurrency/index.ts
+++ b/apps/cowswap-frontend/src/common/services/getQuoteCurrency/index.ts
@@ -1,13 +1,12 @@
+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 { SupportedChainId } from '@cowprotocol/cow-sdk'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import { Nullish } from 'types'
-import { NATIVE_CURRENCY_BUY_ADDRESS } from 'legacy/constants'
-import { DAI, USDC_MAINNET, USDT } from 'legacy/constants/tokens'
-import { USDC_GNOSIS_CHAIN, USDT_GNOSIS_CHAIN, WXDAI } from 'legacy/utils/gnosis_chain/constants'
-import { DAI_GOERLI, USDT_GOERLI, USDC_GOERLI } from 'legacy/utils/goerli/constants'
-
// TODO: Find a solution for using API: https://www.coingecko.com/en/categories/stablecoins
const STABLE_COINS: { [key in SupportedChainId]: string[] } = {
[SupportedChainId.MAINNET]: [USDC_MAINNET, USDT, DAI].map((token) => token.address.toLowerCase()),
diff --git a/apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/atom.ts b/apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/atom.ts
new file mode 100644
index 0000000000..d6288955d7
--- /dev/null
+++ b/apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/atom.ts
@@ -0,0 +1,21 @@
+import { atom } from 'jotai'
+import { atomWithStorage } from 'jotai/utils'
+
+export type WarningBannerVisibility = string[]
+
+const WARNING_BANNER_VISIBILITY_KEY = 'warningBannerVisibility:v0'
+
+export const hiddenReceiverWalletBannersAtom = atomWithStorage(
+ WARNING_BANNER_VISIBILITY_KEY,
+ []
+)
+
+export const hideReceiverWalletBannerAtom = atom(null, (get, set, orderId: string) => {
+ const hiddenBanners = get(hiddenReceiverWalletBannersAtom)
+
+ if (hiddenBanners.includes(orderId)) {
+ return
+ }
+
+ set(hiddenReceiverWalletBannersAtom, [...hiddenBanners, orderId])
+})
diff --git a/apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/hooks.ts b/apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/hooks.ts
new file mode 100644
index 0000000000..369e794ac8
--- /dev/null
+++ b/apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/hooks.ts
@@ -0,0 +1,14 @@
+import { useAtomValue, useSetAtom } from 'jotai'
+import { useMemo } from 'react'
+
+import { hiddenReceiverWalletBannersAtom, hideReceiverWalletBannerAtom } from './atom'
+
+export function useIsReceiverWalletBannerHidden(orderId?: string): boolean {
+ const hiddenBanners = useAtomValue(hiddenReceiverWalletBannersAtom)
+
+ return useMemo(() => !!orderId && hiddenBanners.includes(orderId), [hiddenBanners, orderId])
+}
+
+export function useHideReceiverWalletBanner() {
+ return useSetAtom(hideReceiverWalletBannerAtom)
+}
diff --git a/apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/index.ts b/apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/index.ts
new file mode 100644
index 0000000000..64c191af4c
--- /dev/null
+++ b/apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/index.ts
@@ -0,0 +1 @@
+export { useHideReceiverWalletBanner, useIsReceiverWalletBannerHidden } from './hooks'
diff --git a/apps/cowswap-frontend/src/common/state/totalSurplusState/updaters.ts b/apps/cowswap-frontend/src/common/state/totalSurplusState/updaters.ts
index 7bbd484135..b5993a80ff 100644
--- a/apps/cowswap-frontend/src/common/state/totalSurplusState/updaters.ts
+++ b/apps/cowswap-frontend/src/common/state/totalSurplusState/updaters.ts
@@ -1,12 +1,11 @@
import { useSetAtom } from 'jotai'
import { useCallback, useEffect } from 'react'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import useSWR from 'swr'
-import { useWalletInfo } from 'modules/wallet'
-
import { getSurplusData } from 'api/gnosisProtocol/api'
import useNativeCurrency from 'lib/hooks/useNativeCurrency'
diff --git a/apps/cowswap-frontend/src/legacy/state/application/updater.ts b/apps/cowswap-frontend/src/common/updaters/ApplicationUpdater.ts
similarity index 79%
rename from apps/cowswap-frontend/src/legacy/state/application/updater.ts
rename to apps/cowswap-frontend/src/common/updaters/ApplicationUpdater.ts
index fffdf17284..343dd108e7 100644
--- a/apps/cowswap-frontend/src/legacy/state/application/updater.ts
+++ b/apps/cowswap-frontend/src/common/updaters/ApplicationUpdater.ts
@@ -1,18 +1,14 @@
import { useEffect, useState } from 'react'
+import { usePrevious, useIsWindowVisible, useDebounce } from '@cowprotocol/common-hooks'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { useWeb3React } from '@web3-react/core'
-import useDebounce from 'legacy/hooks/useDebounce'
-import useIsWindowVisible from 'legacy/hooks/useIsWindowVisible'
-import usePrevious from 'legacy/hooks/usePrevious'
+import { updateChainId } from 'legacy/state/application/reducer'
import { useAppDispatch } from 'legacy/state/hooks'
import { updateSelectedWallet } from 'legacy/state/user/reducer'
-import { useWalletInfo } from 'modules/wallet'
-
-import { updateChainId } from './reducer'
-
-export default function Updater(): null {
+export function ApplicationUpdater(): null {
const { chainId } = useWalletInfo()
const { provider, account } = useWeb3React()
const dispatch = useAppDispatch()
diff --git a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/updater/CancelReplaceTxUpdater.tsx b/apps/cowswap-frontend/src/common/updaters/CancelReplaceTxUpdater.tsx
similarity index 94%
rename from apps/cowswap-frontend/src/legacy/state/enhancedTransactions/updater/CancelReplaceTxUpdater.tsx
rename to apps/cowswap-frontend/src/common/updaters/CancelReplaceTxUpdater.tsx
index 97ab21e5d9..46a31bc723 100644
--- a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/updater/CancelReplaceTxUpdater.tsx
+++ b/apps/cowswap-frontend/src/common/updaters/CancelReplaceTxUpdater.tsx
@@ -1,5 +1,6 @@
import { useEffect } from 'react'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { useWeb3React } from '@web3-react/core'
import { Dispatch } from 'redux'
@@ -7,9 +8,8 @@ import { Dispatch } from 'redux'
import { replaceTransaction } from 'legacy/state/enhancedTransactions/actions'
import { useAllTransactionHashes } from 'legacy/state/enhancedTransactions/hooks'
import { useAppDispatch } from 'legacy/state/hooks'
-import { sdk } from 'legacy/utils/blocknative'
-import { useWalletInfo } from 'modules/wallet'
+import { sdk } from 'api/blocknative'
function watchTxChanges(pendingHashes: string[], chainId: number, dispatch: Dispatch) {
for (const hash of pendingHashes) {
@@ -60,7 +60,7 @@ function unwatchTxChanges(pendingHashes: string[], chainId: number) {
}
}
-export default function CancelReplaceTxUpdater(): null {
+export function CancelReplaceTxUpdater(): null {
const { provider } = useWeb3React()
const { chainId, account } = useWalletInfo()
const dispatch = useAppDispatch()
diff --git a/apps/cowswap-frontend/src/legacy/state/price/updater.ts b/apps/cowswap-frontend/src/common/updaters/FeesUpdater.ts
similarity index 88%
rename from apps/cowswap-frontend/src/legacy/state/price/updater.ts
rename to apps/cowswap-frontend/src/common/updaters/FeesUpdater.ts
index dd7b2553f0..dfaf831e1b 100644
--- a/apps/cowswap-frontend/src/legacy/state/price/updater.ts
+++ b/apps/cowswap-frontend/src/common/updaters/FeesUpdater.ts
@@ -1,38 +1,36 @@
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 { OrderKind } from '@cowprotocol/cow-sdk'
+import { useENSAddress } from '@cowprotocol/ens'
+import { useWalletInfo } from '@cowprotocol/wallet'
-import { DEFAULT_DECIMALS } from 'legacy/constants'
-import useDebounce from 'legacy/hooks/useDebounce'
-import useENSAddress from 'legacy/hooks/useENSAddress'
-import useIsOnline from 'legacy/hooks/useIsOnline'
-import useIsWindowVisible from 'legacy/hooks/useIsWindowVisible'
import { useRefetchQuoteCallback } from 'legacy/hooks/useRefetchPriceCallback'
import { useIsUnsupportedTokenGp } from 'legacy/state/lists/hooks'
-import { Field } from 'legacy/state/swap/actions'
-import { useDerivedSwapInfo, useSwapState } from 'legacy/state/swap/hooks'
+import { useAllQuotes, useIsBestQuoteLoading, useSetQuoteError } from 'legacy/state/price/hooks'
+import { QuoteInformationObject } from 'legacy/state/price/reducer'
+import { LegacyFeeQuoteParams } from 'legacy/state/price/types'
import { isWrappingTrade } from 'legacy/state/swap/utils'
+import { Field } from 'legacy/state/types'
import { useOrderValidTo } from 'legacy/state/user/hooks'
-import { isAddress } from 'legacy/utils'
+import { useAppData } from 'modules/appData'
import { useIsEoaEthFlow } from 'modules/swap/hooks/useIsEoaEthFlow'
+import { useDerivedSwapInfo, useSwapState } from 'modules/swap/hooks/useSwapState'
import { useEnoughBalanceAndAllowance } from 'modules/tokens'
-import { useWalletInfo } from 'modules/wallet'
import { getPriceQuality } from 'api/gnosisProtocol/api'
-import { LegacyFeeQuoteParams as LegacyFeeQuoteParamsFull } from 'api/gnosisProtocol/legacy/types'
-import { useVerifiedQuotesEnabled } from 'common/hooks/featureFlags/useVerifiedQuotesEnabled'
-import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount'
-import { useAllQuotes, useIsBestQuoteLoading, useSetQuoteError } from './hooks'
-import { QuoteInformationObject } from './reducer'
+import { useVerifiedQuotesEnabled } from '../hooks/featureFlags/useVerifiedQuotesEnabled'
export const TYPED_VALUE_DEBOUNCE_TIME = 350
const REFETCH_CHECK_INTERVAL = 10000 // Every 10s
const RENEW_FEE_QUOTES_BEFORE_EXPIRATION_TIME = 30000 // Will renew the quote if there's less than 30 seconds left for the quote to expire
const WAITING_TIME_BETWEEN_EQUAL_REQUESTS = 5000 // Prevents from sending the same request to often (max, every 5s)
-type FeeQuoteParams = Omit
+type FeeQuoteParams = Omit
/**
* Returns if the quote has been recently checked
@@ -66,8 +64,9 @@ function quoteUsingSameParameters(currentParams: FeeQuoteParams, quoteInfo: Quot
kind: currentKind,
userAddress: currentUserAddress,
receiver: currentReceiver,
+ appData: currentAppData,
} = currentParams
- const { amount, buyToken, sellToken, kind, userAddress, receiver } = quoteInfo
+ const { amount, buyToken, sellToken, kind, userAddress, receiver, appData } = quoteInfo
const hasSameReceiver = currentReceiver && receiver ? currentReceiver === receiver : true
// cache the base quote params without quoteInfo user address to check
@@ -76,6 +75,7 @@ function quoteUsingSameParameters(currentParams: FeeQuoteParams, quoteInfo: Quot
buyToken === currentBuyToken &&
amount === currentAmount &&
kind === currentKind &&
+ appData === currentAppData &&
hasSameReceiver
// 2 checks: if there's a quoteInfo user address (meaning quote was already calculated once) and one without
// in case user is not connected
@@ -119,7 +119,7 @@ function isRefetchQuoteRequired(
return false
}
-export default function FeesUpdater(): null {
+export function FeesUpdater(): null {
const { chainId, account } = useWalletInfo()
const verifiedQuotesEnabled = useVerifiedQuotesEnabled(chainId)
@@ -130,7 +130,7 @@ export default function FeesUpdater(): null {
parsedAmount,
} = useDerivedSwapInfo()
- const enoughBalance = useEnoughBalanceAndAllowance({ account, amount: parsedAmount })
+ const { enoughBalance } = useEnoughBalanceAndAllowance({ account, amount: parsedAmount })
const { address: ensRecipientAddress } = useENSAddress(recipient)
const receiver = ensRecipientAddress || recipient
@@ -150,6 +150,8 @@ export default function FeesUpdater(): null {
const isUnsupportedTokenGp = useIsUnsupportedTokenGp()
+ const appData = useAppData()
+
const refetchQuote = useRefetchQuoteCallback()
const setQuoteError = useSetQuoteError()
@@ -208,6 +210,8 @@ export default function FeesUpdater(): null {
validTo,
isEthFlow,
priceQuality: getPriceQuality({ verifyQuote: verifiedQuotesEnabled && enoughBalance }),
+ appData: appData?.fullAppData,
+ appDataHash: appData?.appDataKeccak256,
}
// Don't refetch if offline.
@@ -280,6 +284,8 @@ export default function FeesUpdater(): null {
sellTokenAddressInvalid,
enoughBalance,
verifiedQuotesEnabled,
+ appData?.fullAppData,
+ appData?.appDataKeccak256,
])
return null
diff --git a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/updater/FinalizeTxUpdater.tsx b/apps/cowswap-frontend/src/common/updaters/FinalizeTxUpdater.tsx
similarity index 95%
rename from apps/cowswap-frontend/src/legacy/state/enhancedTransactions/updater/FinalizeTxUpdater.tsx
rename to apps/cowswap-frontend/src/common/updaters/FinalizeTxUpdater.tsx
index cc7c7ebf4d..fcedf226cd 100644
--- a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/updater/FinalizeTxUpdater.tsx
+++ b/apps/cowswap-frontend/src/common/updaters/FinalizeTxUpdater.tsx
@@ -1,30 +1,32 @@
import { useSetAtom } from 'jotai'
import { useEffect, useMemo } from 'react'
+import { GetReceipt, useBlockNumber, useGetReceipt } from '@cowprotocol/common-hooks'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { TransactionReceipt } from '@ethersproject/abstract-provider'
import { useWeb3React } from '@web3-react/core'
import ms from 'ms.macro'
-import { GetReceipt, useGetReceipt } from 'legacy/hooks/useGetReceipt'
import { GetSafeInfo, useGetSafeInfo } from 'legacy/hooks/useGetSafeInfo'
import { AppDispatch } from 'legacy/state'
import { useAddPopup } from 'legacy/state/application/hooks'
+import {
+ checkedTransaction,
+ finalizeTransaction,
+ updateSafeTransaction,
+} from 'legacy/state/enhancedTransactions/actions'
import { useAllTransactionsDetails } from 'legacy/state/enhancedTransactions/hooks'
+import { EnhancedTransactionDetails, HashType } from 'legacy/state/enhancedTransactions/reducer'
import { useAppDispatch } from 'legacy/state/hooks'
import { invalidateOrdersBatch } from 'legacy/state/orders/actions'
+import { CancelOrdersBatchCallback, useCancelOrdersBatch } from 'legacy/state/orders/hooks'
import { partialOrderUpdate } from 'legacy/state/orders/utils'
import { removeInFlightOrderIdAtom } from 'modules/swap/state/EthFlow/ethFlowInFlightOrderIdsAtom'
-import { useWalletInfo } from 'modules/wallet'
-import useBlockNumber from 'lib/hooks/useBlockNumber'
import useNativeCurrency from 'lib/hooks/useNativeCurrency'
-import { CancelOrdersBatchCallback, useCancelOrdersBatch } from '../../orders/hooks'
-import { checkedTransaction, finalizeTransaction, updateSafeTransaction } from '../actions'
-import { EnhancedTransactionDetails, HashType } from '../reducer'
-
const DELAY_REMOVAL_ETH_FLOW_ORDER_ID_MILLISECONDS = ms`2m` // Delay removing the order ID since the creation time its mined (minor precaution just to avoid edge cases of delay in indexing times affect the collision detection
type TxInterface = Pick<
@@ -252,7 +254,7 @@ function checkEthereumTransactions(params: CheckEthereumTransactions): Cancel[]
})
}
-export default function Updater(): null {
+export function FinalizeTxUpdater(): null {
const { provider } = useWeb3React()
const { chainId, account } = useWalletInfo()
const lastBlockNumber = useBlockNumber()
@@ -260,7 +262,7 @@ export default function Updater(): null {
const dispatch = useAppDispatch()
const cancelOrdersBatch = useCancelOrdersBatch()
- const getReceipt = useGetReceipt()
+ const getReceipt = useGetReceipt(chainId)
const getSafeInfo = useGetSafeInfo()
const addPopup = useAddPopup()
const removeInFlightOrderId = useSetAtom(removeInFlightOrderIdAtom)
diff --git a/apps/cowswap-frontend/src/legacy/state/gas/updater.tsx b/apps/cowswap-frontend/src/common/updaters/GasUpdater.tsx
similarity index 55%
rename from apps/cowswap-frontend/src/legacy/state/gas/updater.tsx
rename to apps/cowswap-frontend/src/common/updaters/GasUpdater.tsx
index 7b41d0f02c..0c8cef160d 100644
--- a/apps/cowswap-frontend/src/legacy/state/gas/updater.tsx
+++ b/apps/cowswap-frontend/src/common/updaters/GasUpdater.tsx
@@ -1,19 +1,37 @@
-import { useEffect } from 'react'
+import { useSetAtom } from 'jotai/index'
+import { useCallback, useEffect } from 'react'
-import { GAS_PRICE_UPDATE_THRESHOLD } from 'legacy/constants'
+import { GAS_PRICE_UPDATE_THRESHOLD } from '@cowprotocol/common-const'
+import { useBlockNumber } from '@cowprotocol/common-hooks'
+import { gasPriceAtom } from '@cowprotocol/core'
+import { useWalletInfo } from '@cowprotocol/wallet'
-import { useWalletInfo } from 'modules/wallet'
+import { useDispatch } from 'react-redux'
-import { gasFeeApi } from 'api/gasPrices'
-import useBlockNumber from 'lib/hooks/useBlockNumber'
+import { AppDispatch } from 'legacy/state'
+import { updateGasPrices, UpdateGasPrices } from 'legacy/state/gas/actions'
+import { useGasPrices } from 'legacy/state/gas/hooks'
-import { useGasPrices, useUpdateGasPrices } from './hooks'
+import { gasFeeApi } from 'api/gasPrices'
function needsGasUpdate(now: number, lastUpdated: number, threshold: number) {
return now - lastUpdated > threshold
}
-export default function GasUpdater(): null {
+function useUpdateGasPrices() {
+ const dispatch = useDispatch()
+ const setGasPrice = useSetAtom(gasPriceAtom)
+
+ return useCallback(
+ (gasParams: UpdateGasPrices) => {
+ dispatch(updateGasPrices(gasParams))
+ setGasPrice(gasParams)
+ },
+ [dispatch, setGasPrice]
+ )
+}
+
+export function GasUpdater(): null {
const { chainId } = useWalletInfo()
const gas = useGasPrices(chainId)
const updateGasPrices = useUpdateGasPrices()
diff --git a/apps/cowswap-frontend/src/modules/wallet/api/updaters/HwAccountIndexUpdater.tsx b/apps/cowswap-frontend/src/common/updaters/HwAccountIndexUpdater.tsx
similarity index 89%
rename from apps/cowswap-frontend/src/modules/wallet/api/updaters/HwAccountIndexUpdater.tsx
rename to apps/cowswap-frontend/src/common/updaters/HwAccountIndexUpdater.tsx
index 3430a75b4e..9a74887a6b 100644
--- a/apps/cowswap-frontend/src/modules/wallet/api/updaters/HwAccountIndexUpdater.tsx
+++ b/apps/cowswap-frontend/src/common/updaters/HwAccountIndexUpdater.tsx
@@ -1,14 +1,11 @@
import { useAtom } from 'jotai'
import { useEffect, useMemo, useRef } from 'react'
+import { getIsHardWareWallet, getWeb3ReactConnection, hwAccountIndexAtom, useWalletInfo } from '@cowprotocol/wallet'
import { useWeb3React } from '@web3-react/core'
import { useAppSelector } from 'legacy/state/hooks'
-import { getIsHardWareWallet, getWeb3ReactConnection } from '../../web3-react/connection'
-import { useWalletInfo } from '../hooks'
-import { hwAccountIndexAtom } from '../state'
-
const indexChanged = true
export function HwAccountIndexUpdater() {
diff --git a/apps/cowswap-frontend/src/legacy/state/lists/updater.ts b/apps/cowswap-frontend/src/common/updaters/ListsUpdater.ts
similarity index 93%
rename from apps/cowswap-frontend/src/legacy/state/lists/updater.ts
rename to apps/cowswap-frontend/src/common/updaters/ListsUpdater.ts
index 133d4a27bb..4998458b55 100644
--- a/apps/cowswap-frontend/src/legacy/state/lists/updater.ts
+++ b/apps/cowswap-frontend/src/common/updaters/ListsUpdater.ts
@@ -1,22 +1,19 @@
import { useCallback, useEffect } from 'react'
+import { UNSUPPORTED_LIST_URLS } from '@cowprotocol/common-const'
+import { useInterval, useIsWindowVisible } from '@cowprotocol/common-hooks'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { getVersionUpgrade, minVersionBump, VersionUpgrade } from '@uniswap/token-lists'
import { useWeb3React } from '@web3-react/core'
-import { UNSUPPORTED_LIST_URLS } from 'legacy/constants/lists'
import { useFetchListCallback } from 'legacy/hooks/useFetchListCallback'
-import useIsWindowVisible from 'legacy/hooks/useIsWindowVisible'
import { updateVersion } from 'legacy/state/global/actions'
import { useAppDispatch } from 'legacy/state/hooks'
import { acceptListUpdate } from 'legacy/state/lists/actions'
import { useAllLists } from 'legacy/state/lists/hooks'
import { useActiveListUrls } from 'legacy/state/lists/hooks'
-import { useWalletInfo } from 'modules/wallet'
-
-import useInterval from 'lib/hooks/useInterval'
-
-export default function Updater(): null {
+export function ListsUpdater(): null {
const { provider } = useWeb3React()
const { chainId } = useWalletInfo()
const dispatch = useAppDispatch()
diff --git a/apps/cowswap-frontend/src/legacy/state/logs/updater.ts b/apps/cowswap-frontend/src/common/updaters/LogsUpdater.ts
similarity index 86%
rename from apps/cowswap-frontend/src/legacy/state/logs/updater.ts
rename to apps/cowswap-frontend/src/common/updaters/LogsUpdater.ts
index 70240a597b..ef12aecdff 100644
--- a/apps/cowswap-frontend/src/legacy/state/logs/updater.ts
+++ b/apps/cowswap-frontend/src/common/updaters/LogsUpdater.ts
@@ -1,18 +1,15 @@
import { useEffect, useMemo } from 'react'
+import { useBlockNumber } from '@cowprotocol/common-hooks'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Filter } from '@ethersproject/providers'
import { useWeb3React } from '@web3-react/core'
-import { useWalletInfo } from 'modules/wallet'
+import { useAppDispatch, useAppSelector } from 'legacy/state/hooks'
+import { fetchedLogs, fetchedLogsError, fetchingLogs } from 'legacy/state/logs/slice'
+import { isHistoricalLog, keyToFilter } from 'legacy/state/logs/utils'
-import useBlockNumber from 'lib/hooks/useBlockNumber'
-
-import { fetchedLogs, fetchedLogsError, fetchingLogs } from './slice'
-import { isHistoricalLog, keyToFilter } from './utils'
-
-import { useAppDispatch, useAppSelector } from '../hooks'
-
-export default function Updater(): null {
+export function LogsUpdater(): null {
const dispatch = useAppDispatch()
const state = useAppSelector((state) => state.logs)
const { provider } = useWeb3React()
diff --git a/apps/cowswap-frontend/src/legacy/state/sentry/updater/index.ts b/apps/cowswap-frontend/src/common/updaters/SentryUpdater.ts
similarity index 71%
rename from apps/cowswap-frontend/src/legacy/state/sentry/updater/index.ts
rename to apps/cowswap-frontend/src/common/updaters/SentryUpdater.ts
index e2893d1220..0b1d6faf3f 100644
--- a/apps/cowswap-frontend/src/legacy/state/sentry/updater/index.ts
+++ b/apps/cowswap-frontend/src/common/updaters/SentryUpdater.ts
@@ -1,13 +1,14 @@
import { useEffect } from 'react'
+import { useIsWindowVisible } from '@cowprotocol/common-hooks'
+import { SentryTag } from '@cowprotocol/common-utils'
+import { useWalletDetails, useWalletInfo } from '@cowprotocol/wallet'
+
import * as Sentry from '@sentry/browser'
-import useIsWindowVisible from 'legacy/hooks/useIsWindowVisible'
import { useAppSelector } from 'legacy/state/hooks'
-import { useDerivedSwapInfo } from 'legacy/state/swap/hooks'
-import { SentryTag } from 'legacy/utils/logging'
-import { useWalletDetails, useWalletInfo } from 'modules/wallet'
+import { useTradeState } from 'modules/trade/hooks/useTradeState'
/**
* _getSentryChainId
@@ -32,20 +33,16 @@ function _getSentryChainIdAndConnectionStatus(appChainId: number | null, connect
return sentryChainId?.toString() || SentryTag.DISCONNECTED
}
-export default function Updater(): null {
+export function SentryUpdater(): null {
const { account, chainId: connectedChainId } = useWalletInfo()
const { walletName } = useWalletDetails()
// app chain id maintains state for users disconnected but browsing app
const disconnectedChainId = useAppSelector((state) => state.application.chainId)
const windowVisible = useIsWindowVisible()
- const {
- currencies: { INPUT: sellCurrency, OUTPUT: buyCurrency },
- currenciesIds: { INPUT: sellCurrencyId, OUTPUT: buyCurrencyId },
- } = useDerivedSwapInfo()
+ const { state } = useTradeState()
- const { symbol: buySymbol, name: buyName } = buyCurrency || {}
- const { symbol: sellSymbol, name: sellName } = sellCurrency || {}
+ const { inputCurrencyId, outputCurrencyId } = state || {}
useEffect(() => {
if (windowVisible) {
@@ -55,8 +52,8 @@ export default function Updater(): null {
// setup a context
scope.setContext('user', {
user: account || SentryTag.DISCONNECTED,
- sellToken: `${sellCurrencyId} <${sellSymbol || sellName}>`,
- buyToken: `${buyCurrencyId} <${buySymbol || buyName}>`,
+ sellToken: inputCurrencyId,
+ buyToken: outputCurrencyId,
})
// also set tags for each session
scope.setTag('chainId', chainId)
@@ -73,12 +70,8 @@ export default function Updater(): null {
disconnectedChainId,
walletName,
// tokens
- sellSymbol,
- sellName,
- buySymbol,
- buyName,
- sellCurrencyId,
- buyCurrencyId,
+ inputCurrencyId,
+ outputCurrencyId,
// window visibility check
windowVisible,
])
diff --git a/apps/cowswap-frontend/src/legacy/state/user/updater.tsx b/apps/cowswap-frontend/src/common/updaters/UserUpdater.tsx
similarity index 89%
rename from apps/cowswap-frontend/src/legacy/state/user/updater.tsx
rename to apps/cowswap-frontend/src/common/updaters/UserUpdater.tsx
index 1b73711638..20db1f7b2f 100644
--- a/apps/cowswap-frontend/src/legacy/state/user/updater.tsx
+++ b/apps/cowswap-frontend/src/common/updaters/UserUpdater.tsx
@@ -1,10 +1,9 @@
import { useEffect } from 'react'
import { useAppDispatch } from 'legacy/state/hooks'
+import { updateMatchesDarkMode } from 'legacy/state/user/reducer'
-import { updateMatchesDarkMode } from './reducer'
-
-export default function Updater(): null {
+export function UserUpdater(): null {
const dispatch = useAppDispatch()
// keep dark mode in sync with the system
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/updaters/CancelledOrdersUpdater.ts b/apps/cowswap-frontend/src/common/updaters/orders/CancelledOrdersUpdater.ts
similarity index 95%
rename from apps/cowswap-frontend/src/legacy/state/orders/updaters/CancelledOrdersUpdater.ts
rename to apps/cowswap-frontend/src/common/updaters/orders/CancelledOrdersUpdater.ts
index 6ce50042c0..ef9920e84d 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/updaters/CancelledOrdersUpdater.ts
+++ b/apps/cowswap-frontend/src/common/updaters/orders/CancelledOrdersUpdater.ts
@@ -1,16 +1,17 @@
import { useCallback, useEffect, useRef } from 'react'
+import { CANCELLED_ORDERS_PENDING_TIME } from '@cowprotocol/common-const'
import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
+import { useWalletInfo } from '@cowprotocol/wallet'
-import { CANCELLED_ORDERS_PENDING_TIME } from 'legacy/constants'
import { OrderFulfillmentData } from 'legacy/state/orders/actions'
import { MARKET_OPERATOR_API_POLL_INTERVAL } from 'legacy/state/orders/consts'
import { useCancelledOrders, useFulfillOrdersBatch } from 'legacy/state/orders/hooks'
-import { fetchOrderPopupData, OrderLogPopupMixData } from 'legacy/state/orders/updaters/utils'
import { OrderTransitionStatus } from 'legacy/state/orders/utils'
import { useAddOrderToSurplusQueue } from 'modules/swap/state/surplusModal'
-import { useWalletInfo } from 'modules/wallet'
+
+import { fetchOrderPopupData, OrderLogPopupMixData } from './utils'
/**
* Updater for cancelled orders.
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/updaters/ExpiredOrdersUpdater.ts b/apps/cowswap-frontend/src/common/updaters/orders/ExpiredOrdersUpdater.ts
similarity index 74%
rename from apps/cowswap-frontend/src/legacy/state/orders/updaters/ExpiredOrdersUpdater.ts
rename to apps/cowswap-frontend/src/common/updaters/orders/ExpiredOrdersUpdater.ts
index 5d823a8254..006c88b659 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/updaters/ExpiredOrdersUpdater.ts
+++ b/apps/cowswap-frontend/src/common/updaters/orders/ExpiredOrdersUpdater.ts
@@ -1,14 +1,13 @@
import { useEffect, useCallback, useRef } from 'react'
+import { NATIVE_CURRENCY_BUY_ADDRESS } from '@cowprotocol/common-const'
import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
+import { useWalletInfo } from '@cowprotocol/wallet'
-import { EXPIRED_ORDERS_PENDING_TIME } from 'legacy/constants'
import { SetIsOrderRefundedBatch } from 'legacy/state/orders/actions'
import { EXPIRED_ORDERS_CHECK_POLL_INTERVAL } from 'legacy/state/orders/consts'
import { useExpiredOrders, useSetIsOrderRefundedBatch } from 'legacy/state/orders/hooks'
-import { useWalletInfo } from 'modules/wallet'
-
import { getOrder } from 'api/gnosisProtocol'
export function ExpiredOrdersUpdater(): null {
@@ -25,7 +24,6 @@ export function ExpiredOrdersUpdater(): null {
const updateOrders = useCallback(
async (chainId: ChainId, account: string) => {
const lowerCaseAccount = account.toLowerCase()
- const now = Date.now()
if (isUpdating.current) {
return
@@ -34,26 +32,24 @@ export function ExpiredOrdersUpdater(): null {
try {
isUpdating.current = true
- // Filter orders:
+ // Filter expired orders:
+ // - Only eth-flow orders
// - Owned by the current connected account
- // - Created in the last 5 min, no further
// - Not yet refunded
- const pending = expiredRef.current.filter(({ owner, creationTime: creationTimeString, refundHash }) => {
- const creationTime = new Date(creationTimeString).getTime()
+ const orderWithoutRefund = expiredRef.current.filter(({ owner, refundHash, sellToken }) => {
+ const isEthFlowOrder = sellToken === NATIVE_CURRENCY_BUY_ADDRESS
- return (
- owner.toLowerCase() === lowerCaseAccount && now - creationTime < EXPIRED_ORDERS_PENDING_TIME && !refundHash
- )
+ return isEthFlowOrder && owner.toLowerCase() === lowerCaseAccount && !refundHash
})
- if (pending.length === 0) {
+ if (orderWithoutRefund.length === 0) {
// console.debug(`[CancelledOrdersUpdater] No orders are being expired`)
return
} else {
- console.debug(`[ExpiredOrdersUpdater] Checking ${pending.length} recently expired orders...`)
+ console.debug(`[ExpiredOrdersUpdater] Checking ${orderWithoutRefund.length} recently expired orders...`)
}
- const ordersPromises = pending.map(({ id }) => getOrder(chainId, id))
+ const ordersPromises = orderWithoutRefund.map(({ id }) => getOrder(chainId, id))
const resolvedPromises = await Promise.allSettled(ordersPromises)
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/updaters/GpOrdersUpdater.ts b/apps/cowswap-frontend/src/common/updaters/orders/GpOrdersUpdater.ts
similarity index 96%
rename from apps/cowswap-frontend/src/legacy/state/orders/updaters/GpOrdersUpdater.ts
rename to apps/cowswap-frontend/src/common/updaters/orders/GpOrdersUpdater.ts
index 18dcae9e3b..c2cc7923c4 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/updaters/GpOrdersUpdater.ts
+++ b/apps/cowswap-frontend/src/common/updaters/orders/GpOrdersUpdater.ts
@@ -1,23 +1,24 @@
import { useSetAtom } from 'jotai'
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 { useWalletInfo } from '@cowprotocol/wallet'
import { Token } from '@uniswap/sdk-core'
-import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants'
import { useAllTokens } from 'legacy/hooks/Tokens'
import { Order, OrderStatus } from 'legacy/state/orders/actions'
import { useAddOrUpdateOrders, useClearOrdersStorage } from 'legacy/state/orders/hooks'
-import { computeOrderSummary } from 'legacy/state/orders/updaters/utils'
import { classifyOrder, OrderTransitionStatus } from 'legacy/state/orders/utils'
-import { useTokensForOrdersList, getTokensListFromOrders } from 'modules/orders'
+import { getTokensListFromOrders, useTokensForOrdersList } from 'modules/orders'
import { apiOrdersAtom } from 'modules/orders/state/apiOrdersAtom'
-import { useWalletInfo } from 'modules/wallet'
import { useGpOrders } from 'api/gnosisProtocol/hooks'
import { getTokenFromMapping } from 'utils/orderUtils/getTokenFromMapping'
+import { computeOrderSummary } from './utils'
+
// TODO: update this for ethflow states
const statusMapping: Record = {
cancelled: OrderStatus.CANCELLED,
@@ -79,6 +80,7 @@ function _transformGpOrderToStoreOrder(
summary: '',
status,
receiver: receiver || '',
+ fullAppData: order.fullAppData,
apiAdditionalInfo: order,
isCancelling: apiStatus === 'pending' && order.invalidated, // already cancelled in the API, not yet in the UI
// EthFlow related
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/updaters/PendingOrdersUpdater.ts b/apps/cowswap-frontend/src/common/updaters/orders/PendingOrdersUpdater.ts
similarity index 95%
rename from apps/cowswap-frontend/src/legacy/state/orders/updaters/PendingOrdersUpdater.ts
rename to apps/cowswap-frontend/src/common/updaters/orders/PendingOrdersUpdater.ts
index 6db86d83fe..154a24b889 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/updaters/PendingOrdersUpdater.ts
+++ b/apps/cowswap-frontend/src/common/updaters/orders/PendingOrdersUpdater.ts
@@ -1,7 +1,14 @@
import { useSetAtom } from 'jotai'
import { useCallback, useEffect, useRef } from 'react'
+import {
+ getExplorerOrderLink,
+ isOrderInPendingTooLong,
+ openNpsAppziSometimes,
+ timeSinceInSeconds,
+} from '@cowprotocol/common-utils'
import { EthflowData, OrderClass, SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { GetSafeInfo, useGetSafeInfo } from 'legacy/hooks/useGetSafeInfo'
import { FulfillOrdersBatchParams, Order, OrderFulfillmentData, OrderStatus } from 'legacy/state/orders/actions'
@@ -21,18 +28,16 @@ import {
usePresignOrders,
useUpdatePresignGnosisSafeTx,
} from 'legacy/state/orders/hooks'
-import { fetchOrderPopupData, OrderLogPopupMixData } from 'legacy/state/orders/updaters/utils'
import { OrderTransitionStatus } from 'legacy/state/orders/utils'
-import { isOrderInPendingTooLong, openNpsAppziSometimes } from 'legacy/utils/appzi'
-import { getExplorerOrderLink } from 'legacy/utils/explorer'
import { useAddOrderToSurplusQueue } from 'modules/swap/state/surplusModal'
-import { useWalletInfo } from 'modules/wallet'
import { getOrder, OrderID } from 'api/gnosisProtocol'
-import { removeOrdersToCancelAtom } from 'common/hooks/useMultipleOrdersCancellation/state'
-import { useTriggerTotalSurplusUpdateCallback } from 'common/state/totalSurplusState'
-import { timeSinceInSeconds } from 'utils/time'
+
+import { fetchOrderPopupData, OrderLogPopupMixData } from './utils'
+
+import { removeOrdersToCancelAtom } from '../../hooks/useMultipleOrdersCancellation/state'
+import { useTriggerTotalSurplusUpdateCallback } from '../../state/totalSurplusState'
/**
* Return the ids of the orders that we are not yet aware that are signed.
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/updaters/SpotPricesUpdater.ts b/apps/cowswap-frontend/src/common/updaters/orders/SpotPricesUpdater.ts
similarity index 93%
rename from apps/cowswap-frontend/src/legacy/state/orders/updaters/SpotPricesUpdater.ts
rename to apps/cowswap-frontend/src/common/updaters/orders/SpotPricesUpdater.ts
index 1bc75801b0..9f09e4af74 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/updaters/SpotPricesUpdater.ts
+++ b/apps/cowswap-frontend/src/common/updaters/orders/SpotPricesUpdater.ts
@@ -1,20 +1,20 @@
import { useSetAtom } from 'jotai'
import { useCallback, useEffect, useRef } from 'react'
+import { useIsWindowVisible } from '@cowprotocol/common-hooks'
+import { FractionUtils } from '@cowprotocol/common-utils'
import { OrderClass, SupportedChainId } from '@cowprotocol/cow-sdk'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Token } from '@uniswap/sdk-core'
-import useIsWindowVisible from 'legacy/hooks/useIsWindowVisible'
import { SPOT_PRICE_CHECK_POLL_INTERVAL } from 'legacy/state/orders/consts'
import { useCombinedPendingOrders } from 'legacy/state/orders/hooks'
import { requestPrice } from 'modules/limitOrders/hooks/useGetInitialPrice'
import { UpdateSpotPriceAtom, updateSpotPricesAtom } from 'modules/orders/state/spotPricesAtom'
-import { useWalletInfo } from 'modules/wallet'
-import { useSafeMemo } from 'common/hooks/useSafeMemo'
-import { getCanonicalMarketChainKey } from 'common/utils/markets'
-import { FractionUtils } from 'utils/fractionUtils'
+import { useSafeMemo } from '../../hooks/useSafeMemo'
+import { getCanonicalMarketChainKey } from '../../utils/markets'
type MarketRecord = Record<
string,
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/updaters/UnfillableOrdersUpdater.ts b/apps/cowswap-frontend/src/common/updaters/orders/UnfillableOrdersUpdater.ts
similarity index 93%
rename from apps/cowswap-frontend/src/legacy/state/orders/updaters/UnfillableOrdersUpdater.ts
rename to apps/cowswap-frontend/src/common/updaters/orders/UnfillableOrdersUpdater.ts
index c8e3080f99..20270205bc 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/updaters/UnfillableOrdersUpdater.ts
+++ b/apps/cowswap-frontend/src/common/updaters/orders/UnfillableOrdersUpdater.ts
@@ -1,17 +1,18 @@
import { useSetAtom } from 'jotai'
import { useCallback, useEffect, useMemo, useRef } from 'react'
+import { priceOutOfRangeAnalytics } from '@cowprotocol/analytics'
+import { GP_VAULT_RELAYER, NATIVE_CURRENCY_BUY_ADDRESS, WRAPPED_NATIVE_CURRENCY } from '@cowprotocol/common-const'
+import { useIsWindowVisible } from '@cowprotocol/common-hooks'
+import { getPromiseFulfilledValue } from '@cowprotocol/common-utils'
import { timestamp } from '@cowprotocol/contracts'
import { OrderClass, SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Currency, CurrencyAmount, Price } from '@uniswap/sdk-core'
import { FeeInformation, PriceInformation } from 'types'
-import { priceOutOfRangeAnalytics } from 'legacy/components/analytics'
-import { GP_VAULT_RELAYER, NATIVE_CURRENCY_BUY_ADDRESS } from 'legacy/constants'
-import { WRAPPED_NATIVE_CURRENCY } from 'legacy/constants/tokens'
import { useGetGpPriceStrategy } from 'legacy/hooks/useGetGpPriceStrategy'
-import useIsWindowVisible from 'legacy/hooks/useIsWindowVisible'
import { GpPriceStrategy } from 'legacy/state/gas/atoms'
import { Order } from 'legacy/state/orders/actions'
import { PENDING_ORDERS_PRICE_CHECK_POLL_INTERVAL } from 'legacy/state/orders/consts'
@@ -22,16 +23,15 @@ import {
getRemainderAmount,
isOrderUnfillable,
} from 'legacy/state/orders/utils'
-import { getPromiseFulfilledValue } from 'legacy/utils/misc'
import { getBestQuote } from 'legacy/utils/price'
import { updatePendingOrderPricesAtom } from 'modules/orders/state/pendingOrdersPricesAtom'
import { hasEnoughBalanceAndAllowance, useBalancesAndAllowances } from 'modules/tokens'
-import { useWalletInfo } from 'modules/wallet'
import { getPriceQuality } from 'api/gnosisProtocol/api'
-import { PRICE_QUOTE_VALID_TO_TIME } from 'common/constants/quote'
-import { useVerifiedQuotesEnabled } from 'common/hooks/featureFlags/useVerifiedQuotesEnabled'
+
+import { PRICE_QUOTE_VALID_TO_TIME } from '../../constants/quote'
+import { useVerifiedQuotesEnabled } from '../../hooks/featureFlags/useVerifiedQuotesEnabled'
/**
* Updater that checks whether pending orders are still "fillable"
@@ -146,7 +146,7 @@ export function UnfillableOrdersUpdater(): null {
console.debug(`[UnfillableOrdersUpdater] Check order`, order)
const currencyAmount = CurrencyAmount.fromRawAmount(order.inputToken, order.sellAmount)
- const enoughBalance = hasEnoughBalanceAndAllowance({
+ const { enoughBalance } = hasEnoughBalanceAndAllowance({
account,
amount: currencyAmount,
balances: balancesRef.current,
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/updaters/index.ts b/apps/cowswap-frontend/src/common/updaters/orders/index.ts
similarity index 100%
rename from apps/cowswap-frontend/src/legacy/state/orders/updaters/index.ts
rename to apps/cowswap-frontend/src/common/updaters/orders/index.ts
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/updaters/utils.ts b/apps/cowswap-frontend/src/common/updaters/orders/utils.ts
similarity index 96%
rename from apps/cowswap-frontend/src/legacy/state/orders/updaters/utils.ts
rename to apps/cowswap-frontend/src/common/updaters/orders/utils.ts
index e1a916ef03..7fb3f3a37c 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/updaters/utils.ts
+++ b/apps/cowswap-frontend/src/common/updaters/orders/utils.ts
@@ -1,14 +1,12 @@
+import { formatSymbol, formatTokenAmount, shortenAddress } from '@cowprotocol/common-utils'
import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
import { EnrichedOrder, OrderKind } from '@cowprotocol/cow-sdk'
import { Order, OrderFulfillmentData, OrderStatus } from 'legacy/state/orders/actions'
import { classifyOrder, OrderTransitionStatus } from 'legacy/state/orders/utils'
import { stringToCurrency } from 'legacy/state/swap/extension'
-import { shortenAddress } from 'legacy/utils'
import { getOrder, OrderID } from 'api/gnosisProtocol'
-import { formatTokenAmount } from 'utils/amountFormat'
-import { formatSymbol } from 'utils/format'
import { getIsComposableCowChildOrder } from 'utils/orderUtils/getIsComposableCowChildOrder'
export type OrderLogPopupMixData = OrderFulfillmentData | OrderID
diff --git a/apps/cowswap-frontend/src/common/utils/isOrderCancellable.test.ts b/apps/cowswap-frontend/src/common/utils/isOrderCancellable.test.ts
index ac2a9a0aea..c7fbeead13 100644
--- a/apps/cowswap-frontend/src/common/utils/isOrderCancellable.test.ts
+++ b/apps/cowswap-frontend/src/common/utils/isOrderCancellable.test.ts
@@ -1,5 +1,6 @@
-import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants'
-import { COW } from 'legacy/constants/tokens'
+import { COW } from '@cowprotocol/common-const'
+import { NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const'
+
import { Order, OrderStatus } from 'legacy/state/orders/actions'
import { isOrderCancellable } from './isOrderCancellable'
diff --git a/apps/cowswap-frontend/src/common/utils/markets.ts b/apps/cowswap-frontend/src/common/utils/markets.ts
index ceb8728937..e977992483 100644
--- a/apps/cowswap-frontend/src/common/utils/markets.ts
+++ b/apps/cowswap-frontend/src/common/utils/markets.ts
@@ -1,7 +1,4 @@
import { SupportedChainId } from '@cowprotocol/cow-sdk'
-import { Currency, Price } from '@uniswap/sdk-core'
-
-import invariant from 'tiny-invariant'
/**
* Convenient method to identify a market so it doesn't matter what is the sell token or buy token.
@@ -51,11 +48,3 @@ export function getCanonicalMarketChainKey(
marketInverted,
}
}
-
-export function assertSameMarket(price1: Price, price2: Price) {
- // Assert I'm comparing apples with apples (prices should refer to market)
- invariant(
- price1.baseCurrency.equals(price2.baseCurrency) && price1.quoteCurrency.equals(price2.quoteCurrency),
- 'Prices are not from the same market'
- )
-}
diff --git a/apps/cowswap-frontend/src/cosmos.decorator.tsx b/apps/cowswap-frontend/src/cosmos.decorator.tsx
index 3460702d23..04bffb1c00 100644
--- a/apps/cowswap-frontend/src/cosmos.decorator.tsx
+++ b/apps/cowswap-frontend/src/cosmos.decorator.tsx
@@ -3,6 +3,10 @@ import './polyfills'
import React, { StrictMode, useCallback, useContext, ReactNode } from 'react'
+import IMAGE_MOON from '@cowprotocol/assets/cow-swap/moon.svg'
+import IMAGE_SUN from '@cowprotocol/assets/cow-swap/sun.svg'
+import { BlockNumberProvider } from '@cowprotocol/common-hooks'
+import { WalletUpdater, injectedConnection } from '@cowprotocol/wallet'
import { Web3ReactProvider } from '@web3-react/core'
import { LanguageProvider } from 'i18n'
@@ -13,18 +17,10 @@ import { Flex } from 'rebass'
import styled from 'styled-components/macro'
import { ThemeContext } from 'styled-components/macro'
-import IMAGE_MOON from 'legacy/assets/cow-swap/moon.svg'
-import IMAGE_SUN from 'legacy/assets/cow-swap/sun.svg'
-import store from 'legacy/state'
+import { cowSwapStore } from 'legacy/state'
import { useDarkModeManager } from 'legacy/state/user/hooks'
import ThemeProvider, { FixedGlobalStyle, ThemedGlobalStyle } from 'legacy/theme'
-import { injectedConnection } from 'modules/wallet/web3-react/connection/injected'
-
-import { BlockNumberProvider } from 'lib/hooks/useBlockNumber'
-
-import { WalletUpdater } from './modules/wallet'
-
const DarkModeToggleButton = styled.button`
display: flex;
align-items: center;
@@ -98,7 +94,7 @@ const Fixture = ({ children }: { children: ReactNode }) => {
return (
-
+
diff --git a/apps/cowswap-frontend/src/cow-react/index.tsx b/apps/cowswap-frontend/src/cow-react/index.tsx
index f20b500682..550ac9907f 100644
--- a/apps/cowswap-frontend/src/cow-react/index.tsx
+++ b/apps/cowswap-frontend/src/cow-react/index.tsx
@@ -1,12 +1,15 @@
import '@reach/dialog/styles.css'
import 'inter-ui'
-import 'legacy/components/analytics'
-import 'utils/sentry'
+import '@cowprotocol/analytics'
+import './sentry'
import { Provider as AtomProvider } from 'jotai'
import { StrictMode } from 'react'
-import { SnackbarsWidget } from '@cowswap/snackbars'
+import { BlockNumberProvider } from '@cowprotocol/common-hooks'
+import { nodeRemoveChildFix } from '@cowprotocol/common-utils'
+import { jotaiStore } from '@cowprotocol/core'
+import { SnackbarsWidget } from '@cowprotocol/snackbars'
import { LanguageProvider } from 'i18n'
import { createRoot } from 'react-dom/client'
@@ -17,9 +20,8 @@ import * as serviceWorkerRegistration from 'serviceWorkerRegistration'
import AppziButton from 'legacy/components/AppziButton'
import { Popups } from 'legacy/components/Popups'
import Web3Provider from 'legacy/components/Web3Provider'
-import store from 'legacy/state'
+import { cowSwapStore } from 'legacy/state'
import ThemeProvider, { FixedGlobalStyle, ThemedGlobalStyle } from 'legacy/theme'
-import { nodeRemoveChildFix } from 'legacy/utils/node'
import { App } from 'modules/application/containers/App'
import { Updaters } from 'modules/application/containers/App/Updaters'
@@ -27,10 +29,8 @@ import { WithLDProvider } from 'modules/application/containers/WithLDProvider'
import { FortuneWidget } from 'modules/fortune/containers/FortuneWidget'
import { FeatureGuard } from 'common/containers/FeatureGuard'
-import { BlockNumberProvider } from 'lib/hooks/useBlockNumber'
import { WalletUnsupportedNetworkBanner } from '../common/containers/WalletUnsupportedNetworkBanner'
-import { jotaiStore } from '../jotaiStore'
// Node removeChild hackaround
// based on: https://github.com/facebook/react/issues/11538#issuecomment-417504600
@@ -45,7 +45,7 @@ const root = createRoot(document.getElementById('root')!)
root.render(
-
+
diff --git a/apps/cowswap-frontend/src/utils/sentry.ts b/apps/cowswap-frontend/src/cow-react/sentry.ts
similarity index 93%
rename from apps/cowswap-frontend/src/utils/sentry.ts
rename to apps/cowswap-frontend/src/cow-react/sentry.ts
index 868867d629..43cd6d3e11 100644
--- a/apps/cowswap-frontend/src/utils/sentry.ts
+++ b/apps/cowswap-frontend/src/cow-react/sentry.ts
@@ -1,6 +1,6 @@
-import * as Sentry from '@sentry/react'
+import { environmentName } from '@cowprotocol/common-utils'
-import { environmentName } from 'legacy/utils/environments'
+import * as Sentry from '@sentry/react'
import { SENTRY_IGNORED_GP_QUOTE_ERRORS } from 'api/gnosisProtocol/errors/QuoteError'
diff --git a/apps/cowswap-frontend/src/cowSdk.ts b/apps/cowswap-frontend/src/cowSdk.ts
index 94b6582b6c..8fe22917e6 100644
--- a/apps/cowswap-frontend/src/cowSdk.ts
+++ b/apps/cowswap-frontend/src/cowSdk.ts
@@ -1,8 +1,7 @@
import { MetadataApi } from '@cowprotocol/app-data'
+import { isBarnBackendEnv } from '@cowprotocol/common-utils'
import { OrderBookApi } from '@cowprotocol/cow-sdk'
-import { isBarnBackendEnv } from 'legacy/utils/environments'
-
const prodBaseUrls = process.env.REACT_APP_ORDER_BOOK_URLS
? JSON.parse(process.env.REACT_APP_ORDER_BOOK_URLS)
: undefined
diff --git a/apps/cowswap-frontend/src/i18n.tsx b/apps/cowswap-frontend/src/i18n.tsx
index 43c79e78e9..bc78401fc2 100644
--- a/apps/cowswap-frontend/src/i18n.tsx
+++ b/apps/cowswap-frontend/src/i18n.tsx
@@ -1,6 +1,7 @@
import { ReactNode, useCallback } from 'react'
-import { SupportedLocale } from 'legacy/constants/locales'
+import { SupportedLocale } from '@cowprotocol/common-const'
+
import { initialLocale, useActiveLocale } from 'legacy/hooks/useActiveLocale'
import { useUserLocaleManager } from 'legacy/state/user/hooks'
diff --git a/apps/cowswap-frontend/src/legacy/assets/images/arrow-down-grey.svg b/apps/cowswap-frontend/src/legacy/assets/images/arrow-down-grey.svg
deleted file mode 100644
index 886808296c..0000000000
--- a/apps/cowswap-frontend/src/legacy/assets/images/arrow-down-grey.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/apps/cowswap-frontend/src/legacy/components/AMMsLogo/index.tsx b/apps/cowswap-frontend/src/legacy/components/AMMsLogo/index.tsx
index 219680b64a..eb8e1e0c3d 100644
--- a/apps/cowswap-frontend/src/legacy/components/AMMsLogo/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/AMMsLogo/index.tsx
@@ -1,21 +1,20 @@
+import ZeroX from '@cowprotocol/assets/cow-swap/ammslogo/0x.png'
+import Oneinch from '@cowprotocol/assets/cow-swap/ammslogo/1inch.png'
+import Baoswap from '@cowprotocol/assets/cow-swap/ammslogo/baoswap.png'
+import Curve from '@cowprotocol/assets/cow-swap/ammslogo/curve.png'
+import Elk from '@cowprotocol/assets/cow-swap/ammslogo/elk.png'
+import Honeyswap from '@cowprotocol/assets/cow-swap/ammslogo/honeyswap.png'
+import Levinswap from '@cowprotocol/assets/cow-swap/ammslogo/levinswap.png'
+import Matcha from '@cowprotocol/assets/cow-swap/ammslogo/matcha.png'
+import Paraswap from '@cowprotocol/assets/cow-swap/ammslogo/paraswap.png'
+import Sushi from '@cowprotocol/assets/cow-swap/ammslogo/sushi.png'
+import Swapr from '@cowprotocol/assets/cow-swap/ammslogo/swapr.png'
+import Symmetric from '@cowprotocol/assets/cow-swap/ammslogo/symmetric.png'
+import Uniswap from '@cowprotocol/assets/cow-swap/ammslogo/uniswap.png'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import styled from 'styled-components/macro'
-import ZeroX from 'legacy/assets/cow-swap/ammslogo/0x.png'
-import Oneinch from 'legacy/assets/cow-swap/ammslogo/1inch.png'
-import Baoswap from 'legacy/assets/cow-swap/ammslogo/baoswap.png'
-import Curve from 'legacy/assets/cow-swap/ammslogo/curve.png'
-import Elk from 'legacy/assets/cow-swap/ammslogo/elk.png'
-import Honeyswap from 'legacy/assets/cow-swap/ammslogo/honeyswap.png'
-import Levinswap from 'legacy/assets/cow-swap/ammslogo/levinswap.png'
-import Matcha from 'legacy/assets/cow-swap/ammslogo/matcha.png'
-import Paraswap from 'legacy/assets/cow-swap/ammslogo/paraswap.png'
-import Sushi from 'legacy/assets/cow-swap/ammslogo/sushi.png'
-import Swapr from 'legacy/assets/cow-swap/ammslogo/swapr.png'
-import Symmetric from 'legacy/assets/cow-swap/ammslogo/symmetric.png'
-import Uniswap from 'legacy/assets/cow-swap/ammslogo/uniswap.png'
-
import { imagesAnimationDelay, animationDelay, crossFade, fadeInOut, presentationTime } from './utils'
export const Wrapper = styled.div<{ logosLength: number }>`
diff --git a/apps/cowswap-frontend/src/legacy/components/AddressInputPanel/index.tsx b/apps/cowswap-frontend/src/legacy/components/AddressInputPanel/index.tsx
index f75bb1abd8..a16f629887 100644
--- a/apps/cowswap-frontend/src/legacy/components/AddressInputPanel/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/AddressInputPanel/index.tsx
@@ -1,23 +1,25 @@
import { ChangeEvent, Context, ReactNode, useCallback, useContext } from 'react'
+import { getBlockExplorerUrl as getExplorerLink } from '@cowprotocol/common-utils'
+import { useENS } from '@cowprotocol/ens'
+import { RowBetween } from '@cowprotocol/ui'
+import { ExternalLink } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
+
import { t, Trans } from '@lingui/macro'
import styled, { DefaultTheme, ThemeContext } from 'styled-components/macro'
import { AutoColumn } from 'legacy/components/Column'
-import { RowBetween } from 'legacy/components/Row'
-import useENS from 'legacy/hooks/useENS'
-import { ExternalLink, ThemedText } from 'legacy/theme'
-import { getBlockExplorerUrl as getExplorerLink } from 'legacy/utils'
-
-import { useWalletInfo } from 'modules/wallet'
+import { ThemedText } from 'legacy/theme'
+import { UI } from 'common/constants/theme'
import { autofocus } from 'common/utils/autofocus'
const InputPanel = styled.div`
${({ theme }) => theme.flexColumnNoWrap}
position: relative;
border-radius: 16px;
- background-color: ${({ theme }) => theme.grey1};
+ background-color: var(${UI.COLOR_GREY});
z-index: 1;
width: 100%;
`
@@ -28,7 +30,7 @@ const ContainerRow = styled.div<{ error: boolean }>`
align-items: center;
border-radius: 16px;
border: 0;
- background-color: ${({ theme }) => theme.grey1};
+ background-color: var(${UI.COLOR_GREY});
`
export const InputContainer = styled.div`
@@ -50,7 +52,7 @@ const Input = styled.input<{ error?: boolean }>`
width: 100%;
&&::placeholder {
- color: ${({ theme }) => theme.text2};
+ color: var(${UI.COLOR_TEXT2});
}
&:focus::placeholder {
diff --git a/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/Trace.tsx b/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/Trace.tsx
deleted file mode 100644
index 52fe79b8a1..0000000000
--- a/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/Trace.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-import { createContext, memo, PropsWithChildren, useContext, useEffect, useMemo } from 'react'
-
-import {
- ElementName,
- EventName,
- ModalName,
- PageName,
- SectionName,
-} from 'legacy/components/AmplitudeAnalytics/constants' // Mod
-
-import { sendAnalyticsEvent } from '.'
-
-export interface ITraceContext {
- // Highest order context: eg Swap or Explore.
- page?: PageName
-
- // Enclosed section name. For contexts with modals, refers to the
- // section of the page from which the user triggered the modal.
- section?: SectionName
-
- modal?: ModalName
-
- // Element name mostly used to identify events sources
- // Does not need to be unique given the higher order page and section.
- element?: ElementName
-}
-
-export const TraceContext = createContext({})
-
-type TraceProps = {
- shouldLogImpression?: boolean // whether to log impression on mount
- name?: EventName
- properties?: Record
-} & ITraceContext
-
-/**
- * Sends an analytics event on mount (if shouldLogImpression is set),
- * and propagates the context to child traces.
- */
-export const Trace = memo(
- ({ shouldLogImpression, name, children, page, section, element, properties }: PropsWithChildren) => {
- const parentTrace = useContext(TraceContext)
-
- const combinedProps = useMemo(
- () => ({
- ...parentTrace,
- ...Object.fromEntries(Object.entries({ page, section, element }).filter(([_, v]) => v !== undefined)),
- }),
- [element, parentTrace, page, section]
- )
-
- useEffect(() => {
- if (shouldLogImpression) {
- sendAnalyticsEvent(name ?? EventName.PAGE_VIEWED, { ...combinedProps, ...properties })
- }
- // Impressions should only be logged on mount.
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [])
-
- return {children}
- }
-)
-
-Trace.displayName = 'Trace'
diff --git a/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/TraceEvent.tsx b/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/TraceEvent.tsx
deleted file mode 100644
index 08480d63f5..0000000000
--- a/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/TraceEvent.tsx
+++ /dev/null
@@ -1,71 +0,0 @@
-import { Children, cloneElement, isValidElement, memo, PropsWithChildren, SyntheticEvent } from 'react'
-
-import { Event, EventName } from './constants'
-import { ITraceContext, Trace, TraceContext } from './Trace'
-
-import { sendAnalyticsEvent } from '.'
-
-type TraceEventProps = {
- events: Event[]
- name: EventName
- properties?: Record
-} & ITraceContext
-
-/**
- * Analytics instrumentation component that wraps event callbacks with logging logic.
- *
- * @example
- *
- * console.log('clicked')}>Click me
- *
- */
-export const TraceEvent = memo((props: PropsWithChildren) => {
- const { name, properties, events, children, ...traceProps } = props
-
- return (
-
-
- {(traceContext) =>
- Children.map(children, (child) => {
- if (!isValidElement(child)) {
- return child
- }
-
- // For each child, augment event handlers defined in `events` with event tracing.
- return cloneElement(child, getEventHandlers(child, traceContext, events, name, properties))
- })
- }
-
-
- )
-})
-
-TraceEvent.displayName = 'TraceEvent'
-
-/**
- * Given a set of child element and event props, returns a spreadable
- * object of the event handlers augmented with analytics logging.
- */
-function getEventHandlers(
- child: React.ReactElement,
- traceContext: ITraceContext,
- events: Event[],
- name: EventName,
- properties?: Record
-) {
- const eventHandlers: Partial) => void>> = {}
-
- for (const event of events) {
- eventHandlers[event] = (eventHandlerArgs: unknown) => {
- // call child event handler with original arguments, must be in array
- const args = Array.isArray(eventHandlerArgs) ? eventHandlerArgs : [eventHandlerArgs]
- child.props[event]?.apply(child, args)
-
- // augment handler with analytics logging
- sendAnalyticsEvent(name, { ...traceContext, ...properties, action: event })
- }
- }
-
- // return a spreadable event handler object
- return eventHandlers
-}
diff --git a/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/constants.ts b/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/constants.ts
deleted file mode 100644
index e73d0f2ab5..0000000000
--- a/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/constants.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * Event names that can occur in this application.
- *
- * Subject to change as new features are added and new events are defined
- * and logged.
- */
-export enum EventName {
- PAGE_VIEWED = 'Page Viewed',
- SWAP_SUBMITTED = 'Swap Submitted',
- TOKEN_IMPORTED = 'Token Imported',
- TOKEN_SELECTED = 'Token Selected',
- TOKEN_SELECTOR_OPENED = 'Token Selector Opened',
- // alphabetize additional event names.
-}
-
-/**
- * Known pages in the app. Highest order context.
- */
-export const enum PageName {
- EXPLORE_PAGE = 'explore-page',
- POOL_PAGE = 'pool-page',
- SWAP_PAGE = 'swap-page',
- VOTE_PAGE = 'vote-page',
- // alphabetize additional page names.
- ACCOUNT_OVERVIEW_PAGE = 'account-overview-page',
- ACCOUNT_TOKENS_PAGE = 'account-tokens-page',
- ABOUT_PAGE = 'about-page',
- FAQ_OVERVIEW_PAGE = 'faq-overview-page',
- FAQ_PROTOCOL_PAGE = 'faq-protocol-page',
- FAQ_TOKEN_PAGE = 'faq-token-page',
- FAQ_TRADING_PAGE = 'faq-trading-page',
- FAQ_AFFILIATE_PAGE = 'faq-affiliate-page',
- FAQ_LIMIT_ORDERS_PAGE = 'faq-limit-orders-page',
- FAQ_ETH_FLOW = 'faq-eth-flow',
- TOC_PAGE = 'toc-page',
-}
-
-/**
- * Sections. Disambiguates low-level elements that may share a name.
- * eg a `back` button in a modal will have the same `element`,
- * but a different `section`.
- */
-export const enum SectionName {
- CURRENCY_INPUT_PANEL = 'swap-currency-input',
- CURRENCY_OUTPUT_PANEL = 'swap-currency-output',
- // alphabetize additional section names.
-}
-
-/** Known modals for analytics purposes. */
-export const enum ModalName {
- SWAP = 'swap-modal',
- TOKEN_SELECTOR = 'token-selector-modal',
- // alphabetize additional modal names.
-}
-
-/**
- * Known element names for analytics purposes.
- * Use to identify low-level components given a TraceContext
- */
-export const enum ElementName {
- COMMON_BASES_CURRENCY_BUTTON = 'common-bases-currency-button',
- CONFIRM_SWAP_BUTTON = 'confirm-swap-or-send',
- IMPORT_TOKEN_BUTTON = 'import-token-button',
- SWAP_BUTTON = 'swap-button',
- TOKEN_SELECTOR_ROW = 'token-selector-row',
- // alphabetize additional element names.
-}
-
-/**
- * Known events that trigger callbacks.
- * @example
- *
- */
-export enum Event {
- onClick = 'onClick',
- onKeyPress = 'onKeyPress',
- onSelect = 'onSelect',
- // alphabetize additional events.
-}
diff --git a/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/index.ts b/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/index.ts
deleted file mode 100644
index d6533cc94d..0000000000
--- a/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/index.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-import { Identify, identify, init, track } from '@amplitude/analytics-browser'
-
-/**
- * Initializes Amplitude with API key for project.
- *
- * Uniswap has two Amplitude projects: test and production. You must be a
- * member of the organization on Amplitude to view details.
- */
-export function initializeAnalytics(isDevEnvironment = process.env.NODE_ENV === 'development') {
- if (isDevEnvironment) return
-
- const API_KEY = process.env.REACT_APP_AMPLITUDE_KEY
- if (typeof API_KEY === 'undefined') {
- throw new Error(`REACT_APP_AMPLITUDE_KEY must be a defined environment variable`)
- }
-
- init(
- API_KEY,
- /* userId= */ undefined, // User ID should be undefined to let Amplitude default to Device ID
- /* options= */ {
- // Disable tracking of private user information by Amplitude
- trackingOptions: {
- ipAddress: false,
- carrier: false,
- city: false,
- region: false,
- country: false,
- dma: false, // designated market area
- },
- }
- )
-}
-
-/** Sends an event to Amplitude. */
-export function sendAnalyticsEvent(eventName: string, eventProperties?: Record) {
- if (process.env.NODE_ENV === 'development') {
- console.log(`[amplitude(${eventName})]: ${JSON.stringify(eventProperties)}`)
- return
- }
-
- track(eventName, eventProperties)
-}
-
-/**
- * Class that exposes methods to mutate the User Model's properties in
- * Amplitude that represents the current session's user.
- *
- * See https://help.amplitude.com/hc/en-us/articles/115002380567-User-properties-and-event-properties
- * for details.
- */
-class UserModel {
- constructor(private isDevEnvironment = process.env.NODE_ENV === 'development') {}
-
- private log(method: string, ...parameters: unknown[]) {
- console.debug(`[amplitude(Identify)]: ${method}(${parameters})`)
- }
-
- private call(mutate: (event: Identify) => Identify) {
- if (this.isDevEnvironment) {
- const log = (_: Identify, method: string) => this.log.bind(this, method)
- mutate(new Proxy(new Identify(), { get: log }))
- return
- }
- identify(mutate(new Identify()))
- }
-
- set(key: string, value: string | number) {
- this.call((event) => event.set(key, value))
- }
-
- setOnce(key: string, value: string | number) {
- this.call((event) => event.setOnce(key, value))
- }
-
- add(key: string, value: string | number) {
- this.call((event) => event.add(key, typeof value === 'number' ? value : 0))
- }
-
- postInsert(key: string, value: string | number) {
- this.call((event) => event.postInsert(key, value))
- }
-
- remove(key: string, value: string | number) {
- this.call((event) => event.remove(key, value))
- }
-}
-
-export const user = new UserModel()
diff --git a/apps/cowswap-frontend/src/legacy/components/AppziButton/index.tsx b/apps/cowswap-frontend/src/legacy/components/AppziButton/index.tsx
index 8eeb64cd96..a5070de79e 100644
--- a/apps/cowswap-frontend/src/legacy/components/AppziButton/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/AppziButton/index.tsx
@@ -1,10 +1,10 @@
+import FeedbackIcon from '@cowprotocol/assets/cow-swap/feedback.svg'
+import { isAppziEnabled, openFeedbackAppzi } from '@cowprotocol/common-utils'
+
import { transparentize } from 'polished'
import SVG from 'react-inlinesvg'
import styled from 'styled-components/macro'
-import FeedbackIcon from 'legacy/assets/cow-swap/feedback.svg'
-import { isAppziEnabled, openFeedbackAppzi } from 'legacy/utils/appzi'
-
const Wrapper = styled.div`
background: ${({ theme }) => transparentize(0.3, theme.bg2)};
backdrop-filter: blur(5px);
diff --git a/apps/cowswap-frontend/src/legacy/components/Badge/RangeBadge.tsx b/apps/cowswap-frontend/src/legacy/components/Badge/RangeBadge.tsx
index a7d4bb5293..65246370ef 100644
--- a/apps/cowswap-frontend/src/legacy/components/Badge/RangeBadge.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Badge/RangeBadge.tsx
@@ -1,11 +1,11 @@
+import { MouseoverTooltip } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import { AlertCircle } from 'react-feather'
import styled from 'styled-components/macro'
import Badge, { BadgeVariant } from 'legacy/components/Badge'
-import { MouseoverTooltip } from '../Tooltip'
-
const BadgeWrapper = styled.div`
font-size: 14px;
display: flex;
diff --git a/apps/cowswap-frontend/src/legacy/components/Button/__fixtures__/ButtonRadioChecked.tsx b/apps/cowswap-frontend/src/legacy/components/Button/__fixtures__/ButtonRadioChecked.tsx
deleted file mode 100644
index b4d4b772b8..0000000000
--- a/apps/cowswap-frontend/src/legacy/components/Button/__fixtures__/ButtonRadioChecked.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-// ButtonRadioChecked.fixture.jsx
-import { ButtonRadioChecked } from '../index'
-
-const fixtures = {
- active: Active ,
- notActive: Not active ,
-}
-
-export default fixtures
diff --git a/apps/cowswap-frontend/src/legacy/components/Card/index.tsx b/apps/cowswap-frontend/src/legacy/components/Card/index.tsx
index 723d473ed2..d1bb1601c1 100644
--- a/apps/cowswap-frontend/src/legacy/components/Card/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Card/index.tsx
@@ -1,6 +1,8 @@
import { Box } from 'rebass/styled-components'
import styled from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
const Card = styled(Box)<{ width?: string; padding?: string; border?: string; $borderRadius?: string }>`
width: ${({ width }) => width ?? '100%'};
padding: ${({ padding }) => padding ?? '1rem'};
@@ -11,7 +13,7 @@ export default Card
export const LightCard = styled(Card)`
border: 1px solid ${({ theme }) => theme.bg2};
- background-color: ${({ theme }) => theme.bg1};
+ background-color: var(${UI.COLOR_CONTAINER_BG_01});
`
export const LightGreyCard = styled(Card)`
diff --git a/apps/cowswap-frontend/src/legacy/components/Confetti/index.tsx b/apps/cowswap-frontend/src/legacy/components/Confetti/index.tsx
index de5837c7c1..46da1b428f 100644
--- a/apps/cowswap-frontend/src/legacy/components/Confetti/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Confetti/index.tsx
@@ -1,6 +1,6 @@
-import ReactConfetti from 'react-confetti'
+import { useWindowSize } from '@cowprotocol/common-hooks'
-import { useWindowSize } from '../../hooks/useWindowSize'
+import ReactConfetti from 'react-confetti'
// eslint-disable-next-line react/prop-types
export default function Confetti({ start, variant }: { start: boolean; variant?: string }) {
diff --git a/apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx b/apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx
index db283a7f7c..25d9bea369 100644
--- a/apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx
@@ -1,15 +1,17 @@
import React from 'react'
+import { useCopyClipboard } from '@cowprotocol/common-hooks'
+
import { Trans } from '@lingui/macro'
import { CheckCircle, Copy } from 'react-feather'
import styled from 'styled-components/macro'
import { TransactionStatusText } from 'legacy/components/Copy/index'
-import useCopyClipboard from 'legacy/hooks/useCopyClipboard'
import { LinkStyledButton } from 'legacy/theme'
-// MOD imports
+import { UI } from 'common/constants/theme'
+// MOD imports
export const CopyIcon = styled(LinkStyledButton)`
color: ${({ theme }) => theme.text3};
flex-shrink: 0;
@@ -27,7 +29,7 @@ export const CopyIcon = styled(LinkStyledButton)`
:active,
:focus {
text-decoration: none;
- color: ${({ theme }) => theme.text2};
+ color: var(${UI.COLOR_TEXT2});
}
`
diff --git a/apps/cowswap-frontend/src/legacy/components/CowBalance/index.tsx b/apps/cowswap-frontend/src/legacy/components/CowBalance/index.tsx
index 9d43db3680..f9528ff5f7 100644
--- a/apps/cowswap-frontend/src/legacy/components/CowBalance/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/CowBalance/index.tsx
@@ -1,10 +1,11 @@
+import { TokenAmount } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import styled from 'styled-components/macro'
import CowProtocolLogo from 'legacy/components/CowProtocolLogo'
import { CowSubsidyInfoProps } from 'legacy/components/CowSubsidyModal'
-import { TokenAmount } from 'common/pure/TokenAmount'
import { ClaimSummaryTitle, ClaimTotal, ClaimSummary as ClaimSummaryWrapper } from 'pages/Claim/styled'
const Wrapper = styled(ClaimSummaryWrapper)`
diff --git a/apps/cowswap-frontend/src/legacy/components/CowBalanceButton/index.tsx b/apps/cowswap-frontend/src/legacy/components/CowBalanceButton/index.tsx
index 3222ba17da..633bd9ca3e 100644
--- a/apps/cowswap-frontend/src/legacy/components/CowBalanceButton/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/CowBalanceButton/index.tsx
@@ -1,16 +1,18 @@
import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
+import { TokenAmount } from '@cowprotocol/ui'
import { transparentize } from 'polished'
import styled, { css } from 'styled-components/macro'
import CowProtocolLogo from 'legacy/components/CowProtocolLogo'
-import { useCombinedBalance } from 'legacy/state/cowToken/hooks'
-import { TokenAmount } from 'common/pure/TokenAmount'
+import { UI } from 'common/constants/theme'
+
+import { useCombinedBalance } from '../../hooks/useCombinedBalance'
export const Wrapper = styled.div<{ isLoading: boolean }>`
background-color: transparent;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
padding: 6px 12px;
border: 2px solid transparent;
font-weight: 500;
diff --git a/apps/cowswap-frontend/src/legacy/components/CowProtocolLogo/index.tsx b/apps/cowswap-frontend/src/legacy/components/CowProtocolLogo/index.tsx
index deab9db9be..dc22834552 100644
--- a/apps/cowswap-frontend/src/legacy/components/CowProtocolLogo/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/CowProtocolLogo/index.tsx
@@ -1,6 +1,6 @@
-import styled from 'styled-components/macro'
+import CowProtocolIcon from '@cowprotocol/assets/cow-swap/cow_v2.svg'
-import CowProtocolIcon from 'legacy/assets/cow-swap/cow_v2.svg'
+import styled from 'styled-components/macro'
export const Icon = styled.span`
--defaultSize: 24px;
diff --git a/apps/cowswap-frontend/src/legacy/components/CowSubsidyModal/SubsidyTable.tsx b/apps/cowswap-frontend/src/legacy/components/CowSubsidyModal/SubsidyTable.tsx
index a2b4e87679..fe3d6af20e 100644
--- a/apps/cowswap-frontend/src/legacy/components/CowSubsidyModal/SubsidyTable.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/CowSubsidyModal/SubsidyTable.tsx
@@ -1,13 +1,14 @@
+import { V_COW } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { TokenAmount } from '@cowprotocol/ui'
import { CurrencyAmount } from '@uniswap/sdk-core'
import { transparentize, lighten } from 'polished'
import styled from 'styled-components/macro'
-import { V_COW } from 'legacy/constants/tokens'
import { useIsDarkMode } from 'legacy/state/user/hooks'
-import { TokenAmount } from 'common/pure/TokenAmount'
+import { UI } from 'common/constants/theme'
import { COW_SUBSIDY_DATA } from './constants'
@@ -24,7 +25,7 @@ const StyledSubsidyTable = styled.table`
}
tbody {
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
border-radius: 16px;
border: 0;
}
@@ -49,7 +50,7 @@ const SubsidyTr = styled.tr<{ selected?: boolean; darkMode?: boolean }>`
}
&:hover > td {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
background: ${({ theme }) => transparentize(0.9, theme.text1)};
}
@@ -60,7 +61,7 @@ const SubsidyTr = styled.tr<{ selected?: boolean; darkMode?: boolean }>`
> td {
font-size: 15px;
- color: ${({ theme }) => theme.text2};
+ color: var(${UI.COLOR_TEXT2});
transition: background 0.3s ease-in-out;
}
diff --git a/apps/cowswap-frontend/src/legacy/components/CowSubsidyModal/index.tsx b/apps/cowswap-frontend/src/legacy/components/CowSubsidyModal/index.tsx
index b31882b08b..c6d522084d 100644
--- a/apps/cowswap-frontend/src/legacy/components/CowSubsidyModal/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/CowSubsidyModal/index.tsx
@@ -1,27 +1,25 @@
import { useCallback } from 'react'
+import { ExternalLink, Row } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import { Text } from 'rebass'
import { AutoColumn } from 'legacy/components/Column'
-import { ExternalLink } from 'legacy/components/Link'
-import Row from 'legacy/components/Row'
import { ConfirmationModalProps } from 'legacy/components/TransactionConfirmationModal'
-import {
- ConfirmationModalContentProps,
- LegacyConfirmationModalContent,
-} from 'legacy/components/TransactionConfirmationModal/LegacyConfirmationModalContent'
import useCowBalanceAndSubsidy from 'legacy/hooks/useCowBalanceAndSubsidy'
-import { useWalletInfo } from 'modules/wallet'
-
import { CowModal } from 'common/pure/Modal'
import { SUBSIDY_INFO_MESSAGE } from './constants'
import SubsidyTable from './SubsidyTable'
import CowBalance from '../CowBalance'
+import {
+ ConfirmationModalContentProps,
+ LegacyConfirmationModalContent,
+} from '../TransactionConfirmationModal/LegacyConfirmationModalContent'
export type CowSubsidy = { tier: number; discount: number }
export interface CowSubsidyInfoProps {
diff --git a/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/ChunkLoadError.tsx b/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/ChunkLoadError.tsx
index 04d8e6054e..2b97197d37 100644
--- a/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/ChunkLoadError.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/ChunkLoadError.tsx
@@ -1,14 +1,16 @@
import React, { useCallback } from 'react'
+import cowNoConnectionIMG from '@cowprotocol/assets/cow-swap/cow-no-connection.png'
+import { DISCORD_LINK } from '@cowprotocol/common-const'
+import { ButtonPrimary } from '@cowprotocol/ui'
+import { AutoRow } from '@cowprotocol/ui'
+import { ExternalLink } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import styled from 'styled-components/macro'
-import cowNoConnectionIMG from 'legacy/assets/cow-swap/cow-no-connection.png'
-import { ButtonPrimary } from 'legacy/components/Button'
import { AutoColumn } from 'legacy/components/Column'
-import { AutoRow } from 'legacy/components/Row'
-import { DISCORD_LINK } from 'legacy/constants'
-import { ExternalLink, MEDIA_WIDTHS, ThemedText } from 'legacy/theme'
+import { MEDIA_WIDTHS, ThemedText } from 'legacy/theme'
import { Title } from 'modules/application/pure/Page'
diff --git a/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/ErrorWithStackTrace.tsx b/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/ErrorWithStackTrace.tsx
index 6d1c7999e0..13adefa7f7 100644
--- a/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/ErrorWithStackTrace.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/ErrorWithStackTrace.tsx
@@ -1,19 +1,22 @@
import React from 'react'
+import CowError from '@cowprotocol/assets/cow-swap/CowError.png'
+import { CODE_LINK, DISCORD_LINK } from '@cowprotocol/common-const'
+import { userAgent } from '@cowprotocol/common-utils'
+import { AutoRow } from '@cowprotocol/ui'
+import { ExternalLink } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import styled from 'styled-components/macro'
-import CowError from 'legacy/assets/cow-swap/CowError.png'
import { AutoColumn } from 'legacy/components/Column'
-import { AutoRow } from 'legacy/components/Row'
-import { CODE_LINK, DISCORD_LINK } from 'legacy/constants'
-import store, { AppState } from 'legacy/state'
+import { cowSwapStore, AppState } from 'legacy/state'
import { MEDIA_WIDTHS, ThemedText } from 'legacy/theme'
-import { ExternalLink } from 'legacy/theme'
-import { userAgent } from 'legacy/utils/userAgent'
import { Title } from 'modules/application/pure/Page'
+import { UI } from 'common/constants/theme'
+
const FlexContainer = styled.div`
display: flex;
align-items: center;
@@ -37,14 +40,14 @@ const StyledParagraph = styled.p`
`
const CodeBlockWrapper = styled.div`
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
overflow: auto;
white-space: pre;
box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04),
0px 24px 32px rgba(0, 0, 0, 0.01);
border-radius: 16px;
padding: 16px;
- color: ${({ theme }) => theme.text2};
+ color: var(${UI.COLOR_TEXT2});
/* MOD */
${({ theme }) => theme.mediaWidth.upToSmall`
@@ -143,7 +146,7 @@ ${
? `## \`${relevantState}\` state
\`\`\`json
-${JSON.stringify(store.getState()[relevantState], null, 2)}
+${JSON.stringify(cowSwapStore.getState()[relevantState], null, 2)}
\`\`\`
`
: ''
diff --git a/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/index.tsx b/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/index.tsx
index 0e6c5343ae..74d286ca67 100644
--- a/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/index.tsx
@@ -1,5 +1,7 @@
import React, { ErrorInfo, PropsWithChildren } from 'react'
+import { sendError } from '@cowprotocol/analytics'
+
import * as Sentry from '@sentry/react'
import styled from 'styled-components/macro'
@@ -13,8 +15,6 @@ import { Page } from 'modules/application/pure/Page'
import { Routes } from 'common/constants/routes'
-import { sendError } from '../analytics/googleAnalytics'
-
type ErrorBoundaryState = {
error: Error | null
}
diff --git a/apps/cowswap-frontend/src/legacy/components/ExplorerLink/index.tsx b/apps/cowswap-frontend/src/legacy/components/ExplorerLink/index.tsx
index ac4f142808..6f3974491c 100644
--- a/apps/cowswap-frontend/src/legacy/components/ExplorerLink/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/ExplorerLink/index.tsx
@@ -1,13 +1,10 @@
import { PropsWithChildren } from 'react'
+import { getExplorerLabel, getEtherscanLink } from '@cowprotocol/common-utils'
+import { getSafeWebUrl } from '@cowprotocol/core'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
-
-import { ExternalLink } from 'legacy/theme'
-import { getExplorerLabel, getEtherscanLink } from 'legacy/utils'
-
-import { useWalletInfo } from 'modules/wallet'
-
-import { getSafeWebUrl } from 'api/gnosisSafe'
+import { ExternalLink } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
interface PropsBase extends PropsWithChildren {
// type?: BlockExplorerLinkType
diff --git a/apps/cowswap-frontend/src/legacy/components/FlashingLoading/index.tsx b/apps/cowswap-frontend/src/legacy/components/FlashingLoading/index.tsx
index 68fab5b798..8658299810 100644
--- a/apps/cowswap-frontend/src/legacy/components/FlashingLoading/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/FlashingLoading/index.tsx
@@ -1,8 +1,10 @@
+import CowIcon from '@cowprotocol/assets/cow-swap/cowprotocol.svg'
+
import { transparentize } from 'polished'
import SVG from 'react-inlinesvg'
import styled from 'styled-components/macro'
-import CowIcon from 'legacy/assets/cow-swap/cowprotocol.svg'
+import { UI } from 'common/constants/theme'
export const LoadingWrapper = styled.div`
display: flex;
@@ -25,7 +27,7 @@ export const LoadingWrapper = styled.div`
}
> svg > g {
- fill: ${({ theme }) => theme.text2};
+ fill: var(${UI.COLOR_TEXT2});
}
> span {
@@ -35,7 +37,7 @@ export const LoadingWrapper = styled.div`
font-weight: 500;
letter-spacing: 2px;
margin: 5px auto 0;
- color: ${({ theme }) => theme.text2};
+ color: var(${UI.COLOR_TEXT2});
}
@keyframes pulse {
diff --git a/apps/cowswap-frontend/src/legacy/components/Header/ChainConnectivityWarning.tsx b/apps/cowswap-frontend/src/legacy/components/Header/ChainConnectivityWarning.tsx
index 69948f4085..05491ca721 100644
--- a/apps/cowswap-frontend/src/legacy/components/Header/ChainConnectivityWarning.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Header/ChainConnectivityWarning.tsx
@@ -1,14 +1,13 @@
+import { getChainInfo } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Trans } from '@lingui/macro'
import { AlertOctagon } from 'react-feather'
import styled from 'styled-components/macro'
-import { getChainInfo } from 'legacy/constants/chainInfo'
import { MEDIA_WIDTHS } from 'legacy/theme'
-import { useWalletInfo } from 'modules/wallet'
-
const BodyRow = styled.div`
color: ${({ theme }) => theme.black};
font-size: 12px;
diff --git a/apps/cowswap-frontend/src/legacy/components/Header/MobileMenuIcon/index.tsx b/apps/cowswap-frontend/src/legacy/components/Header/MobileMenuIcon/index.tsx
index 393e7ffe99..b14fe517b5 100644
--- a/apps/cowswap-frontend/src/legacy/components/Header/MobileMenuIcon/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Header/MobileMenuIcon/index.tsx
@@ -1,5 +1,7 @@
import styled, { css } from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
const Wrapper = styled.div<{ isMobileMenuOpen: boolean; height?: number; width?: number; lineSize?: number }>`
z-index: 102;
display: flex;
@@ -10,7 +12,7 @@ const Wrapper = styled.div<{ isMobileMenuOpen: boolean; height?: number; width?:
height: ${({ height = 18 }) => `${height}px`};
span {
- background-color: ${({ theme }) => theme.text1};
+ background-color: var(${UI.COLOR_TEXT1});
border-radius: 3px;
height: ${({ lineSize = 2 }) => `${lineSize}px`};
position: absolute;
diff --git a/apps/cowswap-frontend/src/legacy/components/Header/NetworkSelector/index.tsx b/apps/cowswap-frontend/src/legacy/components/Header/NetworkSelector/index.tsx
index 3b47456c5c..eb6cf28201 100644
--- a/apps/cowswap-frontend/src/legacy/components/Header/NetworkSelector/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Header/NetworkSelector/index.tsx
@@ -1,5 +1,7 @@
import { useRef } from 'react'
+import { getChainInfo } from '@cowprotocol/common-const'
+import { useWalletInfo, getIsTallyWallet, useIsSmartContractWallet } from '@cowprotocol/wallet'
import { useWeb3React } from '@web3-react/core'
import { Trans } from '@lingui/macro'
@@ -7,22 +9,18 @@ import { transparentize, darken } from 'polished'
import { AlertTriangle, ChevronDown } from 'react-feather'
import styled from 'styled-components/macro'
-import { getChainInfo } from 'legacy/constants/chainInfo'
import { useMediaQuery, upToMedium } from 'legacy/hooks/useMediaQuery'
import { useCloseModal, useModalIsOpen, useOpenModal, useToggleModal } from 'legacy/state/application/hooks'
import { ApplicationModal } from 'legacy/state/application/reducer'
import { MEDIA_WIDTHS } from 'legacy/theme'
-import { useWalletInfo } from 'modules/wallet'
-import { getIsTallyWallet } from 'modules/wallet/api/utils/connection'
-
+import { UI } from 'common/constants/theme'
import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported'
-import { useIsSmartContractWallet } from 'common/hooks/useIsSmartContractWallet'
import { useOnSelectNetwork } from 'common/hooks/useOnSelectNetwork'
import { NetworksList } from 'common/pure/NetworksList'
const FlyoutHeader = styled.div`
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
font-weight: 400;
`
@@ -43,7 +41,7 @@ const FlyoutMenu = styled.div`
const FlyoutMenuContents = styled.div`
align-items: flex-start;
- background-color: ${({ theme }) => theme.bg1};
+ background-color: var(${UI.COLOR_CONTAINER_BG_01});
border: 1px solid ${({ theme }) => theme.bg0};
box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04),
0px 24px 32px rgba(0, 0, 0, 0.01);
@@ -82,7 +80,7 @@ const SelectorLabel = styled.div`
`
const SelectorControls = styled.div<{ isChainIdUnsupported: boolean }>`
align-items: center;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
display: flex;
font-weight: 500;
justify-content: space-between;
diff --git a/apps/cowswap-frontend/src/legacy/components/Header/Polling.tsx b/apps/cowswap-frontend/src/legacy/components/Header/Polling.tsx
index f340cda3f0..1e22b2748b 100644
--- a/apps/cowswap-frontend/src/legacy/components/Header/Polling.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Header/Polling.tsx
@@ -1,27 +1,25 @@
import { useEffect, useState } from 'react'
+import { getChainInfo } from '@cowprotocol/common-const'
+import { useBlockNumber, useMachineTimeMs, useTheme } from '@cowprotocol/common-hooks'
+import { ExplorerDataType, getExplorerLink } from '@cowprotocol/common-utils'
+import { RowFixed } from '@cowprotocol/ui'
+import { MouseoverTooltip, ExternalLink } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
+
import { Trans } from '@lingui/macro'
import JSBI from 'jsbi'
import ms from 'ms.macro'
import styled, { keyframes } from 'styled-components/macro'
-import { RowFixed } from 'legacy/components/Row'
-import { getChainInfo } from 'legacy/constants/chainInfo'
import useCurrentBlockTimestamp from 'legacy/hooks/useCurrentBlockTimestamp'
import useGasPrice from 'legacy/hooks/useGasPrice'
-import useMachineTimeMs from 'legacy/hooks/useMachineTime'
-import useTheme from 'legacy/hooks/useTheme'
-import { ExternalLink, ThemedText } from 'legacy/theme'
-import { ExplorerDataType, getExplorerLink } from 'legacy/utils/getExplorerLink'
-
-import { useWalletInfo } from 'modules/wallet'
+import { ThemedText } from 'legacy/theme'
-import useBlockNumber from 'lib/hooks/useBlockNumber'
+import { UI } from 'common/constants/theme'
import { ChainConnectivityWarning } from './ChainConnectivityWarning'
-import { MouseoverTooltip } from '../Tooltip'
-
export const StyledPolling = styled.div<{ warning: boolean }>`
position: fixed;
display: flex;
@@ -103,7 +101,7 @@ export const Spinner = styled.div<{ warning: boolean }>`
const Wrapper = styled.div`
${StyledPolling} {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
position: relative;
margin: 0;
padding: 0;
@@ -113,7 +111,7 @@ const Wrapper = styled.div`
opacity: 1;
a {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
opacity: 0.5;
transition: opacity 0.3s ease-in-out;
text-decoration: none;
@@ -130,7 +128,7 @@ const Wrapper = styled.div`
${StyledPollingNumber} > a {
opacity: 1;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
&:hover {
opacity: 1;
@@ -141,7 +139,7 @@ const Wrapper = styled.div`
${StyledGasDot},
${StyledPollingDot} {
- background: ${({ theme }) => theme.text1};
+ background: var(${UI.COLOR_TEXT1});
}
${StyledPollingDot} {
diff --git a/apps/cowswap-frontend/src/legacy/components/Header/URLWarning/index.tsx b/apps/cowswap-frontend/src/legacy/components/Header/URLWarning/index.tsx
index 83b6e26846..e55c067e71 100644
--- a/apps/cowswap-frontend/src/legacy/components/Header/URLWarning/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Header/URLWarning/index.tsx
@@ -1,15 +1,14 @@
+import { useFetchFile } from '@cowprotocol/common-hooks'
+import { hashCode } from '@cowprotocol/common-utils'
+import { environmentName } from '@cowprotocol/common-utils'
import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { AlertTriangle } from 'react-feather'
import styled from 'styled-components/macro'
import { Markdown } from 'legacy/components/Markdown'
-import useFetchFile from 'legacy/hooks/useFetchFile'
import { useAnnouncementVisible, useCloseAnnouncement } from 'legacy/state/profile/hooks'
-import { environmentName } from 'legacy/utils/environments'
-import { hashCode } from 'legacy/utils/misc'
-
-import { useWalletInfo } from 'modules/wallet'
import URLWarningUni, { PhishAlert, StyledClose } from './URLWarningMod'
diff --git a/apps/cowswap-frontend/src/legacy/components/Header/index.tsx b/apps/cowswap-frontend/src/legacy/components/Header/index.tsx
index 1c217fa842..ced341809e 100644
--- a/apps/cowswap-frontend/src/legacy/components/Header/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Header/index.tsx
@@ -1,32 +1,34 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react'
+import { toggleDarkModeAnalytics } from '@cowprotocol/analytics'
+import { isInjectedWidget } from '@cowprotocol/common-utils'
+import { addBodyClass, removeBodyClass } from '@cowprotocol/common-utils'
import { SupportedChainId as ChainId, SupportedChainId } from '@cowprotocol/cow-sdk'
+import { TokenAmount } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import SVG from 'react-inlinesvg'
import { useNavigate } from 'react-router-dom'
-import { toggleDarkModeAnalytics } from 'legacy/components/analytics'
import CowBalanceButton from 'legacy/components/CowBalanceButton'
import { NetworkSelector } from 'legacy/components/Header/NetworkSelector'
import { LargeAndUp, upToLarge, upToMedium, upToSmall, useMediaQuery } from 'legacy/hooks/useMediaQuery'
import { useDarkModeManager } from 'legacy/state/user/hooks'
import { cowSwapLogo } from 'legacy/theme/cowSwapAssets'
-import { addBodyClass, removeBodyClass } from 'legacy/utils/toggleBodyClass'
import { OrdersPanel } from 'modules/account/containers/OrdersPanel'
import { useInjectedWidgetParams } from 'modules/injectedWidget'
-import { MainMenuContext, useMenuItems } from 'modules/mainMenu'
+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 { useWalletInfo, Web3Status } from 'modules/wallet'
+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 { TokenAmount } from 'common/pure/TokenAmount'
-import { isInjectedWidget } from 'common/utils/isInjectedWidget'
import MobileMenuIcon from './MobileMenuIcon'
import {
@@ -54,6 +56,7 @@ export default function Header() {
const isChainIdUnsupported = useIsProviderNetworkUnsupported()
+ const { pendingActivity } = useCategorizeRecentActivity()
const userEthBalance = useNativeCurrencyBalances(account ? [account] : [])?.[account ?? '']
const nativeToken = CHAIN_CURRENCY_LABELS[chainId] || 'ETH'
const [darkMode, toggleDarkModeAux] = useDarkModeManager()
@@ -73,8 +76,6 @@ export default function Header() {
!isOrdersPanelOpen && removeBodyClass('noScroll')
}
- const menuItems = useMenuItems()
-
const navigate = useNavigate()
const isUpToLarge = useMediaQuery(upToLarge)
@@ -139,9 +140,7 @@ export default function Header() {
)}
- {!isInjectedWidgetMode && (
-
- )}
+ {!isInjectedWidgetMode && }
@@ -163,7 +162,7 @@ export default function Header() {
)}
-
+
diff --git a/apps/cowswap-frontend/src/legacy/components/Header/styled.tsx b/apps/cowswap-frontend/src/legacy/components/Header/styled.tsx
index 722d706963..0bdfd8fef0 100644
--- a/apps/cowswap-frontend/src/legacy/components/Header/styled.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Header/styled.tsx
@@ -1,5 +1,7 @@
import { PropsWithChildren } from 'react'
+import { Row, RowFixed } from '@cowprotocol/ui'
+
import useScrollPosition from '@react-hook/window-scroll'
import { transparentize, darken } from 'polished'
import { NavLink } from 'react-router-dom'
@@ -7,7 +9,8 @@ import { Text } from 'rebass'
import styled, { css } from 'styled-components/macro'
import { MenuFlyout, MenuSection, Content as MenuContent, MenuTitle } from 'legacy/components/MenuDropdown/styled'
-import Row, { RowFixed } from 'legacy/components/Row'
+
+import { UI } from 'common/constants/theme'
const activeClassName = 'active'
@@ -77,7 +80,7 @@ export const StyledNavLinkUni = styled(NavLink)`
outline: none;
cursor: pointer;
text-decoration: none;
- color: ${({ theme }) => theme.text2};
+ color: var(${UI.COLOR_TEXT2});
font-size: 1rem;
width: fit-content;
margin: 0 12px;
@@ -85,7 +88,7 @@ export const StyledNavLinkUni = styled(NavLink)`
&.${activeClassName} {
border-radius: 12px;
font-weight: 600;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
:hover,
@@ -119,7 +122,7 @@ export const StyledMenuButton = styled.button`
margin-top: 2px;
}
> * {
- stroke: ${({ theme }) => theme.text1};
+ stroke: var(${UI.COLOR_TEXT1});
}
`
@@ -177,7 +180,7 @@ export const StyledNavLink = styled(StyledNavLinkUni)`
&:hover,
&:focus {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
`
@@ -223,7 +226,7 @@ export const HeaderElement = styled(HeaderElementUni)`
width: 100%;
border-radius: 0;
height: 64px;
- background-color: ${({ theme }) => theme.bg1};
+ background-color: var(${UI.COLOR_CONTAINER_BG_01});
border-top: 1px solid ${({ theme }) => theme.grey1};
backdrop-filter: blur(21px);
padding: 10px 16px;
@@ -253,7 +256,7 @@ export const Wrapper = styled.div<{ isMobileMenuOpen: boolean }>`
width: 100%;
display: flex;
height: 60px;
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
position: fixed;
top: 0;
left: 0;
@@ -283,7 +286,7 @@ export const HeaderModWrapper = styled(HeaderMod)``
export const Title = styled(TitleMod)<{ isMobileMenuOpen: boolean }>`
margin: 0;
text-decoration: none;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
${({ theme, isMobileMenuOpen }) => theme.mediaWidth.upToLarge`
${
@@ -315,7 +318,7 @@ export const HeaderLinks = styled(HeaderLinksMod)<{ isMobileMenuOpen: boolean }>
cursor: pointer;
background: transparent;
transition: background 0.15s ease-in-out, color 0.15s ease-in-out;
- color: ${({ theme }) => theme.text2};
+ color: var(${UI.COLOR_TEXT2});
${({ theme }) => theme.mediaWidth.upToLarge`
width: 100%;
@@ -324,17 +327,17 @@ export const HeaderLinks = styled(HeaderLinksMod)<{ isMobileMenuOpen: boolean }>
font-weight: 600;
font-size: 17px;
padding: 28px 10px;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
border-bottom: 1px solid ${({ theme }) => transparentize(0.9, theme.text1)};
`};
> svg > path {
- fill: ${({ theme }) => theme.text2};
+ fill: var(${UI.COLOR_TEXT2});
transition: fill 0.15s ease-in-out;
}
&:hover {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
background: ${({ theme }) => transparentize(0.95, theme.text1)};
${({ theme }) => theme.mediaWidth.upToLarge`
@@ -342,7 +345,7 @@ export const HeaderLinks = styled(HeaderLinksMod)<{ isMobileMenuOpen: boolean }>
`};
> svg > path {
- fill: ${({ theme }) => theme.text1};
+ fill: var(${UI.COLOR_TEXT1});
}
}
@@ -357,7 +360,7 @@ export const HeaderLinks = styled(HeaderLinksMod)<{ isMobileMenuOpen: boolean }>
}
&.ACTIVE {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
font-weight: 600;
}
}
@@ -407,7 +410,7 @@ export const HeaderLinks = styled(HeaderLinksMod)<{ isMobileMenuOpen: boolean }>
left: 0;
bottom: 0;
z-index: 3;
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
outline: 0;
padding: 60px 8px;
overflow-x: hidden;
@@ -447,11 +450,11 @@ export const TwitterLink = styled(StyledMenuButton)`
}
> a > svg > path {
- fill: ${({ theme }) => theme.text1};
+ fill: var(${UI.COLOR_TEXT1});
}
> a:hover > svg > path {
- fill: ${({ theme }) => theme.text1};
+ fill: var(${UI.COLOR_TEXT1});
}
`
diff --git a/apps/cowswap-frontend/src/legacy/components/HoverInlineText/index.tsx b/apps/cowswap-frontend/src/legacy/components/HoverInlineText/index.tsx
index b7351ee304..1f4b44e51f 100644
--- a/apps/cowswap-frontend/src/legacy/components/HoverInlineText/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/HoverInlineText/index.tsx
@@ -1,8 +1,8 @@
import { useState } from 'react'
-import styled from 'styled-components/macro'
+import { Tooltip } from '@cowprotocol/ui'
-import Tooltip from 'legacy/components/Tooltip'
+import styled from 'styled-components/macro'
export const TextWrapper = styled.span<{
margin: boolean
diff --git a/apps/cowswap-frontend/src/legacy/components/InfoIcon/index.tsx b/apps/cowswap-frontend/src/legacy/components/InfoIcon/index.tsx
index 739716c0c2..39a7acc21e 100644
--- a/apps/cowswap-frontend/src/legacy/components/InfoIcon/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/InfoIcon/index.tsx
@@ -1,19 +1,25 @@
import { ReactNode } from 'react'
-import { Info } from 'react-feather'
+import { MouseoverTooltipContent, TooltipContainer } from '@cowprotocol/ui'
+
+import { Info, HelpCircle } from 'react-feather'
import styled from 'styled-components/macro'
-import { MouseoverTooltipContent, TooltipContainer } from 'legacy/components/Tooltip'
+import { UI } from 'common/constants/theme'
+
+const StyledIcon = styled.div`
+ display: inline-block;
-const StyledInfoIcon = styled(Info)`
- opacity: 0.5;
- stroke: ${({ theme }) => theme.text1};
- line-height: 0;
- vertical-align: middle;
- transition: opacity 0.2s ease-in-out;
+ > svg {
+ opacity: 0.5;
+ stroke: var(${UI.COLOR_TEXT1});
+ line-height: 0;
+ vertical-align: middle;
+ transition: opacity 0.2s ease-in-out;
- :hover {
- opacity: 1;
+ :hover {
+ opacity: 1;
+ }
}
`
@@ -26,15 +32,22 @@ const StyledTooltipContainer = styled(TooltipContainer)`
export interface InfoIconProps {
content: ReactNode
+ iconType?: 'info' | 'help'
className?: string
}
-export function InfoIcon(props: InfoIconProps) {
- const content = {props.content}
+export function InfoIcon({ content, iconType = 'info', className }: InfoIconProps) {
+ const tooltipContent = {content}
return (
-
-
+
+
+ {iconType === 'info' ? (
+
+ ) : (
+
+ )}
+
)
}
diff --git a/apps/cowswap-frontend/src/legacy/components/Link/index.tsx b/apps/cowswap-frontend/src/legacy/components/Link/index.tsx
index 192a934994..ce16f3850f 100644
--- a/apps/cowswap-frontend/src/legacy/components/Link/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Link/index.tsx
@@ -1,7 +1,7 @@
+import { ExternalLink } from '@cowprotocol/ui'
+
import HashLink from 'legacy/components/HashLink'
-import { ExternalLink } from 'legacy/theme'
-export { ExternalLink } from 'legacy/theme'
const SCROLL_OFFSET = 24
export interface LinkRendererProps {
diff --git a/apps/cowswap-frontend/src/legacy/components/ListLogo/index.tsx b/apps/cowswap-frontend/src/legacy/components/ListLogo/index.tsx
index f74c6891cc..f14a5d1def 100644
--- a/apps/cowswap-frontend/src/legacy/components/ListLogo/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/ListLogo/index.tsx
@@ -2,8 +2,9 @@ import React from 'react'
import styled from 'styled-components/macro'
+import Logo from 'legacy/components/Loader/Logo'
+
import useHttpLocations from '../../hooks/useHttpLocations'
-import Logo from '../Logo'
export const StyledListLogo = styled(Logo)<{ size: string }>`
width: ${({ size }) => size};
diff --git a/apps/cowswap-frontend/src/legacy/components/Logo/index.tsx b/apps/cowswap-frontend/src/legacy/components/Loader/Logo/index.tsx
similarity index 94%
rename from apps/cowswap-frontend/src/legacy/components/Logo/index.tsx
rename to apps/cowswap-frontend/src/legacy/components/Loader/Logo/index.tsx
index 1608d514b0..1f55d85414 100644
--- a/apps/cowswap-frontend/src/legacy/components/Logo/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Loader/Logo/index.tsx
@@ -1,10 +1,10 @@
import { useState } from 'react'
+import { useTheme } from '@cowprotocol/common-hooks'
+
import { Slash } from 'react-feather'
import { ImageProps } from 'rebass'
-import useTheme from '../../hooks/useTheme'
-
const BAD_SRCS: { [tokenAddress: string]: true } = {}
export interface LogoProps extends Pick {
diff --git a/apps/cowswap-frontend/src/legacy/components/Markdown/index.tsx b/apps/cowswap-frontend/src/legacy/components/Markdown/index.tsx
index 516a2f8915..5b7bc15e28 100644
--- a/apps/cowswap-frontend/src/legacy/components/Markdown/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Markdown/index.tsx
@@ -1,15 +1,13 @@
import { ReactNode } from 'react'
+import { useFetchFile } from '@cowprotocol/common-hooks'
+
import ReactMarkdown, { ReactMarkdownPropsBase } from 'react-markdown'
import ReactMarkdownHtml from 'react-markdown/with-html'
import styled from 'styled-components/macro'
import { WithClassName } from 'types'
-// AmplitudeAnalytics
-import { PageName } from 'legacy/components/AmplitudeAnalytics/constants'
-import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace'
import { LinkScrollable, Link } from 'legacy/components/Link'
-import useFetchFile from 'legacy/hooks/useFetchFile'
import { Page, Title, Content } from 'modules/application/pure/Page'
@@ -34,7 +32,7 @@ const MarkdownContent = (props: ReactMarkdownPropsBase & { children: string }) =
export function MarkdownPage({ contentFile, title, className }: MarkdownParams) {
const { error, file } = useFetchFile(contentFile)
return (
-
+ <>
{title && {title} }
@@ -42,6 +40,6 @@ export function MarkdownPage({ contentFile, title, className }: MarkdownParams)
{error && {error} }
-
+ >
)
}
diff --git a/apps/cowswap-frontend/src/legacy/components/MenuDropdown/index.tsx b/apps/cowswap-frontend/src/legacy/components/MenuDropdown/index.tsx
index 55b7dd1a78..0d6f5372d3 100644
--- a/apps/cowswap-frontend/src/legacy/components/MenuDropdown/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/MenuDropdown/index.tsx
@@ -1,10 +1,11 @@
import { useState, useRef } from 'react'
+import IMAGE_CARRET_DOWN from '@cowprotocol/assets/cow-swap/carret-down.svg'
+import { useOnClickOutside } from '@cowprotocol/common-hooks'
+
import SVG from 'react-inlinesvg'
-import IMAGE_CARRET_DOWN from 'legacy/assets/cow-swap/carret-down.svg'
import { useMediaQuery, LargeAndUp } from 'legacy/hooks/useMediaQuery'
-import { useOnClickOutside } from 'legacy/hooks/useOnClickOutside'
import { MenuFlyout, Content } from './styled'
diff --git a/apps/cowswap-frontend/src/legacy/components/MenuDropdown/styled.ts b/apps/cowswap-frontend/src/legacy/components/MenuDropdown/styled.ts
index 5ce1c5fa51..a772f40a3f 100644
--- a/apps/cowswap-frontend/src/legacy/components/MenuDropdown/styled.ts
+++ b/apps/cowswap-frontend/src/legacy/components/MenuDropdown/styled.ts
@@ -1,6 +1,8 @@
import { transparentize } from 'polished'
import styled from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
export const MenuFlyout = styled.ol`
display: flex;
padding: 0;
@@ -50,7 +52,7 @@ export const Content = styled.div`
left: 0;
border-radius: 16px;
border: 1px solid ${({ theme }) => transparentize(0.6, theme.white)};
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
box-shadow: ${({ theme }) => theme.boxShadow2};
padding: 32px;
gap: 62px;
@@ -107,7 +109,7 @@ export const MenuSection = styled.div`
font-weight: 500;
margin: 0;
padding: 0;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
opacity: 0.8;
transition: opacity 0.15s ease-in-out;
@@ -118,11 +120,11 @@ export const MenuSection = styled.div`
max-height: 21px;
margin: 0 7px 0 0;
object-fit: contain;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
> svg > path {
- fill: ${({ theme }) => theme.text1};
+ fill: var(${UI.COLOR_TEXT1});
}
&:hover {
diff --git a/apps/cowswap-frontend/src/legacy/components/NetworkAlert/NetworkAlert.tsx b/apps/cowswap-frontend/src/legacy/components/NetworkAlert/NetworkAlert.tsx
index c277515592..42fc0b07ea 100644
--- a/apps/cowswap-frontend/src/legacy/components/NetworkAlert/NetworkAlert.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/NetworkAlert/NetworkAlert.tsx
@@ -1,17 +1,19 @@
+import { getChainInfo } from '@cowprotocol/common-const'
+import { useTheme } from '@cowprotocol/common-hooks'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { AutoRow } from '@cowprotocol/ui'
+import { ExternalLink } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Trans } from '@lingui/macro'
import { transparentize } from 'polished'
import { ArrowUpRight } from 'react-feather'
import styled from 'styled-components/macro'
-import { AutoRow } from 'legacy/components/Row'
-import { getChainInfo } from 'legacy/constants/chainInfo'
-import useTheme from 'legacy/hooks/useTheme'
import { useDarkModeManager } from 'legacy/state/user/hooks'
-import { ExternalLink, HideSmall } from 'legacy/theme'
+import { HideSmall } from 'legacy/theme'
-import { useWalletInfo } from 'modules/wallet'
+import { UI } from 'common/constants/theme'
const L2Icon = styled.img`
width: 24px;
@@ -74,19 +76,19 @@ const ContentWrapper = styled.div<{ chainId: NetworkAlertChains; darkMode: boole
${BodyText},
${StyledArrowUpRight} {
- color: ${({ theme }) => theme.text2};
- stroke: ${({ theme }) => theme.text2};
+ color: var(${UI.COLOR_TEXT2});
+ stroke: var(${UI.COLOR_TEXT2});
text-decoration: none;
transition: transform 0.2s ease-in-out, stroke 0.2s ease-in-out, color 0.2s ease-in-out;
}
&:hover {
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
${BodyText},
${StyledArrowUpRight} {
- color: ${({ theme }) => theme.text1};
- stroke: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
+ stroke: var(${UI.COLOR_TEXT1});
transform: rotate(0);
}
diff --git a/apps/cowswap-frontend/src/legacy/components/NetworkAlert/styles.ts b/apps/cowswap-frontend/src/legacy/components/NetworkAlert/styles.ts
index 9241855a54..3e9a04a57d 100644
--- a/apps/cowswap-frontend/src/legacy/components/NetworkAlert/styles.ts
+++ b/apps/cowswap-frontend/src/legacy/components/NetworkAlert/styles.ts
@@ -1,8 +1,10 @@
+import { ExternalLink } from '@cowprotocol/ui'
+
import styled from 'styled-components/macro'
-import { ExternalLink } from 'legacy/theme'
+import { UI } from 'common/constants/theme'
export const ReadMoreLink = styled(ExternalLink)`
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
text-decoration: underline;
`
diff --git a/apps/cowswap-frontend/src/legacy/components/NumericalInput/index.tsx b/apps/cowswap-frontend/src/legacy/components/NumericalInput/index.tsx
index 6d63de857e..40f25d7239 100644
--- a/apps/cowswap-frontend/src/legacy/components/NumericalInput/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/NumericalInput/index.tsx
@@ -1,11 +1,12 @@
import React from 'react'
+import { escapeRegExp } from '@cowprotocol/common-utils'
+
import styled from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
import { autofocus } from 'common/utils/autofocus'
-import { escapeRegExp } from '../../utils'
-
const StyledInput = styled.input<{ error?: boolean; fontSize?: string; align?: string }>`
color: ${({ error, theme }) => (error ? theme.red1 : theme.text1)};
width: 0;
@@ -14,7 +15,7 @@ const StyledInput = styled.input<{ error?: boolean; fontSize?: string; align?: s
outline: none;
border: none;
flex: 1 1 auto;
- background-color: ${({ theme }) => theme.bg1};
+ background-color: var(${UI.COLOR_CONTAINER_BG_01});
font-size: ${({ fontSize }) => fontSize ?? '28px'};
text-align: ${({ align }) => align && align};
white-space: nowrap;
diff --git a/apps/cowswap-frontend/src/legacy/components/OrderProgressBar/index.tsx b/apps/cowswap-frontend/src/legacy/components/OrderProgressBar/index.tsx
index b277aec583..c92a266a40 100644
--- a/apps/cowswap-frontend/src/legacy/components/OrderProgressBar/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/OrderProgressBar/index.tsx
@@ -1,24 +1,24 @@
import { useEffect, useMemo, useState } from 'react'
+import loadingCowWebp from '@cowprotocol/assets/cow-swap/cow-load.webp'
+import ammsGraphGC from '@cowprotocol/assets/images/amms-graph-gc.svg'
+import ammsGraphEth from '@cowprotocol/assets/images/amms-graph.svg'
+import cowGraph from '@cowprotocol/assets/images/cow-graph.svg'
+import cowMeditatingSmooth from '@cowprotocol/assets/images/cow-meditating-smoooth.svg'
+import cowMeditatingGraph from '@cowprotocol/assets/images/cow-meditating.svg'
+import { getExplorerOrderLink } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { useIsSmartContractWallet } from '@cowprotocol/wallet'
import { useTransition } from '@react-spring/web'
import ms from 'ms.macro'
-import loadingCowWebp from 'legacy/assets/cow-swap/cow-load.webp'
-import ammsGraphGC from 'legacy/assets/images/amms-graph-gc.svg'
-import ammsGraphEth from 'legacy/assets/images/amms-graph.svg'
-import cowGraph from 'legacy/assets/images/cow-graph.svg'
-import cowMeditatingSmooth from 'legacy/assets/images/cow-meditating-smoooth.svg'
-import cowMeditatingGraph from 'legacy/assets/images/cow-meditating.svg'
import { AMMsLogo } from 'legacy/components/AMMsLogo'
import { EXPECTED_EXECUTION_TIME, getPercentage } from 'legacy/components/OrderProgressBar/utils'
-import { getExplorerOrderLink } from 'legacy/utils/explorer'
import { ActivityDerivedState } from 'modules/account/containers/Transaction'
import { useCancelOrder } from 'common/hooks/useCancelOrder'
-import { useIsSmartContractWallet } from 'common/hooks/useIsSmartContractWallet'
import { CancelButton } from 'common/pure/CancelButton'
import {
diff --git a/apps/cowswap-frontend/src/legacy/components/OrderProgressBar/styled.ts b/apps/cowswap-frontend/src/legacy/components/OrderProgressBar/styled.ts
index b0d1f9cf8d..365aba86da 100644
--- a/apps/cowswap-frontend/src/legacy/components/OrderProgressBar/styled.ts
+++ b/apps/cowswap-frontend/src/legacy/components/OrderProgressBar/styled.ts
@@ -1,9 +1,11 @@
+import CowProtocolLogo from '@cowprotocol/assets/cow-swap/cowprotocol.svg'
+import { ExternalLink } from '@cowprotocol/ui'
+
import { animated } from '@react-spring/web'
import { CheckCircle, Clock } from 'react-feather'
import styled from 'styled-components/macro'
-import CowProtocolLogo from 'legacy/assets/cow-swap/cowprotocol.svg'
-import { ExternalLink } from 'legacy/theme'
+import { UI } from 'common/constants/theme'
export const ProgressBarWrapper = animated(styled.div`
display: flex;
@@ -16,8 +18,8 @@ export const ProgressBarWrapper = animated(styled.div`
flex-flow: column wrap;
border-radius: 12px;
padding: 20px 20px 0;
- color: ${({ theme }) => theme.text1};
- background-color: ${({ theme }) => theme.grey1};
+ color: var(${UI.COLOR_TEXT1});
+ background-color: var(${UI.COLOR_GREY});
transition: height 0.2s ease;
${({ theme }) => theme.mediaWidth.upToSmall`
@@ -205,7 +207,7 @@ export const StatusWrapper = styled.div`
export const StatusMsg = styled.p`
font-size: 0.85rem;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
margin: 0;
${({ theme }) => theme.mediaWidth.upToSmall`
font-size: 0.835rem;
@@ -217,7 +219,7 @@ export const StatusMsg = styled.p`
`
export const StyledCoWLink = styled(ExternalLink)`
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
text-decoration: underline;
opacity: 1 !important;
diff --git a/apps/cowswap-frontend/src/legacy/components/Popups/FailedNetworkSwitchPopup.tsx b/apps/cowswap-frontend/src/legacy/components/Popups/FailedNetworkSwitchPopup.tsx
index 0825bcd3d7..9f84c557de 100644
--- a/apps/cowswap-frontend/src/legacy/components/Popups/FailedNetworkSwitchPopup.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Popups/FailedNetworkSwitchPopup.tsx
@@ -1,14 +1,14 @@
import { useContext } from 'react'
+import { getChainInfo } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { AutoRow } from '@cowprotocol/ui'
import { Trans } from '@lingui/macro'
import { AlertCircle } from 'react-feather'
import styled, { ThemeContext } from 'styled-components/macro'
import { AutoColumn } from 'legacy/components/Column'
-import { AutoRow } from 'legacy/components/Row'
-import { getChainInfo } from 'legacy/constants/chainInfo'
const RowNoFlex = styled(AutoRow)`
flex-wrap: nowrap;
diff --git a/apps/cowswap-frontend/src/legacy/components/Popups/PopupItem.tsx b/apps/cowswap-frontend/src/legacy/components/Popups/PopupItem.tsx
index 9042d107ca..6004c1f7da 100644
--- a/apps/cowswap-frontend/src/legacy/components/Popups/PopupItem.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Popups/PopupItem.tsx
@@ -12,7 +12,7 @@ import { AnimatedFader, PopupWrapper, StyledClose } from './styled'
import { TransactionPopup } from './TransactionPopup'
/**
- * @deprecated use @cowswap/snackbars instead
+ * @deprecated use @cowprotocol/snackbars instead
*/
export function PopupItem({
removeAfterMs,
diff --git a/apps/cowswap-frontend/src/legacy/components/Popups/TransactionPopup.tsx b/apps/cowswap-frontend/src/legacy/components/Popups/TransactionPopup.tsx
index 69a30c03f1..43e2611136 100644
--- a/apps/cowswap-frontend/src/legacy/components/Popups/TransactionPopup.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Popups/TransactionPopup.tsx
@@ -1,15 +1,15 @@
import { useContext } from 'react'
+import { BlockExplorerLinkType } from '@cowprotocol/common-utils'
+import { AutoRow } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
+
import { AlertCircle, CheckCircle } from 'react-feather'
import styled, { ThemeContext } from 'styled-components/macro'
import { AutoColumn } from 'legacy/components/Column'
import { ExplorerLink } from 'legacy/components/ExplorerLink'
-import { AutoRow } from 'legacy/components/Row'
import { ThemedText } from 'legacy/theme'
-import { BlockExplorerLinkType } from 'legacy/utils'
-
-import { useWalletInfo } from 'modules/wallet'
const RowNoFlex = styled(AutoRow)`
flex-wrap: nowrap;
diff --git a/apps/cowswap-frontend/src/legacy/components/Popups/WarningPopup.tsx b/apps/cowswap-frontend/src/legacy/components/Popups/WarningPopup.tsx
index cce6f893ca..38b94a90ec 100644
--- a/apps/cowswap-frontend/src/legacy/components/Popups/WarningPopup.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Popups/WarningPopup.tsx
@@ -1,10 +1,11 @@
import { useContext } from 'react'
+import { AutoRow } from '@cowprotocol/ui'
+
import { AlertCircle } from 'react-feather'
import styled, { ThemeContext } from 'styled-components/macro'
import { AutoColumn } from 'legacy/components/Column'
-import { AutoRow } from 'legacy/components/Row'
import { ThemedText } from 'legacy/theme'
const RowNoFlex = styled(AutoRow)`
diff --git a/apps/cowswap-frontend/src/legacy/components/Popups/index.tsx b/apps/cowswap-frontend/src/legacy/components/Popups/index.tsx
index 3ba3b376d0..35a1a41892 100644
--- a/apps/cowswap-frontend/src/legacy/components/Popups/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Popups/index.tsx
@@ -1,6 +1,7 @@
import { MouseEvent, useCallback, useRef } from 'react'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { transparentize } from 'polished'
import styled from 'styled-components/macro'
@@ -11,8 +12,6 @@ import { useActivePopups, useRemovePopup } from 'legacy/state/application/hooks'
import { useURLWarningVisible } from 'legacy/state/user/hooks'
import { MEDIA_WIDTHS } from 'legacy/theme'
-import { useWalletInfo } from 'modules/wallet'
-
export const MobilePopupInner = styled.div`
height: 99%;
overflow-x: auto;
@@ -75,7 +74,7 @@ const FixedPopupColumn = styled(AutoColumn)<{ extraPadding: boolean; xlPadding:
`
/**
- * @deprecated use @cowswap/snackbars instead
+ * @deprecated use @cowprotocol/snackbars instead
*/
export function Popups() {
// get all popups
diff --git a/apps/cowswap-frontend/src/legacy/components/Popups/styled.ts b/apps/cowswap-frontend/src/legacy/components/Popups/styled.ts
index e2c42b455d..c730ac9988 100644
--- a/apps/cowswap-frontend/src/legacy/components/Popups/styled.ts
+++ b/apps/cowswap-frontend/src/legacy/components/Popups/styled.ts
@@ -2,6 +2,8 @@ import { animated } from '@react-spring/web'
import { X } from 'react-feather'
import styled, { DefaultTheme, FlattenInterpolation, ThemeProps } from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
const Fader = styled.div`
position: absolute;
bottom: 0px;
@@ -15,7 +17,7 @@ export const PopupWrapper = styled.div<{ css?: FlattenInterpolation theme.bg1};
+ background-color: var(${UI.COLOR_CONTAINER_BG_01});
position: relative;
border-radius: 10px;
padding: 20px 35px 20px 20px;
diff --git a/apps/cowswap-frontend/src/legacy/components/QuestionHelper/QuestionHelperMod.tsx b/apps/cowswap-frontend/src/legacy/components/QuestionHelper/QuestionHelperMod.tsx
index 1d92e7e479..9fb689e300 100644
--- a/apps/cowswap-frontend/src/legacy/components/QuestionHelper/QuestionHelperMod.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/QuestionHelper/QuestionHelperMod.tsx
@@ -1,38 +1,11 @@
import { useCallback, useState } from 'react'
-import styled from 'styled-components/macro'
+import { Tooltip, TooltipProps, renderTooltip } from '@cowprotocol/ui'
-import Tooltip, { renderTooltip } from 'legacy/components/Tooltip'
-import { TooltipProps } from 'legacy/components/Tooltip'
+import styled from 'styled-components/macro'
import { QuestionWrapper } from './index'
-/* const QuestionWrapper = styled.div`
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 0px;
- width: 18px;
- height: 18px;
- border: none;
- background: none;
- outline: none;
- cursor: default;
- border-radius: 36px;
- font-size: 12px;
- background-color: ${({ theme }) => theme.bg2};
- color: ${({ theme }) => theme.text2};
-
- :hover,
- :focus {
- opacity: 0.7;
- }
-` */
-
-/* const QuestionMark = styled.span`
- font-size: 14px;
-` */
-
const QuestionHelperContainer = styled.span`
margin-left: 4px;
display: flex;
@@ -73,7 +46,6 @@ export default function QuestionHelper({ text, className, QuestionMark, ...toolt
- {/* ? */}
diff --git a/apps/cowswap-frontend/src/legacy/components/QuestionHelper/index.tsx b/apps/cowswap-frontend/src/legacy/components/QuestionHelper/index.tsx
index cabd13ed59..9597b3f168 100644
--- a/apps/cowswap-frontend/src/legacy/components/QuestionHelper/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/QuestionHelper/index.tsx
@@ -1,10 +1,12 @@
import { ReactNode } from 'react'
+import QuestionImage from '@cowprotocol/assets/svg/question.svg'
+import { renderTooltip } from '@cowprotocol/ui'
+
import SVG from 'react-inlinesvg'
import styled from 'styled-components/macro'
-import QuestionImage from 'legacy/assets/svg/question.svg'
-import { renderTooltip } from 'legacy/components/Tooltip'
+import { UI } from 'common/constants/theme'
import QuestionHelperMod, { QuestionHelperProps } from './QuestionHelperMod'
@@ -24,7 +26,7 @@ export const QuestionWrapper = styled.div`
background-color: transparent;
> svg > path {
- stroke: ${({ theme }) => theme.text1};
+ stroke: var(${UI.COLOR_TEXT1});
}
`
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CommonBases/CommonBasesMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/CommonBases/CommonBasesMod.tsx
index b059f3410a..5843ee98a6 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CommonBases/CommonBasesMod.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CommonBases/CommonBasesMod.tsx
@@ -1,20 +1,17 @@
-import { Currency, Token } from '@uniswap/sdk-core'
+import { currencyId } from '@cowprotocol/common-utils'
+import { TokenSymbol, AutoRow } from '@cowprotocol/ui'
+import { Currency } from '@uniswap/sdk-core'
import { Trans } from '@lingui/macro'
import { Text } from 'rebass'
import styled from 'styled-components/macro'
-import { ElementName, Event, EventName } from 'legacy/components/AmplitudeAnalytics/constants'
-import { TraceEvent } from 'legacy/components/AmplitudeAnalytics/TraceEvent'
import QuestionHelper from 'legacy/components/QuestionHelper'
-import { AutoRow } from 'legacy/components/Row'
import { useFavouriteOrCommonTokens } from 'legacy/hooks/useFavouriteOrCommonTokens'
-import { currencyId } from 'legacy/utils/currencyId'
import { CurrencyLogo } from 'common/pure/CurrencyLogo'
-import { TokenSymbol } from 'common/pure/TokenSymbol'
-import { BaseWrapper, CommonBasesRow, MobileWrapper } from './index' // mod
+import { BaseWrapper, CommonBasesRow, MobileWrapper } from './index'
export const StyledScrollarea = styled.div`
overflow-y: auto; // fallback for 'overlay'
@@ -28,35 +25,16 @@ export const StyledScrollarea = styled.div`
`}
`
-const formatAnalyticsEventProperties = (
- currency: Currency,
- tokenAddress: string | undefined,
- searchQuery: string,
- isAddressSearch: string | false
-) => ({
- token_symbol: currency?.symbol,
- token_chain_id: currency?.chainId,
- ...(tokenAddress ? { token_address: tokenAddress } : {}),
- is_suggested_token: true,
- is_selected_from_list: false,
- is_imported_by_user: false,
- ...(isAddressSearch === false
- ? { search_token_symbol_input: searchQuery }
- : { search_token_address_input: isAddressSearch }),
-})
-
const MAX_LENGTH_OVERFLOW = 12
export default function CommonBases({
onSelect,
selectedCurrency,
- searchQuery,
- isAddressSearch,
}: {
chainId?: number
selectedCurrency?: Currency | null
onSelect: (currency: Currency) => void
- searchQuery: string
- isAddressSearch: string | false
+ searchQuery?: string
+ isAddressSearch?: string | false
}) {
const tokens = useFavouriteOrCommonTokens()
@@ -72,16 +50,9 @@ export default function CommonBases({
{tokens.map((currency: Currency) => {
const isSelected = selectedCurrency?.equals(currency)
- const tokenAddress = currency instanceof Token ? currency?.address : undefined
return (
-
+ <>
!isSelected && e.key === 'Enter' && onSelect(currency)}
@@ -94,7 +65,7 @@ export default function CommonBases({
-
+ >
)
})}
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CommonBases/index.ts b/apps/cowswap-frontend/src/legacy/components/SearchModal/CommonBases/index.ts
index c8f4cc0ac5..269b7f262b 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CommonBases/index.ts
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CommonBases/index.ts
@@ -1,10 +1,10 @@
+import { AutoRow } from '@cowprotocol/ui'
import { Currency } from '@uniswap/sdk-core'
import { transparentize } from 'polished'
import styled from 'styled-components/macro'
import { AutoColumn as AutoColumnUni } from 'legacy/components/Column'
-import { AutoRow } from 'legacy/components/Row'
export { default } from './CommonBasesMod'
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/CurrencyListMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/CurrencyListMod.tsx
index 1f3ccbb4e5..354a7510c1 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/CurrencyListMod.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/CurrencyListMod.tsx
@@ -1,5 +1,10 @@
import { CSSProperties, MutableRefObject, useCallback, useMemo } from 'react'
+import TokenListLogo from '@cowprotocol/assets/svg/tokenlist.svg'
+import { useTheme } from '@cowprotocol/common-hooks'
+import { TokenAmount, TokenSymbol, Loader, RowBetween, RowFixed } from '@cowprotocol/ui'
+import { MouseoverTooltip } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
import { Trans } from '@lingui/macro'
@@ -7,29 +12,19 @@ import { FixedSizeList } from 'react-window'
import { Text } from 'rebass'
import styled from 'styled-components/macro'
-import TokenListLogo from 'legacy/assets/svg/tokenlist.svg'
-import { ElementName, Event, EventName } from 'legacy/components/AmplitudeAnalytics/constants'
-import { TraceEvent } from 'legacy/components/AmplitudeAnalytics/TraceEvent'
import { LightGreyCard } from 'legacy/components/Card'
import Column from 'legacy/components/Column'
-import Loader from 'legacy/components/Loader'
import QuestionHelper from 'legacy/components/QuestionHelper'
-import { RowBetween, RowFixed } from 'legacy/components/Row'
import ImportRow from 'legacy/components/SearchModal/ImportRow'
import { LoadingRows } from 'legacy/components/SearchModal/styleds'
-import { MouseoverTooltip } from 'legacy/components/Tooltip'
import { useAllTokens, useIsUserAddedToken } from 'legacy/hooks/Tokens'
-import useTheme from 'legacy/hooks/useTheme'
import { useIsUnsupportedTokenGp } from 'legacy/state/lists/hooks'
import { WrappedTokenInfo } from 'legacy/state/lists/wrappedTokenInfo'
import { ThemedText } from 'legacy/theme'
import useCurrencyBalance from 'modules/tokens/hooks/useCurrencyBalance'
-import { useWalletInfo } from 'modules/wallet'
import { CurrencyLogo } from 'common/pure/CurrencyLogo'
-import { TokenAmount } from 'common/pure/TokenAmount'
-import { TokenSymbol } from 'common/pure/TokenSymbol'
import { Tag } from './styled' // mod
@@ -65,6 +60,7 @@ function Balance({ balance }: { balance: CurrencyAmount }) {
export const TagContainer = styled.div`
display: flex;
justify-content: flex-end;
+ flex-flow: row wrap;
`
export const TokenListLogoWrapper = styled.img`
@@ -92,8 +88,13 @@ function TokenTags({ currency }: { currency: Currency }) {
return (
- {tag.name}
+
+ {tag.icon && }
+ {tag.name}
+
+
+ {/* If there are more than one tag, show the first one and a '...' tag */}
{tags.length > 1 ? (
isUnsupported: boolean // gp-added
+ isPermitCompatible: boolean // gp-added
allTokens: { [address: string]: Token } // gp-added
BalanceComponent?: (params: { balance: CurrencyAmount }) => JSX.Element // gp-swap added
- TokenTagsComponent?: (params: { currency: Currency; isUnsupported: boolean }) => JSX.Element // gp-swap added
+ TokenTagsComponent?: (params: {
+ currency: Currency
+ isUnsupported: boolean
+ isPermitCompatible: boolean
+ }) => JSX.Element // gp-swap added
}) {
const { account } = useWalletInfo()
const key = currencyKey(currency)
@@ -141,12 +146,7 @@ function CurrencyRow({
// only show add or remove buttons if not on selected list
return (
-
+ <>
{/* */}
-
+
{showCurrencyAmount && (
{balance ? : account ? : null}
)}
-
+ >
)
}
@@ -231,25 +231,6 @@ interface TokenRowProps {
style: CSSProperties
}
-const formatAnalyticsEventProperties = (
- token: Token,
- index: number,
- data: any[],
- searchQuery: string,
- isAddressSearch: string | false
-) => ({
- token_symbol: token?.symbol,
- token_address: token?.address,
- is_suggested_token: false,
- is_selected_from_list: true,
- scroll_position: '',
- token_list_index: index,
- token_list_length: data.length,
- ...(isAddressSearch === false
- ? { search_token_symbol_input: searchQuery }
- : { search_token_address_input: isAddressSearch }),
-})
-
// TODO: refactor the component
export default function CurrencyList({
height,
@@ -263,8 +244,6 @@ export default function CurrencyList({
setImportToken,
showCurrencyAmount,
isLoading,
- searchQuery,
- isAddressSearch,
additionalTokens,
BalanceComponent = Balance, // gp-swap added
TokenTagsComponent = TokenTags, // gp-swap added
@@ -280,8 +259,8 @@ export default function CurrencyList({
setImportToken: (token: Token) => void
showCurrencyAmount?: boolean
isLoading: boolean
- searchQuery: string
- isAddressSearch: string | false
+ searchQuery?: string
+ isAddressSearch?: string | false
additionalTokens?: Currency[]
BalanceComponent?: (params: { balance: CurrencyAmount }) => JSX.Element // gp-swap added
TokenTagsComponent?: (params: { currency: Currency; isUnsupported: boolean }) => JSX.Element // gp-swap added
@@ -336,6 +315,7 @@ export default function CurrencyList({
const showImport = index > currencies.length
const isUnsupported = !!isUnsupportedToken(token?.address)
+ const isPermitCompatible = false // TODO: Make dynamic
if (isLoading) {
return (
@@ -361,8 +341,8 @@ export default function CurrencyList({
BalanceComponent={BalanceComponent} // gp-swap added
TokenTagsComponent={TokenTagsComponent} // gp-swap added
isUnsupported={isUnsupported}
+ isPermitCompatible={isPermitCompatible} // gp-swap added
showCurrencyAmount={showCurrencyAmount}
- eventProperties={formatAnalyticsEventProperties(token, index, data, searchQuery, isAddressSearch)}
/>
)
} else {
@@ -378,8 +358,6 @@ export default function CurrencyList({
showImportView,
showCurrencyAmount,
isLoading,
- isAddressSearch,
- searchQuery,
isUnsupportedToken,
BalanceComponent,
TokenTagsComponent,
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/index.tsx
index 22c4363b78..43987756c4 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/index.tsx
@@ -1,153 +1,84 @@
+import { UNSUPPORTED_TOKENS_FAQ_URL } from '@cowprotocol/common-const'
+import { TokenAmount } from '@cowprotocol/ui'
+import { MouseoverTooltip } from '@cowprotocol/ui'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
-// eslint-disable-next-line no-restricted-imports
-import { t } from '@lingui/macro'
-import { transparentize } from 'polished'
+import ICON_GAS_FREE from 'assets/icon/gas-free.svg'
import { HashLink } from 'react-router-hash-link'
import styled from 'styled-components/macro'
-import { LightGreyCard } from 'legacy/components/Card'
-import Column from 'legacy/components/Column'
-import { RowFixed } from 'legacy/components/Row'
import { MenuItem as MenuItemMod } from 'legacy/components/SearchModal/styleds'
-import { MouseoverTooltip } from 'legacy/components/Tooltip'
-import { UNSUPPORTED_TOKENS_FAQ_URL } from 'legacy/constants'
import { TagInfo } from 'legacy/state/lists/wrappedTokenInfo'
-import { StyledLogo } from 'common/pure/CurrencyLogo'
-import { TokenAmount } from 'common/pure/TokenAmount'
-
import CurrencyListMod, { StyledBalanceText, TagContainer } from './CurrencyListMod'
-import { Tag as TagMod } from './styled'
+import { Wrapper, Tag, TagLink } from './styled'
+
+enum Tags {
+ UNSUPPORTED = '0',
+ GAS_FREE = '1',
+}
-const UNSUPPORTED_TOKEN_TAG = [
- {
+const TOKEN_TAGS: Record = {
+ [Tags.UNSUPPORTED]: {
name: 'Unsupported',
description:
'This token is unsupported as it does not operate optimally with CoW Protocol. Please refer to the FAQ for more information.',
id: '0',
},
-]
-
-const Tag = styled(TagMod)<{ tag?: TagInfo }>`
- // Todo: Prevent usage of !important
- background: ${({ tag, theme }) => (tag?.id === '0' ? transparentize(0.85, theme.danger) : theme.grey1)};
- color: ${({ tag, theme }) => (tag?.id === '0' ? theme.danger : theme.text1)}!important;
- max-width: 6.1rem;
-`
+ [Tags.GAS_FREE]: {
+ name: 'Gas-free approval',
+ icon: ICON_GAS_FREE,
+ description: 'This token can be approved without spending gas, using the token Permit.',
+ id: '1',
+ },
+}
-const TagLink = styled(Tag)`
- display: flex;
- align-items: center;
- font-size: x-small;
- a {
- color: inherit;
- font-weight: bold;
+export const MenuItem = styled(MenuItemMod)`
+ &:hover {
+ background-color: ${({ theme, disabled }) => !disabled && theme.grey1};
}
`
-const Wrapper = styled.div`
- ${Column} {
- > div {
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- max-width: 220px;
- width: 100%;
-
- // Token symbol name
- &:first-of-type {
- color: ${({ theme }) => theme.text1};
- }
-
- // Token full name
- &:last-of-type {
- color: ${({ theme }) => theme.text2};
- font-weight: 400;
- }
-
- ${({ theme }) => theme.mediaWidth.upToSmall`
- max-width: 140px;
- `};
- }
- }
-
- ${StyledLogo} {
- height: 36px;
- width: 36px;
- border-radius: 36px;
- }
-
- ${TagMod} {
- color: ${({ theme }) => theme.text2};
- }
-
- ${TagLink} {
- color: ${({ theme }) => theme.text1};
- }
+function TokenTags({ isUnsupported, isPermitCompatible }: { isUnsupported: boolean; isPermitCompatible?: boolean }) {
+ const tagsToShow: TagInfo[] = []
- ${LightGreyCard} {
- background: ${({ theme }) => theme.bg1};
- }
-
- ${LightGreyCard} ${RowFixed} > div {
- color: ${({ theme }) => theme.text1};
+ if (isUnsupported) {
+ tagsToShow.push(TOKEN_TAGS[Tags.UNSUPPORTED])
+ } else if (isPermitCompatible) {
+ tagsToShow.push(TOKEN_TAGS[Tags.GAS_FREE])
}
-`
-export const MenuItem = styled(MenuItemMod)`
- &:hover {
- background-color: ${({ theme, disabled }) => !disabled && theme.grey1};
+ if (tagsToShow.length === 0) {
+ return
}
-`
-function TagDescriptor({ tags, children }: { children?: React.ReactNode; tags: TagInfo[]; bg?: string }) {
- const tag = tags[0]
return (
-
-
-
- {tag.name}
-
-
- {tags.length > 1 ? (
- t`${name}: ${description}`)
- .join('; \n')}
- >
- ...
-
- ) : null}
- {children}
-
- )
-}
-
-function TokenTags({ /* currency, */ isUnsupported }: { /* currency: Currency; */ isUnsupported: boolean }) {
- if (isUnsupported) {
- return (
-
+
+ {isUnsupported && (
e.stopPropagation()}>
FAQ
-
- )
- }
-
- return // MOD: return only UnsupportedToken tags
-
- /* if (!(currency instanceof WrappedTokenInfo)) {
- return
- }
-
- const tags = currency.tags
- if (!tags || tags.length === 0) return
+ )}
+
+ )
+}
- return */
+function TagDescriptor({ tags, children }: { children?: React.ReactNode; tags: TagInfo[] }) {
+ return (
+
+ {tags.map((tag) => (
+
+
+ {tag.icon ? : null}
+ {tag.name}
+
+
+ ))}
+ {children}
+
+ )
}
export function Balance({ balance }: { balance: CurrencyAmount }) {
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/styled.ts b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/styled.ts
index 83165c1e07..610ead735d 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/styled.ts
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/styled.ts
@@ -1,15 +1,92 @@
+import { RowFixed } from '@cowprotocol/ui'
+
import styled from 'styled-components/macro'
-export const Tag = styled.div`
- background-color: ${({ theme }) => theme.bg3};
- color: ${({ theme }) => theme.text2};
- font-size: 14px;
+import { LightGreyCard } from 'legacy/components/Card'
+import Column from 'legacy/components/Column'
+import { TagInfo } from 'legacy/state/lists/wrappedTokenInfo'
+
+import { UI } from 'common/constants/theme'
+import { StyledLogo } from 'common/pure/CurrencyLogo'
+
+export const Tag = styled.div<{ tag?: TagInfo }>`
+ display: flex;
+ align-items: center;
+ background: ${({ tag }) =>
+ tag?.id === '0'
+ ? `var(${UI.COLOR_DANGER_BG})`
+ : tag?.id === '1'
+ ? `var(${UI.COLOR_SUCCESS_BG})`
+ : `var(${UI.COLOR_GREY})`};
+ color: ${({ tag }) =>
+ tag?.id === '0'
+ ? `var(${UI.COLOR_DANGER_TEXT})`
+ : tag?.id === '1'
+ ? `var(${UI.COLOR_SUCCESS_TEXT})`
+ : `var(${UI.COLOR_TEXT1})`};
+ font-size: 12px;
+ font-weight: var(${UI.FONT_WEIGHT_MEDIUM});
border-radius: 4px;
- padding: 0.25rem 0.3rem 0.25rem 0.3rem;
- max-width: 6rem;
+ padding: 4px 6px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
justify-self: flex-end;
- margin-right: 4px;
+ margin: 0 4px 0 0;
+
+ > img {
+ --size: 14px;
+ display: inline-block;
+ margin: 0 5px 0 0;
+ width: var(--size);
+ height: var(--size);
+ }
+`
+
+export const TagLink = styled(Tag)`
+ a {
+ color: inherit;
+ font-weight: inherit;
+ }
+`
+
+export const Wrapper = styled.div`
+ ${Column} {
+ > div {
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ max-width: 220px;
+ width: 100%;
+
+ // Token symbol name
+ &:first-of-type {
+ color: var(${UI.COLOR_TEXT1});
+ }
+
+ // Token full name
+ &:last-of-type {
+ color: var(${UI.COLOR_TEXT2});
+ font-weight: 400;
+ }
+
+ ${({ theme }) => theme.mediaWidth.upToSmall`
+ max-width: 140px;
+ `};
+ }
+ }
+ ${StyledLogo} {
+ height: 36px;
+ width: 36px;
+ border-radius: 36px;
+ }
+ ${TagLink} {
+ color: var(${UI.COLOR_TEXT1});
+ }
+ ${LightGreyCard} {
+ background: var(${UI.COLOR_CONTAINER_BG_01});
+ }
+ ${LightGreyCard} ${RowFixed} > div {
+ color: var(${UI.COLOR_TEXT1});
+ }
`
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/CurrencySearchMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/CurrencySearchMod.tsx
index 500ca4483c..693e2efdfa 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/CurrencySearchMod.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/CurrencySearchMod.tsx
@@ -1,5 +1,10 @@
import { ChangeEvent, KeyboardEvent, RefObject, useCallback, useEffect, useMemo, useRef, useState } from 'react'
+import { searchByAddressAnalytics } from '@cowprotocol/analytics'
+import { useTheme, useDebounce, useNetworkName, useOnClickOutside, useToggle } from '@cowprotocol/common-hooks'
+import { isAddress } from '@cowprotocol/common-utils'
+import { Row } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Currency, Token } from '@uniswap/sdk-core'
import { t, Trans } from '@lingui/macro'
@@ -8,27 +13,21 @@ import { FixedSizeList } from 'react-window'
import { Text } from 'rebass'
import styled, { DefaultTheme } from 'styled-components/macro'
-import { EventName, ModalName } from 'legacy/components/AmplitudeAnalytics/constants'
-import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace'
-import { searchByAddressAnalytics } from 'legacy/components/analytics'
import Column from 'legacy/components/Column'
-import Row /* RowBetween , RowFixed */ from 'legacy/components/Row'
import CommonBases from 'legacy/components/SearchModal/CommonBases'
import CurrencyList from 'legacy/components/SearchModal/CurrencyList'
import ImportRow from 'legacy/components/SearchModal/ImportRow'
import { PaddedColumn, SearchInput, Separator, PaddedRow } from 'legacy/components/SearchModal/styleds'
-import { useAllTokens, useIsUserAddedToken, useSearchInactiveTokenLists, useToken } from 'legacy/hooks/Tokens'
-import useDebounce from 'legacy/hooks/useDebounce'
-import useNetworkName from 'legacy/hooks/useNetworkName'
-import { useOnClickOutside } from 'legacy/hooks/useOnClickOutside'
-import useTheme from 'legacy/hooks/useTheme'
-import useToggle from 'legacy/hooks/useToggle'
-import { useAllTokenBalances } from 'legacy/state/connection/hooks'
+import {
+ useAllTokenBalances,
+ useAllTokens,
+ useIsUserAddedToken,
+ useSearchInactiveTokenLists,
+ useToken,
+} from 'legacy/hooks/Tokens'
import { ButtonText, CloseIcon, ThemedText } from 'legacy/theme'
-import { isAddress } from 'legacy/utils'
-
-import { useWalletInfo } from 'modules/wallet'
+import { UI } from 'common/constants/theme'
import { useExternalTokenSearch } from 'common/hooks/useExternalTokenSearch'
import useNativeCurrency from 'lib/hooks/useNativeCurrency'
import { getTokenFilter } from 'lib/hooks/useTokenList/filtering'
@@ -42,7 +41,7 @@ export const Footer = styled.div`
padding: 20px;
border-top-left-radius: 0;
border-top-right-radius: 0;
- background-color: ${({ theme }) => theme.bg1};
+ background-color: var(${UI.COLOR_CONTAINER_BG_01});
`
export interface CurrencySearchProps {
@@ -207,7 +206,7 @@ export function CurrencySearch({
}, [])
return (
-
+ <>
@@ -287,6 +286,6 @@ export function CurrencySearch({
-
+ >
)
}
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/index.tsx
index 7174b3c087..568b8c912b 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/index.tsx
@@ -1,3 +1,5 @@
+import { RowFixed } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import { transparentize } from 'polished'
import { Edit } from 'react-feather'
@@ -5,10 +7,11 @@ import styled from 'styled-components/macro'
import { DefaultTheme } from 'styled-components/macro'
import Column from 'legacy/components/Column'
-import { RowFixed } from 'legacy/components/Row'
import { Separator } from 'legacy/components/SearchModal/styleds'
import { IconWrapper, ThemedText } from 'legacy/theme'
+import { UI } from 'common/constants/theme'
+
import { CurrencySearch as CurrencySearchMod, CurrencySearchProps } from './CurrencySearchMod'
export const ContentWrapper = styled(Column)`
@@ -19,8 +22,8 @@ export const ContentWrapper = styled(Column)`
> input {
border: none;
transition: background 0.3s ease-in-out;
- background: ${({ theme }) => theme.bg1};
- color: ${({ theme }) => theme.text1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
+ color: var(${UI.COLOR_TEXT1});
}
> input::placeholder {
@@ -33,7 +36,7 @@ export const ContentWrapper = styled(Column)`
}
${Separator} {
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
// Target the token list container
+ div {
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/sorting.ts b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/sorting.ts
index 141f362f8a..c3fb6ccc26 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/sorting.ts
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/sorting.ts
@@ -2,7 +2,7 @@ import { useMemo } from 'react'
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
-import { useAllTokenBalances } from 'legacy/state/connection/hooks'
+import { useAllTokenBalances } from 'legacy/hooks/Tokens'
import { TokenAmounts } from 'modules/tokens'
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearchModal.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearchModal.tsx
index 403c1540a4..3fc6e94102 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearchModal.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearchModal.tsx
@@ -1,20 +1,17 @@
import { useCallback, useEffect, useState } from 'react'
+import { usePrevious, useLast } from '@cowprotocol/common-hooks'
import { Currency, Token } from '@uniswap/sdk-core'
import { TokenList } from '@uniswap/token-lists'
-// import Modal from '../Modal'
import { CurrencySearch } from 'legacy/components/SearchModal/CurrencySearch'
import { ImportList } from 'legacy/components/SearchModal/ImportList'
import { ImportToken } from 'legacy/components/SearchModal/ImportToken'
import Manage from 'legacy/components/SearchModal/Manage'
-import usePrevious from 'legacy/hooks/usePrevious'
import { WrappedTokenInfo } from 'legacy/state/lists/wrappedTokenInfo'
import { CowModal as Modal } from 'common/pure/Modal'
-import useLast from '../../hooks/useLast'
-
export interface CurrencySearchModalProps {
isOpen: boolean
onDismiss: () => void
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportList/ImportListMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportList/ImportListMod.tsx
index 3c925130d1..d047a1f786 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportList/ImportListMod.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportList/ImportListMod.tsx
@@ -1,24 +1,25 @@
import { useCallback, useState } from 'react'
+import { addListAnalytics } from '@cowprotocol/analytics'
+import { useTheme } from '@cowprotocol/common-hooks'
+import { ButtonPrimary } from '@cowprotocol/ui'
+import { AutoRow, RowBetween, RowFixed } from '@cowprotocol/ui'
+import { ExternalLink } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import { transparentize } from 'polished'
import { AlertTriangle, ArrowLeft } from 'react-feather'
import styled from 'styled-components/macro'
-import { addListAnalytics } from 'legacy/components/analytics'
-import { ButtonPrimary } from 'legacy/components/Button'
import { AutoColumn } from 'legacy/components/Column'
import ListLogo from 'legacy/components/ListLogo'
-import { AutoRow, RowBetween, RowFixed } from 'legacy/components/Row'
import { CurrencyModalView } from 'legacy/components/SearchModal/CurrencySearchModal'
import { Card } from 'legacy/components/SearchModal/ManageLists'
import { Checkbox, PaddedColumn, TextDot } from 'legacy/components/SearchModal/styleds'
import { SectionBreak } from 'legacy/components/swap/styleds'
import { useFetchListCallback } from 'legacy/hooks/useFetchListCallback'
-import useTheme from 'legacy/hooks/useTheme'
import { useAllLists } from 'legacy/state/lists/hooks'
import { CloseIcon, ThemedText } from 'legacy/theme'
-import { ExternalLink } from 'legacy/theme'
import { ImportProps } from './index'
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportList/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportList/index.tsx
index b29590c17e..031b52b50c 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportList/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportList/index.tsx
@@ -1,15 +1,14 @@
import { useCallback } from 'react'
+import { DEFAULT_NETWORK_FOR_LISTS } from '@cowprotocol/common-const'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { TokenList } from '@uniswap/token-lists'
import { useDispatch } from 'react-redux'
import { CurrencyModalView } from 'legacy/components/SearchModal/CurrencySearchModal'
-import { DEFAULT_NETWORK_FOR_LISTS } from 'legacy/constants/lists'
import { enableList as enableListMod, removeList as removeListMod } from 'legacy/state/lists/actions'
-import { useWalletInfo } from 'modules/wallet'
-
import { ImportList as ImportListMod } from './ImportListMod'
export interface ImportProps {
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportRow/ImportRowMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportRow/ImportRowMod.tsx
index 710e4a5256..628055712d 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportRow/ImportRowMod.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportRow/ImportRowMod.tsx
@@ -1,17 +1,17 @@
import { CSSProperties } from 'react'
+import { useTheme } from '@cowprotocol/common-hooks'
+import { ButtonPrimary } from '@cowprotocol/ui'
+import { AutoRow, RowFixed } from '@cowprotocol/ui'
import { Token } from '@uniswap/sdk-core'
import { Trans } from '@lingui/macro'
import { CheckCircle } from 'react-feather'
import styled from 'styled-components/macro'
-import { ButtonPrimary } from 'legacy/components/Button'
import { AutoColumn } from 'legacy/components/Column'
import ListLogo from 'legacy/components/ListLogo'
-import { AutoRow, RowFixed } from 'legacy/components/Row'
import { useIsTokenActive, useIsUserAddedToken } from 'legacy/hooks/Tokens'
-import useTheme from 'legacy/hooks/useTheme'
import { WrappedTokenInfo } from 'legacy/state/lists/wrappedTokenInfo'
import { ThemedText } from 'legacy/theme'
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportRow/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportRow/index.tsx
index 38d8522d74..24e27be063 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportRow/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportRow/index.tsx
@@ -1,12 +1,14 @@
import { CSSProperties } from 'react'
+import { ButtonPrimary } from '@cowprotocol/ui'
+import { AutoRow } from '@cowprotocol/ui'
import { Token } from '@uniswap/sdk-core'
import styled from 'styled-components/macro'
-import { ButtonPrimary } from 'legacy/components/Button'
import { StyledListLogo } from 'legacy/components/ListLogo'
-import { AutoRow } from 'legacy/components/Row'
+
+import { UI } from 'common/constants/theme'
import ImportRowMod, { TokenSection } from './ImportRowMod'
@@ -31,7 +33,7 @@ const Wrapper = styled.div`
}
${TokenSection} > svg {
- stroke: ${({ theme }) => theme.text2};
+ stroke: var(${UI.COLOR_TEXT2});
}
${TokenSection} ${AutoRow} {
@@ -40,7 +42,7 @@ const Wrapper = styled.div`
}
${AutoRow} > div {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
margin: 0;
}
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/ImportTokenMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/ImportTokenMod.tsx
index 8c35abf901..f752e237ea 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/ImportTokenMod.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/ImportTokenMod.tsx
@@ -1,3 +1,6 @@
+import { useTheme } from '@cowprotocol/common-hooks'
+import { ButtonPrimary } from '@cowprotocol/ui'
+import { RowBetween } from '@cowprotocol/ui'
import { Currency, Token } from '@uniswap/sdk-core'
import { TokenList } from '@uniswap/token-lists'
@@ -6,16 +9,11 @@ import { transparentize } from 'polished'
import { AlertCircle, ArrowLeft } from 'react-feather'
import styled from 'styled-components/macro'
-import { ElementName, Event, EventName } from 'legacy/components/AmplitudeAnalytics/constants'
-import { TraceEvent } from 'legacy/components/AmplitudeAnalytics/TraceEvent'
-import { ButtonPrimary } from 'legacy/components/Button'
import Card from 'legacy/components/Card'
import { AutoColumn } from 'legacy/components/Column'
-import { RowBetween } from 'legacy/components/Row'
import { PaddedColumn } from 'legacy/components/SearchModal/styleds'
import TokenImportCard from 'legacy/components/SearchModal/TokenImportCard'
import { SectionBreak } from 'legacy/components/swap/styleds'
-import useTheme from 'legacy/hooks/useTheme'
import { useAddUserToken } from 'legacy/state/user/hooks'
import { CloseIcon, ThemedText } from 'legacy/theme'
@@ -50,12 +48,6 @@ export interface ImportProps {
CardComponent: (props: CardComponentProps) => JSX.Element // mod
}
-const formatAnalyticsEventProperties = (tokens: Token[]) => ({
- token_symbols: tokens.map((token) => token?.symbol),
- token_addresses: tokens.map((token) => token?.address),
- token_chain_ids: tokens.map((token) => token?.chainId),
-})
-
export function ImportToken(props: ImportProps) {
const { tokens, list, onBack, onDismiss, handleCurrencySelect } = props
const theme = useTheme()
@@ -87,12 +79,7 @@ export function ImportToken(props: ImportProps) {
{tokens.map((token) => (
))}
-
+ <>
Import
-
+ >
)
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/index.tsx
index 1d2312a50b..c06016c36d 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/index.tsx
@@ -1,3 +1,5 @@
+import { getEtherscanLink as getExplorerLink } from '@cowprotocol/common-utils'
+import { RowFixed, ExternalLink } from '@cowprotocol/ui'
import { Token } from '@uniswap/sdk-core'
import { Trans } from '@lingui/macro'
@@ -8,12 +10,10 @@ import styled from 'styled-components/macro'
import Card from 'legacy/components/Card'
import { AutoColumn } from 'legacy/components/Column'
import ListLogo from 'legacy/components/ListLogo'
-import { RowFixed } from 'legacy/components/Row'
import { PaddedColumn } from 'legacy/components/SearchModal/styleds'
import { ThemedText } from 'legacy/theme'
-import { ExternalLink } from 'legacy/theme/components'
-import { getEtherscanLink as getExplorerLink } from 'legacy/utils'
+import { UI } from 'common/constants/theme'
import { CurrencyLogo } from 'common/pure/CurrencyLogo'
import { AddressText, ImportProps, ImportToken as ImportTokenMod, WarningWrapper } from './ImportTokenMod'
@@ -48,7 +48,7 @@ const Wrapper = styled.div`
${({ theme }) => theme.mediaWidth.upToSmall`
position: sticky;
top: 0;
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
`}
}
`
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/Manage/ManageMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/Manage/ManageMod.tsx
index 85e4791b3f..1a186824d8 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/Manage/ManageMod.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/Manage/ManageMod.tsx
@@ -1,10 +1,11 @@
import { useState } from 'react'
+import { RowBetween } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import { ArrowLeft } from 'react-feather'
import { Text } from 'rebass'
-import { RowBetween } from 'legacy/components/Row'
import { CurrencyModalView } from 'legacy/components/SearchModal/CurrencySearchModal'
import { ManageLists } from 'legacy/components/SearchModal/ManageLists'
import ManageTokens from 'legacy/components/SearchModal/ManageTokens'
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/Manage/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/Manage/index.tsx
index 51da5e661a..1c757d948d 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/Manage/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/Manage/index.tsx
@@ -1,13 +1,15 @@
+import { RowBetween } from '@cowprotocol/ui'
import { Token } from '@uniswap/sdk-core'
import { TokenList } from '@uniswap/token-lists'
import { transparentize } from 'polished'
import styled from 'styled-components/macro'
-import { RowBetween } from 'legacy/components/Row'
import { CurrencyModalView } from 'legacy/components/SearchModal/CurrencySearchModal'
import { SearchInput, Separator } from 'legacy/components/SearchModal/styleds'
+import { UI } from 'common/constants/theme'
+
import ManageMod from './ManageMod'
export const Wrapper = styled.div`
@@ -19,7 +21,7 @@ export const Wrapper = styled.div`
${SearchInput} {
border: none;
transition: background 0.3s ease-in-out;
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
}
${SearchInput}::placeholder {
@@ -50,7 +52,7 @@ const ToggleOption = styled.div<{ active?: boolean }>`
border-radius: 12px;
font-weight: 600;
background-color: ${({ theme, active }) => (active ? theme.bg1 : theme.bg1)};
- color: ${({ theme, active }) => (active ? theme.text1 : theme.disabled)};
+ color: ${({ theme, active }) => (active ? `var(${UI.COLOR_TEXT1})` : theme.disabled)};
user-select: none;
:hover {
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/ManageListsMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/ManageListsMod.tsx
index b60e1a86f5..7f4cf67124 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/ManageListsMod.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/ManageListsMod.tsx
@@ -1,38 +1,36 @@
import { ChangeEvent, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
-import { TokenList } from '@uniswap/token-lists'
+import { updateListAnalytics, removeListAnalytics, toggleListAnalytics } from '@cowprotocol/analytics'
+import { useListColor, useTheme, useToggle, useOnClickOutside } from '@cowprotocol/common-hooks'
+import { parseENSAddress, uriToHttp } from '@cowprotocol/common-utils'
+import { Row, RowBetween, RowFixed, ButtonEmpty, ButtonPrimary, ExternalLink } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
+import { TokenList, Version } from '@uniswap/token-lists'
import { t, Trans } from '@lingui/macro'
import { CheckCircle, Settings } from 'react-feather'
import { usePopper } from 'react-popper'
import styled from 'styled-components/macro'
-import { updateListAnalytics, removeListAnalytics, toggleListAnalytics } from 'legacy/components/analytics'
-import { ButtonEmpty, ButtonPrimary } from 'legacy/components/Button'
import Column, { AutoColumn } from 'legacy/components/Column'
import ListLogo from 'legacy/components/ListLogo'
-import Row, { RowBetween, RowFixed } from 'legacy/components/Row'
import { CurrencyModalView } from 'legacy/components/SearchModal/CurrencySearchModal'
import { PaddedColumn, SearchInput, Separator, SeparatorDark } from 'legacy/components/SearchModal/styleds'
-import Toggle from 'legacy/components/Toggle'
-import { useListColor } from 'legacy/hooks/useColor'
+import { Toggle } from 'legacy/components/Toggle'
import { useFetchListCallback } from 'legacy/hooks/useFetchListCallback'
-import { useOnClickOutside } from 'legacy/hooks/useOnClickOutside'
-import useTheme from 'legacy/hooks/useTheme'
-import useToggle from 'legacy/hooks/useToggle'
import { useAppDispatch, useAppSelector } from 'legacy/state/hooks'
import { useActiveListUrls, useAllLists, useIsListActive } from 'legacy/state/lists/hooks'
-import { ExternalLink, IconWrapper, LinkStyledButton, ThemedText } from 'legacy/theme'
-import listVersionLabel from 'legacy/utils/listVersionLabel'
-
-import { useWalletInfo } from 'modules/wallet'
+import { IconWrapper, LinkStyledButton, ThemedText } from 'legacy/theme'
+import { UI } from 'common/constants/theme'
import { useConfirmationRequest } from 'common/hooks/useConfirmationRequest'
-import parseENSAddress from 'lib/utils/parseENSAddress'
-import uriToHttp from 'lib/utils/uriToHttp'
import { ListRowProps, RowWrapper, Card } from './index'
+function listVersionLabel(version: Version): string {
+ return `v${version.major}.${version.minor}.${version.patch}`
+}
+
const Wrapper = styled(Column)`
width: 100%;
height: 100%;
@@ -53,7 +51,7 @@ export const PopoverContainer = styled.div<{ show: boolean }>`
border: 1px solid ${({ theme }) => theme.bg3};
box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04),
0px 24px 32px rgba(0, 0, 0, 0.01);
- color: ${({ theme }) => theme.text2};
+ color: var(${UI.COLOR_TEXT2});
border-radius: 0.5rem;
padding: 1rem;
display: grid;
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/index.tsx
index 04a9ea8889..b43c63e955 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/index.tsx
@@ -1,17 +1,18 @@
+import { UNSUPPORTED_LIST_URLS } from '@cowprotocol/common-const'
+import { ButtonPrimary } from '@cowprotocol/ui'
+import { Row, RowFixed, RowBetween } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { TokenList } from '@uniswap/token-lists'
import { transparentize } from 'polished'
import styled from 'styled-components/macro'
-import { ButtonPrimary } from 'legacy/components/Button'
import CardUni from 'legacy/components/Card'
-import Row, { RowFixed, RowBetween } from 'legacy/components/Row'
import { CurrencyModalView } from 'legacy/components/SearchModal/CurrencySearchModal'
import { TextDot } from 'legacy/components/SearchModal/styleds'
-import { UNSUPPORTED_LIST_URLS } from 'legacy/constants/lists'
import { acceptListUpdate, removeList, disableList, enableList } from 'legacy/state/lists/actions'
-import { useWalletInfo } from 'modules/wallet'
+import { UI } from 'common/constants/theme'
import { ManageLists as ManageListsMod, ListContainer, PopoverContainer } from './ManageListsMod'
@@ -33,12 +34,12 @@ const Wrapper = styled.div`
svg > path,
svg > circle {
- stroke: ${({ theme }) => theme.text1};
+ stroke: var(${UI.COLOR_TEXT1});
}
}
${PopoverContainer} {
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
}
`
@@ -54,18 +55,18 @@ export const RowWrapper = styled(Row)<{ bgColor: string; active: boolean; hasAct
${Row}, ${RowFixed}, ${RowBetween} {
> div {
- color: ${({ active, theme }) => (active ? theme.text1 : theme.text2)};
+ color: ${({ active, theme }) => (active ? `var(${UI.COLOR_TEXT1})` : theme.text2)};
}
}
`
export const Card = styled(CardUni)`
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
${Row},
${Row} > div > div,
${Row} > div > div > div {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
${Row} > img {
@@ -76,7 +77,7 @@ export const Card = styled(CardUni)`
}
${TextDot} {
- background: ${({ theme }) => theme.text1};
+ background: var(${UI.COLOR_TEXT1});
}
${ButtonPrimary} {
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageTokens/ManageTokensMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageTokens/ManageTokensMod.tsx
index f288c3c4b8..5c8af0a5de 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageTokens/ManageTokensMod.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageTokens/ManageTokensMod.tsx
@@ -1,26 +1,23 @@
import { ChangeEventHandler, RefObject, useCallback, useMemo, useRef, useState } from 'react'
+import { useNetworkName, useTheme } from '@cowprotocol/common-hooks'
+import { getEtherscanLink as getExplorerLink, isAddress } from '@cowprotocol/common-utils'
+import { TokenSymbol, Row, RowBetween, RowFixed } from '@cowprotocol/ui'
+import { ExternalLink, ExternalLinkIcon } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Token } from '@uniswap/sdk-core'
import { Trans } from '@lingui/macro'
import styled from 'styled-components/macro'
import Column from 'legacy/components/Column'
-import Row, { RowBetween, RowFixed } from 'legacy/components/Row'
import { CurrencyModalView } from 'legacy/components/SearchModal/CurrencySearchModal'
import { PaddedColumn, SearchInput, Separator } from 'legacy/components/SearchModal/styleds'
import { useToken } from 'legacy/hooks/Tokens'
-import useNetworkName from 'legacy/hooks/useNetworkName'
-import useTheme from 'legacy/hooks/useTheme'
import { useRemoveUserAddedToken, useUserAddedTokens } from 'legacy/state/user/hooks'
-import { ButtonText, ExternalLink, ExternalLinkIcon, ThemedText, TrashIcon } from 'legacy/theme'
-import { isAddress } from 'legacy/utils'
-import { getEtherscanLink as getExplorerLink } from 'legacy/utils'
-
-import { useWalletInfo } from 'modules/wallet'
+import { ButtonText, ThemedText, TrashIcon } from 'legacy/theme'
import { CurrencyLogo } from 'common/pure/CurrencyLogo'
-import { TokenSymbol } from 'common/pure/TokenSymbol'
import { ImportTokensRowProps } from './index'
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageTokens/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageTokens/index.tsx
index 5180018406..25b2642d96 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageTokens/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageTokens/index.tsx
@@ -1,14 +1,17 @@
+import { Row, RowFixed, RowBetween } from '@cowprotocol/ui'
+import { LinkIcon } from '@cowprotocol/ui'
import { Token } from '@uniswap/sdk-core'
import styled, { DefaultTheme } from 'styled-components/macro'
import Card from 'legacy/components/Card'
import Column from 'legacy/components/Column'
-import Row, { RowFixed, RowBetween } from 'legacy/components/Row'
import { CurrencyModalView } from 'legacy/components/SearchModal/CurrencySearchModal'
import ImportRow from 'legacy/components/SearchModal/ImportRow'
import { Separator } from 'legacy/components/SearchModal/styleds'
-import { ButtonText, LinkIcon } from 'legacy/theme'
+import { ButtonText } from 'legacy/theme'
+
+import { UI } from 'common/constants/theme'
import ManageTokensMod, { ManageTokensProps, Footer } from './ManageTokensMod'
@@ -31,7 +34,7 @@ export const Wrapper = styled.div`
}
${RowBetween} > div {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
// Custom Tokens Title
@@ -41,7 +44,7 @@ export const Wrapper = styled.div`
// Token name
${RowBetween} > div > a > div {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
${RowFixed} > svg,
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/TokenImportCard/TokenImportCardMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/TokenImportCard/TokenImportCardMod.tsx
index 97794db10d..e382e4e1da 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/TokenImportCard/TokenImportCardMod.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/TokenImportCard/TokenImportCardMod.tsx
@@ -1,3 +1,7 @@
+import { getEtherscanLink as getExplorerLink } from '@cowprotocol/common-utils'
+import { RowFixed } from '@cowprotocol/ui'
+import { ExternalLink } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Token } from '@uniswap/sdk-core'
import { TokenList } from '@uniswap/token-lists'
@@ -9,11 +13,7 @@ import styled, { useTheme } from 'styled-components/macro'
import Card from 'legacy/components/Card'
import { AutoColumn } from 'legacy/components/Column'
import ListLogo from 'legacy/components/ListLogo'
-import { RowFixed } from 'legacy/components/Row'
-import { ExternalLink, ThemedText } from 'legacy/theme'
-import { getEtherscanLink as getExplorerLink } from 'legacy/utils'
-
-import { useWalletInfo } from 'modules/wallet'
+import { ThemedText } from 'legacy/theme'
import { CurrencyLogo } from 'common/pure/CurrencyLogo'
diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/styleds.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/styleds.tsx
index 814ce124a4..652b80ed9c 100644
--- a/apps/cowswap-frontend/src/legacy/components/SearchModal/styleds.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/styleds.tsx
@@ -1,14 +1,15 @@
+import { LoadingRows as BaseLoadingRows, RowBetween } from '@cowprotocol/ui'
+
import styled from 'styled-components/macro'
-import { LoadingRows as BaseLoadingRows } from 'legacy/components/Loader/styled'
+import { UI } from 'common/constants/theme'
import { AutoColumn } from '../Column'
-import { RowBetween } from '../Row'
export const TextDot = styled.div`
height: 3px;
width: 3px;
- background-color: ${({ theme }) => theme.text2};
+ background-color: var(${UI.COLOR_TEXT2});
border-radius: 50%;
`
@@ -52,7 +53,7 @@ export const SearchInput = styled.input`
border: none;
outline: none;
border-radius: 20px;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
border-style: solid;
border: 1px solid ${({ theme }) => theme.bg3};
-webkit-appearance: none;
diff --git a/apps/cowswap-frontend/src/legacy/components/Settings/SettingsMod.tsx b/apps/cowswap-frontend/src/legacy/components/Settings/SettingsMod.tsx
index 63913309a9..76589bf0cb 100644
--- a/apps/cowswap-frontend/src/legacy/components/Settings/SettingsMod.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Settings/SettingsMod.tsx
@@ -1,26 +1,28 @@
import { useCallback, useContext, useRef, useState } from 'react'
+import {
+ showExpertModeConfirmationAnalytics,
+ toggleExpertModeAnalytics,
+ toggleRecepientAddressAnalytics,
+} from '@cowprotocol/analytics'
+import { useOnClickOutside } from '@cowprotocol/common-hooks'
+import { RowBetween, RowFixed } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import { Settings } from 'react-feather'
import { Text } from 'rebass'
import styled, { ThemeContext } from 'styled-components/macro'
-import {
- showExpertModeConfirmationAnalytics,
- toggleExpertModeAnalytics,
- toggleRecepientAddressAnalytics,
-} from 'legacy/components/analytics'
import { AutoColumn } from 'legacy/components/Column'
import QuestionHelper from 'legacy/components/QuestionHelper'
-import { RowBetween, RowFixed } from 'legacy/components/Row'
-import Toggle from 'legacy/components/Toggle'
+import { Toggle } from 'legacy/components/Toggle'
import TransactionSettings from 'legacy/components/TransactionSettings'
-import { useOnClickOutside } from 'legacy/hooks/useOnClickOutside'
import { useModalIsOpen, useToggleSettingsMenu } from 'legacy/state/application/hooks'
import { ApplicationModal } from 'legacy/state/application/reducer'
import { useExpertModeManager, useRecipientToggleManager } from 'legacy/state/user/hooks'
import { ThemedText } from 'legacy/theme'
+import { UI } from 'common/constants/theme'
import { ExpertModeModal } from 'common/pure/ExpertModeModal'
import { SettingsTabProp } from './index'
@@ -30,7 +32,7 @@ export const StyledMenuIcon = styled(Settings)`
width: 20px;
> * {
- stroke: ${({ theme }) => theme.text2};
+ stroke: var(${UI.COLOR_TEXT2});
}
:hover {
diff --git a/apps/cowswap-frontend/src/legacy/components/Settings/index.tsx b/apps/cowswap-frontend/src/legacy/components/Settings/index.tsx
index d3e255ac47..c166d8cf30 100644
--- a/apps/cowswap-frontend/src/legacy/components/Settings/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Settings/index.tsx
@@ -1,10 +1,11 @@
+import { RowFixed } from '@cowprotocol/ui'
import { Percent } from '@uniswap/sdk-core'
import { transparentize } from 'polished'
import styled from 'styled-components/macro'
import { WithClassName } from 'types'
-import { RowFixed } from 'legacy/components/Row'
+import { UI } from 'common/constants/theme'
import SettingsMod, { StyledMenuButton, MenuFlyout, StyledMenuIcon, EmojiWrapper } from './SettingsMod'
@@ -12,8 +13,8 @@ const Settings = styled(SettingsMod)`
${MenuFlyout} {
box-shadow: ${({ theme }) => theme.boxShadow2};
border: 1px solid ${({ theme }) => transparentize(0.95, theme.white)};
- background-color: ${({ theme }) => theme.bg1};
- color: ${({ theme }) => theme.text1};
+ background-color: var(${UI.COLOR_CONTAINER_BG_01});
+ color: var(${UI.COLOR_TEXT1});
padding: 0;
margin: 0;
top: 36px;
@@ -23,7 +24,7 @@ const Settings = styled(SettingsMod)`
${RowFixed} {
> div {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
opacity: 0.85;
}
}
@@ -42,7 +43,7 @@ const Settings = styled(SettingsMod)`
&:focus {
cursor: pointer;
outline: none;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
svg {
@@ -57,7 +58,7 @@ const Settings = styled(SettingsMod)`
&:hover svg > path,
&:hover svg > circle {
- stroke: ${({ theme }) => theme.text1};
+ stroke: var(${UI.COLOR_TEXT1});
}
}
diff --git a/apps/cowswap-frontend/src/legacy/components/SideMenu/index.tsx b/apps/cowswap-frontend/src/legacy/components/SideMenu/index.tsx
index ca314064a2..600010d723 100644
--- a/apps/cowswap-frontend/src/legacy/components/SideMenu/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SideMenu/index.tsx
@@ -1,6 +1,8 @@
import { transparentize } from 'polished'
import styled from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
export const SideMenu = styled.div<{ isAccountPage?: boolean }>`
display: flex;
flex-flow: column wrap;
@@ -8,7 +10,7 @@ export const SideMenu = styled.div<{ isAccountPage?: boolean }>`
font-weight: 500;
line-height: 1;
margin: 0 24px 0 0;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
height: max-content;
position: sticky;
top: 0;
diff --git a/apps/cowswap-frontend/src/legacy/components/Stepper/index.tsx b/apps/cowswap-frontend/src/legacy/components/Stepper/index.tsx
index c86fdc0f68..b06c382c86 100644
--- a/apps/cowswap-frontend/src/legacy/components/Stepper/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Stepper/index.tsx
@@ -1,7 +1,9 @@
+import CheckCircle from '@cowprotocol/assets/cow-swap/check.svg'
+
import { transparentize } from 'polished'
import styled from 'styled-components/macro'
-import CheckCircle from 'legacy/assets/cow-swap/check.svg'
+import { UI } from 'common/constants/theme'
export const Wrapper = styled.div<{ totalSteps: number }>`
width: 100%;
@@ -84,7 +86,11 @@ export const Step = styled.div<{
> b {
color: ${({ isActiveStep, completedStep, theme }) =>
- completedStep ? theme.text1 : isActiveStep ? theme.text1 : transparentize(0.4, theme.text1)};
+ completedStep
+ ? `var(${UI.COLOR_TEXT1})`
+ : isActiveStep
+ ? `var(${UI.COLOR_TEXT1})`
+ : transparentize(0.4, theme.text1)};
font-weight: ${({ isActiveStep, completedStep }) => (completedStep ? '300' : isActiveStep ? 'bold' : '300')};
text-align: center;
diff --git a/apps/cowswap-frontend/src/legacy/components/SwapWarnings/index.tsx b/apps/cowswap-frontend/src/legacy/components/SwapWarnings/index.tsx
index 557df61a87..75ff6f23cc 100644
--- a/apps/cowswap-frontend/src/legacy/components/SwapWarnings/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/SwapWarnings/index.tsx
@@ -1,17 +1,19 @@
import React, { useContext, useMemo } from 'react'
+import { MouseoverTooltipContent } from '@cowprotocol/ui'
import { Fraction } from '@uniswap/sdk-core'
import { AlertTriangle } from 'react-feather'
import styled, { ThemeContext } from 'styled-components/macro'
-import { MouseoverTooltipContent } from 'legacy/components/Tooltip'
-import { useHighFeeWarning } from 'legacy/state/swap/hooks'
import TradeGp from 'legacy/state/swap/TradeGp'
import { useIsDarkMode } from 'legacy/state/user/hooks'
+import { useHighFeeWarning } from 'modules/swap/hooks/useSwapState'
import { StyledInfoIcon } from 'modules/swap/pure/styled'
+import { UI } from 'common/constants/theme'
+
import { AuxInformationContainer } from '../swap/styleds'
interface HighFeeContainerProps {
@@ -52,7 +54,7 @@ const WarningContainer = styled(AuxInformationContainer).attrs((props) => ({
: LOW_TIER_FEE
? theme.alert
: theme.info};
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
padding: ${({ padding = '16px' }) => padding};
width: ${({ width = '100%' }) => width};
border-radius: 16px;
diff --git a/apps/cowswap-frontend/src/legacy/components/Toggle/index.tsx b/apps/cowswap-frontend/src/legacy/components/Toggle/index.tsx
index 57779b537f..2b1a82c409 100644
--- a/apps/cowswap-frontend/src/legacy/components/Toggle/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Toggle/index.tsx
@@ -4,24 +4,26 @@ import { darken, transparentize } from 'polished'
import styled, { keyframes } from 'styled-components/macro'
import { WithClassName } from 'types'
+import { UI } from 'common/constants/theme'
+
const turnOnToggle = keyframes`
from {
- margin-left: 0em;
+ margin-left: 0;
margin-right: 2.2em;
}
to {
margin-left: 2.2em;
- margin-right: 0em;
+ margin-right: 0;
}
`
const turnOffToggle = keyframes`
from {
margin-left: 2.2em;
- margin-right: 0em;
+ margin-right: 0;
}
to {
- margin-left: 0em;
+ margin-left: 0;
margin-right: 2.2em;
}
`
@@ -54,7 +56,7 @@ export const ToggleElement = styled.span<{ isActive?: boolean; bgColor?: string;
const Wrapper = styled.button<{ isActive?: boolean; activeElement?: boolean }>`
align-items: center;
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
background: ${({ theme, isActive }) => (isActive ? theme.bg2 : theme.grey1)};
border: none;
border-radius: 20px;
@@ -97,7 +99,7 @@ export interface ToggleProps extends WithClassName {
isDisabled?: boolean // Mod
}
-export default function Toggle({ id, bgColor, isActive, toggle, className, isDisabled }: ToggleProps) {
+export function Toggle({ id, bgColor, isActive, toggle, className, isDisabled }: ToggleProps) {
const [isInitialToggleLoad, setIsInitialToggleLoad] = useState(true)
const switchToggle = () => {
diff --git a/apps/cowswap-frontend/src/legacy/components/Tokens/BalanceCell.tsx b/apps/cowswap-frontend/src/legacy/components/Tokens/BalanceCell.tsx
index 9f22e84b80..3c1029cba8 100644
--- a/apps/cowswap-frontend/src/legacy/components/Tokens/BalanceCell.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Tokens/BalanceCell.tsx
@@ -1,12 +1,9 @@
+import { useTheme } from '@cowprotocol/common-hooks'
+import { TokenAmount } from '@cowprotocol/ui'
+import { Loader } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Token, CurrencyAmount } from '@uniswap/sdk-core'
-import Loader from 'legacy/components/Loader'
-import useTheme from 'legacy/hooks/useTheme'
-
-import { useWalletInfo } from 'modules/wallet'
-
-import { TokenAmount } from 'common/pure/TokenAmount'
-
import { BalanceValue } from './styled'
type BalanceCellProps = {
diff --git a/apps/cowswap-frontend/src/legacy/components/Tokens/FavouriteTokenButton.tsx b/apps/cowswap-frontend/src/legacy/components/Tokens/FavouriteTokenButton.tsx
index fee13ac2fb..c87cbaecfb 100644
--- a/apps/cowswap-frontend/src/legacy/components/Tokens/FavouriteTokenButton.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Tokens/FavouriteTokenButton.tsx
@@ -1,13 +1,15 @@
import { MouseEventHandler, useCallback, useMemo } from 'react'
+import { useTheme } from '@cowprotocol/common-hooks'
+import { ButtonStar } from '@cowprotocol/ui'
import { Token } from '@uniswap/sdk-core'
import styled from 'styled-components/macro'
-import { ButtonStar } from 'legacy/components/Button'
-import useTheme from 'legacy/hooks/useTheme'
import { useFavouriteTokens, useToggleFavouriteToken } from 'legacy/state/user/hooks'
+import { UI } from 'common/constants/theme'
+
export const StyledButtonStar = styled(ButtonStar)`
z-index: 9;
`
@@ -38,7 +40,7 @@ export default function FavouriteTokenButton({ tokenData }: FavouriteTokenButton
return (
)
diff --git a/apps/cowswap-frontend/src/legacy/components/Tokens/FiatBalanceCell.tsx b/apps/cowswap-frontend/src/legacy/components/Tokens/FiatBalanceCell.tsx
index 09f9dd696c..a525a4d522 100644
--- a/apps/cowswap-frontend/src/legacy/components/Tokens/FiatBalanceCell.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Tokens/FiatBalanceCell.tsx
@@ -1,13 +1,11 @@
+import { FiatAmount } from '@cowprotocol/ui'
+import { MouseoverTooltip } from '@cowprotocol/ui'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { Trans } from '@lingui/macro'
-import { MouseoverTooltip } from 'legacy/components/Tooltip'
-
import { useUsdAmount } from 'modules/usdAmount'
-import { FiatAmount } from 'common/pure/FiatAmount'
-
import { BalanceValue, FiatValue, InfoCircle } from './styled'
type FiatBalanceCellProps = {
diff --git a/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTable.tsx b/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTable.tsx
index 71c5a5780e..e42ee2aed5 100644
--- a/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTable.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTable.tsx
@@ -1,16 +1,15 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
+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 { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal'
import { useErrorModal } from 'legacy/hooks/useErrorMessageAndModal'
-import useFilterTokens from 'legacy/hooks/useFilterTokens'
-import usePrevious from 'legacy/hooks/usePrevious'
import useTransactionConfirmationModal from 'legacy/hooks/useTransactionConfirmationModal'
import { useToggleWalletModal } from 'legacy/state/application/hooks'
+import { ConfirmOperationType } from 'legacy/state/types'
import { TokenAmounts } from 'modules/tokens'
diff --git a/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTableRow.tsx b/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTableRow.tsx
index 7ac7575b74..a633cc108d 100644
--- a/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTableRow.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTableRow.tsx
@@ -1,28 +1,24 @@
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 { usePrevious, useTheme } from '@cowprotocol/common-hooks'
+import { getBlockExplorerUrl } from '@cowprotocol/common-utils'
import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
+import { TokenAmount, TokenSymbol, Loader } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { CurrencyAmount, MaxUint256, Token } from '@uniswap/sdk-core'
import SVG from 'react-inlinesvg'
import { Link } from 'react-router-dom'
-import EtherscanImage from 'legacy/assets/cow-swap/etherscan-icon.svg'
-import Loader from 'legacy/components/Loader'
-import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal'
-import { GP_VAULT_RELAYER } from 'legacy/constants'
import { useErrorModal } from 'legacy/hooks/useErrorMessageAndModal'
-import usePrevious from 'legacy/hooks/usePrevious'
-import useTheme from 'legacy/hooks/useTheme'
import { useTokenAllowance } from 'legacy/hooks/useTokenAllowance'
-import { getBlockExplorerUrl } from 'legacy/utils'
import { parameterizeTradeRoute } from 'modules/trade/utils/parameterizeTradeRoute'
-import { useWalletInfo } from 'modules/wallet'
import { Routes } from 'common/constants/routes'
import { useAreThereTokensWithSameSymbol } from 'common/hooks/useAreThereTokensWithSameSymbol'
-import { TokenAmount } from 'common/pure/TokenAmount'
-import { TokenSymbol } from 'common/pure/TokenSymbol'
import { CardsSpinner, ExtLink } from 'pages/Account/styled'
import BalanceCell from './BalanceCell'
@@ -40,6 +36,7 @@ import {
} from './styled'
import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback/useApproveCallbackMod'
+import { ConfirmOperationType } from '../../state/types'
type DataRowParams = {
tokenData: Token
diff --git a/apps/cowswap-frontend/src/legacy/components/Tokens/styled.ts b/apps/cowswap-frontend/src/legacy/components/Tokens/styled.ts
index 942abb6dae..f0eb8101d0 100644
--- a/apps/cowswap-frontend/src/legacy/components/Tokens/styled.ts
+++ b/apps/cowswap-frontend/src/legacy/components/Tokens/styled.ts
@@ -1,10 +1,11 @@
+import { BaseButton } from '@cowprotocol/ui'
+
import { transparentize } from 'polished'
import { HelpCircle } from 'react-feather'
import { Link } from 'react-router-dom'
import styled from 'styled-components/macro'
-import { BaseButton } from 'legacy/components/Button'
-
+import { UI } from 'common/constants/theme'
import { CurrencyLogo } from 'common/pure/CurrencyLogo'
export const TokenSearchInput = styled.input`
@@ -14,7 +15,7 @@ export const TokenSearchInput = styled.input`
width: 100%;
align-self: flex-end;
box-shadow: none;
- background: ${({ theme }) => theme.grey1};
+ 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;
@@ -25,7 +26,7 @@ export const TokenSearchInput = styled.input`
&:focus {
max-width: 500px;
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
outline: 0;
${({ theme }) => theme.mediaWidth.upToMedium`
@@ -59,7 +60,7 @@ export const Wrapper = styled.div`
width: 100%;
border: none;
padding: 0;
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
border-radius: 16px;
display: grid;
`
@@ -80,8 +81,8 @@ export const ResponsiveLogo = styled(CurrencyLogo)`
width: 28px;
height: 28px;
border-radius: 28px;
- background: ${({ theme }) => theme.bg1};
- color: ${({ theme }) => theme.text1}!important; // TODO: prevent styles override
+ background: var(${UI.COLOR_CONTAINER_BG_01});
+ color: var(${UI.COLOR_TEXT1}) !important; // TODO: prevent styles override
${({ theme }) => theme.mediaWidth.upToMedium`
width: 21px;
@@ -166,7 +167,7 @@ export const ArrowButton = styled.button`
`
export const Arrow = styled.div<{ faded: boolean }>`
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
opacity: ${(props) => (props.faded ? 0.3 : 1)};
padding: 0 10px;
user-select: none;
@@ -207,7 +208,7 @@ export const Row = styled.div`
`}
&:hover {
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
}
`
@@ -248,11 +249,11 @@ export const Cell = styled.div`
transition: text-decoration-color 0.2s ease-in-out;
overflow: hidden;
display: flex;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
&:hover {
- color: ${({ theme }) => theme.text1};
- text-decoration-color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
+ text-decoration-color: var(${UI.COLOR_TEXT1});
}
}
`
@@ -263,7 +264,7 @@ export const IndexNumber = styled.span`
`
export const BalanceValue = styled.span<{ hasBalance: boolean }>`
- color: ${({ hasBalance, theme }) => (hasBalance ? theme.text1 : transparentize(0.3, theme.text1))};
+ color: ${({ hasBalance, theme }) => (hasBalance ? `var(${UI.COLOR_TEXT1})` : transparentize(0.3, theme.text1))};
font-weight: 500;
font-size: 14px;
white-space: nowrap;
@@ -297,7 +298,7 @@ export const TableButton = styled(BaseButton)<{ color?: string; outlined?: boole
max-height: 100%;
> path {
- fill: ${({ theme }) => theme.text1};
+ fill: var(${UI.COLOR_TEXT1});
}
}
@@ -416,7 +417,7 @@ export const FiatValue = styled.div`
`
export const InfoCircle = styled(HelpCircle)`
- stroke: ${({ theme }) => theme.text1};
+ stroke: var(${UI.COLOR_TEXT1});
width: 15px;
height: 15px;
margin-left: 5px;
diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/DisplayLink.tsx b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/DisplayLink.tsx
index 8e52480795..e8dbc87f05 100644
--- a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/DisplayLink.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/DisplayLink.tsx
@@ -1,11 +1,12 @@
import React, { useContext } from 'react'
+import { getBlockExplorerUrl, getEtherscanLink, getExplorerLabel } from '@cowprotocol/common-utils'
+
import { Text } from 'rebass'
import { ThemeContext } from 'styled-components/macro'
import { OrderStatus } from 'legacy/state/orders/actions'
import { useOrder } from 'legacy/state/orders/hooks'
-import { getBlockExplorerUrl, getEtherscanLink, getExplorerLabel } from 'legacy/utils'
import { ExternalLinkCustom } from './styled'
diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/LegacyConfirmationPendingContent.tsx b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/LegacyConfirmationPendingContent.tsx
index b85cbee668..f7f117013c 100644
--- a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/LegacyConfirmationPendingContent.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/LegacyConfirmationPendingContent.tsx
@@ -1,23 +1,27 @@
import React, { ReactNode, useMemo } from 'react'
+import alertImage from '@cowprotocol/assets/cow-swap/alert-circle.svg'
+import checkImage from '@cowprotocol/assets/cow-swap/check.svg'
+import { getChainCurrencySymbols } from '@cowprotocol/common-const'
+import { shortenAddress } from '@cowprotocol/common-utils'
+import { ExternalLink } from '@cowprotocol/ui'
+import {
+ getWeb3ReactConnection,
+ useGnosisSafeInfo,
+ useWalletDetails,
+ useWalletInfo,
+ getIsMetaMask,
+ injectedConnection,
+} from '@cowprotocol/wallet'
import { useWeb3React } from '@web3-react/core'
import { t, Trans } from '@lingui/macro'
import { CheckCircle, UserCheck } from 'react-feather'
import SVG from 'react-inlinesvg'
-import alertImage from 'legacy/assets/cow-swap/alert-circle.svg'
-import checkImage from 'legacy/assets/cow-swap/check.svg'
import { MediumAndUp, useMediaQuery } from 'legacy/hooks/useMediaQuery'
-import { ExternalLink } from 'legacy/theme'
-import { shortenAddress } from 'legacy/utils'
-import { getChainCurrencySymbols } from 'legacy/utils/gnosis_chain/hack'
import { getStatusIcon } from 'modules/account/containers/AccountDetails'
-import { useGnosisSafeInfo, useWalletDetails, useWalletInfo } from 'modules/wallet'
-import { getIsMetaMask } from 'modules/wallet/api/utils/connection'
-import { getWeb3ReactConnection } from 'modules/wallet/web3-react/connection'
-import { injectedConnection } from 'modules/wallet/web3-react/connection/injected'
import {
ApproveComparison,
@@ -33,7 +37,8 @@ import {
WalletIcon,
Wrapper,
} from './styled'
-import { ConfirmOperationType } from './types'
+
+import { ConfirmOperationType } from '../../state/types'
enum WalletType {
SAFE,
diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.cosmos.tsx b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.cosmos.tsx
index 85175f9bf8..0a1630b537 100644
--- a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.cosmos.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.cosmos.tsx
@@ -1,14 +1,15 @@
+import { COW, GNO } from '@cowprotocol/common-const'
import { OrderClass, OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk'
import styled from 'styled-components/macro'
-import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal'
-import { COW, GNO } from 'legacy/constants/tokens'
-import store from 'legacy/state'
import { addPendingOrder, OrderStatus } from 'legacy/state/orders/actions'
+import { ConfirmOperationType } from 'legacy/state/types'
import { LegacyConfirmationPendingContent } from './LegacyConfirmationPendingContent'
+import { cowSwapStore } from '../../state'
+
const txHash = '0xe87e1d02b052daa9605abe018e8172feffd1bc38ed2284e6hhhhhh' + Date.now()
const defaultProps = {
@@ -40,7 +41,7 @@ const Fixtures = {
),
}
-store.dispatch(
+cowSwapStore.dispatch(
addPendingOrder({
id: txHash,
chainId: 5,
diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.tsx b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.tsx
index 321445cb45..76dbd956da 100644
--- a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.tsx
@@ -1,23 +1,24 @@
import { useSetAtom } from 'jotai'
import React, { ReactNode, useCallback, useEffect } from 'react'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Currency } from '@uniswap/sdk-core'
import { getActivityState, useActivityDerivedState } from 'legacy/hooks/useActivityDerivedState'
import { useMultipleActivityDescriptors } from 'legacy/hooks/useRecentActivity'
-import { handleFollowPendingTxPopupAtom } from 'legacy/state/application/atoms'
+import { ConfirmOperationType } from 'legacy/state/types'
import { useSetIsConfirmationModalOpen } from 'modules/swap/state/surplusModal'
-import { useWalletInfo } from 'modules/wallet'
+import { SwapConfirmState } from 'modules/swap/state/swapConfirmAtom'
+import { handleFollowPendingTxPopupAtom } from 'modules/wallet/state/followPendingTxPopupAtom'
+import { PermitModal } from 'common/containers/PermitModal'
import { useGetSurplusData } from 'common/hooks/useGetSurplusFiatValue'
import { CowModal } from 'common/pure/Modal'
import { TransactionSubmittedContent } from 'common/pure/TransactionSubmittedContent'
+import { TradeAmounts } from 'common/types'
import { LegacyConfirmationPendingContent } from './LegacyConfirmationPendingContent'
-import { ConfirmOperationType } from './types'
-
-export * from './types'
export interface ConfirmationModalProps {
isOpen: boolean
@@ -28,6 +29,8 @@ export interface ConfirmationModalProps {
pendingText?: ReactNode
currencyToAdd?: Currency | undefined
operationType: ConfirmOperationType
+ tradeAmounts?: TradeAmounts | undefined
+ swapConfirmState?: SwapConfirmState | undefined
}
export function TransactionConfirmationModal({
@@ -39,6 +42,8 @@ export function TransactionConfirmationModal({
content,
currencyToAdd,
operationType,
+ tradeAmounts,
+ swapConfirmState,
}: ConfirmationModalProps) {
const { chainId } = useWalletInfo()
const setShowFollowPendingTxPopup = useSetAtom(handleFollowPendingTxPopupAtom)
@@ -72,7 +77,15 @@ export function TransactionConfirmationModal({
return (
- {attemptingTxn ? (
+ {showPermitModal(swapConfirmState) ? (
+
+ ) : attemptingTxn ? (
theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
position: sticky;
top: 0;
left: 0;
@@ -115,7 +119,7 @@ export const GPModalHeader = styled(RowBetween)`
left: 0;
width: 100%;
padding: 16px 0;
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
z-index: 20;
`
@@ -154,7 +158,7 @@ export const ButtonCustom = styled.button`
border-radius: 16px;
min-height: 52px;
border: 1px solid ${({ theme }) => theme.border2};
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
background: transparent;
outline: 0;
padding: 8px 16px;
@@ -181,7 +185,7 @@ export const UpperSection = styled.div`
display: flex;
flex-flow: column wrap;
padding: 16px 16px 32px;
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
border-radius: 16px 16px 0 0;
${({ theme }) => theme.mediaWidth.upToSmall`
@@ -246,7 +250,7 @@ export const StepsIconWrapper = styled.div`
height: 100%;
width: 100%;
padding: 18px;
- stroke: ${({ theme }) => theme.text1};
+ stroke: var(${UI.COLOR_TEXT1});
}
@keyframes spin {
@@ -304,7 +308,7 @@ export const StepsWrapper = styled.div`
flex: 1 1 auto;
height: 2px;
border: 0;
- background: ${({ theme }) => theme.text1};
+ background: var(${UI.COLOR_TEXT1});
margin: auto;
position: absolute;
width: 100%;
@@ -319,7 +323,7 @@ export const StepsWrapper = styled.div`
content: '';
height: 4px;
width: 100%;
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
display: block;
margin: 0;
animation: Shrink 1s forwards linear;
diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionExecutedContent/index.tsx b/apps/cowswap-frontend/src/legacy/components/TransactionExecutedContent/index.tsx
index 5f351f8b59..bcb94824a0 100644
--- a/apps/cowswap-frontend/src/legacy/components/TransactionExecutedContent/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/TransactionExecutedContent/index.tsx
@@ -1,6 +1,6 @@
+import cowMeditatingSmooth from '@cowprotocol/assets/images/cow-meditating-smoooth.svg'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
-import cowMeditatingSmooth from 'legacy/assets/images/cow-meditating-smoooth.svg'
import { DisplayLink } from 'legacy/components/TransactionConfirmationModal/DisplayLink'
import { Order } from 'legacy/state/orders/actions'
diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionExecutedContent/styled.ts b/apps/cowswap-frontend/src/legacy/components/TransactionExecutedContent/styled.ts
index 92b126fb5c..5dc912d358 100644
--- a/apps/cowswap-frontend/src/legacy/components/TransactionExecutedContent/styled.ts
+++ b/apps/cowswap-frontend/src/legacy/components/TransactionExecutedContent/styled.ts
@@ -1,7 +1,6 @@
-import styled from 'styled-components/macro'
+import { FiatAmount, TokenAmount } from '@cowprotocol/ui'
-import { FiatAmount } from 'common/pure/FiatAmount'
-import { TokenAmount } from 'common/pure/TokenAmount'
+import styled from 'styled-components/macro'
export const ExecutedWrapper = styled.div`
display: flex;
diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionSettings/TransactionSettingsMod.tsx b/apps/cowswap-frontend/src/legacy/components/TransactionSettings/TransactionSettingsMod.tsx
index ae8541430c..7b286b19a8 100644
--- a/apps/cowswap-frontend/src/legacy/components/TransactionSettings/TransactionSettingsMod.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/TransactionSettings/TransactionSettingsMod.tsx
@@ -1,14 +1,7 @@
import { useContext, useState } from 'react'
-import { Percent } from '@uniswap/sdk-core'
-
-import { Trans } from '@lingui/macro'
-import { darken } from 'polished'
-import styled, { ThemeContext } from 'styled-components/macro'
-
-import { orderExpirationTimeAnalytics, slippageToleranceAnalytics } from 'legacy/components/analytics'
-import { AutoColumn } from 'legacy/components/Column'
-import { RowBetween, RowFixed } from 'legacy/components/Row'
+import { orderExpirationTimeAnalytics, slippageToleranceAnalytics } from '@cowprotocol/analytics'
+import { DEFAULT_DEADLINE_FROM_NOW } from '@cowprotocol/common-const'
import {
DEFAULT_SLIPPAGE_BPS,
HIGH_ETH_FLOW_SLIPPAGE_BIPS,
@@ -20,16 +13,24 @@ import {
MINIMUM_ETH_FLOW_SLIPPAGE,
MINIMUM_ETH_FLOW_SLIPPAGE_BIPS,
MINIMUM_ORDER_VALID_TO_TIME_SECONDS,
-} from 'legacy/constants'
-import { DEFAULT_DEADLINE_FROM_NOW } from 'legacy/constants/misc'
+} from '@cowprotocol/common-const'
+import { RowBetween, RowFixed } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
+import { Percent } from '@uniswap/sdk-core'
+
+import { Trans } from '@lingui/macro'
+import { darken } from 'polished'
+import styled, { ThemeContext } from 'styled-components/macro'
+
+import { AutoColumn } from 'legacy/components/Column'
import { useSetUserSlippageTolerance, useUserSlippageTolerance, useUserTransactionTTL } from 'legacy/state/user/hooks'
import { ThemedText } from 'legacy/theme'
import { useIsEoaEthFlow } from 'modules/swap/hooks/useIsEoaEthFlow'
import { getNativeOrderDeadlineTooltip, getNonNativeOrderDeadlineTooltip } from 'modules/swap/pure/Row/RowDeadline'
import { getNativeSlippageTooltip, getNonNativeSlippageTooltip } from 'modules/swap/pure/Row/RowSlippageContent'
-import { useWalletInfo } from 'modules/wallet'
+import { UI } from 'common/constants/theme'
import useNativeCurrency from 'lib/hooks/useNativeCurrency'
import QuestionHelper from '../QuestionHelper'
@@ -47,7 +48,7 @@ enum DeadlineError {
}
export const FancyButton = styled.button`
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
align-items: center;
height: 2rem;
border-radius: 36px;
@@ -57,7 +58,7 @@ export const FancyButton = styled.button`
/* border: 1px solid ${({ theme }) => theme.bg3}; */
border: 0; // mod
outline: none;
- /* background: ${({ theme }) => theme.bg1}; */
+ /* background: var(${UI.COLOR_CONTAINER_BG_01}); */
background: ${({ theme }) => theme.bg2}; // mod
:hover {
/* border: 1px solid ${({ theme }) => theme.bg4}; */
@@ -84,7 +85,7 @@ const Option = styled(FancyButton)<{ active: boolean }>`
`
export const Input = styled.input`
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
font-size: 16px;
width: auto;
outline: none;
@@ -301,7 +302,7 @@ export default function TransactionSettings({ placeholderSlippage }: Transaction
fontSize: '14px',
paddingTop: '7px',
// color: slippageError ? 'red' : '#F3841E',
- color: slippageError ? theme.danger : theme.warning, // MOD
+ color: slippageError ? `var(${UI.COLOR_DANGER})` : theme.warning, // MOD
}}
>
{slippageError ? (
diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionSettings/index.tsx b/apps/cowswap-frontend/src/legacy/components/TransactionSettings/index.tsx
index 34734c77d9..dfa63150f2 100644
--- a/apps/cowswap-frontend/src/legacy/components/TransactionSettings/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/TransactionSettings/index.tsx
@@ -1,7 +1,9 @@
+import { RowBetween, RowFixed } from '@cowprotocol/ui'
+
import { darken } from 'polished'
import styled from 'styled-components/macro'
-import { RowBetween, RowFixed } from 'legacy/components/Row'
+import { UI } from 'common/constants/theme'
import SlippageTabsMod, { TransactionSettingsProps, OptionCustom } from './TransactionSettingsMod'
@@ -15,7 +17,7 @@ const Wrapper = styled.div`
}
${OptionCustom} {
- background-color: ${({ theme }) => theme.grey1};
+ background-color: var(${UI.COLOR_GREY});
border: 0;
> div > input {
@@ -27,18 +29,18 @@ const Wrapper = styled.div`
> div > input::placeholder {
opacity: 0.5;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
}
${RowFixed} {
> div {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
opacity: 0.85;
}
> button {
- background-color: ${({ theme }) => theme.grey1};
+ background-color: var(${UI.COLOR_GREY});
border: 0;
}
@@ -49,7 +51,7 @@ const Wrapper = styled.div`
> button > input::placeholder {
background: transparent;
opacity: 0.5;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
}
`
diff --git a/apps/cowswap-frontend/src/legacy/components/Version/index.tsx b/apps/cowswap-frontend/src/legacy/components/Version/index.tsx
index 42d2e7f177..ab78ef57e9 100644
--- a/apps/cowswap-frontend/src/legacy/components/Version/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Version/index.tsx
@@ -1,14 +1,18 @@
+import {
+ CODE_LINK,
+ DEFAULT_NETWORK_FOR_LISTS,
+ 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'
+import { ExternalLink } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import styled from 'styled-components/macro'
-import { CODE_LINK, GP_VAULT_RELAYER, GP_SETTLEMENT_CONTRACT_ADDRESS } from 'legacy/constants'
-import { DEFAULT_NETWORK_FOR_LISTS } from 'legacy/constants/lists'
-import { ExternalLink } from 'legacy/theme'
-import { getEtherscanLink } from 'legacy/utils'
-
-import { useWalletInfo } from 'modules/wallet'
+import { UI } from 'common/constants/theme'
// eslint-disable-next-line @nx/enforce-module-boundaries
import pkg from '../../../../../../package.json'
@@ -67,7 +71,7 @@ const StyledPolling = styled.div`
flex-flow: column nowrap;
align-items: flex-start;
padding: 16px 0;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
gap: 10px;
`
diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useEagerlyConnect.ts b/apps/cowswap-frontend/src/legacy/components/Web3Provider/hooks/useEagerlyConnect.ts
similarity index 73%
rename from apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useEagerlyConnect.ts
rename to apps/cowswap-frontend/src/legacy/components/Web3Provider/hooks/useEagerlyConnect.ts
index ddec61ccf5..cc5021f357 100644
--- a/apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useEagerlyConnect.ts
+++ b/apps/cowswap-frontend/src/legacy/components/Web3Provider/hooks/useEagerlyConnect.ts
@@ -1,18 +1,16 @@
import { useEffect } from 'react'
+import { getCurrentChainIdFromUrl, isInjectedWidget } from '@cowprotocol/common-utils'
+import {
+ BACKFILLABLE_WALLETS,
+ getWeb3ReactConnection,
+ injectedWidgetConnection,
+ networkConnection,
+ gnosisSafeConnection,
+} from '@cowprotocol/wallet'
import { Connector } from '@web3-react/types'
-import { useAppSelector } from 'legacy/state/hooks'
-
-import { BACKFILLABLE_WALLETS } from 'modules/wallet/api/types'
-
-import { isInjectedWidget } from 'common/utils/isInjectedWidget'
-import { getCurrentChainIdFromUrl } from 'utils/getCurrentChainIdFromUrl'
-
-import { getWeb3ReactConnection } from '../connection'
-import { injectedWidgetConnection } from '../connection/injectedWidget'
-import { networkConnection } from '../connection/network'
-import { gnosisSafeConnection } from '../connection/safe'
+import { useAppSelector } from '../../../state/hooks'
async function connect(connector: Connector) {
const chainId = getCurrentChainIdFromUrl()
diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useOrderedConnections.ts b/apps/cowswap-frontend/src/legacy/components/Web3Provider/hooks/useOrderedConnections.ts
similarity index 79%
rename from apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useOrderedConnections.ts
rename to apps/cowswap-frontend/src/legacy/components/Web3Provider/hooks/useOrderedConnections.ts
index 622c8df2cc..8203dc8bde 100644
--- a/apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useOrderedConnections.ts
+++ b/apps/cowswap-frontend/src/legacy/components/Web3Provider/hooks/useOrderedConnections.ts
@@ -1,13 +1,11 @@
import { useMemo } from 'react'
-import { useAppSelector } from 'legacy/state/hooks'
-
-import { BACKFILLABLE_WALLETS, ConnectionType } from 'modules/wallet'
-import { getWeb3ReactConnection } from 'modules/wallet/web3-react/connection'
+import { isInjectedWidget } from '@cowprotocol/common-utils'
+import { BACKFILLABLE_WALLETS, ConnectionType, getWeb3ReactConnection } from '@cowprotocol/wallet'
-import { isInjectedWidget } from 'common/utils/isInjectedWidget'
+import { useAppSelector } from 'legacy/state/hooks'
-const SELECTABLE_WALLETS = [...BACKFILLABLE_WALLETS, ConnectionType.FORTMATIC]
+const SELECTABLE_WALLETS = [...BACKFILLABLE_WALLETS]
// TODO: The logic looks very similar with useEagerlyConnect
export function useOrderedConnections() {
diff --git a/apps/cowswap-frontend/src/legacy/components/Web3Provider/index.tsx b/apps/cowswap-frontend/src/legacy/components/Web3Provider/index.tsx
index fb57ba9b28..934d45baf0 100644
--- a/apps/cowswap-frontend/src/legacy/components/Web3Provider/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Web3Provider/index.tsx
@@ -1,14 +1,15 @@
import { ReactNode, useMemo } from 'react'
+import { getConnectionName, Web3ReactConnection } from '@cowprotocol/wallet'
import { Web3ReactHooks, Web3ReactProvider } from '@web3-react/core'
import { Connector } from '@web3-react/types'
-import { useOrderedConnections, useEagerlyConnect } from 'modules/wallet'
-import { getConnectionName } from 'modules/wallet/api/utils/connection'
-import { Web3ReactConnection } from 'modules/wallet/web3-react/types'
+import { useEagerlyConnect } from './hooks/useEagerlyConnect'
+import { useOrderedConnections } from './hooks/useOrderedConnections'
export default function Web3Provider({ children }: { children: ReactNode }) {
useEagerlyConnect()
+
const connections = useOrderedConnections()
const connectors: [Connector, Web3ReactHooks][] = connections.map(({ hooks, connector }) => [connector, hooks])
diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/constants.ts b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/constants.ts
deleted file mode 100644
index ab431341be..0000000000
--- a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/constants.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { isEns, isProd } from 'legacy/utils/environments'
-
-export const PIXEL_ENABLED = isProd || isEns
-
-export enum PIXEL_EVENTS {
- INIT = 'init',
- CONNECT_WALLET = 'connect_wallet',
- POST_TRADE = 'post_trade',
-}
diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/facebook.ts b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/facebook.ts
deleted file mode 100644
index 024b01b9b4..0000000000
--- a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/facebook.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { PIXEL_EVENTS } from './constants'
-import { sendPixel } from './utils'
-
-const events = {
- [PIXEL_EVENTS.INIT]: 'InitiateCheckout',
- [PIXEL_EVENTS.CONNECT_WALLET]: 'Contact',
- [PIXEL_EVENTS.POST_TRADE]: 'Lead',
-}
-
-export const sendFacebookEvent = sendPixel((event) => {
- window.fbq?.('track', events[event])
-})
diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/linkedin.ts b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/linkedin.ts
deleted file mode 100644
index f041dcb559..0000000000
--- a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/linkedin.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { PIXEL_EVENTS } from './constants'
-import { sendPixel } from './utils'
-
-const events = {
- [PIXEL_EVENTS.INIT]: 10759506,
- [PIXEL_EVENTS.CONNECT_WALLET]: 10759514,
- [PIXEL_EVENTS.POST_TRADE]: 10759522,
-}
-
-export const sendLinkedinEvent = sendPixel((event) => {
- window.lintrk?.('track', { conversion_id: events[event] })
-})
diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/microsoft.ts b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/microsoft.ts
deleted file mode 100644
index db9ad254b0..0000000000
--- a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/microsoft.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { PIXEL_EVENTS } from './constants'
-import { sendPixel } from './utils'
-
-const events = {
- [PIXEL_EVENTS.INIT]: 'page_view',
- [PIXEL_EVENTS.CONNECT_WALLET]: 'begin_checkout',
- [PIXEL_EVENTS.POST_TRADE]: 'purchase',
-}
-
-export const sendMicrosoftEvent = sendPixel((event) => {
- window.uetq = window.uetq || []
- window.uetq.push('event', events[event], {})
-})
diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/paved.ts b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/paved.ts
deleted file mode 100644
index a26d0eb24c..0000000000
--- a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/paved.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { PIXEL_EVENTS } from './constants'
-import { sendPixel } from './utils'
-
-const events = {
- [PIXEL_EVENTS.INIT]: 'search',
- [PIXEL_EVENTS.CONNECT_WALLET]: 'sign_up',
- [PIXEL_EVENTS.POST_TRADE]: 'purchase',
-}
-
-export const sendPavedEvent = sendPixel((event: PIXEL_EVENTS) => {
- window.pvd?.('event', events[event])
-})
diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/reddit.ts b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/reddit.ts
deleted file mode 100644
index c979b6ee08..0000000000
--- a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/reddit.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { PIXEL_EVENTS } from './constants'
-import { sendPixel } from './utils'
-
-const events = {
- [PIXEL_EVENTS.INIT]: 'Lead',
- [PIXEL_EVENTS.CONNECT_WALLET]: 'SignUp',
- [PIXEL_EVENTS.POST_TRADE]: 'Purchase',
-}
-
-export const sendRedditEvent = sendPixel((event) => {
- window.rdt?.('track', events[event])
-})
diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/twitter.ts b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/twitter.ts
deleted file mode 100644
index 9f5969461d..0000000000
--- a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/twitter.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { PIXEL_EVENTS } from './constants'
-import { sendPixel } from './utils'
-
-const events = {
- [PIXEL_EVENTS.INIT]: 'tw-oddz2-oddz8',
- [PIXEL_EVENTS.CONNECT_WALLET]: 'tw-oddz2-oddza',
- [PIXEL_EVENTS.POST_TRADE]: 'tw-oddz2-oddzb',
-}
-
-export const sendTwitterEvent = sendPixel((event: PIXEL_EVENTS) => {
- window.twq?.('event', events[event], {})
-})
diff --git a/apps/cowswap-frontend/src/legacy/components/earn/styled.ts b/apps/cowswap-frontend/src/legacy/components/earn/styled.ts
index d918821091..f5a38f2b46 100644
--- a/apps/cowswap-frontend/src/legacy/components/earn/styled.ts
+++ b/apps/cowswap-frontend/src/legacy/components/earn/styled.ts
@@ -1,8 +1,8 @@
-import styled from 'styled-components/macro'
+import uImage from '@cowprotocol/assets/images/big_unicorn.png'
+import noise from '@cowprotocol/assets/images/noise.png'
+import xlUnicorn from '@cowprotocol/assets/images/xl_uni.png'
-import uImage from 'legacy/assets/images/big_unicorn.png'
-import noise from 'legacy/assets/images/noise.png'
-import xlUnicorn from 'legacy/assets/images/xl_uni.png'
+import styled from 'styled-components/macro'
import { AutoColumn } from '../Column'
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 a9d2eea105..951d0d7237 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 { TokenSymbol } from '@cowprotocol/ui'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import { Nullish } from 'types'
@@ -7,8 +8,6 @@ import { Nullish } from 'types'
import { useIsSafeApprovalBundle } from 'modules/limitOrders/hooks/useIsSafeApprovalBundle'
import { useIsSafeEthFlow } from 'modules/swap/hooks/useIsSafeEthFlow'
-import { TokenSymbol } from 'common/pure/TokenSymbol'
-
export function useButtonText(slippageAdjustedSellAmount: Nullish>) {
const isSafeApprovalBundle = useIsSafeApprovalBundle(slippageAdjustedSellAmount)
const isSafeEthFlowBundle = useIsSafeEthFlow()
diff --git a/apps/cowswap-frontend/src/legacy/components/swap/ConfirmSwapModal/index.tsx b/apps/cowswap-frontend/src/legacy/components/swap/ConfirmSwapModal/index.tsx
index bc2d8bb3f0..f02968dd43 100644
--- a/apps/cowswap-frontend/src/legacy/components/swap/ConfirmSwapModal/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/swap/ConfirmSwapModal/index.tsx
@@ -1,24 +1,27 @@
import { useCallback, useMemo } from 'react'
+import { TokenAmount } from '@cowprotocol/ui'
+import { useWalletDetails } from '@cowprotocol/wallet'
import { Percent } from '@uniswap/sdk-core'
import { Trans } from '@lingui/macro'
import { SwapModalFooter } from 'legacy/components/swap/SwapModalFooter'
-import SwapModalHeader from 'legacy/components/swap/SwapModalHeader'
-import { ConfirmOperationType, TransactionConfirmationModal } from 'legacy/components/TransactionConfirmationModal'
-import { LegacyConfirmationModalContent } from 'legacy/components/TransactionConfirmationModal/LegacyConfirmationModalContent'
import TradeGp from 'legacy/state/swap/TradeGp'
import { SwapConfirmState } from 'modules/swap/state/swapConfirmAtom'
-import { useWalletDetails } from 'modules/wallet'
import { RateInfoParams } from 'common/pure/RateInfo'
-import { TokenAmount } from 'common/pure/TokenAmount'
import { TransactionErrorContent } from 'common/pure/TransactionErrorContent'
+import { TradeAmounts } from 'common/types'
import { useButtonText } from './hooks'
+import { ConfirmOperationType } from '../../../state/types'
+import { TransactionConfirmationModal } from '../../TransactionConfirmationModal'
+import { LegacyConfirmationModalContent } from '../../TransactionConfirmationModal/LegacyConfirmationModalContent'
+import { SwapModalHeader } from '../SwapModalHeader'
+
type ConfirmSwapModalProps = {
swapConfirmState: SwapConfirmState
trade: TradeGp | undefined
@@ -100,7 +103,13 @@ export function ConfirmSwapModal({
bottomContent={modalBottom}
/>
),
- [onDismiss, modalBottom, modalHeader, swapErrorMessage]
+ [swapErrorMessage, onDismiss, modalHeader, modalBottom]
+ )
+
+ const tradeAmounts: TradeAmounts | undefined = useMemo(
+ () =>
+ trade ? { inputAmount: trade.inputAmountWithoutFee, outputAmount: trade.outputAmountWithoutFee } : undefined,
+ [trade]
)
return (
@@ -113,6 +122,8 @@ export function ConfirmSwapModal({
pendingText={ }
currencyToAdd={trade?.outputAmount.currency}
operationType={ConfirmOperationType.ORDER_SIGN}
+ tradeAmounts={tradeAmounts}
+ swapConfirmState={swapConfirmState}
/>
)
}
diff --git a/apps/cowswap-frontend/src/legacy/components/swap/FeeInformationTooltip.tsx b/apps/cowswap-frontend/src/legacy/components/swap/FeeInformationTooltip.tsx
index 851afbc62b..74d25969f2 100644
--- a/apps/cowswap-frontend/src/legacy/components/swap/FeeInformationTooltip.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/swap/FeeInformationTooltip.tsx
@@ -1,19 +1,18 @@
import React from 'react'
+import { useTheme } from '@cowprotocol/common-hooks'
+import { FiatAmount } from '@cowprotocol/ui'
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
import styled from 'styled-components/macro'
import QuestionHelper from 'legacy/components/QuestionHelper'
import useCowBalanceAndSubsidy from 'legacy/hooks/useCowBalanceAndSubsidy'
-import useTheme from 'legacy/hooks/useTheme'
import TradeGp from 'legacy/state/swap/TradeGp'
import { getInputReceiveAmountInfo, getOutputReceiveAmountInfo } from 'modules/swap/helpers/tradeReceiveAmount'
import { ReceiveAmountInfoTooltip } from 'modules/swap/pure/ReceiveAmountInfo'
-import { FiatAmount } from 'common/pure/FiatAmount'
-
interface FeeInformationTooltipProps {
trade?: TradeGp
label: React.ReactNode
@@ -52,7 +51,7 @@ const FeeAmountAndFiat = styled.span`
}
`
-export default function FeeInformationTooltip(props: FeeInformationTooltipProps) {
+export function FeeInformationTooltip(props: FeeInformationTooltipProps) {
const { trade, label, amountAfterFees, type, showHelper, fiatValue, showFiat = false, allowsOffchainSigning } = props
const theme = useTheme()
diff --git a/apps/cowswap-frontend/src/legacy/components/swap/SwapHeader/SwapHeaderMod.tsx b/apps/cowswap-frontend/src/legacy/components/swap/SwapHeader/SwapHeaderMod.tsx
index 47485e4672..0c85c1d9c6 100644
--- a/apps/cowswap-frontend/src/legacy/components/swap/SwapHeader/SwapHeaderMod.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/swap/SwapHeader/SwapHeaderMod.tsx
@@ -1,15 +1,17 @@
+import { RowBetween, RowFixed } from '@cowprotocol/ui'
import { Percent } from '@uniswap/sdk-core'
import styled from 'styled-components/macro'
-import { RowBetween, RowFixed } from 'legacy/components/Row'
import SettingsTab from 'legacy/components/Settings'
import { TradeWidgetLinks } from 'modules/application/containers/TradeWidgetLinks'
+import { UI } from 'common/constants/theme'
+
const StyledSwapHeader = styled.div`
width: 100%;
- color: ${({ theme }) => theme.text2};
+ color: var(${UI.COLOR_TEXT2});
`
export default function SwapHeader({ allowedSlippage, className }: { allowedSlippage: Percent; className?: string }) {
diff --git a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalFooter/index.tsx b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalFooter/index.tsx
index 054e7ddd5a..e65c8d691c 100644
--- a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalFooter/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalFooter/index.tsx
@@ -1,18 +1,19 @@
import { ReactNode } from 'react'
+import { ButtonSize, ButtonError, AutoRow, RowBetween, RowFixed } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import { Text } from 'rebass'
import styled from 'styled-components/macro'
-import { ButtonError } from 'legacy/components/Button'
-import { AutoRow, RowBetween, RowFixed } from 'legacy/components/Row'
import { SwapCallbackError } from 'legacy/components/swap/styleds'
-import { ButtonSize } from 'legacy/theme/enum'
+
+import { UI } from 'common/constants/theme'
const Wrapper = styled.div`
${RowBetween} > div,
${RowFixed} > div {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
`
diff --git a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/SwapModalHeaderMod.tsx b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/SwapModalHeaderMod.tsx
deleted file mode 100644
index a69b1e413e..0000000000
--- a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/SwapModalHeaderMod.tsx
+++ /dev/null
@@ -1,255 +0,0 @@
-import React, { useContext, useMemo } from 'react'
-
-import { Percent, TradeType } from '@uniswap/sdk-core'
-
-import { Trans } from '@lingui/macro'
-import { transparentize } from 'polished'
-import { ArrowDown } from 'react-feather'
-import { Text } from 'rebass'
-import styled, { ThemeContext } from 'styled-components/macro'
-
-import { AutoColumn } from 'legacy/components/Column'
-import { RowBetween, RowFixed } from 'legacy/components/Row'
-import { AdvancedSwapDetails } from 'legacy/components/swap/AdvancedSwapDetails'
-import { AuxInformationContainer, TruncatedText } from 'legacy/components/swap/styleds'
-import { WarningProps } from 'legacy/components/SwapWarnings'
-import { INPUT_OUTPUT_EXPLANATION } from 'legacy/constants'
-import { Field } from 'legacy/state/swap/actions'
-import TradeGp from 'legacy/state/swap/TradeGp'
-import { ThemedText } from 'legacy/theme'
-import { isAddress, shortenAddress } from 'legacy/utils'
-import { computeSlippageAdjustedAmounts } from 'legacy/utils/prices'
-
-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 { RateInfo, RateInfoParams } from 'common/pure/RateInfo'
-import { TokenAmount } from 'common/pure/TokenAmount'
-import { TokenSymbol } from 'common/pure/TokenSymbol'
-
-import FeeInformationTooltip from '../FeeInformationTooltip'
-
-import { LightCardType } from './index'
-
-export const ArrowWrapper = styled.div`
- --size: 26px;
- padding: 0;
- height: var(--size);
- width: var(--size);
- position: relative;
- margin: -13px 0;
- left: calc(50% - var(--size) / 2);
- display: flex;
- justify-content: center;
- align-items: center;
- z-index: 2;
- border-radius: 8px;
- border: ${({ theme }) => `2px solid ${theme.grey1}`};
- box-shadow: 0px 0px 0px 3px ${({ theme }) => theme.bg1};
- background: ${({ theme }) => (theme.darkMode ? theme.grey1 : theme.white)};
-
- > svg {
- stroke-width: 2px;
- padding: 1px;
- height: 100%;
- width: 100%;
- cursor: pointer;
- }
-`
-
-const StyledRateInfo = styled(RateInfo)`
- font-size: 13px;
- font-weight: 500;
- margin: 0 auto;
-`
-
-export interface SwapModalHeaderProps {
- trade: TradeGp
- allowedSlippage: Percent
- recipient: string | null
- showAcceptChanges: boolean
- priceImpactWithoutFee?: Percent
- priceImpact?: Percent
- onAcceptChanges: () => void
- LightCard: LightCardType
- HighFeeWarning: React.FC
- NoImpactWarning: React.ReactNode
- allowsOffchainSigning: boolean
- rateInfoParams: RateInfoParams
-}
-
-export default function SwapModalHeader({
- trade,
- allowedSlippage,
- recipient,
- showAcceptChanges,
- onAcceptChanges,
- priceImpact,
- LightCard,
- HighFeeWarning,
- NoImpactWarning,
- allowsOffchainSigning,
- rateInfoParams,
-}: SwapModalHeaderProps) {
- const slippageAdjustedAmounts = useMemo(
- () => computeSlippageAdjustedAmounts(trade, allowedSlippage),
- [trade, allowedSlippage]
- )
-
- const theme = useContext(ThemeContext)
-
- const {
- inputAmount: { value: fiatValueInput },
- outputAmount: { value: fiatValueOutput },
- } = useTradeUsdAmounts(trade.inputAmountWithoutFee, trade.outputAmountWithoutFee)
-
- const [slippageIn, slippageOut] = useMemo(
- () => [slippageAdjustedAmounts[Field.INPUT], slippageAdjustedAmounts[Field.OUTPUT]],
- [slippageAdjustedAmounts]
- )
-
- const [exactInLabel, exactOutLabel] = useMemo(() => {
- return [
- trade?.tradeType === TradeType.EXACT_OUTPUT ? From (incl. fee) : null,
- trade?.tradeType === TradeType.EXACT_INPUT ? Receive (incl. fee) : null,
- ]
- }, [trade])
-
- return (
-
-
-
-
-
- From
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {!!exactInLabel && (
-
- }
- amountBeforeFees={ }
- feeAmount={trade.fee.feeAsCurrency}
- allowsOffchainSigning={allowsOffchainSigning}
- label={exactInLabel}
- showHelper
- trade={trade}
- type="From"
- fiatValue={fiatValueInput}
- />
-
- )}
-
-
-
-
-
-
-
- To
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- { }
-
-
-
-
-
- {!!exactOutLabel && (
-
- }
- amountBeforeFees={ }
- feeAmount={trade.outputAmountWithoutFee?.subtract(trade.outputAmount)}
- label={exactOutLabel}
- allowsOffchainSigning={allowsOffchainSigning}
- showHelper
- trade={trade}
- type="To"
- fiatValue={fiatValueOutput}
- />
-
- )}
-
-
- {showAcceptChanges && }
-
- {trade.tradeType === TradeType.EXACT_INPUT ? (
-
-
- Output is estimated. You will receive at least{' '}
-
- {' '}
- {' '}
- or the swap will not execute. {INPUT_OUTPUT_EXPLANATION}
-
-
- ) : (
-
-
- Input is estimated. You will sell at most{' '}
-
- {' '}
- {' '}
- or the swap will not execute. {INPUT_OUTPUT_EXPLANATION}
-
-
- )}
-
- {recipient !== null ? (
-
-
-
- Output will be sent to{' '}
- {isAddress(recipient) ? shortenAddress(recipient) : recipient}
-
-
-
- ) : null}
- {/* High Fee Warning */}
-
- {/* No Impact Warning */}
- {!priceImpact && NoImpactWarning}
-
- )
-}
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 802cc6b9e0..23524ae1f5 100644
--- a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/index.tsx
@@ -1,58 +1,46 @@
-import React from 'react'
+import React, { useContext, useMemo } from 'react'
+import { INPUT_OUTPUT_EXPLANATION } from '@cowprotocol/common-const'
+import { isAddress, shortenAddress } from '@cowprotocol/common-utils'
+import { RowBetween, RowFixed, TokenAmount, TokenSymbol } from '@cowprotocol/ui'
+import { useWalletDetails } from '@cowprotocol/wallet'
+import { Percent, TradeType } from '@uniswap/sdk-core'
+
+import { Trans } from '@lingui/macro'
import { transparentize } from 'polished'
-import styled from 'styled-components/macro'
+import { ArrowDown } from 'react-feather'
+import { Text } from 'rebass'
+import { ThemeContext } from 'styled-components/macro'
-import { LightCard as LightCardUni } from 'legacy/components/Card'
-import { SwapShowAcceptChanges } from 'legacy/components/swap/styleds'
-import { HighFeeWarning as HighFeeWarningBase } from 'legacy/components/SwapWarnings'
+import { AutoColumn } from 'legacy/components/Column'
+import { AdvancedSwapDetails } from 'legacy/components/swap/AdvancedSwapDetails'
+import { AuxInformationContainer, TruncatedText } from 'legacy/components/swap/styleds'
+import { WarningProps } from 'legacy/components/SwapWarnings'
+import TradeGp from 'legacy/state/swap/TradeGp'
+import { ThemedText } from 'legacy/theme'
+import { computeSlippageAdjustedAmounts } from 'legacy/utils/prices'
import { NoImpactWarning } from 'modules/trade/pure/NoImpactWarning'
-import { useWalletDetails } from 'modules/wallet'
-
-import SwapModalHeaderMod, { SwapModalHeaderProps } from './SwapModalHeaderMod'
-
-const LightCard = styled(LightCardUni)<{ flatBorder?: boolean }>`
- background-color: ${({ theme }) => theme.grey1};
- border: none;
- ${({ flatBorder = false }) => flatBorder && `border-radius: 20px 20px 0 0;`};
-`
-
-export type LightCardType = typeof LightCard
-
-// targettable by styled injection
-const HighFeeWarning = styled(HighFeeWarningBase)``
+import { PriceUpdatedBanner } from 'modules/trade/pure/PriceUpdatedBanner'
+import { useTradeUsdAmounts } from 'modules/usdAmount'
-const Wrapper = styled.div`
- ${({ theme }) => theme.mediaWidth.upToSmall`
- margin: 0 auto;
- `};
+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'
- ${SwapShowAcceptChanges} {
- background: ${({ theme }) => transparentize(0.85, theme.alert)};
- border: 1px solid ${({ theme }) => transparentize(0.75, theme.alert)};
- padding: 8px 8px 8px 16px;
- margin: 8px 0 0;
+import { ArrowWrapper, HighFeeWarning, LightCard, LightCardType, StyledRateInfo, Wrapper } from './styled'
- svg {
- stroke: ${({ theme }) => theme.alert};
- }
- }
+import { Field } from '../../../state/types'
+import { FeeInformationTooltip } from '../FeeInformationTooltip'
- svg {
- stroke: ${({ theme }) => theme.text1};
- }
-`
-
-export default function SwapModalHeader(
- props: Omit
-) {
+export function SwapModalHeader(props: Omit) {
const { allowsOffchainSigning } = useWalletDetails()
const NoImpactWarningComponent =
return (
-
)
}
+
+interface SwapModalHeaderProps {
+ trade: TradeGp
+ allowedSlippage: Percent
+ recipient: string | null
+ showAcceptChanges: boolean
+ priceImpactWithoutFee?: Percent
+ priceImpact?: Percent
+ onAcceptChanges: () => void
+ LightCard: LightCardType
+ HighFeeWarning: React.FC
+ NoImpactWarning: React.ReactNode
+ allowsOffchainSigning: boolean
+ rateInfoParams: RateInfoParams
+}
+
+function SwapModalHeaderComponent({
+ trade,
+ allowedSlippage,
+ recipient,
+ showAcceptChanges,
+ onAcceptChanges,
+ priceImpact,
+ LightCard,
+ HighFeeWarning,
+ NoImpactWarning,
+ allowsOffchainSigning,
+ rateInfoParams,
+}: SwapModalHeaderProps) {
+ const slippageAdjustedAmounts = useMemo(
+ () => computeSlippageAdjustedAmounts(trade, allowedSlippage),
+ [trade, allowedSlippage]
+ )
+
+ const theme = useContext(ThemeContext)
+
+ const {
+ inputAmount: { value: fiatValueInput },
+ outputAmount: { value: fiatValueOutput },
+ } = useTradeUsdAmounts(trade.inputAmountWithoutFee, trade.outputAmountWithoutFee)
+
+ const [slippageIn, slippageOut] = useMemo(
+ () => [slippageAdjustedAmounts[Field.INPUT], slippageAdjustedAmounts[Field.OUTPUT]],
+ [slippageAdjustedAmounts]
+ )
+
+ const [exactInLabel, exactOutLabel] = useMemo(() => {
+ return [
+ trade?.tradeType === TradeType.EXACT_OUTPUT ? From (incl. fee) : null,
+ trade?.tradeType === TradeType.EXACT_INPUT ? Receive (incl. fee) : null,
+ ]
+ }, [trade])
+
+ const isCustomRecipient = recipient !== null
+
+ return (
+
+
+
+
+
+ From
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {!!exactInLabel && (
+
+ }
+ amountBeforeFees={ }
+ feeAmount={trade.fee.feeAsCurrency}
+ allowsOffchainSigning={allowsOffchainSigning}
+ label={exactInLabel}
+ showHelper
+ trade={trade}
+ type="From"
+ fiatValue={fiatValueInput}
+ />
+
+ )}
+
+
+
+
+
+
+
+ To
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { }
+
+
+
+
+
+ {!!exactOutLabel && (
+
+ }
+ amountBeforeFees={ }
+ feeAmount={trade.outputAmountWithoutFee?.subtract(trade.outputAmount)}
+ label={exactOutLabel}
+ allowsOffchainSigning={allowsOffchainSigning}
+ showHelper
+ trade={trade}
+ type="To"
+ fiatValue={fiatValueOutput}
+ />
+
+ )}
+
+
+ {showAcceptChanges && }
+
+ {trade.tradeType === TradeType.EXACT_INPUT ? (
+
+
+ Output is estimated. You will receive at least{' '}
+
+ {' '}
+ {' '}
+ or the swap will not execute. {INPUT_OUTPUT_EXPLANATION}
+
+
+ ) : (
+
+
+ Input is estimated. You will sell at most{' '}
+
+ {' '}
+ {' '}
+ or the swap will not execute. {INPUT_OUTPUT_EXPLANATION}
+
+
+ )}
+
+ {/*TODO: adjust styles and maybe merge with the indication below? */}
+ {isCustomRecipient && (
+
+
+
+ )}
+ {isCustomRecipient ? (
+
+
+
+ Output will be sent to{' '}
+ {isAddress(recipient) ? shortenAddress(recipient) : recipient}
+
+
+
+ ) : null}
+ {/* High Fee Warning */}
+
+ {/* No Impact Warning */}
+ {!priceImpact && NoImpactWarning}
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/styled.ts b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/styled.ts
new file mode 100644
index 0000000000..a75c03e991
--- /dev/null
+++ b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/styled.ts
@@ -0,0 +1,73 @@
+import { transparentize } from 'polished'
+import styled from 'styled-components/macro'
+
+import { LightCard as LightCardUni } from 'legacy/components/Card'
+import { SwapShowAcceptChanges } from 'legacy/components/swap/styleds'
+import { HighFeeWarning as HighFeeWarningBase } from 'legacy/components/SwapWarnings'
+
+import { UI } from 'common/constants/theme'
+import { RateInfo } from 'common/pure/RateInfo'
+
+export const LightCard = styled(LightCardUni)<{ flatBorder?: boolean }>`
+ background-color: var(${UI.COLOR_GREY});
+ border: none;
+ ${({ flatBorder = false }) => flatBorder && `border-radius: 20px 20px 0 0;`};
+`
+
+export type LightCardType = typeof LightCard
+
+// targettable by styled injection
+export const HighFeeWarning = styled(HighFeeWarningBase)``
+
+export const Wrapper = styled.div`
+ ${({ theme }) => theme.mediaWidth.upToSmall`
+ margin: 0 auto;
+ `};
+
+ ${SwapShowAcceptChanges} {
+ background: ${({ theme }) => transparentize(0.85, theme.alert)};
+ border: 1px solid ${({ theme }) => transparentize(0.75, theme.alert)};
+ padding: 8px 8px 8px 16px;
+ margin: 8px 0 0;
+
+ svg {
+ stroke: ${({ theme }) => theme.alert};
+ }
+ }
+
+ svg {
+ stroke: var(${UI.COLOR_TEXT1});
+ }
+`
+
+export const ArrowWrapper = styled.div`
+ --size: 26px;
+ padding: 0;
+ height: var(--size);
+ width: var(--size);
+ position: relative;
+ margin: -13px 0;
+ left: calc(50% - var(--size) / 2);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ z-index: 2;
+ border-radius: 8px;
+ border: ${({ theme }) => `2px solid ${theme.grey1}`};
+ box-shadow: 0px 0px 0px 3px ${({ theme }) => theme.bg1};
+ background: ${({ theme }) => (theme.darkMode ? theme.grey1 : theme.white)};
+
+ > svg {
+ stroke-width: 2px;
+ padding: 1px;
+ height: 100%;
+ width: 100%;
+ cursor: pointer;
+ }
+`
+
+export const StyledRateInfo = styled(RateInfo)`
+ font-size: 13px;
+ font-weight: 500;
+ margin: 0 auto;
+`
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 f6c24ca0fc..420a3b9338 100644
--- a/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/UnsupportedCurrencyFooterMod.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/UnsupportedCurrencyFooterMod.tsx
@@ -1,20 +1,21 @@
import { useState } from 'react'
+import { getEtherscanLink } from '@cowprotocol/common-utils'
+import { ButtonEmpty } from '@cowprotocol/ui'
+import { AutoRow, RowBetween } from '@cowprotocol/ui'
+import { ExternalLink } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Currency } from '@uniswap/sdk-core'
import { Trans } from '@lingui/macro'
import styled from 'styled-components/macro'
-import { ButtonEmpty } from 'legacy/components/Button'
import Card, { OutlineCard } from 'legacy/components/Card'
import { AutoColumn } from 'legacy/components/Column'
-import { AutoRow, RowBetween } from 'legacy/components/Row'
import { useIsUnsupportedTokenGp } from 'legacy/state/lists/hooks'
-import { CloseIcon, ExternalLink, ThemedText, Z_INDEX } from 'legacy/theme'
-import { getEtherscanLink } from 'legacy/utils'
-
-import { useWalletInfo } from 'modules/wallet'
+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'
@@ -28,7 +29,7 @@ export const DetailsFooter = styled.div<{ show: boolean }>`
max-width: 400px;
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
- color: ${({ theme }) => theme.text2};
+ color: var(${UI.COLOR_TEXT2});
background-color: ${({ theme }) => theme.advancedBG};
z-index: ${Z_INDEX.deprecated_zero};
diff --git a/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/index.tsx b/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/index.tsx
index 377a9e79fe..8782215615 100644
--- a/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/index.tsx
@@ -1,9 +1,9 @@
+import { UNSUPPORTED_TOKENS_FAQ_URL } from '@cowprotocol/common-const'
+
import { transparentize } from 'polished'
import { HashLink } from 'react-router-hash-link'
import styled from 'styled-components/macro'
-import { UNSUPPORTED_TOKENS_FAQ_URL } from 'legacy/constants'
-
import UnsupportedCurrencyFooterMod, {
UnsupportedCurrencyFooterParams,
DetailsFooter,
diff --git a/apps/cowswap-frontend/src/legacy/components/swap/confirmPriceImpactWithoutFee.ts b/apps/cowswap-frontend/src/legacy/components/swap/confirmPriceImpactWithoutFee.ts
index a3febf01c4..89c6afecc1 100644
--- a/apps/cowswap-frontend/src/legacy/components/swap/confirmPriceImpactWithoutFee.ts
+++ b/apps/cowswap-frontend/src/legacy/components/swap/confirmPriceImpactWithoutFee.ts
@@ -1,8 +1,7 @@
/** Should not be used. */
+import { ALLOWED_PRICE_IMPACT_HIGH, PRICE_IMPACT_WITHOUT_FEE_CONFIRM_MIN } from '@cowprotocol/common-const'
import { Percent } from '@uniswap/sdk-core'
-import { ALLOWED_PRICE_IMPACT_HIGH, PRICE_IMPACT_WITHOUT_FEE_CONFIRM_MIN } from '../../constants/misc'
-
/**
* Given the price impact, get user confirmation.
*
diff --git a/apps/cowswap-frontend/src/legacy/components/swap/styleds.tsx b/apps/cowswap-frontend/src/legacy/components/swap/styleds.tsx
index c95220e200..20444c6fe9 100644
--- a/apps/cowswap-frontend/src/legacy/components/swap/styleds.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/swap/styleds.tsx
@@ -1,13 +1,16 @@
import { MouseEventHandler, ReactNode } from 'react'
+import { TooltipContainer } from '@cowprotocol/ui'
+
import { transparentize } from 'polished'
import { AlertTriangle } from 'react-feather'
import { Text } from 'rebass'
import styled, { css } from 'styled-components/macro'
-import { TooltipContainer } from 'legacy/components/Tooltip'
import { ThemedText } from 'legacy/theme'
+import { UI } from 'common/constants/theme'
+
import { FeeInformationTooltipWrapper } from './FeeInformationTooltip'
import { AutoColumn } from '../Column'
@@ -30,7 +33,7 @@ export const ArrowWrapper = styled.div<{ clickable: boolean }>`
margin-top: -14px;
margin-bottom: -14px;
left: 16px;
- background-color: ${({ theme }) => theme.bg1};
+ background-color: var(${UI.COLOR_CONTAINER_BG_01});
z-index: 2;
${({ clickable }) =>
clickable
@@ -183,7 +186,7 @@ export const AuxInformationContainer = styled.div<{
showAux?: boolean
}>`
border: 1px solid ${({ theme, hideInput }) => (hideInput ? ' transparent' : theme.bg2)};
- background-color: ${({ theme }) => theme.bg1};
+ background-color: var(${UI.COLOR_CONTAINER_BG_01});
width: ${({ hideInput }) => (hideInput ? '100%' : 'initial')};
:focus,
diff --git a/apps/cowswap-frontend/src/legacy/constants/chains.ts b/apps/cowswap-frontend/src/legacy/constants/chains.ts
deleted file mode 100644
index 7ae490cd42..0000000000
--- a/apps/cowswap-frontend/src/legacy/constants/chains.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { SupportedChainId } from '@cowprotocol/cow-sdk'
-
-/**
- * Array of all the supported chain IDs
- */
-export const ALL_SUPPORTED_CHAIN_IDS: SupportedChainId[] = Object.values(SupportedChainId).filter(
- (id) => typeof id === 'number'
-) as SupportedChainId[]
diff --git a/apps/cowswap-frontend/src/legacy/constants/proposals/index.ts b/apps/cowswap-frontend/src/legacy/constants/proposals/index.ts
deleted file mode 100644
index 337aa84f69..0000000000
--- a/apps/cowswap-frontend/src/legacy/constants/proposals/index.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export const UNISWAP_GRANTS_START_BLOCK = 11473815
-export const BRAVO_START_BLOCK = 13059344
-export const ONE_BIP_START_BLOCK = 13551293
-export const POLYGON_START_BLOCK = 13786993
-export const MOONBEAN_START_BLOCK = 14732457
diff --git a/apps/cowswap-frontend/src/legacy/constants/proposals/polygon_proposal_title.ts b/apps/cowswap-frontend/src/legacy/constants/proposals/polygon_proposal_title.ts
deleted file mode 100644
index 9e3897c792..0000000000
--- a/apps/cowswap-frontend/src/legacy/constants/proposals/polygon_proposal_title.ts
+++ /dev/null
@@ -1 +0,0 @@
-export const POLYGON_PROPOSAL_TITLE = 'Should Uniswap v3 be deployed to Polygon?'
diff --git a/apps/cowswap-frontend/src/legacy/constants/proposals/uniswap_grants_proposal_description.ts b/apps/cowswap-frontend/src/legacy/constants/proposals/uniswap_grants_proposal_description.ts
deleted file mode 100644
index 51347d38fd..0000000000
--- a/apps/cowswap-frontend/src/legacy/constants/proposals/uniswap_grants_proposal_description.ts
+++ /dev/null
@@ -1,106 +0,0 @@
-export const UNISWAP_GRANTS_PROPOSAL_DESCRIPTION = `# Uniswap Grants Program v0.1
-
-*co-authored with [Ken Ng](https://twitter.com/nkennethk?lang=en)*
-
-## Summary:
-
-**This post outlines a framework for funding Uniswap ecosystem development with grants from the[ UNI Community Treasury](https://uniswap.org/blog/uni/).** The program starts small—sponsoring hackathons, [for example](https://gov.uniswap.org/c/proposal-discussion/5)—but could grow in significance over time (with renewals approved by governance) to fund core protocol development. Grants administration is a subjective process that cannot be easily automated, and thus we propose a nimble committee of 6 members —1 lead and 5 reviewers—to deliver an efficient, predictable process to applicants, such that funding can be administered without having to put each application to a vote. We propose the program start with an initial cap of $750K per quarter and a limit of 2 quarters before renewal—a sum that we feel is appropriate for an MVP relative to the size of the treasury that UNI token holders are entrusted with allocating.
-
-**Purpose:**
-
-**The mission of the UGP is to provide valuable resources to help grow the Uniswap ecosystem.** Through public discourse and inbound applications, the community will get first-hand exposure to identify and respond to the most pressing needs of the ecosystem, as well as the ability to support innovative projects expanding the capabilities of Uniswap. By rewarding talent early with developer incentives, bounties, and infrastructure support, UGP acts as a catalyst for growth and helps to maintain Uniswap as a nexus for DeFi on Ethereum.
-
-**Quarterly Budget:**
-
-* Max quarterly budget of up to $750k
-* Budget and caps to be assessed every six months
-
-**Grant Allocation Committee:**
-
-* Of 6 committee members: 1 lead and 5 reviewers
-* Each committee has a term of 2 quarters (6 months) after which the program needs to be renewed by UNI governance
-* Committee functions as a 4 of 5 multi-sig
-
-**Committee Members**
-
-While the goals and priorities of the grant program will be thoroughly discussed and reviewed by the community through public discourse, **the decision to start UGP by operating as a small committee is to ensure that the application and decision process will be efficient and predictable, so applicants have clear objectives and timely decisions.**
-
-Starting with just six members enables the committee to efficiently fund projects with tight feedback loops and rapid iterations. The purpose of this committee would be to test the hypothesis that the Grants Program can successfully provide value for the UNI ecosystem before scaling the program.
-
-**We suggest the grants program is administered by a single lead. Here we propose Kenneth Ng, a co-author of this post**. Ken has helped grow the Ethereum Foundation Grants Program over the last two years in establishing high level priorities and adapting for the ecosystems needs.
-
-**The other 5 committee members should be thought of as “reviewers” — UNI community members who will keep the grants program functional by ensuring Ken is leading effectively and, of course, not absconding with funds.** Part of the reviewers job is to hold the program accountable for success (defined below) and/or return any excess funds to the UNI treasury. Reviewers are not compensated as part of this proposal as we expect their time commitment to be minimal. Compensation for the lead role is discussed below, as we expect this to be a labor intensive role.
-
-**Program Lead:** [Ken Ng](https://twitter.com/nkennethk?lang=en) (HL Creative Corp)
-*Ecosystem Support Program at the Ethereum Foundation*
-
-1. Reviewer: [Jesse Walden](https://twitter.com/jessewldn) (o/b/o Unofficial LLC dba [Variant Fund](http://twitter.com/variantfund))
-*Founder and Investor at Variant Fund (holds UNI)*
-
-2. Reviewer: [Monet Supply](https://twitter.com/MonetSupply)
-*Risk Analyst at MakerDAO*
-
-3. Reviewer: [Robert Leshner](https://twitter.com/rleshner)
-*Founder and CEO of Compound Finance*
-
-4. Reviewer: [Kain Warwick](https://twitter.com/kaiynne)
-*Founder of Synthetix*
-
-5. Reviewer: [Ashleigh Schap](https://twitter.com/ashleighschap)
-*Growth Lead, Uniswap (Company)*
-
-## Methodology
-
-**1.1 Budget**
-
-This proposal recommends a max cap of $750K per quarter, with the ability to reevaluate biannually at each epoch (two fiscal quarters). While the UGP Grants Committee will be the decision makers around individual grants, respective budgets, roadmaps, and milestones, any top-level changes to UGP including epochs and max cap, will require full community quorum (4% approval).
-
-The UGP will be funded by the UNI treasury according to the[ release schedule](https://uniswap.org/blog/uni/) set out by the Uniswap team, whereby 43% of the UNI treasury is released over a four-year timeline. In Year 1 this will total to 172,000,000 UNI (~$344M as of writing).
-
-Taking into consideration the current landscape of ecosystem funding across Ethereum, the community would be hard-pressed to allocate even 5% of Year 1’s treasury. For context Gitcoin CLR Round 7 distributed $725k ($450k in matched) across 857 projects and YTD, Moloch has granted just under $200k but in contrast, the EF has committed to somewhere in the 8 figure range.
-
-**1.2 Committee Compensation**
-
-Operating a successful grants program takes considerable time and effort. Take, for instance, the EF Ecosystem Support Program, which has awarded grants since 2018, consists of an internal team at the Foundation as well as an ever increasing roster of community advisors in order to keep expanding and adapting to best serve the needs of the Ethereum ecosystem. While the structure of the allocation committee has six members, we propose that only the lead will be remunerated for their work in establishing the initial processes, vetting applications, and managing the program overall as this role is expected to be time consuming if the program is to be succesful. We propose that the other committee members be unpaid UNI ecosystem stakeholders who have an interest in seeing the protocol ecosystem continue to operate and grow.
-
-**We propose the lead be compensated 25 UNI/hr (approximately $100 USD at time of this writing) capped at 30 hours/week. This compensation, along with the quarterly budget, will be allocated to the UGP multisig from the UNI treasury**. In keeping with the committee’s commitment to the community, hours and duties will be logged publicly and transparently .
-
-**2.1 Priorities**
-
-Initially, the program aims to start narrow in scope, funding peripheral ecosystem initiatives, such as targeted bounties, hackathon sponsorships, and other low-stakes means of building out the Uniswap developer ecosystem. Over time, if the program proves effective, the grant allocations can grow in scope to include, for example, improved frontends, trading interfaces, and eventually, core protocol development.
-
-![|624x199](upload://vNP0APCOjiwQMurCmYI47cTLklc.png)
-
-With the initial priorities in mind, some effective measures for quick successes might look like:
-
-* Total number of projects funded
-* Quarterly increase in applications
-* Project engagement post-event/funding
-* Overall community engagement/sentiment
-
-**2.2 Timeline**
-
-In keeping with the fast pace of the UNI ecosystem, we organize time in epochs, or two calendar quarters. Each epoch will see two funding rounds, one per quarter, after which the community can review and create proposals to improve or revamp the program as they deem fit.
-
-**![|624x245](upload://n56TSh5X3mt4TSqVVMFhbnZM0eM.png)**
-
-**Rolling Wave 1 & 2 Applications**
-
-* Starting in Q1 2021, UGP will start accepting applications for events looking for support in the form of bounties or prizes that in parallel can be proactively sourced. During these first two waves of funding projects, the allocation committee lead can begin laying out guardrails for continued funding
-
-* Considering the immediate feedback loops for the first epoch, we expect these allocation decisions to be discussed and reviewed by the larger community. Should this not be of value, the community can submit a formal governance proposal to change any piece of UGP that was not effective
-
-**Wave 3 & Beyond**
-
-* Beginning with Wave 3, there should have been enough time with impactful projects funded to be considered for follow-on funding, should it make sense. In the same vein, projects within scope will be expanded to also include those working on integrations and and other key components.
-
-* Beyond the second epoch, as the community helps to review and help adapt UGP to be most effective, the scope will continue to grow in order to accommodate the state of the ecosystem including that of core protocol improvements
-
-## Conclusion:
-
-**If this proposal is successfully approved, UGP will start accepting applications on a rolling basis beginning at the start of 2021.** With the phases and priorities laid out above, UGP will aim to make a significant impact by catalyzing growth and innovation in the UNI ecosystem.
-
-**This program is meant to be the simplest possible MVP of a Uniswap Ecosystem Grants initiative.** While the multi-sig committee comes with trust assumptions about the members, our hope is the community will approve this limited engagement to get the ball rolling in an efficient structure. **After the first epoch (2 fiscal quarters) the burden of proof will be on UGP to show empirical evidence that the program is worth continuing in its existing form and will submit to governance to renew treasury funding.**
-
-If this program proves successful, we hope it will inspire others to follow suit and create their own funding committees for allocating treasury capital—ideally with different specializations.
-`
diff --git a/apps/cowswap-frontend/src/legacy/constants/routing.ts b/apps/cowswap-frontend/src/legacy/constants/routing.ts
deleted file mode 100644
index 07369e0c80..0000000000
--- a/apps/cowswap-frontend/src/legacy/constants/routing.ts
+++ /dev/null
@@ -1,130 +0,0 @@
-// a list of tokens by chain
-
-import { SupportedChainId } from '@cowprotocol/cow-sdk'
-import { Currency, Token } from '@uniswap/sdk-core'
-
-import {
- AMPL,
- COW,
- DAI,
- ETH2X_FLI,
- EURE_GNOSIS_CHAIN,
- FEI,
- FRAX,
- FXS,
- renBTC,
- rETH2,
- sETH2,
- SWISE,
- TRIBE,
- USDC_MAINNET,
- USDT,
- WBTC,
- WRAPPED_NATIVE_CURRENCY,
-} from 'legacy/constants/tokens'
-import { USDC_GNOSIS_CHAIN, WBTC_GNOSIS_CHAIN, WETH_GNOSIS_CHAIN } from 'legacy/utils/gnosis_chain/constants'
-import { DAI_GOERLI, USDC_GOERLI } from 'legacy/utils/goerli/constants'
-
-type ChainTokenList = {
- readonly [chainId: number]: Token[]
-}
-
-type ChainCurrencyList = {
- readonly [chainId: number]: Currency[]
-}
-
-const WRAPPED_NATIVE_CURRENCIES_ONLY: ChainTokenList = Object.fromEntries(
- Object.entries(WRAPPED_NATIVE_CURRENCY)
- .map(([key, value]) => [key, [value]])
- .filter(Boolean)
-)
-
-// used to construct intermediary pairs for trading
-export const BASES_TO_CHECK_TRADES_AGAINST: ChainTokenList = {
- ...WRAPPED_NATIVE_CURRENCIES_ONLY,
- [SupportedChainId.MAINNET]: [
- ...WRAPPED_NATIVE_CURRENCIES_ONLY[SupportedChainId.MAINNET],
- DAI,
- USDC_MAINNET,
- USDT,
- WBTC,
- ],
-}
-export const ADDITIONAL_BASES: { [chainId: number]: { [tokenAddress: string]: Token[] } } = {
- [SupportedChainId.MAINNET]: {
- '0xF16E4d813f4DcfDe4c5b44f305c908742De84eF0': [ETH2X_FLI],
- [rETH2.address]: [sETH2],
- [SWISE.address]: [sETH2],
- [FEI.address]: [TRIBE],
- [TRIBE.address]: [FEI],
- [FRAX.address]: [FXS],
- [FXS.address]: [FRAX],
- [WBTC.address]: [renBTC],
- [renBTC.address]: [WBTC],
- },
-}
-/**
- * Some tokens can only be swapped via certain pairs, so we override the list of bases that are considered for these
- * tokens.
- */
-export const CUSTOM_BASES: { [chainId: number]: { [tokenAddress: string]: Token[] } } = {
- [SupportedChainId.MAINNET]: {
- [AMPL.address]: [DAI, WRAPPED_NATIVE_CURRENCY[SupportedChainId.MAINNET] as Token],
- },
-}
-
-/**
- * Shows up in the currency select for swap and add liquidity
- */
-export const COMMON_BASES: ChainCurrencyList = {
- [SupportedChainId.MAINNET]: [
- DAI,
- COW[SupportedChainId.MAINNET],
- USDC_MAINNET,
- USDT,
- WBTC,
- WRAPPED_NATIVE_CURRENCY[SupportedChainId.MAINNET],
- ],
- [SupportedChainId.GOERLI]: [
- WRAPPED_NATIVE_CURRENCY[SupportedChainId.GOERLI],
- COW[SupportedChainId.GOERLI],
- DAI_GOERLI,
- USDC_GOERLI,
- ],
- [SupportedChainId.GNOSIS_CHAIN]: [
- USDC_GNOSIS_CHAIN,
- COW[SupportedChainId.GNOSIS_CHAIN],
- EURE_GNOSIS_CHAIN,
- WRAPPED_NATIVE_CURRENCY[SupportedChainId.GNOSIS_CHAIN],
- WETH_GNOSIS_CHAIN,
- WBTC_GNOSIS_CHAIN,
- ],
-}
-
-// used to construct the list of all pairs we consider by default in the frontend
-export const BASES_TO_TRACK_LIQUIDITY_FOR: ChainTokenList = {
- ...WRAPPED_NATIVE_CURRENCIES_ONLY,
- [SupportedChainId.MAINNET]: [
- ...WRAPPED_NATIVE_CURRENCIES_ONLY[SupportedChainId.MAINNET],
- DAI,
- USDC_MAINNET,
- USDT,
- WBTC,
- ],
-}
-export const PINNED_PAIRS: { readonly [chainId: number]: [Token, Token][] } = {
- [SupportedChainId.MAINNET]: [
- [
- new Token(SupportedChainId.MAINNET, '0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643', 8, 'cDAI', 'Compound Dai'),
- new Token(
- SupportedChainId.MAINNET,
- '0x39AA39c021dfbaE8faC545936693aC917d5E7563',
- 8,
- 'cUSDC',
- 'Compound USD Coin'
- ),
- ],
- [USDC_MAINNET, USDT],
- [DAI, USDT],
- ],
-}
diff --git a/apps/cowswap-frontend/src/legacy/hooks/Tokens.ts b/apps/cowswap-frontend/src/legacy/hooks/Tokens.ts
index f158677721..4026518ad4 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/Tokens.ts
+++ b/apps/cowswap-frontend/src/legacy/hooks/Tokens.ts
@@ -1,120 +1,24 @@
import { useAtomValue } from 'jotai'
import { useMemo } from 'react'
-import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { doesTokenMatchSymbolOrAddress } from '@cowprotocol/common-utils'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Currency, Token } from '@uniswap/sdk-core'
-import { getChainInfo } from 'legacy/constants/chainInfo'
import { useAllLists, useInactiveListUrls } from 'legacy/state/lists/hooks'
-import { deserializeToken, useUserAddedTokens } from 'legacy/state/user/hooks'
+import { deserializeToken, useFavouriteTokens, useUserAddedTokens } from 'legacy/state/user/hooks'
import { TokensByAddress, tokensByAddressAtom } from 'modules/tokensList/state/tokensListAtom'
-import { useWalletInfo } from 'modules/wallet'
-import { useCurrencyFromMap, useTokenFromMapOrNetwork } from 'lib/hooks/useCurrency'
import { getTokenFilter } from 'lib/hooks/useTokenList/filtering'
-import { doesTokenMatchSymbolOrAddress } from 'utils/doesTokenMatchSymbolOrAddress'
-import { TokenAddressMap, useUnsupportedTokenList } from './../state/lists/hooks'
-
-// reduce token map into standard address <-> Token mapping, optionally include user added tokens
-export function useTokensFromMap(tokenMap: TokenAddressMap, includeUserAdded: boolean): { [address: string]: Token } {
- const { chainId } = useWalletInfo()
- const userAddedTokens = useUserAddedTokens()
-
- return useMemo(() => {
- if (!chainId) return {}
-
- // reduce to just tokens
- const mapWithoutUrls = Object.keys(tokenMap[chainId] ?? {}).reduce<{ [address: string]: Token }>(
- (newMap, address) => {
- newMap[address] = tokenMap[chainId][address].token
- return newMap
- },
- {}
- )
-
- if (includeUserAdded) {
- return (
- userAddedTokens
- // reduce into all ALL_TOKENS filtered by the current chain
- .reduce<{ [address: string]: Token }>(
- (tokenMap, token) => {
- tokenMap[token.address] = token
- return tokenMap
- },
- // must make a copy because reduce modifies the map, and we do not
- // want to make a copy in every iteration
- { ...mapWithoutUrls }
- )
- )
- }
-
- return mapWithoutUrls
- }, [chainId, userAddedTokens, tokenMap, includeUserAdded])
-}
+import { useCurrencyFromMap, useTokenFromMapOrNetwork } from '../../lib/hooks/useCurrency'
+import { TokenAmounts, useOnchainBalances } from '../../modules/tokens'
export function useAllTokens(): TokensByAddress {
return useAtomValue(tokensByAddressAtom)
}
-type BridgeInfo = Record<
- SupportedChainId,
- {
- tokenAddress: string
- originBridgeAddress: string
- destBridgeAddress: string
- }
->
-
-export function useUnsupportedTokens(): { [address: string]: Token } {
- const { chainId } = useWalletInfo()
- const listsByUrl = useAllLists()
- const unsupportedTokensMap = useUnsupportedTokenList()
- const unsupportedTokens = useTokensFromMap(unsupportedTokensMap, false)
-
- // checks the default L2 lists to see if `bridgeInfo` has an L1 address value that is unsupported
- const l2InferredBlockedTokens: typeof unsupportedTokens = useMemo(() => {
- if (!chainId) {
- return {}
- }
-
- if (!listsByUrl) {
- return {}
- }
-
- const listUrl = getChainInfo(chainId)?.defaultListUrl
-
- if (!listUrl) {
- return {}
- }
-
- const { current: list } = listsByUrl[listUrl]
- if (!list) {
- return {}
- }
-
- const unsupportedSet = new Set(Object.keys(unsupportedTokens))
-
- return list.tokens.reduce((acc, tokenInfo) => {
- const bridgeInfo = tokenInfo.extensions?.bridgeInfo as unknown as BridgeInfo
- if (
- bridgeInfo &&
- bridgeInfo[SupportedChainId.MAINNET] &&
- bridgeInfo[SupportedChainId.MAINNET].tokenAddress &&
- unsupportedSet.has(bridgeInfo[SupportedChainId.MAINNET].tokenAddress)
- ) {
- const address = bridgeInfo[SupportedChainId.MAINNET].tokenAddress
- // don't rely on decimals--it's possible that a token could be bridged w/ different decimals on the L2
- return { ...acc, [address]: new Token(SupportedChainId.MAINNET, address, tokenInfo.decimals) }
- }
- return acc
- }, {})
- }, [chainId, listsByUrl, unsupportedTokens])
-
- return { ...unsupportedTokens, ...l2InferredBlockedTokens }
-}
-
export function useSearchInactiveTokenLists(
search: string | undefined,
minResults = 10,
@@ -190,3 +94,31 @@ export function useCurrency(currencyId?: string | null): Currency | null | undef
const tokens = useAllTokens()
return useCurrencyFromMap(tokens, currencyId)
}
+
+// mimics useAllBalances
+export function useAllTokenBalances(): [TokenAmounts, boolean] {
+ const { account } = useWalletInfo()
+ const allTokens = useAllTokens()
+ // Mod, add favourite tokens to balances
+ const favTokens = useFavouriteTokens()
+
+ const allTokensArray = useMemo(() => {
+ const favTokensObj = favTokens.reduce(
+ (acc, cur: Token) => {
+ acc[cur.address] = cur
+ return acc
+ },
+ {} as {
+ [address: string]: Token
+ }
+ )
+
+ return Object.values({ ...favTokensObj, ...allTokens })
+ }, [allTokens, favTokens])
+
+ const { isLoading, amounts } = useOnchainBalances({
+ account: account ?? undefined,
+ tokens: allTokensArray,
+ })
+ return [amounts ?? {}, isLoading]
+}
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useAccountRiskCheck.ts b/apps/cowswap-frontend/src/legacy/hooks/useAccountRiskCheck.ts
deleted file mode 100644
index 29de90842e..0000000000
--- a/apps/cowswap-frontend/src/legacy/hooks/useAccountRiskCheck.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import { useEffect } from 'react'
-
-import ms from 'ms.macro'
-
-import { ApplicationModal, setOpenModal } from 'legacy/state/application/reducer'
-import { useAppDispatch } from 'legacy/state/hooks'
-
-import { sendEvent } from '../components/analytics/googleAnalytics'
-
-export default function useAccountRiskCheck(account: string | null | undefined) {
- const dispatch = useAppDispatch()
-
- useEffect(() => {
- if (account) {
- const riskCheckLocalStorageKey = `risk-check-${account}`
- const now = Date.now()
- try {
- const storedTime = localStorage.getItem(riskCheckLocalStorageKey)
- const checkExpirationTime = storedTime ? parseInt(storedTime) : now - 1
- if (checkExpirationTime < Date.now()) {
- const headers = new Headers({ 'Content-Type': 'application/json' })
- fetch('https://screening-worker.uniswap.workers.dev', {
- method: 'POST',
- headers,
- body: JSON.stringify({ address: account }),
- })
- .then((res) => res.json())
- .then((data) => {
- if (data.block) {
- dispatch(setOpenModal(ApplicationModal.BLOCKED_ACCOUNT))
- sendEvent({
- category: 'Address Screening',
- action: 'blocked',
- label: account,
- })
- }
- })
- .catch(() => dispatch(setOpenModal(null)))
- }
- } finally {
- localStorage.setItem(riskCheckLocalStorageKey, (now + ms`7 days`).toString())
- }
- }
- }, [account, dispatch])
-}
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useActiveLocale.ts b/apps/cowswap-frontend/src/legacy/hooks/useActiveLocale.ts
index 92a9aa942b..65ecf2614f 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/useActiveLocale.ts
+++ b/apps/cowswap-frontend/src/legacy/hooks/useActiveLocale.ts
@@ -1,11 +1,10 @@
import { useMemo } from 'react'
-import { DEFAULT_LOCALE, SUPPORTED_LOCALES, SupportedLocale } from 'legacy/constants/locales'
-import store from 'legacy/state'
-import { useUserLocale } from 'legacy/state/user/hooks'
+import { DEFAULT_LOCALE, SUPPORTED_LOCALES, SupportedLocale } from '@cowprotocol/common-const'
+import { useParsedQueryString, parsedQueryString } from '@cowprotocol/common-hooks'
-import useParsedQueryString from './useParsedQueryString'
-import { parsedQueryString } from './useParsedQueryString'
+import { cowSwapStore } from 'legacy/state'
+import { useUserLocale } from 'legacy/state/user/hooks'
/**
* Given a locale string (e.g. from user agent), return the best match for corresponding SupportedLocale
@@ -35,7 +34,7 @@ export function navigatorLocale(): SupportedLocale | undefined {
}
function storeLocale(): SupportedLocale | undefined {
- return store.getState().user.userLocale ?? undefined
+ return cowSwapStore.getState().user.userLocale ?? undefined
}
export const initialLocale =
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useActivityDerivedState.ts b/apps/cowswap-frontend/src/legacy/hooks/useActivityDerivedState.ts
index 02876405e1..1572f033de 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/useActivityDerivedState.ts
+++ b/apps/cowswap-frontend/src/legacy/hooks/useActivityDerivedState.ts
@@ -1,17 +1,16 @@
import { useMemo } from 'react'
+import { getEtherscanLink, getExplorerOrderLink } from '@cowprotocol/common-utils'
+import { getSafeWebUrl } from '@cowprotocol/core'
+import { useGnosisSafeInfo } from '@cowprotocol/wallet'
import { SafeInfoResponse } from '@safe-global/api-kit'
-import { ActivityDescriptors, ActivityStatus, ActivityType } from 'legacy/hooks/useRecentActivity'
import { EnhancedTransactionDetails } from 'legacy/state/enhancedTransactions/reducer'
import { Order, OrderStatus } from 'legacy/state/orders/actions'
-import { getEtherscanLink } from 'legacy/utils'
-import { getExplorerOrderLink } from 'legacy/utils/explorer'
import { ActivityDerivedState } from 'modules/account/containers/Transaction'
-import { useGnosisSafeInfo } from 'modules/wallet'
-import { getSafeWebUrl } from 'api/gnosisSafe'
+import { ActivityDescriptors, ActivityStatus, ActivityType } from './useRecentActivity'
export function useActivityDerivedState({
chainId,
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useAllCurrencyCombinations.ts b/apps/cowswap-frontend/src/legacy/hooks/useAllCurrencyCombinations.ts
deleted file mode 100644
index 412a82200f..0000000000
--- a/apps/cowswap-frontend/src/legacy/hooks/useAllCurrencyCombinations.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-import { useMemo } from 'react'
-
-import { Currency, Token } from '@uniswap/sdk-core'
-
-import { ADDITIONAL_BASES, BASES_TO_CHECK_TRADES_AGAINST, CUSTOM_BASES } from '../constants/routing'
-
-export function useAllCurrencyCombinations(currencyA?: Currency, currencyB?: Currency): [Token, Token][] {
- const chainId = currencyA?.chainId
-
- const [tokenA, tokenB] = chainId ? [currencyA?.wrapped, currencyB?.wrapped] : [undefined, undefined]
-
- const bases: Token[] = useMemo(() => {
- if (!chainId || chainId !== tokenB?.chainId) return []
-
- const common = BASES_TO_CHECK_TRADES_AGAINST[chainId] ?? []
- const additionalA = tokenA ? ADDITIONAL_BASES[chainId]?.[tokenA.address] ?? [] : []
- const additionalB = tokenB ? ADDITIONAL_BASES[chainId]?.[tokenB.address] ?? [] : []
-
- return [...common, ...additionalA, ...additionalB]
- }, [chainId, tokenA, tokenB])
-
- const basePairs: [Token, Token][] = useMemo(
- () =>
- bases
- .flatMap((base): [Token, Token][] => bases.map((otherBase) => [base, otherBase]))
- // though redundant with the first filter below, that expression runs more often, so this is probably worthwhile
- .filter(([t0, t1]) => !t0.equals(t1)),
- [bases]
- )
-
- return useMemo(
- () =>
- tokenA && tokenB
- ? [
- // the direct pair
- [tokenA, tokenB] as [Token, Token],
- // token A against all bases
- ...bases.map((base): [Token, Token] => [tokenA, base]),
- // token B against all bases
- ...bases.map((base): [Token, Token] => [tokenB, base]),
- // each base against all bases
- ...basePairs,
- ]
- // filter out invalid pairs comprised of the same asset (e.g. WETH<>WETH)
- .filter(([t0, t1]) => !t0.equals(t1))
- // filter out duplicate pairs
- .filter(([t0, t1], i, otherPairs) => {
- // find the first index in the array at which there are the same 2 tokens as the current
- const firstIndexInOtherPairs = otherPairs.findIndex(([t0Other, t1Other]) => {
- return (t0.equals(t0Other) && t1.equals(t1Other)) || (t0.equals(t1Other) && t1.equals(t0Other))
- })
- // only accept the first occurrence of the same 2 tokens
- return firstIndexInOtherPairs === i
- })
- // optionally filter out some pairs for tokens with custom bases defined
- .filter(([tokenA, tokenB]) => {
- if (!chainId) return true
- const customBases = CUSTOM_BASES[chainId]
-
- const customBasesA: Token[] | undefined = customBases?.[tokenA.address]
- const customBasesB: Token[] | undefined = customBases?.[tokenB.address]
-
- if (!customBasesA && !customBasesB) return true
-
- if (customBasesA && !customBasesA.find((base) => tokenB.equals(base))) return false
- if (customBasesB && !customBasesB.find((base) => tokenA.equals(base))) return false
-
- return true
- })
- : [],
- [tokenA, tokenB, bases, basePairs, chainId]
- )
-}
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useApeModeQueryParamReader.ts b/apps/cowswap-frontend/src/legacy/hooks/useApeModeQueryParamReader.ts
deleted file mode 100644
index 8cd1cc6071..0000000000
--- a/apps/cowswap-frontend/src/legacy/hooks/useApeModeQueryParamReader.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { useEffect } from 'react'
-
-import { useAppDispatch } from 'legacy/state/hooks'
-
-import useParsedQueryString from './useParsedQueryString'
-
-import { updateUserExpertMode } from '../state/user/reducer'
-
-export default function ApeModeQueryParamReader(): null {
- useApeModeQueryParamReader()
- return null
-}
-
-function useApeModeQueryParamReader() {
- const dispatch = useAppDispatch()
- const { ape } = useParsedQueryString()
-
- useEffect(() => {
- if (typeof ape !== 'string') return
- if (ape === '' || ape.toLowerCase() === 'true') {
- dispatch(updateUserExpertMode({ userExpertMode: true }))
- }
- })
-}
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useApproveCallback/index.ts b/apps/cowswap-frontend/src/legacy/hooks/useApproveCallback/index.ts
index 406809c49f..0016fa3732 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/useApproveCallback/index.ts
+++ b/apps/cowswap-frontend/src/legacy/hooks/useApproveCallback/index.ts
@@ -1,17 +1,15 @@
import { useMemo } from 'react'
+import { V_COW_CONTRACT_ADDRESS } from '@cowprotocol/common-const'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { TransactionResponse } from '@ethersproject/providers'
import { Currency, CurrencyAmount, MaxUint256 } from '@uniswap/sdk-core'
-import { V_COW_CONTRACT_ADDRESS } from 'legacy/constants'
-import { ClaimType } from 'legacy/state/claim/hooks'
-
-import { useWalletInfo } from 'modules/wallet'
-
-import { EnhancedUserClaimData } from 'pages/Claim/types'
-
import { ApprovalState, ApproveCallbackParams, useApproveCallback } from './useApproveCallbackMod'
+import { ClaimType } from '../../state/claim/hooks/types'
+import { EnhancedUserClaimData } from '../../state/claim/types'
+
export type OptionalApproveCallbackParams = {
transactionSummary?: string
modalMessage?: string
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useApproveCallback/useApproveCallbackMod.ts b/apps/cowswap-frontend/src/legacy/hooks/useApproveCallback/useApproveCallbackMod.ts
index 525a5b4f12..24d3238d5e 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/useApproveCallback/useApproveCallbackMod.ts
+++ b/apps/cowswap-frontend/src/legacy/hooks/useApproveCallback/useApproveCallbackMod.ts
@@ -1,19 +1,18 @@
import { useCallback, useMemo } from 'react'
+import { useTokenContract, usePrevious } from '@cowprotocol/common-hooks'
+import { calculateGasMargin } from '@cowprotocol/common-utils'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { BigNumber } from '@ethersproject/bignumber'
import { MaxUint256 } from '@ethersproject/constants'
import { TransactionResponse } from '@ethersproject/providers'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
-import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal'
-import { useCurrency } from 'legacy/hooks/Tokens'
-import { useTokenContract } from 'legacy/hooks/useContract'
-import usePrevious from 'legacy/hooks/usePrevious'
import { useTokenAllowance } from 'legacy/hooks/useTokenAllowance'
import { useHasPendingApproval, useTransactionAdder } from 'legacy/state/enhancedTransactions/hooks'
-import { calculateGasMargin } from 'legacy/utils/calculateGasMargin'
-import { useWalletInfo } from 'modules/wallet'
+import { ConfirmOperationType } from '../../state/types'
+import { useCurrency } from '../Tokens'
import { ApproveCallbackState, OptionalApproveCallbackParams } from './index'
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useArgentWalletContract.ts b/apps/cowswap-frontend/src/legacy/hooks/useArgentWalletContract.ts
deleted file mode 100644
index 880bed8133..0000000000
--- a/apps/cowswap-frontend/src/legacy/hooks/useArgentWalletContract.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { ArgentWalletContract, ArgentWalletContractAbi } from '@cowswap/abis'
-
-import { useWalletInfo } from 'modules/wallet'
-
-import { useContract } from './useContract'
-import useIsArgentWallet from './useIsArgentWallet'
-
-export function useArgentWalletContract(): ArgentWalletContract | null {
- const { account } = useWalletInfo()
- const isArgentWallet = useIsArgentWallet()
- return useContract(
- isArgentWallet ? account ?? undefined : undefined,
- ArgentWalletContractAbi,
- true
- ) as ArgentWalletContract
-}
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useColor/index.ts b/apps/cowswap-frontend/src/legacy/hooks/useColor/index.ts
deleted file mode 100644
index 5f84aa9829..0000000000
--- a/apps/cowswap-frontend/src/legacy/hooks/useColor/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './useColorMod'
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useCombinedBalance.ts b/apps/cowswap-frontend/src/legacy/hooks/useCombinedBalance.ts
new file mode 100644
index 0000000000..24ada8485b
--- /dev/null
+++ b/apps/cowswap-frontend/src/legacy/hooks/useCombinedBalance.ts
@@ -0,0 +1,57 @@
+import { useMemo } from 'react'
+
+import { COW } from '@cowprotocol/common-const'
+import { useWalletInfo } from '@cowprotocol/wallet'
+import { CurrencyAmount } from '@uniswap/sdk-core'
+
+import JSBI from 'jsbi'
+
+import { useVCowData } from 'legacy/state/cowToken/hooks'
+
+import { useTokenBalance } from 'modules/tokens/hooks/useCurrencyBalance'
+
+/**
+ * Hook that returns COW balance
+ */
+function useCowBalance() {
+ const { chainId, account } = useWalletInfo()
+ const cowToken = chainId ? COW[chainId] : undefined
+ return useTokenBalance(account || undefined, cowToken)
+}
+
+/**
+ * Hook that returns combined vCOW + COW balance + vCow from locked GNO
+ */
+export function useCombinedBalance() {
+ const { chainId, account } = useWalletInfo()
+ const { total: vCowBalance } = useVCowData()
+ // const { allocated, claimed } = useCowFromLockedGnoBalances()
+ const cowBalance = useCowBalance()
+
+ // const lockedGnoBalance = useMemo(() => {
+ // if (!allocated || !claimed) {
+ // return
+ // }
+
+ // return JSBI.subtract(allocated.quotient, claimed.quotient)
+ // }, [allocated, claimed])
+
+ return useMemo(() => {
+ let tmpBalance = JSBI.BigInt(0)
+
+ const isLoading = !!(account && (!vCowBalance /* || !lockedGnoBalance */ || !cowBalance))
+
+ const cow = COW[chainId]
+
+ if (account) {
+ if (vCowBalance) tmpBalance = JSBI.add(tmpBalance, vCowBalance.quotient)
+ // if (lockedGnoBalance) tmpBalance = JSBI.add(tmpBalance, lockedGnoBalance)
+ if (cowBalance) tmpBalance = JSBI.add(tmpBalance, cowBalance.quotient)
+ }
+
+ // TODO: check COW vs vCOW
+ const balance = CurrencyAmount.fromRawAmount(cow, tmpBalance)
+
+ return { balance, isLoading }
+ }, [vCowBalance, /* lockedGnoBalance, */ cowBalance, chainId, account])
+}
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useCowBalanceAndSubsidy.ts b/apps/cowswap-frontend/src/legacy/hooks/useCowBalanceAndSubsidy.ts
index 566e0a6d1f..c6055b0d90 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/useCowBalanceAndSubsidy.ts
+++ b/apps/cowswap-frontend/src/legacy/hooks/useCowBalanceAndSubsidy.ts
@@ -1,14 +1,14 @@
import { useMemo } from 'react'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { BigNumber } from 'bignumber.js'
import { COW_SUBSIDY_DATA } from 'legacy/components/CowSubsidyModal/constants'
import { getDiscountFromBalance } from 'legacy/components/CowSubsidyModal/utils'
-import { useCombinedBalance } from 'legacy/state/cowToken/hooks'
-import { useWalletInfo } from 'modules/wallet'
+import { useCombinedBalance } from './useCombinedBalance'
const ZERO_BALANCE_SUBSIDY = { subsidy: { tier: 0, discount: COW_SUBSIDY_DATA[0][1] }, balance: undefined }
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useCurrentBlockTimestamp.ts b/apps/cowswap-frontend/src/legacy/hooks/useCurrentBlockTimestamp.ts
index 0198ea62c8..701b902783 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/useCurrentBlockTimestamp.ts
+++ b/apps/cowswap-frontend/src/legacy/hooks/useCurrentBlockTimestamp.ts
@@ -1,11 +1,10 @@
import { useMemo } from 'react'
+import { useInterfaceMulticall } from '@cowprotocol/common-hooks'
import { BigNumber } from '@ethersproject/bignumber'
import { useSingleCallResult } from 'lib/hooks/multicall'
-import { useInterfaceMulticall } from './useContract'
-
// gets the current timestamp from the blockchain
export default function useCurrentBlockTimestamp(): BigNumber | undefined {
const multicall = useInterfaceMulticall()
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useENSAddress.ts b/apps/cowswap-frontend/src/legacy/hooks/useENSAddress.ts
deleted file mode 100644
index dacd96b5b5..0000000000
--- a/apps/cowswap-frontend/src/legacy/hooks/useENSAddress.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import { useMemo } from 'react'
-
-import { safeNamehash } from 'legacy/utils/safeNamehash'
-
-import { useSingleCallResult } from 'lib/hooks/multicall'
-
-import { useENSRegistrarContract, useENSResolverContract } from './useContract'
-import useDebounce from './useDebounce'
-
-import isZero from '../utils/isZero'
-
-/**
- * Does a lookup for an ENS name to find its address.
- */
-export default function useENSAddress(ensName?: string | null): { loading: boolean; address: string | null } {
- const debouncedName = useDebounce(ensName, 200)
- const ensNodeArgument = useMemo(
- () => [debouncedName === null ? undefined : safeNamehash(debouncedName)],
- [debouncedName]
- )
- const registrarContract = useENSRegistrarContract(false)
- const resolverAddress = useSingleCallResult(registrarContract, 'resolver', ensNodeArgument)
- const resolverAddressResult = resolverAddress.result?.[0]
- const resolverContract = useENSResolverContract(
- resolverAddressResult && !isZero(resolverAddressResult) ? resolverAddressResult : undefined,
- false
- )
- const addr = useSingleCallResult(resolverContract, 'addr', ensNodeArgument)
-
- const changed = debouncedName !== ensName
- return useMemo(
- () => ({
- address: changed ? null : addr.result?.[0] ?? null,
- loading: changed || resolverAddress.loading || addr.loading,
- }),
- [addr.loading, addr.result, changed, resolverAddress.loading]
- )
-}
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useENSAvatar.ts b/apps/cowswap-frontend/src/legacy/hooks/useENSAvatar.ts
deleted file mode 100644
index f53e194dd1..0000000000
--- a/apps/cowswap-frontend/src/legacy/hooks/useENSAvatar.ts
+++ /dev/null
@@ -1,165 +0,0 @@
-import { useEffect, useMemo, useState } from 'react'
-
-import { BigNumber } from '@ethersproject/bignumber'
-import { hexZeroPad } from '@ethersproject/bytes'
-import { namehash } from '@ethersproject/hash'
-
-import { safeNamehash } from 'legacy/utils/safeNamehash'
-
-import { useWalletInfo } from 'modules/wallet'
-
-import { fetchWithBackoff } from 'common/utils/fetch'
-import { useSingleCallResult } from 'lib/hooks/multicall'
-import uriToHttp from 'lib/utils/uriToHttp'
-
-import { useENSRegistrarContract, useENSResolverContract, useERC1155Contract, useERC721Contract } from './useContract'
-import useDebounce from './useDebounce'
-import useENSName from './useENSName'
-
-import { isAddress } from '../utils'
-import isZero from '../utils/isZero'
-
-/**
- * Returns the ENS avatar URI, if available.
- * Spec: https://gist.github.com/Arachnid/9db60bd75277969ee1689c8742b75182.
- */
-export default function useENSAvatar(
- address?: string,
- enforceOwnership = true
-): { avatar: string | null; loading: boolean } {
- const debouncedAddress = useDebounce(address, 200)
- const node = useMemo(() => {
- if (!debouncedAddress || !isAddress(debouncedAddress)) return undefined
- return namehash(`${debouncedAddress.toLowerCase().substr(2)}.addr.reverse`)
- }, [debouncedAddress])
-
- const addressAvatar = useAvatarFromNode(node)
- const ENSName = useENSName(address).ENSName
- const nameAvatar = useAvatarFromNode(ENSName === null ? undefined : safeNamehash(ENSName))
- let avatar = addressAvatar.avatar || nameAvatar.avatar
-
- const nftAvatar = useAvatarFromNFT(avatar, enforceOwnership)
- avatar = nftAvatar.avatar || avatar
-
- const http = avatar && uriToHttp(avatar)[0]
-
- const changed = debouncedAddress !== address
- return useMemo(
- () => ({
- avatar: changed ? null : http ?? null,
- loading: changed || addressAvatar.loading || nameAvatar.loading || nftAvatar.loading,
- }),
- [addressAvatar.loading, changed, http, nameAvatar.loading, nftAvatar.loading]
- )
-}
-
-function useAvatarFromNode(node?: string): { avatar?: string; loading: boolean } {
- const nodeArgument = useMemo(() => [node], [node])
- const textArgument = useMemo(() => [node, 'avatar'], [node])
- const registrarContract = useENSRegistrarContract(false)
- const resolverAddress = useSingleCallResult(registrarContract, 'resolver', nodeArgument)
- const resolverAddressResult = resolverAddress.result?.[0]
- const resolverContract = useENSResolverContract(
- resolverAddressResult && !isZero(resolverAddressResult) ? resolverAddressResult : undefined,
- false
- )
- const avatar = useSingleCallResult(resolverContract, 'text', textArgument)
-
- return useMemo(
- () => ({
- avatar: avatar.result?.[0],
- loading: resolverAddress.loading || avatar.loading,
- }),
- [avatar.loading, avatar.result, resolverAddress.loading]
- )
-}
-
-function useAvatarFromNFT(nftUri = '', enforceOwnership: boolean): { avatar?: string; loading: boolean } {
- const parts = nftUri.toLowerCase().split(':')
- const protocol = parts[0]
- // ignore the chain from eip155
- // TODO: when we are able, pull only from the specified chain
- const [, erc] = parts[1]?.split('/') ?? []
- const [contractAddress, id] = parts[2]?.split('/') ?? []
- const isERC721 = protocol === 'eip155' && erc === 'erc721'
- const isERC1155 = protocol === 'eip155' && erc === 'erc1155'
- const erc721 = useERC721Uri(isERC721 ? contractAddress : undefined, id, enforceOwnership)
- const erc1155 = useERC1155Uri(isERC1155 ? contractAddress : undefined, id, enforceOwnership)
- const uri = erc721.uri || erc1155.uri
- const http = uri && uriToHttp(uri)[0]
-
- const [loading, setLoading] = useState(false)
- const [avatar, setAvatar] = useState(undefined)
- useEffect(() => {
- setAvatar(undefined)
- if (http) {
- setLoading(true)
- fetchWithBackoff(http)
- .then((res) => res.json())
- .then(({ image }) => {
- setAvatar(image)
- })
- .catch((e) => console.warn(e))
- .finally(() => {
- setLoading(false)
- })
- }
- }, [http])
-
- return useMemo(
- () => ({ avatar, loading: erc721.loading || erc1155.loading || loading }),
- [avatar, erc1155.loading, erc721.loading, loading]
- )
-}
-
-function useERC721Uri(
- contractAddress: string | undefined,
- id: string | undefined,
- enforceOwnership: boolean
-): { uri?: string; loading: boolean } {
- const idArgument = useMemo(() => [id], [id])
- const { account } = useWalletInfo()
- const contract = useERC721Contract(contractAddress)
- const owner = useSingleCallResult(contract, 'ownerOf', idArgument)
- const uri = useSingleCallResult(contract, 'tokenURI', idArgument)
- return useMemo(
- () => ({
- uri: !enforceOwnership || account === owner.result?.[0] ? uri.result?.[0] : undefined,
- loading: owner.loading || uri.loading,
- }),
- [account, enforceOwnership, owner.loading, owner.result, uri.loading, uri.result]
- )
-}
-
-function useERC1155Uri(
- contractAddress: string | undefined,
- id: string | undefined,
- enforceOwnership: boolean
-): { uri?: string; loading: boolean } {
- const { account } = useWalletInfo()
- const idArgument = useMemo(() => [id], [id])
- const accountArgument = useMemo(() => [account || '', id], [account, id])
- const contract = useERC1155Contract(contractAddress)
- const balance = useSingleCallResult(contract, 'balanceOf', accountArgument)
- const uri = useSingleCallResult(contract, 'uri', idArgument)
- // ERC-1155 allows a generic {id} in the URL, so prepare to replace if relevant,
- // in lowercase hexadecimal (with no 0x prefix) and leading zero padded to 64 hex characters.
- const idHex = getIdHex(id)
- return useMemo(
- () => ({
- uri: !enforceOwnership || balance.result?.[0] > 0 ? uri.result?.[0]?.replaceAll('{id}', idHex) : undefined,
- loading: balance.loading || uri.loading,
- }),
- [balance.loading, balance.result, enforceOwnership, uri.loading, uri.result, idHex]
- )
-}
-
-function getIdHex(id: string | undefined): string | undefined {
- try {
- return id ? hexZeroPad(BigNumber.from(id).toHexString(), 32).substring(2) : id
- } catch (e) {
- console.log(`Couldn't get id hex from id: ${id}`, e)
-
- return undefined
- }
-}
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useENSContentHash.ts b/apps/cowswap-frontend/src/legacy/hooks/useENSContentHash.ts
deleted file mode 100644
index 9c07f471df..0000000000
--- a/apps/cowswap-frontend/src/legacy/hooks/useENSContentHash.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { useMemo } from 'react'
-
-import { safeNamehash } from 'legacy/utils/safeNamehash'
-
-import { useSingleCallResult } from 'lib/hooks/multicall'
-
-import { useENSRegistrarContract, useENSResolverContract } from './useContract'
-
-import isZero from '../utils/isZero'
-
-/**
- * Does a lookup for an ENS name to find its contenthash.
- */
-export default function useENSContentHash(ensName?: string | null): { loading: boolean; contenthash: string | null } {
- const ensNodeArgument = useMemo(() => [ensName === null ? undefined : safeNamehash(ensName)], [ensName])
- const registrarContract = useENSRegistrarContract(false)
- const resolverAddressResult = useSingleCallResult(registrarContract, 'resolver', ensNodeArgument)
- const resolverAddress = resolverAddressResult.result?.[0]
- const resolverContract = useENSResolverContract(
- resolverAddress && isZero(resolverAddress) ? undefined : resolverAddress,
- false
- )
- const contenthash = useSingleCallResult(resolverContract, 'contenthash', ensNodeArgument)
-
- return useMemo(
- () => ({
- contenthash: contenthash.result?.[0] ?? null,
- loading: resolverAddressResult.loading || contenthash.loading,
- }),
- [contenthash.loading, contenthash.result, resolverAddressResult.loading]
- )
-}
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useENSName.ts b/apps/cowswap-frontend/src/legacy/hooks/useENSName.ts
deleted file mode 100644
index a745544073..0000000000
--- a/apps/cowswap-frontend/src/legacy/hooks/useENSName.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import { useMemo } from 'react'
-
-import { namehash } from '@ethersproject/hash'
-
-import { useSingleCallResult } from 'lib/hooks/multicall'
-
-import { useENSRegistrarContract, useENSResolverContract } from './useContract'
-import useDebounce from './useDebounce'
-import useENSAddress from './useENSAddress'
-
-import { isAddress } from '../utils'
-import isZero from '../utils/isZero'
-
-/**
- * Does a reverse lookup for an address to find its ENS name.
- * Note this is not the same as looking up an ENS name to find an address.
- */
-export default function useENSName(address?: string): { ENSName: string | null; loading: boolean } {
- const debouncedAddress = useDebounce(address, 200)
- const ensNodeArgument = useMemo(() => {
- if (!debouncedAddress || !isAddress(debouncedAddress)) return [undefined]
- return [namehash(`${debouncedAddress.toLowerCase().substr(2)}.addr.reverse`)]
- }, [debouncedAddress])
- const registrarContract = useENSRegistrarContract(false)
- const resolverAddress = useSingleCallResult(registrarContract, 'resolver', ensNodeArgument)
- const resolverAddressResult = resolverAddress.result?.[0]
- const resolverContract = useENSResolverContract(
- resolverAddressResult && !isZero(resolverAddressResult) ? resolverAddressResult : undefined,
- false
- )
- const nameCallRes = useSingleCallResult(resolverContract, 'name', ensNodeArgument)
- const name = nameCallRes.result?.[0]
-
- /* ENS does not enforce that an address owns a .eth domain before setting it as a reverse proxy
- and recommends that you perform a match on the forward resolution
- see: https://docs.ens.domains/dapp-developer-guide/resolving-names#reverse-resolution
- */
- const fwdAddr = useENSAddress(name)
- const checkedName = address === fwdAddr?.address ? name : null
-
- const changed = debouncedAddress !== address
- return useMemo(
- () => ({
- ENSName: changed ? null : checkedName,
- loading: changed || resolverAddress.loading || nameCallRes.loading,
- }),
- [changed, nameCallRes.loading, checkedName, resolverAddress.loading]
- )
-}
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useErrorMessageAndModal.tsx b/apps/cowswap-frontend/src/legacy/hooks/useErrorMessageAndModal.tsx
index 70633e00d8..b7a659aa9c 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/useErrorMessageAndModal.tsx
+++ b/apps/cowswap-frontend/src/legacy/hooks/useErrorMessageAndModal.tsx
@@ -1,36 +1,7 @@
import { useMemo, useState } from 'react'
-import { ErrorMessageProps, SwapCallbackError } from 'legacy/components/swap/styleds'
-
import useTransactionErrorModal from './useTransactionErrorModal'
-/**
- * @description hook for getting CoW Swap error and handling them visually
- * @description ErrorMessage component accepts an error message to override exported error state, and a close option
- * @returns returns object: { error, setError, ErrorMessage } => error message, error message setter, and our ErrorMessage component
- */
-export function useErrorMessage() {
- const [internalError, setError] = useState()
-
- return useMemo(() => {
- const handleCloseError = () => setError(undefined)
-
- return {
- error: internalError,
- handleSetError: setError,
- ErrorMessage: function ErrorMessage({
- error = internalError,
- showClose = false,
- ...rest
- }: Pick) {
- return error ? (
-
- ) : null
- },
- }
- }, [internalError])
-}
-
export function useErrorModal() {
const [internalError, setInternalError] = useState()
const { openModal, closeModal, TransactionErrorModal } = useTransactionErrorModal()
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useFavouriteOrCommonTokens.tsx b/apps/cowswap-frontend/src/legacy/hooks/useFavouriteOrCommonTokens.tsx
index 8b0aa5d85b..ed8f8f8f4d 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/useFavouriteOrCommonTokens.tsx
+++ b/apps/cowswap-frontend/src/legacy/hooks/useFavouriteOrCommonTokens.tsx
@@ -1,9 +1,9 @@
import { useMemo } from 'react'
-import { COMMON_BASES } from 'legacy/constants/routing'
-import { useFavouriteTokens } from 'legacy/state/user/hooks'
+import { COMMON_BASES } from '@cowprotocol/common-const'
+import { useWalletInfo } from '@cowprotocol/wallet'
-import { useWalletInfo } from 'modules/wallet'
+import { useFavouriteTokens } from 'legacy/state/user/hooks'
export function useFavouriteOrCommonTokens() {
const { chainId } = useWalletInfo()
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useFetchListCallback.ts b/apps/cowswap-frontend/src/legacy/hooks/useFetchListCallback.ts
index 78880c8ba8..4246458c47 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/useFetchListCallback.ts
+++ b/apps/cowswap-frontend/src/legacy/hooks/useFetchListCallback.ts
@@ -2,20 +2,18 @@ import { useAtomValue, useSetAtom } from 'jotai'
import { atomWithStorage } from 'jotai/utils'
import { useCallback } from 'react'
+import { MAINNET_PROVIDER } from '@cowprotocol/common-const'
+import { atomWithPartialUpdate, resolveENSContentHash } from '@cowprotocol/common-utils'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { TokenList } from '@uniswap/token-lists'
import { nanoid } from '@reduxjs/toolkit'
import ms from 'ms.macro'
-import { MAINNET_PROVIDER } from 'legacy/constants/networks'
import { useAppDispatch } from 'legacy/state/hooks'
import { fetchTokenList } from 'legacy/state/lists/actions'
-import { useWalletInfo } from 'modules/wallet'
-
import getTokenList from 'lib/hooks/useTokenList/fetchTokenList'
-import resolveENSContentHash from 'lib/utils/resolveENSContentHash'
-import { atomWithPartialUpdate } from 'utils/jotai/atomWithPartialUpdate'
const TOKENS_LIST_ENS_CACHE_TIMEOUT = ms`6h`
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useGasPrice.ts b/apps/cowswap-frontend/src/legacy/hooks/useGasPrice.ts
index ebfcfbdf56..327f0fa5b2 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/useGasPrice.ts
+++ b/apps/cowswap-frontend/src/legacy/hooks/useGasPrice.ts
@@ -1,12 +1,12 @@
import { useMemo } from 'react'
+import { useContract } from '@cowprotocol/common-hooks'
+import { useENSAddress } from '@cowprotocol/ens'
+
import JSBI from 'jsbi'
import { useSingleCallResult } from 'lib/hooks/multicall'
-import { useContract } from './useContract'
-import useENSAddress from './useENSAddress'
-
const CHAIN_DATA_ABI = [
{
inputs: [],
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useGetSafeInfo.ts b/apps/cowswap-frontend/src/legacy/hooks/useGetSafeInfo.ts
index 9ab23ace1b..3f8fdedf1b 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/useGetSafeInfo.ts
+++ b/apps/cowswap-frontend/src/legacy/hooks/useGetSafeInfo.ts
@@ -1,16 +1,13 @@
import { useCallback } from 'react'
+import { retry, RetryOptions } from '@cowprotocol/common-utils'
+import { getSafeTransaction } from '@cowprotocol/core'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { SafeMultisigTransactionResponse } from '@safe-global/safe-core-sdk-types'
import { useWeb3React } from '@web3-react/core'
import { RetryResult } from 'types'
-import { retry, RetryOptions } from 'legacy/utils/retry'
-
-import { useWalletInfo } from 'modules/wallet'
-
-import { getSafeTransaction } from 'api/gnosisSafe'
-
const DEFAULT_RETRY_OPTIONS: RetryOptions = { n: 3, minWait: 1000, maxWait: 3000 }
export type GetSafeInfo = (hash: string) => RetryResult
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useHttpLocations.ts b/apps/cowswap-frontend/src/legacy/hooks/useHttpLocations.ts
index 688e25aba1..20f04ebe38 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/useHttpLocations.ts
+++ b/apps/cowswap-frontend/src/legacy/hooks/useHttpLocations.ts
@@ -1,10 +1,7 @@
import { useMemo } from 'react'
-import contenthashToUri from 'lib/utils/contenthashToUri'
-import parseENSAddress from 'lib/utils/parseENSAddress'
-import uriToHttp from 'lib/utils/uriToHttp'
-
-import useENSContentHash from './useENSContentHash'
+import { contenthashToUri, parseENSAddress, uriToHttp } from '@cowprotocol/common-utils'
+import { useENSContentHash } from '@cowprotocol/ens'
export default function useHttpLocations(uri: string | undefined): string[] {
const ens = useMemo(() => (uri ? parseENSAddress(uri) : undefined), [uri])
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useIsActiveWallet.ts b/apps/cowswap-frontend/src/legacy/hooks/useIsActiveWallet.ts
index b4cad5ac9d..5034ca64f9 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/useIsActiveWallet.ts
+++ b/apps/cowswap-frontend/src/legacy/hooks/useIsActiveWallet.ts
@@ -1,9 +1,8 @@
+import { Web3ReactConnection } from '@cowprotocol/wallet'
import { useWeb3React } from '@web3-react/core'
import { useSelectedWallet } from 'legacy/state/user/hooks'
-import { Web3ReactConnection } from 'modules/wallet/web3-react/types'
-
export const useIsActiveWallet = (connection: Web3ReactConnection) => {
const { account } = useWeb3React()
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useIsAmbireWallet.ts b/apps/cowswap-frontend/src/legacy/hooks/useIsAmbireWallet.ts
deleted file mode 100644
index c817985c2f..0000000000
--- a/apps/cowswap-frontend/src/legacy/hooks/useIsAmbireWallet.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { useWalletMetaData } from 'modules/wallet'
-import { getIsAmbireWallet } from 'modules/wallet/api/utils/connection'
-
-export default function useIsAmbireWallet(): boolean {
- const { walletName } = useWalletMetaData()
-
- return getIsAmbireWallet(walletName)
-}
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useIsArgentWallet.ts b/apps/cowswap-frontend/src/legacy/hooks/useIsArgentWallet.ts
deleted file mode 100644
index 8e10102a9a..0000000000
--- a/apps/cowswap-frontend/src/legacy/hooks/useIsArgentWallet.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { useMemo } from 'react'
-
-import { useWalletInfo } from 'modules/wallet'
-
-import { NEVER_RELOAD, useSingleCallResult } from 'lib/hooks/multicall'
-
-import { useArgentWalletDetectorContract } from './useContract'
-
-export default function useIsArgentWallet(): boolean {
- const { account } = useWalletInfo()
- const argentWalletDetector = useArgentWalletDetectorContract()
- const inputs = useMemo(() => [account ?? undefined], [account])
- const call = useSingleCallResult(argentWalletDetector, 'isArgentWallet', inputs, NEVER_RELOAD)
- return Boolean(call?.result?.[0])
-}
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useIsSwapUnsupported.ts b/apps/cowswap-frontend/src/legacy/hooks/useIsSwapUnsupported.ts
deleted file mode 100644
index fac7bceb86..0000000000
--- a/apps/cowswap-frontend/src/legacy/hooks/useIsSwapUnsupported.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { useMemo } from 'react'
-
-import { Currency } from '@uniswap/sdk-core'
-
-import { useUnsupportedTokens } from 'legacy/hooks/Tokens'
-
-/**
- * Returns true if the input currency or output currency cannot be traded in the interface
- * @param currencyIn the input currency to check
- * @param currencyOut the output currency to check
- */
-export function useIsSwapUnsupported(currencyIn?: Currency | null, currencyOut?: Currency | null): boolean {
- const unsupportedTokens = useUnsupportedTokens()
- return useMemo(() => {
- if (!unsupportedTokens) {
- return false
- }
- const currencyInUnsupported = Boolean(currencyIn?.isToken && unsupportedTokens[currencyIn.address])
- const currencyOutUnsupported = Boolean(currencyOut?.isToken && unsupportedTokens[currencyOut.address])
- return currencyInUnsupported || currencyOutUnsupported
- }, [currencyIn, currencyOut, unsupportedTokens])
-}
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useLocationLinkProps.ts b/apps/cowswap-frontend/src/legacy/hooks/useLocationLinkProps.ts
deleted file mode 100644
index d812001598..0000000000
--- a/apps/cowswap-frontend/src/legacy/hooks/useLocationLinkProps.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import { useMemo } from 'react'
-
-import { LocationDescriptor } from 'history'
-import { stringify } from 'qs'
-import { useLocation } from 'react-router-dom'
-
-import { SupportedLocale } from 'legacy/constants/locales'
-import useParsedQueryString from 'legacy/hooks/useParsedQueryString'
-
-import { useActiveLocale } from './useActiveLocale'
-
-import { sendEvent } from '../components/analytics/googleAnalytics'
-
-export function useLocationLinkProps(locale: SupportedLocale | null): {
- to?: LocationDescriptor
- onClick?: () => void
-} {
- const location = useLocation()
- const qs = useParsedQueryString()
- const activeLocale = useActiveLocale()
-
- return useMemo(
- () =>
- !locale
- ? {}
- : {
- to: {
- ...location,
- search: stringify({ ...qs, lng: locale }),
- },
- onClick: () => {
- sendEvent({
- category: 'Localization',
- action: 'Switch Locale',
- label: `${activeLocale} -> ${locale}`,
- })
- },
- },
- [location, qs, activeLocale, locale]
- )
-}
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useNetworkName.ts b/apps/cowswap-frontend/src/legacy/hooks/useNetworkName.ts
deleted file mode 100644
index a25b5b1adf..0000000000
--- a/apps/cowswap-frontend/src/legacy/hooks/useNetworkName.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { useMemo } from 'react'
-
-import { CHAIN_INFO } from 'legacy/constants/chainInfo'
-
-import { useWalletInfo } from 'modules/wallet'
-
-export default function useNetworkName(): string | undefined {
- const { chainId } = useWalletInfo()
-
- return useMemo(() => {
- return CHAIN_INFO[chainId].label || ''
- }, [chainId])
-}
diff --git a/apps/cowswap-frontend/src/legacy/hooks/usePriceImpact/useFiatValuePriceImpact.ts b/apps/cowswap-frontend/src/legacy/hooks/usePriceImpact/useFiatValuePriceImpact.ts
index e0561dcd3a..519cc9db61 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/usePriceImpact/useFiatValuePriceImpact.ts
+++ b/apps/cowswap-frontend/src/legacy/hooks/usePriceImpact/useFiatValuePriceImpact.ts
@@ -1,11 +1,10 @@
+import { ONE_HUNDRED_PERCENT } from '@cowprotocol/common-const'
+import { useDebounce } from '@cowprotocol/common-hooks'
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import JSBI from 'jsbi'
import ms from 'ms.macro'
-import { ONE_HUNDRED_PERCENT } from 'legacy/constants/misc'
-import useDebounce from 'legacy/hooks/useDebounce'
-
import { useDerivedTradeState } from 'modules/trade/hooks/useDerivedTradeState'
import { useTradeUsdAmounts } from 'modules/usdAmount'
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useRecentActivity.ts b/apps/cowswap-frontend/src/legacy/hooks/useRecentActivity.ts
index 435fcfb60f..1f653b49e0 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/useRecentActivity.ts
+++ b/apps/cowswap-frontend/src/legacy/hooks/useRecentActivity.ts
@@ -1,17 +1,15 @@
import { useMemo } from 'react'
+import { MAXIMUM_ORDERS_TO_DISPLAY } from '@cowprotocol/common-const'
+import { getDateTimestamp } from '@cowprotocol/common-utils'
import { OrderClass, SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
+import { useWalletInfo } from '@cowprotocol/wallet'
-import { MAXIMUM_ORDERS_TO_DISPLAY } from 'legacy/constants'
import { isTransactionRecent, useAllTransactions, useTransactionsByHash } from 'legacy/state/enhancedTransactions/hooks'
import { EnhancedTransactionDetails } from 'legacy/state/enhancedTransactions/reducer'
import { Order, OrderStatus } from 'legacy/state/orders/actions'
import { useCombinedPendingOrders, useOrder, useOrders, useOrdersById } from 'legacy/state/orders/hooks'
-import { useWalletInfo } from 'modules/wallet'
-
-import { getDateTimestamp } from 'utils/time'
-
export interface AddedOrder extends Order {
addedTime: number
}
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useRefetchPriceCallback.tsx b/apps/cowswap-frontend/src/legacy/hooks/useRefetchPriceCallback.tsx
index d858a2fe29..95ff6ea1f0 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/useRefetchPriceCallback.tsx
+++ b/apps/cowswap-frontend/src/legacy/hooks/useRefetchPriceCallback.tsx
@@ -1,9 +1,18 @@
import { useCallback } from 'react'
+import { isOnline } from '@cowprotocol/common-hooks'
+import {
+ CancelableResult,
+ onlyResolvesLast,
+ getPromiseFulfilledValue,
+ isPromiseFulfilled,
+ registerOnWindow,
+ calculateValidTo,
+ getQuoteUnsupportedToken,
+} from '@cowprotocol/common-utils'
import { PriceQuality } from '@cowprotocol/cow-sdk'
import { useGetGpPriceStrategy } from 'legacy/hooks/useGetGpPriceStrategy'
-import { isOnline } from 'legacy/hooks/useIsOnline'
import { AddGpUnsupportedTokenParams } from 'legacy/state/lists/actions'
import {
useAddGpUnsupportedToken,
@@ -13,9 +22,8 @@ import {
import { QuoteError } from 'legacy/state/price/actions'
import { useQuoteDispatchers } from 'legacy/state/price/hooks'
import { QuoteInformationObject } from 'legacy/state/price/reducer'
+import { LegacyFeeQuoteParams, LegacyQuoteParams } from 'legacy/state/price/types'
import { useUserTransactionTTL } from 'legacy/state/user/hooks'
-import { CancelableResult, onlyResolvesLast } from 'legacy/utils/async'
-import { getPromiseFulfilledValue, isPromiseFulfilled, registerOnWindow } from 'legacy/utils/misc'
import { getBestQuote, getFastQuote, QuoteResult } from 'legacy/utils/price'
import { useIsEoaEthFlow } from 'modules/swap/hooks/useIsEoaEthFlow'
@@ -26,9 +34,6 @@ import GpQuoteError, {
GpQuoteErrorDetails,
isValidQuoteError,
} from 'api/gnosisProtocol/errors/QuoteError'
-import { LegacyFeeQuoteParams, LegacyQuoteParams } from 'api/gnosisProtocol/legacy/types'
-import { getQuoteUnsupportedToken } from 'utils/getQuoteUnsupportedToken'
-import { calculateValidTo } from 'utils/time'
interface HandleQuoteErrorParams {
quoteData: QuoteInformationObject | LegacyFeeQuoteParams
@@ -241,12 +246,6 @@ export function useRefetchQuoteCallback() {
},
}
- // Register get best and fast quote methods on window
- registerOnWindow({
- getBestQuote: async () => getBestQuoteResolveOnlyLastCall(bestQuoteParams),
- getFastQuote: async () => getFastQuoteResolveOnlyLastCall(fastQuoteParams),
- })
-
// Get the fast quote
if (!isPriceRefresh) {
getFastQuoteResolveOnlyLastCall(fastQuoteParams)
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useTheme.ts b/apps/cowswap-frontend/src/legacy/hooks/useTheme.ts
deleted file mode 100644
index eca5cc2471..0000000000
--- a/apps/cowswap-frontend/src/legacy/hooks/useTheme.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { useContext } from 'react'
-
-import { ThemeContext } from 'styled-components/macro'
-
-export default function useTheme() {
- return useContext(ThemeContext)
-}
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useTokenAllowance.ts b/apps/cowswap-frontend/src/legacy/hooks/useTokenAllowance.ts
index 673d35f939..0de703a8f2 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/useTokenAllowance.ts
+++ b/apps/cowswap-frontend/src/legacy/hooks/useTokenAllowance.ts
@@ -1,13 +1,12 @@
import { useMemo } from 'react'
+import { useTokenContract } from '@cowprotocol/common-hooks'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { Nullish } from 'types'
import { useSingleCallResult } from 'lib/hooks/multicall'
-import { useTokenContract } from './useContract'
-
export function useTokenAllowance(
token: Nullish,
owner?: string,
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useTokenInfoFromActiveList.ts b/apps/cowswap-frontend/src/legacy/hooks/useTokenInfoFromActiveList.ts
deleted file mode 100644
index 788cd14f2c..0000000000
--- a/apps/cowswap-frontend/src/legacy/hooks/useTokenInfoFromActiveList.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { useMemo } from 'react'
-
-import { Currency } from '@uniswap/sdk-core'
-
-import { useCombinedActiveList } from 'legacy/state/lists/hooks'
-
-import { useWalletInfo } from 'modules/wallet'
-
-/**
- * Returns a WrappedTokenInfo from the active token lists when possible,
- * or the passed token otherwise. */
-export function useTokenInfoFromActiveList(currency: Currency) {
- const { chainId } = useWalletInfo()
- const activeList = useCombinedActiveList()
-
- return useMemo(() => {
- if (!chainId) return
- if (currency.isNative) return currency
-
- try {
- return activeList[chainId][currency.wrapped.address].token
- } catch (e: any) {
- return currency
- }
- }, [activeList, chainId, currency])
-}
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useTokenLazy.ts b/apps/cowswap-frontend/src/legacy/hooks/useTokenLazy.ts
index 4a1acbf487..a1978de686 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/useTokenLazy.ts
+++ b/apps/cowswap-frontend/src/legacy/hooks/useTokenLazy.ts
@@ -1,16 +1,15 @@
import { useCallback } from 'react'
-import { Erc20 } from '@cowswap/abis'
+import { Erc20 } from '@cowprotocol/abis'
+import { getBytes32TokenContract, getTokenContract } from '@cowprotocol/common-hooks'
+import { retry } from '@cowprotocol/common-utils'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Contract } from '@ethersproject/contracts'
import { JsonRpcProvider } from '@ethersproject/providers'
import { Token } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
-import { getBytes32TokenContract, getTokenContract } from 'legacy/hooks/useContract'
import { useAddUserToken } from 'legacy/state/user/hooks'
-import { retry } from 'legacy/utils/retry'
-
-import { useWalletInfo } from 'modules/wallet'
import { parseStringOrBytes32 } from 'lib/hooks/useCurrency'
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useTotalSupply.ts b/apps/cowswap-frontend/src/legacy/hooks/useTotalSupply.ts
index 070dfc2571..87b1b9db60 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/useTotalSupply.ts
+++ b/apps/cowswap-frontend/src/legacy/hooks/useTotalSupply.ts
@@ -1,11 +1,10 @@
import { useMemo } from 'react'
+import { useTokenContract } from '@cowprotocol/common-hooks'
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
import { useSingleCallResult } from 'lib/hooks/multicall'
-import { useTokenContract } from './useContract'
-
// returns undefined if input token is undefined, or fails to get token contract,
// or contract total supply cannot be fetched
export function useTotalSupply(token?: Currency): CurrencyAmount | undefined {
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useTransactionConfirmationModal.tsx b/apps/cowswap-frontend/src/legacy/hooks/useTransactionConfirmationModal.tsx
index 574eac9894..157b2f0c1a 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/useTransactionConfirmationModal.tsx
+++ b/apps/cowswap-frontend/src/legacy/hooks/useTransactionConfirmationModal.tsx
@@ -1,9 +1,11 @@
import { useState, useCallback } from 'react'
-import { TransactionConfirmationModal, ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal'
+import { TransactionConfirmationModal } from 'legacy/components/TransactionConfirmationModal'
import { useOpenModal, useCloseModals, useModalIsOpen } from 'legacy/state/application/hooks'
import { ApplicationModal } from 'legacy/state/application/reducer'
+import { ConfirmOperationType } from '../state/types'
+
export default function useTransactionConfirmationModal(
defaultOperationType: ConfirmOperationType = ConfirmOperationType.WRAP_ETHER
) {
diff --git a/apps/cowswap-frontend/src/legacy/hooks/useWrapCallback.ts b/apps/cowswap-frontend/src/legacy/hooks/useWrapCallback.ts
index 363b5ce6af..7dc8c777ae 100644
--- a/apps/cowswap-frontend/src/legacy/hooks/useWrapCallback.ts
+++ b/apps/cowswap-frontend/src/legacy/hooks/useWrapCallback.ts
@@ -1,22 +1,19 @@
+import { wrapAnalytics } from '@cowprotocol/analytics'
+import { RADIX_HEX } from '@cowprotocol/common-const'
+import { getChainCurrencySymbols } from '@cowprotocol/common-const'
+import { calculateGasMargin, formatTokenAmount, isRejectRequestProviderError } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { BigNumber } from '@ethersproject/bignumber'
import { Contract } from '@ethersproject/contracts'
import { TransactionResponse } from '@ethersproject/providers'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
-import { wrapAnalytics } from 'legacy/components/analytics'
-import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal'
-import { getOperationMessage } from 'legacy/components/TransactionConfirmationModal/LegacyConfirmationPendingContent'
-import { RADIX_HEX } from 'legacy/constants'
import { useTransactionAdder } from 'legacy/state/enhancedTransactions/hooks'
-import { calculateGasMargin } from 'legacy/utils/calculateGasMargin'
-import { getChainCurrencySymbols } from 'legacy/utils/gnosis_chain/hack'
import { ExtendedTradeRawState, TradeRawState } from 'modules/trade/types/TradeRawState'
-import { formatTokenAmount } from 'utils/amountFormat'
-
-import { isRejectRequestProviderError } from '../utils/misc'
+import { getOperationMessage } from '../components/TransactionConfirmationModal/LegacyConfirmationPendingContent'
+import { ConfirmOperationType } from '../state/types'
// Use a 180K gas as a fallback if there's issue calculating the gas estimation (fixes some issues with some nodes failing to calculate gas costs for SC wallets)
const WRAP_UNWRAP_GAS_LIMIT_DEFAULT = BigNumber.from('180000')
diff --git a/apps/cowswap-frontend/src/legacy/state/application/hooks.ts b/apps/cowswap-frontend/src/legacy/state/application/hooks.ts
index cb8eb4da2b..73990bfb27 100644
--- a/apps/cowswap-frontend/src/legacy/state/application/hooks.ts
+++ b/apps/cowswap-frontend/src/legacy/state/application/hooks.ts
@@ -1,11 +1,13 @@
import { useCallback, useMemo } from 'react'
+import { DEFAULT_TXN_DISMISS_MS } from '@cowprotocol/common-const'
+
import { createAction } from '@reduxjs/toolkit'
-import { DEFAULT_TXN_DISMISS_MS } from 'legacy/constants/misc'
-import { AppState } from 'legacy/state'
-import { addPopup, ApplicationModal, PopupContent, removePopup } from 'legacy/state/application/reducer'
-import { useAppDispatch, useAppSelector } from 'legacy/state/hooks'
+import { addPopup, ApplicationModal, PopupContent, removePopup } from './reducer'
+
+import { useAppDispatch, useAppSelector } from '../hooks'
+import { AppState } from '../index'
export const setOpenModal = createAction('application/setOpenModal')
@@ -66,7 +68,7 @@ export function useTogglePrivacyPolicy(): () => void {
}
/**
- * @deprecated use @cowswap/snackbars instead
+ * @deprecated use @cowprotocol/snackbars instead
*/
export function useRemovePopup(): (key: string) => void {
const dispatch = useAppDispatch()
@@ -79,7 +81,7 @@ export function useRemovePopup(): (key: string) => void {
}
/**
- * @deprecated use @cowswap/snackbars instead
+ * @deprecated use @cowprotocol/snackbars instead
*/
export function useActivePopups(): AppState['application']['popupList'] {
const list = useAppSelector((state: AppState) => state.application.popupList)
@@ -102,7 +104,7 @@ export function useCloseModals(): () => void {
}
/**
- * @deprecated use @cowswap/snackbars instead
+ * @deprecated use @cowprotocol/snackbars instead
*/
export function useAddPopup(): (content: PopupContent, key?: string, removeAfterMs?: number | null) => void {
const dispatch = useAppDispatch()
diff --git a/apps/cowswap-frontend/src/legacy/state/application/initialState.ts b/apps/cowswap-frontend/src/legacy/state/application/initialState.ts
index 506ed1ca9d..e3f262d3a6 100644
--- a/apps/cowswap-frontend/src/legacy/state/application/initialState.ts
+++ b/apps/cowswap-frontend/src/legacy/state/application/initialState.ts
@@ -1,5 +1,5 @@
-import { localWarning } from 'legacy/state/application/localWarning'
-import { ApplicationState } from 'legacy/state/application/reducer'
+import { localWarning } from './localWarning'
+import { ApplicationState } from './reducer'
const popupList: ApplicationState['popupList'] = []
diff --git a/apps/cowswap-frontend/src/legacy/state/application/localWarning.ts b/apps/cowswap-frontend/src/legacy/state/application/localWarning.ts
index 6f8039615f..f89b5293c9 100644
--- a/apps/cowswap-frontend/src/legacy/state/application/localWarning.ts
+++ b/apps/cowswap-frontend/src/legacy/state/application/localWarning.ts
@@ -1,5 +1,5 @@
-import { PINATA_API_KEY, PINATA_SECRET_API_KEY } from 'legacy/constants/ipfs'
-import { isLocal } from 'legacy/utils/environments'
+import { PINATA_API_KEY, PINATA_SECRET_API_KEY } from '@cowprotocol/common-const'
+import { isLocal } from '@cowprotocol/common-utils'
let warningMsg
diff --git a/apps/cowswap-frontend/src/legacy/state/application/reducer.ts b/apps/cowswap-frontend/src/legacy/state/application/reducer.ts
index 4add005de0..3b1d4f3c94 100644
--- a/apps/cowswap-frontend/src/legacy/state/application/reducer.ts
+++ b/apps/cowswap-frontend/src/legacy/state/application/reducer.ts
@@ -1,12 +1,12 @@
+import { DEFAULT_TXN_DISMISS_MS } from '@cowprotocol/common-const'
+import { BlockExplorerLinkType } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { createSlice, nanoid } from '@reduxjs/toolkit'
import { FlattenInterpolation, ThemeProps, DefaultTheme } from 'styled-components/macro'
import { Nullish } from 'types'
-import { DEFAULT_TXN_DISMISS_MS } from 'legacy/constants/misc'
-import { initialState } from 'legacy/state/application/initialState'
-import { BlockExplorerLinkType } from 'legacy/utils'
+import { initialState } from './initialState'
type BasePopupContent = {
failedSwitchNetwork: SupportedChainId
diff --git a/apps/cowswap-frontend/src/legacy/state/claim/actions.ts b/apps/cowswap-frontend/src/legacy/state/claim/actions.ts
index 36a2668ddc..358368d100 100644
--- a/apps/cowswap-frontend/src/legacy/state/claim/actions.ts
+++ b/apps/cowswap-frontend/src/legacy/state/claim/actions.ts
@@ -2,7 +2,7 @@ import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { createAction } from '@reduxjs/toolkit'
-import { ClaimInfo } from 'legacy/state/claim/reducer'
+import { ClaimInfo } from './reducer'
export enum ClaimStatus {
DEFAULT = 'DEFAULT',
@@ -12,33 +12,6 @@ export enum ClaimStatus {
FAILED = 'FAILED',
}
-export type ClaimActions = {
- // account
- setInputAddress: (payload: string) => void
- setActiveClaimAccount: (payload: string) => void
- setActiveClaimAccountENS: (payload: string) => void
-
- // search
- setIsSearchUsed: (payload: boolean) => void
-
- // claiming
- setClaimStatus: (payload: ClaimStatus) => void
- setClaimedAmount: (payload: string) => void
- setEstimatedGas: (payload: string) => void
-
- // investing
- setIsInvestFlowActive: (payload: boolean) => void
- setInvestFlowStep: (payload: number) => void
- initInvestFlowData: () => void
- updateInvestAmount: (payload: { index: number; amount: string }) => void
- updateInvestError: (payload: { index: number; error: string | undefined }) => void
- setIsTouched: (payload: { index: number; isTouched: boolean }) => void
-
- // claim row selection
- setSelected: (payload: number[]) => void
- setSelectedAll: (payload: boolean) => void
-}
-
// accounts
export const setInputAddress = createAction('claim/setInputAddress')
export const setActiveClaimAccount = createAction('claim/setActiveClaimAccount')
diff --git a/apps/cowswap-frontend/src/legacy/state/claim/hooks/const.ts b/apps/cowswap-frontend/src/legacy/state/claim/hooks/const.ts
new file mode 100644
index 0000000000..c684a50073
--- /dev/null
+++ b/apps/cowswap-frontend/src/legacy/state/claim/hooks/const.ts
@@ -0,0 +1,7 @@
+import { ClaimType } from './types'
+
+const CLAIMS_REPO_BRANCH = 'main'
+
+export const CLAIMS_REPO = `https://raw.githubusercontent.com/cowprotocol/cow-merkle-drop/${CLAIMS_REPO_BRANCH}/`
+export const FREE_CLAIM_TYPES: ClaimType[] = [ClaimType.Airdrop, ClaimType.Team, ClaimType.Advisor]
+export const PAID_CLAIM_TYPES: ClaimType[] = [ClaimType.GnoOption, ClaimType.UserOption, ClaimType.Investor]
diff --git a/apps/cowswap-frontend/src/legacy/state/claim/hooks/index.ts b/apps/cowswap-frontend/src/legacy/state/claim/hooks/index.ts
index a5aaba7fe6..ccedc9e2b8 100644
--- a/apps/cowswap-frontend/src/legacy/state/claim/hooks/index.ts
+++ b/apps/cowswap-frontend/src/legacy/state/claim/hooks/index.ts
@@ -1,8 +1,11 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
-import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
-import { SupportedChainId } from '@cowprotocol/cow-sdk'
-import { VCow } from '@cowswap/abis'
+import { VCow } from '@cowprotocol/abis'
+import { GpEther, V_COW } from '@cowprotocol/common-const'
+import { useIsMounted, useVCowContract } from '@cowprotocol/common-hooks'
+import { calculateGasMargin, formatTokenAmount, isAddress } from '@cowprotocol/common-utils'
+import { SupportedChainId as ChainId, SupportedChainId } from '@cowprotocol/cow-sdk'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { BigNumber } from '@ethersproject/bignumber'
import { TransactionResponse } from '@ethersproject/providers'
import { parseUnits } from '@ethersproject/units'
@@ -11,55 +14,44 @@ import { CurrencyAmount, Price, Token } from '@uniswap/sdk-core'
import JSBI from 'jsbi'
import ms from 'ms.macro'
-import { useSelector, useDispatch } from 'react-redux'
+import { useDispatch, useSelector } from 'react-redux'
-import { GpEther, V_COW } from 'legacy/constants/tokens'
-import { useVCowContract } from 'legacy/hooks/useContract'
-import useIsMounted from 'legacy/hooks/useIsMounted'
-import { AppDispatch } from 'legacy/state'
-import { AppState } from 'legacy/state'
+import { useSingleContractMultipleData } from 'lib/hooks/multicall'
+
+import { PAID_CLAIM_TYPES } from './const'
+import { ClaimInput, ClaimType, RepoClaims, UserClaims, VCowPrices } from './types'
import {
+ claimTypeToTokenAmount,
getClaimKey,
getClaimsRepoPath,
isFreeClaim,
- claimTypeToTokenAmount,
transformRepoClaimsToUserClaims,
-} from 'legacy/state/claim/hooks/utils'
-import { ClaimInfo } from 'legacy/state/claim/reducer'
-import { useTransactionAdder } from 'legacy/state/enhancedTransactions/hooks'
-import { useAllClaimingTransactionIndices } from 'legacy/state/enhancedTransactions/hooks'
-import { isAddress } from 'legacy/utils'
-import { calculateGasMargin } from 'legacy/utils/calculateGasMargin'
-
-import { useWalletInfo } from 'modules/wallet'
-
-import { useSingleContractMultipleData } from 'lib/hooks/multicall'
-import { EnhancedUserClaimData } from 'pages/Claim/types'
-import { formatTokenAmount } from 'utils/amountFormat'
+} from './utils'
+import { useAllClaimingTransactionIndices, useTransactionAdder } from '../../enhancedTransactions/hooks'
+import { AppDispatch, AppState } from '../../index'
import {
- setInputAddress,
+ ClaimStatus,
+ initInvestFlowData,
+ resetClaimUi,
setActiveClaimAccount,
setActiveClaimAccountENS,
- setIsSearchUsed,
- setClaimStatus,
setClaimedAmount,
- setIsInvestFlowActive,
+ setClaimsCount,
+ setClaimStatus,
+ setEstimatedGas,
+ setInputAddress,
setInvestFlowStep,
- initInvestFlowData,
- updateInvestAmount,
+ setIsInvestFlowActive,
+ setIsSearchUsed,
+ setIsTouched,
setSelected,
setSelectedAll,
- ClaimStatus,
- resetClaimUi,
+ updateInvestAmount,
updateInvestError,
- setEstimatedGas,
- setIsTouched,
- setClaimsCount,
} from '../actions'
-
-const CLAIMS_REPO_BRANCH = 'main'
-export const CLAIMS_REPO = `https://raw.githubusercontent.com/cowprotocol/cow-merkle-drop/${CLAIMS_REPO_BRANCH}/`
+import { ClaimInfo } from '../reducer'
+import { EnhancedUserClaimData } from '../types'
// Base amount = 1 VCOW
const ONE_VCOW = CurrencyAmount.fromRawAmount(
@@ -74,20 +66,8 @@ const AIRDROP_TIME = ms`6 weeks`
// For native token price calculation
const DENOMINATOR = JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(18))
-export enum ClaimType {
- Airdrop, // free, no vesting, can be available on both mainnet and gchain
- GnoOption, // paid, with vesting, must use GNO, can be available on both mainnet and gchain
- UserOption, // paid, with vesting, must use Native currency, can be available on both mainnet and gchain
- Investor, // paid, with vesting, must use USDC, only on mainnet
- Team, // free, with vesting, only on mainnet
- Advisor, // free, with vesting, only on mainnet
-}
-
type RepoClaimType = keyof typeof ClaimType
-export const FREE_CLAIM_TYPES: ClaimType[] = [ClaimType.Airdrop, ClaimType.Team, ClaimType.Advisor]
-export const PAID_CLAIM_TYPES: ClaimType[] = [ClaimType.GnoOption, ClaimType.UserOption, ClaimType.Investor]
-
export interface UserClaimData {
index: number
amount: string
@@ -99,23 +79,8 @@ export type RepoClaimData = Omit & {
type: RepoClaimType
}
-export interface ClaimInput {
- /**
- * The index of the claim
- */
- index: number
- /**
- * The amount of the claim. Optional
- * If not present, will claim the full amount
- */
- amount?: string
-}
-
type Account = string | null | undefined
-export type UserClaims = UserClaimData[]
-export type RepoClaims = RepoClaimData[]
-
export type ClassifiedUserClaims = {
available: UserClaims
expired: UserClaims
@@ -402,12 +367,6 @@ function _useVCowPriceForToken(priceFnName: VCowPriceFnNames): string | null {
return price
}
-export type VCowPrices = {
- native: string | null
- gno: string | null
- usdc: string | null
-}
-
export function useVCowPrices(): VCowPrices {
const native = useNativeTokenPrice()
const gno = useGnoPrice()
diff --git a/apps/cowswap-frontend/src/legacy/state/claim/hooks/types.ts b/apps/cowswap-frontend/src/legacy/state/claim/hooks/types.ts
new file mode 100644
index 0000000000..dd593fd8b3
--- /dev/null
+++ b/apps/cowswap-frontend/src/legacy/state/claim/hooks/types.ts
@@ -0,0 +1,30 @@
+import { RepoClaimData, UserClaimData } from './index'
+
+export enum ClaimType {
+ Airdrop, // free, no vesting, can be available on both mainnet and gchain
+ GnoOption, // paid, with vesting, must use GNO, can be available on both mainnet and gchain
+ UserOption, // paid, with vesting, must use Native currency, can be available on both mainnet and gchain
+ Investor, // paid, with vesting, must use USDC, only on mainnet
+ Team, // free, with vesting, only on mainnet
+ Advisor, // free, with vesting, only on mainnet
+}
+
+export interface ClaimInput {
+ /**
+ * The index of the claim
+ */
+ index: number
+ /**
+ * The amount of the claim. Optional
+ * If not present, will claim the full amount
+ */
+ amount?: string
+}
+
+export type UserClaims = UserClaimData[]
+export type RepoClaims = RepoClaimData[]
+export type VCowPrices = {
+ native: string | null
+ gno: string | null
+ usdc: string | null
+}
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 e936f0e6f5..d6cca292b8 100644
--- a/apps/cowswap-frontend/src/legacy/state/claim/hooks/utils.ts
+++ b/apps/cowswap-frontend/src/legacy/state/claim/hooks/utils.ts
@@ -1,21 +1,12 @@
+import { GpEther, USDC, GNO, ZERO_PERCENT, ONE_HUNDRED_PERCENT } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { Currency, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core'
-import { ONE_HUNDRED_PERCENT, ZERO_PERCENT } from 'legacy/constants/misc'
-import { GNO, GpEther, USDC } from 'legacy/constants/tokens'
-import {
- CLAIMS_REPO,
- ClaimType,
- FREE_CLAIM_TYPES,
- PAID_CLAIM_TYPES,
- RepoClaims,
- UserClaims,
- VCowPrices,
-} from 'legacy/state/claim/hooks/index'
-import { ClaimInput } from 'legacy/state/claim/hooks/index'
-import { InvestClaim } from 'legacy/state/claim/reducer'
-
-import { EnhancedUserClaimData, InvestmentAmounts } from 'pages/Claim/types'
+import { CLAIMS_REPO, FREE_CLAIM_TYPES, PAID_CLAIM_TYPES } from './const'
+import { ClaimInput, ClaimType, RepoClaims, UserClaims, VCowPrices } from './types'
+
+import { InvestClaim } from '../reducer'
+import { EnhancedUserClaimData, InvestmentAmounts } from '../types'
/**
* Helper function to check whether any claim is an investment option
diff --git a/apps/cowswap-frontend/src/pages/Claim/types.ts b/apps/cowswap-frontend/src/legacy/state/claim/types.ts
similarity index 89%
rename from apps/cowswap-frontend/src/pages/Claim/types.ts
rename to apps/cowswap-frontend/src/legacy/state/claim/types.ts
index 436889852d..bba01d01c3 100644
--- a/apps/cowswap-frontend/src/pages/Claim/types.ts
+++ b/apps/cowswap-frontend/src/legacy/state/claim/types.ts
@@ -1,9 +1,9 @@
import { SyntheticEvent } from 'react'
+import { GpEther } from '@cowprotocol/common-const'
import { Currency, CurrencyAmount, Price, Token } from '@uniswap/sdk-core'
-import { GpEther } from 'legacy/constants/tokens'
-import { UserClaimData } from 'legacy/state/claim/hooks'
+import { UserClaimData } from './hooks'
export type ClaimCommonTypes = {
account: string | null | undefined
diff --git a/apps/cowswap-frontend/src/legacy/state/claim/updater.tsx b/apps/cowswap-frontend/src/legacy/state/claim/updater.tsx
index 23e17bc005..3388fd2753 100644
--- a/apps/cowswap-frontend/src/legacy/state/claim/updater.tsx
+++ b/apps/cowswap-frontend/src/legacy/state/claim/updater.tsx
@@ -1,16 +1,10 @@
import { useEffect, useMemo } from 'react'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { useWalletInfo } from '@cowprotocol/wallet'
-import {
- ClassifiedUserClaims,
- useClaimDispatchers,
- useClaimState,
- useClassifiedUserClaims,
-} from 'legacy/state/claim/hooks'
-import { ClaimInfo } from 'legacy/state/claim/reducer'
-
-import { useWalletInfo } from 'modules/wallet'
+import { ClassifiedUserClaims, useClaimDispatchers, useClaimState, useClassifiedUserClaims } from './hooks'
+import { ClaimInfo } from './reducer'
export default function Updater() {
const { chainId } = useWalletInfo()
diff --git a/apps/cowswap-frontend/src/legacy/state/connection/hooks.ts b/apps/cowswap-frontend/src/legacy/state/connection/hooks.ts
deleted file mode 100644
index d75ecd87e5..0000000000
--- a/apps/cowswap-frontend/src/legacy/state/connection/hooks.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import { useMemo } from 'react'
-
-import { Token } from '@uniswap/sdk-core'
-
-import { useAllTokens } from 'legacy/hooks/Tokens'
-import { useFavouriteTokens } from 'legacy/state/user/hooks'
-
-import { useOnchainBalances } from 'modules/tokens'
-import { TokenAmounts } from 'modules/tokens'
-import { useWalletInfo } from 'modules/wallet'
-
-// mimics useAllBalances
-export function useAllTokenBalances(): [TokenAmounts, boolean] {
- const { account } = useWalletInfo()
- const allTokens = useAllTokens()
- // Mod, add favourite tokens to balances
- const favTokens = useFavouriteTokens()
-
- const allTokensArray = useMemo(() => {
- const favTokensObj = favTokens.reduce(
- (acc, cur: Token) => {
- acc[cur.address] = cur
- return acc
- },
- {} as {
- [address: string]: Token
- }
- )
-
- return Object.values({ ...favTokensObj, ...allTokens })
- }, [allTokens, favTokens])
-
- const { isLoading, amounts } = useOnchainBalances({
- account: account ?? undefined,
- tokens: allTokensArray,
- })
- return [amounts ?? {}, isLoading]
-}
diff --git a/apps/cowswap-frontend/src/legacy/state/connection/reducer.ts b/apps/cowswap-frontend/src/legacy/state/connection/reducer.ts
index 14ae1b7651..c5c8f5ce32 100644
--- a/apps/cowswap-frontend/src/legacy/state/connection/reducer.ts
+++ b/apps/cowswap-frontend/src/legacy/state/connection/reducer.ts
@@ -1,6 +1,6 @@
-import { createSlice } from '@reduxjs/toolkit'
+import { ConnectionType } from '@cowprotocol/wallet'
-import { ConnectionType } from 'modules/wallet'
+import { createSlice } from '@reduxjs/toolkit'
export interface ConnectionState {
errorByConnectionType: Record
@@ -14,7 +14,7 @@ export const initialState: ConnectionState = {
}
const connectionSlice = createSlice({
- name: 'modules/wallet/web3-react/utils/connection',
+ name: 'wallet-connection',
initialState,
reducers: {
updateConnectionError(
diff --git a/apps/cowswap-frontend/src/legacy/state/cowToken/hooks.ts b/apps/cowswap-frontend/src/legacy/state/cowToken/hooks.ts
index 5770448a2a..6558986cbc 100644
--- a/apps/cowswap-frontend/src/legacy/state/cowToken/hooks.ts
+++ b/apps/cowswap-frontend/src/legacy/state/cowToken/hooks.ts
@@ -1,25 +1,21 @@
import { useCallback, useMemo } from 'react'
+import { V_COW } from '@cowprotocol/common-const'
+import { useVCowContract } from '@cowprotocol/common-hooks'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { TransactionResponse } from '@ethersproject/providers'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
-import JSBI from 'jsbi'
-
-import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal'
-import { V_COW, COW } from 'legacy/constants/tokens'
-import { APPROVE_GAS_LIMIT_DEFAULT } from 'legacy/hooks/useApproveCallback/useApproveCallbackMod'
-import { useVCowContract } from 'legacy/hooks/useContract'
-import { AppState } from 'legacy/state'
-import { useTransactionAdder } from 'legacy/state/enhancedTransactions/hooks'
-import { useAppDispatch, useAppSelector } from 'legacy/state/hooks'
-
-import { useTokenBalance } from 'modules/tokens/hooks/useCurrencyBalance'
-import { useWalletInfo } from 'modules/wallet'
-
-import { useSingleCallResult, CallStateResult as Result } from 'lib/hooks/multicall'
+import { CallStateResult as Result, useSingleCallResult } from 'lib/hooks/multicall'
import { setSwapVCowStatus, SwapVCowStatus } from './actions'
+import { APPROVE_GAS_LIMIT_DEFAULT } from '../../hooks/useApproveCallback/useApproveCallbackMod'
+import { useTransactionAdder } from '../enhancedTransactions/hooks'
+import { useAppDispatch, useAppSelector } from '../hooks'
+import { AppState } from '../index'
+import { ConfirmOperationType } from '../types'
+
export type SetSwapVCowStatusCallback = (payload: SwapVCowStatus) => void
type VCowData = {
@@ -156,49 +152,3 @@ export function useSetSwapVCowStatus(): SetSwapVCowStatusCallback {
export function useSwapVCowStatus() {
return useAppSelector((state: AppState) => state.cowToken.swapVCowStatus)
}
-
-/**
- * Hook that returns COW balance
- */
-export function useCowBalance() {
- const { chainId, account } = useWalletInfo()
- const cowToken = chainId ? COW[chainId] : undefined
- return useTokenBalance(account || undefined, cowToken)
-}
-
-/**
- * Hook that returns combined vCOW + COW balance + vCow from locked GNO
- */
-export function useCombinedBalance() {
- const { chainId, account } = useWalletInfo()
- const { total: vCowBalance } = useVCowData()
- // const { allocated, claimed } = useCowFromLockedGnoBalances()
- const cowBalance = useCowBalance()
-
- // const lockedGnoBalance = useMemo(() => {
- // if (!allocated || !claimed) {
- // return
- // }
-
- // return JSBI.subtract(allocated.quotient, claimed.quotient)
- // }, [allocated, claimed])
-
- return useMemo(() => {
- let tmpBalance = JSBI.BigInt(0)
-
- const isLoading = !!(account && (!vCowBalance /* || !lockedGnoBalance */ || !cowBalance))
-
- const cow = COW[chainId]
-
- if (account) {
- if (vCowBalance) tmpBalance = JSBI.add(tmpBalance, vCowBalance.quotient)
- // if (lockedGnoBalance) tmpBalance = JSBI.add(tmpBalance, lockedGnoBalance)
- if (cowBalance) tmpBalance = JSBI.add(tmpBalance, cowBalance.quotient)
- }
-
- // TODO: check COW vs vCOW
- const balance = CurrencyAmount.fromRawAmount(cow, tmpBalance)
-
- return { balance, isLoading }
- }, [vCowBalance, /* lockedGnoBalance, */ cowBalance, chainId, account])
-}
diff --git a/apps/cowswap-frontend/src/legacy/state/cowToken/middleware.ts b/apps/cowswap-frontend/src/legacy/state/cowToken/middleware.ts
index 46670f65de..89852f3350 100644
--- a/apps/cowswap-frontend/src/legacy/state/cowToken/middleware.ts
+++ b/apps/cowswap-frontend/src/legacy/state/cowToken/middleware.ts
@@ -1,11 +1,11 @@
-import { isAnyOf, Middleware } from '@reduxjs/toolkit'
+import { getCowSoundError, getCowSoundSuccess } from '@cowprotocol/common-utils'
-import { AppState } from 'legacy/state'
-import { getCowSoundSuccess, getCowSoundError } from 'legacy/utils/sound'
+import { isAnyOf, Middleware } from '@reduxjs/toolkit'
import { setSwapVCowStatus, SwapVCowStatus } from './actions'
import { finalizeTransaction } from '../enhancedTransactions/actions'
+import { AppState } from '../index'
const isFinalizeTransaction = isAnyOf(finalizeTransaction)
diff --git a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/hooks/TransactionHooksMod.tsx b/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/hooks/TransactionHooksMod.tsx
index 08efffa04b..16bbf7479f 100644
--- a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/hooks/TransactionHooksMod.tsx
+++ b/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/hooks/TransactionHooksMod.tsx
@@ -1,9 +1,8 @@
import { useMemo } from 'react'
-import { useAppSelector } from 'legacy/state/hooks'
-
-import { useWalletInfo } from 'modules/wallet'
+import { useWalletInfo } from '@cowprotocol/wallet'
+import { useAppSelector } from '../../hooks'
import { EnhancedTransactionDetails } from '../reducer'
// returns all the transactions for the current chain
diff --git a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/hooks/index.ts b/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/hooks/index.ts
index d90451ad02..cb9a814b0f 100644
--- a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/hooks/index.ts
+++ b/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/hooks/index.ts
@@ -1,10 +1,10 @@
import { useCallback, useMemo } from 'react'
-import { useAllTransactions } from 'legacy/state/enhancedTransactions/hooks/index'
-import { useAppDispatch } from 'legacy/state/hooks'
+import { useWalletInfo, useIsSafeWallet } from '@cowprotocol/wallet'
-import { useWalletInfo, useIsSafeWallet } from 'modules/wallet'
+import { useAllTransactions } from './TransactionHooksMod'
+import { useAppDispatch } from '../../hooks'
import { addTransaction, AddTransactionParams } from '../actions'
import { EnhancedTransactionDetails, HashType } from '../reducer'
diff --git a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/reducer.ts b/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/reducer.ts
index 797e31daf7..5b491a5ad0 100644
--- a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/reducer.ts
+++ b/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/reducer.ts
@@ -12,7 +12,7 @@ import {
updateSafeTransaction,
ReplacementType,
SerializableTransactionReceipt,
-} from 'legacy/state/enhancedTransactions/actions'
+} from './actions'
export enum HashType {
ETHEREUM_TX = 'ETHEREUM_TX',
diff --git a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/updater/index.tsx b/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/updater/index.tsx
deleted file mode 100644
index 44786f61ae..0000000000
--- a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/updater/index.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import React from 'react'
-
-import CancelReplaceTxUpdater from './CancelReplaceTxUpdater'
-import FinalizeTxUpdater from './FinalizeTxUpdater'
-
-export default function Updater() {
- return (
- <>
-
-
- >
- )
-}
diff --git a/apps/cowswap-frontend/src/legacy/state/gas/actions.ts b/apps/cowswap-frontend/src/legacy/state/gas/actions.ts
index 4af7a31ade..e89e042717 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 { createAction } from '@reduxjs/toolkit'
-import { WithChainId } from 'legacy/state/lists/actions'
-
import { GasFeeEndpointResponse } from 'api/gasPrices'
+import { WithChainId } from '../lists/actions'
+
export type UpdateGasPrices = GasFeeEndpointResponse & WithChainId
export const updateGasPrices = createAction('gas/updateGasPrices')
diff --git a/apps/cowswap-frontend/src/legacy/state/gas/atoms.ts b/apps/cowswap-frontend/src/legacy/state/gas/atoms.ts
index 6c4b231ac5..53cb47e594 100644
--- a/apps/cowswap-frontend/src/legacy/state/gas/atoms.ts
+++ b/apps/cowswap-frontend/src/legacy/state/gas/atoms.ts
@@ -1,6 +1,6 @@
import { atom } from 'jotai'
-import { DEFAULT_GP_PRICE_STRATEGY } from 'legacy/constants'
+import { DEFAULT_GP_PRICE_STRATEGY } from '@cowprotocol/common-const'
export type GpPriceStrategy = 'COWSWAP' | 'LEGACY'
diff --git a/apps/cowswap-frontend/src/legacy/state/gas/gas-price-strategy-updater.tsx b/apps/cowswap-frontend/src/legacy/state/gas/gas-price-strategy-updater.tsx
index fa2e021437..d1bb63d8c8 100644
--- a/apps/cowswap-frontend/src/legacy/state/gas/gas-price-strategy-updater.tsx
+++ b/apps/cowswap-frontend/src/legacy/state/gas/gas-price-strategy-updater.tsx
@@ -1,15 +1,15 @@
import { useSetAtom } from 'jotai'
import { useEffect } from 'react'
-import ms from 'ms.macro'
-
-import { DEFAULT_GP_PRICE_STRATEGY } from 'legacy/constants'
-import { gasPriceStrategyAtom } from 'legacy/state/gas/atoms'
+import { DEFAULT_GP_PRICE_STRATEGY } from '@cowprotocol/common-const'
+import { useWalletInfo } from '@cowprotocol/wallet'
-import { useWalletInfo } from 'modules/wallet'
+import ms from 'ms.macro'
import { getPriceStrategy } from 'api/gnosisProtocol/priceApi'
+import { gasPriceStrategyAtom } from './atoms'
+
const GP_PRICE_STRATEGY_INTERVAL_TIME = ms`30 minutes`
export function GasPriceStrategyUpdater(): null {
diff --git a/apps/cowswap-frontend/src/legacy/state/gas/hooks.ts b/apps/cowswap-frontend/src/legacy/state/gas/hooks.ts
index 753bedece7..df58a68901 100644
--- a/apps/cowswap-frontend/src/legacy/state/gas/hooks.ts
+++ b/apps/cowswap-frontend/src/legacy/state/gas/hooks.ts
@@ -1,33 +1,13 @@
-import { useSetAtom } from 'jotai'
-import { useCallback } from 'react'
-
import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
-import { useSelector, useDispatch } from 'react-redux'
-
-import { AppDispatch } from 'legacy/state'
-import { AppState } from 'legacy/state'
+import { useSelector } from 'react-redux'
-import { gasPriceAtom } from 'modules/gasPirce'
-
-import { updateGasPrices, UpdateGasPrices } from './actions'
import { GasState } from './reducer'
+import { AppState } from '../index'
+
export function useGasPrices(chainId?: ChainId) {
return useSelector((state) => {
return chainId ? state.gas[chainId] : null
})
}
-
-export function useUpdateGasPrices() {
- const dispatch = useDispatch()
- const setGasPrice = useSetAtom(gasPriceAtom)
-
- return useCallback(
- (gasParams: UpdateGasPrices) => {
- dispatch(updateGasPrices(gasParams))
- setGasPrice(gasParams)
- },
- [dispatch, setGasPrice]
- )
-}
diff --git a/apps/cowswap-frontend/src/legacy/state/global/actions.ts b/apps/cowswap-frontend/src/legacy/state/global/actions.ts
index d4cfa1d5e4..4094748f77 100644
--- a/apps/cowswap-frontend/src/legacy/state/global/actions.ts
+++ b/apps/cowswap-frontend/src/legacy/state/global/actions.ts
@@ -1,6 +1,6 @@
import { createAction } from '@reduxjs/toolkit'
-import { WithChainId } from 'legacy/state/lists/actions'
+import { WithChainId } from '../lists/actions'
// fired once when the app reloads but before the app renders
// allows any updates to be applied to store data loaded from localStorage
diff --git a/apps/cowswap-frontend/src/legacy/state/hooks/index.ts b/apps/cowswap-frontend/src/legacy/state/hooks/index.ts
index 0b2089a33e..1412b2aef9 100644
--- a/apps/cowswap-frontend/src/legacy/state/hooks/index.ts
+++ b/apps/cowswap-frontend/src/legacy/state/hooks/index.ts
@@ -1,6 +1,6 @@
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
-import { AppDispatch, AppState } from 'legacy/state'
+import { AppDispatch, AppState } from '../index'
export const useAppDispatch = () => useDispatch()
export const useAppSelector: TypedUseSelectorHook = useSelector
diff --git a/apps/cowswap-frontend/src/legacy/state/index.ts b/apps/cowswap-frontend/src/legacy/state/index.ts
index 86b5acadd5..d76c9a9fab 100644
--- a/apps/cowswap-frontend/src/legacy/state/index.ts
+++ b/apps/cowswap-frontend/src/legacy/state/index.ts
@@ -1,39 +1,36 @@
+import { DEFAULT_NETWORK_FOR_LISTS } from '@cowprotocol/common-const'
+
import { configureStore, StateFromReducersMapObject } from '@reduxjs/toolkit'
import { load, save } from 'redux-localstorage-simple'
-import { DEFAULT_NETWORK_FOR_LISTS } from 'legacy/constants/lists'
-import application from 'legacy/state/application/reducer'
-import claim from 'legacy/state/claim/reducer'
-import connection from 'legacy/state/connection/reducer'
-import { cowTokenMiddleware } from 'legacy/state/cowToken/middleware'
-import cowToken from 'legacy/state/cowToken/reducer'
-import enhancedTransactions from 'legacy/state/enhancedTransactions/reducer'
-import gas from 'legacy/state/gas/reducer'
-import { updateVersion } from 'legacy/state/global/actions'
-import lists from 'legacy/state/lists/reducer'
-import logs from 'legacy/state/logs/slice'
-import orders from 'legacy/state/orders/reducer'
-import { priceMiddleware } from 'legacy/state/price/middleware'
-import price from 'legacy/state/price/reducer'
-import profile from 'legacy/state/profile/reducer'
-import swap from 'legacy/state/swap/reducer'
-import user from 'legacy/state/user/reducer'
-
-import multicall from 'lib/state/multicall'
+// import { composableOrdersPopupMiddleware } from 'modules/twap/state/composableOrdersPopupMiddleware'
-import { appziMiddleware, popupMiddleware, soundMiddleware, composableOrdersPopupMiddleware } from './orders/middleware'
+import application from './application/reducer'
+import claim from './claim/reducer'
+import connection from './connection/reducer'
+import { cowTokenMiddleware } from './cowToken/middleware'
+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'
+import orders from './orders/reducer'
+import { priceMiddleware } from './price/middleware'
+import price from './price/reducer'
+import profile from './profile/reducer'
+import swap from './swap/reducer'
+import user from './user/reducer'
-const UNISWAP_REDUCERS = {
+const reducers = {
application,
user,
connection,
swap,
multicall: multicall.reducer,
logs,
-}
-
-const reducers = {
- ...UNISWAP_REDUCERS,
transactions: enhancedTransactions, // replace transactions state by "enhancedTransactions"
lists,
orders,
@@ -46,13 +43,14 @@ const reducers = {
const PERSISTED_KEYS: string[] = ['user', 'transactions', 'orders', 'lists', 'gas', 'affiliate', 'profile', 'swap']
-const store = configureStore({
+export const cowSwapStore = configureStore({
reducer: reducers,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({ thunk: true, serializableCheck: false })
.concat(save({ states: PERSISTED_KEYS, debounce: 1000 }))
.concat(popupMiddleware)
- .concat(composableOrdersPopupMiddleware)
+ // TODO: fix it
+ // .concat(composableOrdersPopupMiddleware)
.concat(cowTokenMiddleware)
.concat(soundMiddleware)
.concat(appziMiddleware)
@@ -61,12 +59,10 @@ const store = configureStore({
})
// this instantiates the app / reducers in several places using the default chainId
-store.dispatch(updateVersion({ chainId: DEFAULT_NETWORK_FOR_LISTS }))
+cowSwapStore.dispatch(updateVersion({ chainId: DEFAULT_NETWORK_FOR_LISTS }))
// TODO: this is new, should we enable it?
// setupListeners(store.dispatch)
-export default store
-
export type AppState = StateFromReducersMapObject
-export type AppDispatch = typeof store.dispatch
+export type AppDispatch = typeof cowSwapStore.dispatch
diff --git a/apps/cowswap-frontend/src/legacy/state/lists/hooks.ts b/apps/cowswap-frontend/src/legacy/state/lists/hooks.ts
index 428ddc176b..c9f96e4f02 100644
--- a/apps/cowswap-frontend/src/legacy/state/lists/hooks.ts
+++ b/apps/cowswap-frontend/src/legacy/state/lists/hooks.ts
@@ -1,6 +1,8 @@
import { useCallback, useMemo } from 'react'
+import { UNSUPPORTED_LIST_URLS } from '@cowprotocol/common-const'
import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
+import { useWalletInfo } from '@cowprotocol/wallet'
import DEFAULT_TOKEN_LIST from '@uniswap/default-token-list'
import { Currency } from '@uniswap/sdk-core'
import { TokenInfo } from '@uniswap/token-lists'
@@ -8,23 +10,18 @@ import { TokenInfo } from '@uniswap/token-lists'
import { shallowEqual } from 'react-redux'
import { Nullish } from 'types'
-import { UNSUPPORTED_LIST_URLS } from 'legacy/constants/lists'
-import BROKEN_LIST from 'legacy/constants/tokenLists/broken.tokenlist.json'
-import UNSUPPORTED_TOKEN_LIST from 'legacy/constants/tokenLists/unsupported.tokenlist.json'
-import { AppState } from 'legacy/state'
-import { useAppDispatch, useAppSelector } from 'legacy/state/hooks'
+import { UnsupportedToken } from 'api/gnosisProtocol'
+import { ChainTokenMap, tokensToChainTokenMap } from 'lib/hooks/useTokenList/utils'
+
import {
addGpUnsupportedToken,
AddGpUnsupportedTokenParams,
removeGpUnsupportedToken,
RemoveGpUnsupportedTokenParams,
-} from 'legacy/state/lists/actions'
-import sortByListPriority from 'legacy/utils/listSort'
+} from './actions'
-import { useWalletInfo } from 'modules/wallet'
-
-import { UnsupportedToken } from 'api/gnosisProtocol'
-import { ChainTokenMap, tokensToChainTokenMap } from 'lib/hooks/useTokenList/utils'
+import { useAppDispatch, useAppSelector } from '../hooks'
+import { AppState } from '../index'
export type TokenAddressMap = ChainTokenMap
@@ -34,11 +31,8 @@ type Mutable = {
export function useActiveListUrls(): string[] | undefined {
const { chainId } = useWalletInfo()
- const activeListUrls = useAppSelector((state) => state.lists[chainId]?.activeListUrls, shallowEqual)
- return useMemo(() => {
- return activeListUrls?.filter((url) => !UNSUPPORTED_LIST_URLS[chainId]?.includes(url))
- }, [chainId, activeListUrls])
+ return useAppSelector((state) => state.lists[chainId]?.activeListUrls, shallowEqual)
}
export function useAllLists(): AppState['lists'][ChainId]['byUrl'] {
@@ -77,48 +71,22 @@ export function useCombinedTokenMapFromUrls(urls: string[] | undefined): TokenAd
const lists = useAllLists()
return useMemo(() => {
if (!urls) return {}
- return (
- urls
- .slice()
- // sort by priority so top priority goes last
- .sort(sortByListPriority)
- .reduce((allTokens, currentUrl) => {
- const current = lists[currentUrl]?.current
- if (!current) return allTokens
- try {
- return combineMaps(allTokens, tokensToChainTokenMap(current))
- } catch (error: any) {
- console.error('Could not show token list due to error', error)
- return allTokens
- }
- }, {})
- )
+ return urls.slice().reduce((allTokens, currentUrl) => {
+ const current = lists[currentUrl]?.current
+ if (!current) return allTokens
+ try {
+ return combineMaps(allTokens, tokensToChainTokenMap(current))
+ } catch (error: any) {
+ console.error('Could not show token list due to error', error)
+ return allTokens
+ }
+ }, {})
}, [lists, urls])
}
-// get all the tokens from active lists, combine with local default tokens
-export function useCombinedActiveList(): TokenAddressMap {
- const activeListUrls = useActiveListUrls()
- const activeTokens = useCombinedTokenMapFromUrls(activeListUrls)
- return activeTokens
-}
-
// list of tokens not supported on interface for various reasons, used to show warnings and prevent swaps and adds
export function useUnsupportedTokenList(): TokenAddressMap {
- // get hard-coded broken tokens
- const brokenListMap = useMemo(() => tokensToChainTokenMap(BROKEN_LIST), [])
-
- // get hard-coded list of unsupported tokens
- const localUnsupportedListMap = useMemo(() => tokensToChainTokenMap(UNSUPPORTED_TOKEN_LIST), [])
-
- // get dynamic list of unsupported tokens
- const loadedUnsupportedListMap = useCombinedTokenMapFromUrls(UNSUPPORTED_LIST_URLS[1])
-
- // format into one token address map
- return useMemo(
- () => combineMaps(brokenListMap, combineMaps(localUnsupportedListMap, loadedUnsupportedListMap)),
- [brokenListMap, localUnsupportedListMap, loadedUnsupportedListMap]
- )
+ return useCombinedTokenMapFromUrls(UNSUPPORTED_LIST_URLS[1])
}
export function useTokensListFromUrls(urls: string[] | undefined): TokenInfo[] {
@@ -127,16 +95,12 @@ export function useTokensListFromUrls(urls: string[] | undefined): TokenInfo[] {
return useMemo(() => {
if (!urls) return []
- return (
- urls
- .slice()
- // sort by priority so top priority goes last
- .sort(sortByListPriority)
- .map((url) => {
- return lists?.[url]?.current?.tokens || []
- })
- .flat()
- )
+ return urls
+ .slice()
+ .map((url) => {
+ return lists?.[url]?.current?.tokens || []
+ })
+ .flat()
}, [lists, urls])
}
diff --git a/apps/cowswap-frontend/src/legacy/state/lists/reducer.test.ts b/apps/cowswap-frontend/src/legacy/state/lists/reducer.test.ts
index 8fe6778621..ce5824454c 100644
--- a/apps/cowswap-frontend/src/legacy/state/lists/reducer.test.ts
+++ b/apps/cowswap-frontend/src/legacy/state/lists/reducer.test.ts
@@ -1,11 +1,12 @@
+import { DEFAULT_ACTIVE_LIST_URLS_BY_NETWORK, DEFAULT_LIST_OF_LISTS_BY_NETWORK } from '@cowprotocol/common-const'
import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
import { createStore, Store } from 'redux'
-import { DEFAULT_ACTIVE_LIST_URLS_BY_NETWORK, DEFAULT_LIST_OF_LISTS_BY_NETWORK } from 'legacy/constants/lists'
-import { updateVersion } from 'legacy/state/global/actions'
-import { fetchTokenList, acceptListUpdate, addList, removeList, enableList } from 'legacy/state/lists/actions'
-import reducer, { ListsStateByNetwork } from 'legacy/state/lists/reducer'
+import { fetchTokenList, acceptListUpdate, addList, removeList, enableList } from './actions'
+import reducer, { ListsStateByNetwork } from './reducer'
+
+import { updateVersion } from '../global/actions'
const DEFAULT_LIST_OF_LISTS = DEFAULT_LIST_OF_LISTS_BY_NETWORK[ChainId.MAINNET]
diff --git a/apps/cowswap-frontend/src/legacy/state/lists/reducer.ts b/apps/cowswap-frontend/src/legacy/state/lists/reducer.ts
index 26194307d5..e1a59f405c 100644
--- a/apps/cowswap-frontend/src/legacy/state/lists/reducer.ts
+++ b/apps/cowswap-frontend/src/legacy/state/lists/reducer.ts
@@ -1,16 +1,14 @@
-import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
-import { getVersionUpgrade, TokenList, VersionUpgrade } from '@uniswap/token-lists'
-
-import { createReducer } from '@reduxjs/toolkit'
-
import {
DEFAULT_ACTIVE_LIST_URLS_BY_NETWORK,
DEFAULT_LIST_OF_LISTS_BY_NETWORK,
DEFAULT_NETWORK_FOR_LISTS,
UNSUPPORTED_LIST_URLS,
-} from 'legacy/constants/lists'
-import { updateVersion } from 'legacy/state/global/actions'
-import { getChainIdValues } from 'legacy/utils/misc'
+} from '@cowprotocol/common-const'
+import { getChainIdValues } from '@cowprotocol/common-utils'
+import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
+import { getVersionUpgrade, TokenList, VersionUpgrade } from '@uniswap/token-lists'
+
+import { createReducer } from '@reduxjs/toolkit'
import { UnsupportedToken } from 'api/gnosisProtocol'
@@ -25,6 +23,8 @@ import {
removeList,
} from './actions'
+import { updateVersion } from '../global/actions'
+
export interface ListsState {
readonly byUrl: {
readonly [url: string]: {
diff --git a/apps/cowswap-frontend/src/legacy/state/lists/wrappedTokenInfo.ts b/apps/cowswap-frontend/src/legacy/state/lists/wrappedTokenInfo.ts
index 6ca86f5fd9..3e446c5866 100644
--- a/apps/cowswap-frontend/src/legacy/state/lists/wrappedTokenInfo.ts
+++ b/apps/cowswap-frontend/src/legacy/state/lists/wrappedTokenInfo.ts
@@ -1,11 +1,11 @@
+import { isAddress } from '@cowprotocol/common-utils'
import { Currency, Token } from '@uniswap/sdk-core'
import { Tags, TokenInfo, TokenList } from '@uniswap/token-lists'
-import { isAddress } from '../../utils'
-
type TagDetails = Tags[keyof Tags]
export interface TagInfo extends TagDetails {
id: string
+ icon?: string
}
/**
* Token instances created from token info on a token list.
diff --git a/apps/cowswap-frontend/src/legacy/state/logs/hooks.ts b/apps/cowswap-frontend/src/legacy/state/logs/hooks.ts
index f73ebd1b6b..1719211d3b 100644
--- a/apps/cowswap-frontend/src/legacy/state/logs/hooks.ts
+++ b/apps/cowswap-frontend/src/legacy/state/logs/hooks.ts
@@ -1,11 +1,9 @@
import { useEffect, useMemo } from 'react'
+import { useBlockNumber } from '@cowprotocol/common-hooks'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Filter } from '@ethersproject/providers'
-import { useWalletInfo } from 'modules/wallet'
-
-import useBlockNumber from 'lib/hooks/useBlockNumber'
-
import { addListener, removeListener } from './slice'
import { filterToKey, isHistoricalLog, Log } from './utils'
diff --git a/apps/cowswap-frontend/src/legacy/state/multicall.tsx b/apps/cowswap-frontend/src/legacy/state/multicall.tsx
new file mode 100644
index 0000000000..b4cb8342c2
--- /dev/null
+++ b/apps/cowswap-frontend/src/legacy/state/multicall.tsx
@@ -0,0 +1,13 @@
+import { useInterfaceMulticall, useBlockNumber } from '@cowprotocol/common-hooks'
+import { createMulticall } from '@uniswap/redux-multicall'
+import { useWeb3React } from '@web3-react/core'
+
+export const multicall = createMulticall()
+
+export function MulticallUpdater() {
+ const { chainId } = useWeb3React()
+ const latestBlockNumber = useBlockNumber()
+ const contract = useInterfaceMulticall()
+
+ return
+}
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/actions.ts b/apps/cowswap-frontend/src/legacy/state/orders/actions.ts
index c9696db9b8..162055f7c8 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/actions.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/actions.ts
@@ -5,10 +5,10 @@ import { Token } from '@uniswap/sdk-core'
import { createAction } from '@reduxjs/toolkit'
-import { SerializedToken } from 'legacy/state/user/types'
-
import { ComposableCowInfo } from 'common/types'
+import { SerializedToken } from '../user/types'
+
export enum OrderStatus {
PENDING = 'pending',
PRESIGNATURE_PENDING = 'presignaturePending',
@@ -59,6 +59,10 @@ export interface BaseOrder extends Omit {
// Additional information from the order available in the API
apiAdditionalInfo?: OrderInfoApi
+ // De-normalizing it as this is known at order placement time as `appData`,
+ // but when returned from the api is replaced with the `appDataHash`
+ // See this order response for example https://barn.api.cow.fi/goerli/api/v1/orders/0xc170856a42f38ba07a7af3ea8f299ea724ec0aa22445eb741cbad7f9dd4fcda05b0abe214ab7875562adee331deff0fe1912fe4265269bb1
+ fullAppData?: EnrichedOrder['fullAppData']
// Wallet specific
presignGnosisSafeTxHash?: string // Gnosis Safe tx
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/buildCancellationPopupSummary.tsx b/apps/cowswap-frontend/src/legacy/state/orders/buildCancellationPopupSummary.tsx
index da99578d51..98ac575f44 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/buildCancellationPopupSummary.tsx
+++ b/apps/cowswap-frontend/src/legacy/state/orders/buildCancellationPopupSummary.tsx
@@ -1,9 +1,13 @@
-import styled from 'styled-components/macro'
-
-import { CancellationSummary } from 'modules/account/containers/Transaction/styled'
+import { shortenOrderId } from '@cowprotocol/common-utils'
-import { shortenOrderId } from '../../utils'
+import styled from 'styled-components/macro'
+const CancellationSummary = styled.span`
+ padding: 12px;
+ margin: 0;
+ border-radius: 6px;
+ background: ${({ theme }) => theme.bg1};
+`
// Moved this function to separate file to avoid curcular deps
const Wrapper = styled.div`
diff --git a/apps/cowswap-frontend/src/modules/orders/utils/flatOrdersStateNetwork.ts b/apps/cowswap-frontend/src/legacy/state/orders/flatOrdersStateNetwork.ts
similarity index 78%
rename from apps/cowswap-frontend/src/modules/orders/utils/flatOrdersStateNetwork.ts
rename to apps/cowswap-frontend/src/legacy/state/orders/flatOrdersStateNetwork.ts
index 32de96257a..04cb870963 100644
--- a/apps/cowswap-frontend/src/modules/orders/utils/flatOrdersStateNetwork.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/flatOrdersStateNetwork.ts
@@ -1,4 +1,4 @@
-import { OrdersStateNetwork, PartialOrdersMap } from 'legacy/state/orders/reducer'
+import { OrdersStateNetwork, PartialOrdersMap } from './reducer'
export function flatOrdersStateNetwork(state: OrdersStateNetwork): PartialOrdersMap {
return {
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/helpers.tsx b/apps/cowswap-frontend/src/legacy/state/orders/helpers.tsx
index 56e2a876f5..589541102e 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/helpers.tsx
+++ b/apps/cowswap-frontend/src/legacy/state/orders/helpers.tsx
@@ -1,4 +1,4 @@
-import { BlockExplorerLinkType, formatOrderId } from 'legacy/utils'
+import { BlockExplorerLinkType, formatOrderId } from '@cowprotocol/common-utils'
import { OrderStatus } from './actions'
import { OrderObject, OrdersStateNetwork } from './reducer'
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/hooks.ts b/apps/cowswap-frontend/src/legacy/state/orders/hooks.ts
index 93fa1f58fc..e31c65b69d 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/hooks.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/hooks.ts
@@ -1,16 +1,10 @@
import { useCallback, useMemo } from 'react'
+import { isTruthy } from '@cowprotocol/common-utils'
import { OrderClass, SupportedChainId } from '@cowprotocol/cow-sdk'
import { useDispatch, useSelector } from 'react-redux'
-import { AppDispatch, AppState } from 'legacy/state'
-import { isOrderExpired, partialOrderUpdate } from 'legacy/state/orders/utils'
-import { deserializeToken, serializeToken } from 'legacy/state/user/hooks'
-import { isTruthy } from 'legacy/utils/misc'
-
-import { flatOrdersStateNetwork } from 'modules/orders/utils/flatOrdersStateNetwork'
-
import { OrderID } from 'api/gnosisProtocol'
import {
@@ -35,6 +29,7 @@ import {
UpdatePresignGnosisSafeTxParams,
clearOrdersStorage,
} from './actions'
+import { flatOrdersStateNetwork } from './flatOrdersStateNetwork'
import {
getDefaultNetworkState,
ORDER_LIST_KEYS,
@@ -46,6 +41,10 @@ import {
PartialOrdersMap,
V2OrderObject,
} from './reducer'
+import { isOrderExpired, partialOrderUpdate } from './utils'
+
+import { AppDispatch, AppState } from '../index'
+import { deserializeToken, serializeToken } from '../user/hooks'
export interface AddOrUpdateUnserialisedOrdersParams extends Omit {
orders: Order[]
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/appziMiddleware.test.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/appziMiddleware.test.ts
index 8e9c366034..d47f88132f 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/appziMiddleware.test.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/appziMiddleware.test.ts
@@ -1,16 +1,15 @@
+import { isOrderInPendingTooLong, openNpsAppziSometimes } from '@cowprotocol/common-utils'
import { OrderClass } from '@cowprotocol/cow-sdk'
import { AnyAction, Dispatch, MiddlewareAPI } from 'redux'
import { instance, mock, resetCalls, when } from 'ts-mockito'
-import { isOrderInPendingTooLong, openNpsAppziSometimes } from 'legacy/utils/appzi'
-
import { appziMiddleware } from './appziMiddleware'
import { AppState } from '../../index'
import { getOrderByIdFromState } from '../helpers'
-jest.mock('legacy/utils/appzi')
+jest.mock('@cowprotocol/common-utils')
jest.mock('../helpers', () => {
return {
...jest.requireActual('../helpers'),
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/appziMiddleware.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/appziMiddleware.ts
index a073cd9e64..69a95df740 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/appziMiddleware.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/appziMiddleware.ts
@@ -1,11 +1,14 @@
+import {
+ getExplorerOrderLink,
+ isOrderInPendingTooLong,
+ openNpsAppziSometimes,
+ timeSinceInSeconds,
+} from '@cowprotocol/common-utils'
import { OrderClass, SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
import { isAnyOf } from '@reduxjs/toolkit'
import { AnyAction, Dispatch, Middleware, MiddlewareAPI } from 'redux'
-import { timeSinceInSeconds } from '../../../../utils/time'
-import { isOrderInPendingTooLong, openNpsAppziSometimes } from '../../../utils/appzi'
-import { getExplorerOrderLink } from '../../../utils/explorer'
import { AppState } from '../../index'
import * as OrderActions from '../actions'
import { getOrderByIdFromState } from '../helpers'
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchCancelOrdersPopup.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchCancelOrdersPopup.ts
index 9686978e14..44f701cbec 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchCancelOrdersPopup.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchCancelOrdersPopup.ts
@@ -1,6 +1,7 @@
+import { orderAnalytics } from '@cowprotocol/analytics'
+
import { Dispatch, MiddlewareAPI } from 'redux'
-import { orderAnalytics } from '../../../components/analytics'
import { addPopup, AddPopupPayload } from '../../application/reducer'
import { AppState } from '../../index'
import { BaseOrder } from '../actions'
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchExpireOrdersPopup.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchExpireOrdersPopup.ts
index 55ed23ab6c..ca49e806de 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchExpireOrdersPopup.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchExpireOrdersPopup.ts
@@ -1,6 +1,7 @@
+import { orderAnalytics } from '@cowprotocol/analytics'
+
import { Dispatch, MiddlewareAPI } from 'redux'
-import { orderAnalytics } from '../../../components/analytics'
import { addPopup } from '../../application/reducer'
import { AppState } from '../../index'
import { ExpireOrdersBatchParams } from '../actions'
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchFulfillOrderPopup.tsx b/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchFulfillOrderPopup.tsx
index c9192cb58c..d57af681b8 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchFulfillOrderPopup.tsx
+++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchFulfillOrderPopup.tsx
@@ -1,8 +1,8 @@
+import { orderAnalytics } from '@cowprotocol/analytics'
+
import { MiddlewareAPI } from '@reduxjs/toolkit'
import { Dispatch } from 'redux'
-import { orderAnalytics } from 'legacy/components/analytics'
-
import { ExecutedSummary } from 'common/pure/ExecutedSummary'
import { parseOrder } from 'utils/orderUtils/parseOrder'
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchPresignOrdersPopup.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchPresignOrdersPopup.ts
index b8c3bcb04c..5e9ccdc52c 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchPresignOrdersPopup.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchPresignOrdersPopup.ts
@@ -1,6 +1,7 @@
+import { orderAnalytics } from '@cowprotocol/analytics'
+
import { Dispatch, MiddlewareAPI } from 'redux'
-import { orderAnalytics } from '../../../components/analytics'
import { addPopup } from '../../application/reducer'
import { AppState } from '../../index'
import { PresignedOrdersParams } from '../actions'
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/index.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/index.ts
index 6c4190f6f5..e4e8161399 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/index.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/index.ts
@@ -1,4 +1,3 @@
export { popupMiddleware } from './popupMiddleware'
export { soundMiddleware } from './soundMiddleware'
export { appziMiddleware } from './appziMiddleware'
-export { composableOrdersPopupMiddleware } from './composableOrdersPopupMiddleware'
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/pendingOrderPopup.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/pendingOrderPopup.ts
index 208c437c45..10e801ef6d 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/pendingOrderPopup.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/pendingOrderPopup.ts
@@ -1,7 +1,8 @@
+import { orderAnalytics } from '@cowprotocol/analytics'
+
import { MiddlewareAPI } from '@reduxjs/toolkit'
import { Dispatch } from 'redux'
-import { orderAnalytics } from '../../../components/analytics'
import { addPopup, AddPopupPayload } from '../../application/reducer'
import { AppState } from '../../index'
import { AddPendingOrderParams } from '../actions'
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/popupMiddleware.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/popupMiddleware.ts
index b90d059b41..c007d14c4d 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/popupMiddleware.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/popupMiddleware.ts
@@ -1,8 +1,8 @@
+import { isTruthy } from '@cowprotocol/common-utils'
+
import { isAnyOf } from '@reduxjs/toolkit'
import { Middleware } from 'redux'
-import { isTruthy } from 'legacy/utils/misc'
-
import { batchCancelOrdersPopup } from './batchCancelOrdersPopup'
import { batchExpireOrdersPopup } from './batchExpireOrdersPopup'
import { batchFulfillOrderPopup } from './batchFulfillOrderPopup'
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.test.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.test.ts
index 87a094ec6e..76ba9c1439 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.test.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.test.ts
@@ -1,8 +1,8 @@
+import { getCowSoundError, getCowSoundSend, getCowSoundSuccess } from '@cowprotocol/common-utils'
+
import { AnyAction, Dispatch, MiddlewareAPI } from 'redux'
import { instance, mock, resetCalls, when } from 'ts-mockito'
-import { getCowSoundError, getCowSoundSend, getCowSoundSuccess } from 'legacy/utils/sound'
-
import { soundMiddleware } from './soundMiddleware'
import { AppState } from '../../index'
@@ -11,7 +11,7 @@ const mockStore = mock>()
const nextMock = jest.fn()
const actionMock = mock()
-jest.mock('legacy/utils/sound')
+jest.mock('@cowprotocol/common-utils')
describe('soundMiddleware', () => {
beforeEach(() => {
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.ts
index 5a80d95192..23eb9683de 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.ts
@@ -1,8 +1,9 @@
// On each Pending, Expired, Fulfilled order action a corresponding sound is dispatched
+import { getCowSoundError, getCowSoundSend, getCowSoundSuccess } from '@cowprotocol/common-utils'
+
import { isAnyOf } from '@reduxjs/toolkit'
import { AnyAction, Dispatch, Middleware, MiddlewareAPI } from 'redux'
-import { getCowSoundError, getCowSoundSend, getCowSoundSuccess } from '../../../utils/sound'
import { addPopup } from '../../application/reducer'
import { AppState } from '../../index'
import { AddPendingOrderParams, BatchOrdersUpdateParams, UpdateOrderParams } from '../actions'
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/updateOrderPopup.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/updateOrderPopup.ts
index ec774ddeb2..8d86c9828f 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/updateOrderPopup.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/updateOrderPopup.ts
@@ -1,11 +1,10 @@
+import { orderAnalytics } from '@cowprotocol/analytics'
+import { BlockExplorerLinkType } from '@cowprotocol/common-utils'
import { OrderClass } from '@cowprotocol/cow-sdk'
import { MiddlewareAPI } from '@reduxjs/toolkit'
import { Dispatch } from 'redux'
-import { BlockExplorerLinkType } from 'legacy/utils'
-
-import { orderAnalytics } from '../../../components/analytics'
import { addPopup } from '../../application/reducer'
import { AppState } from '../../index'
import { UpdateOrderParams } from '../actions'
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/mocks.ts b/apps/cowswap-frontend/src/legacy/state/orders/mocks.ts
index 53bfe946f0..229a3b7894 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/mocks.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/mocks.ts
@@ -1,12 +1,12 @@
+import { RADIX_DECIMAL } from '@cowprotocol/common-const'
import { OrderClass, OrderKind } from '@cowprotocol/cow-sdk'
import { Token } from '@uniswap/sdk-core'
-import { RADIX_DECIMAL } from 'legacy/constants'
-import store from 'legacy/state'
-import { serializeToken } from 'legacy/state/user/hooks'
-
import { Order, OrderStatus, SerializedOrder, addPendingOrder, AddPendingOrderParams } from './actions'
+import { cowSwapStore } from '../index'
+import { serializeToken } from '../user/hooks'
+
const randomNumberInRange = (min: number, max: number) => {
return Math.random() * (max - min) + min
}
@@ -122,6 +122,6 @@ export const mockOrderDispatches = {
},
}
- store.dispatch(addPendingOrder(actionParams))
+ cowSwapStore.dispatch(addPendingOrder(actionParams))
},
}
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/priceUtils.ts b/apps/cowswap-frontend/src/legacy/state/orders/priceUtils.ts
index 4c06b8fca2..4c01fee136 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/priceUtils.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/priceUtils.ts
@@ -1,8 +1,8 @@
// Copied from @cowprotocol/cow-js
-import { BigNumber } from 'bignumber.js'
+import { DEFAULT_DECIMALS } from '@cowprotocol/common-const'
-import { DEFAULT_DECIMALS } from 'legacy/constants'
+import { BigNumber } from 'bignumber.js'
interface PriceTokenInfo {
amount: BigNumber | string
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/reducer.ts b/apps/cowswap-frontend/src/legacy/state/orders/reducer.ts
index ad959f0526..26d7908258 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/reducer.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/reducer.ts
@@ -3,8 +3,6 @@ import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
import { createReducer, PayloadAction } from '@reduxjs/toolkit'
import { Writable } from 'types'
-import { flatOrdersStateNetwork } from 'modules/orders/utils/flatOrdersStateNetwork'
-
import { OrderID } from 'api/gnosisProtocol'
import { getIsComposableCowDiscreteOrder } from 'utils/orderUtils/getIsComposableCowDiscreteOrder'
import { getIsComposableCowParentOrder } from 'utils/orderUtils/getIsComposableCowParentOrder'
@@ -35,6 +33,7 @@ import {
CONFIRMED_STATES,
} from './actions'
import { ContractDeploymentBlocks, MAX_ITEMS_PER_STATUS } from './consts'
+import { flatOrdersStateNetwork } from './flatOrdersStateNetwork'
export interface OrderObject {
id: OrderID
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/utils.test.ts b/apps/cowswap-frontend/src/legacy/state/orders/utils.test.ts
index f2335c134d..9cef5fc005 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/utils.test.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/utils.test.ts
@@ -1,10 +1,9 @@
+import { USDC_MAINNET as USDC, USDT } from '@cowprotocol/common-const'
import { OrderKind, OrderStatus, SigningScheme } from '@cowprotocol/cow-sdk'
import { Price } from '@uniswap/sdk-core'
import ms from 'ms.macro'
-import { USDC_MAINNET as USDC, USDT } from 'legacy/constants/tokens'
-
import { generateOrder } from './mocks'
import { classifyOrder, getOrderMarketPrice, isOrderUnfillable } from './utils'
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/utils.ts b/apps/cowswap-frontend/src/legacy/state/orders/utils.ts
index 7c0fde7b4a..3461931b06 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/utils.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/utils.ts
@@ -1,21 +1,20 @@
+import { ONE_HUNDRED_PERCENT, PENDING_ORDERS_BUFFER, ZERO_FRACTION } from '@cowprotocol/common-const'
+import { buildPriceFromCurrencyAmounts } from '@cowprotocol/common-utils'
import { EnrichedOrder, OrderClass, OrderKind, OrderStatus } from '@cowprotocol/cow-sdk'
import { Currency, CurrencyAmount, Price } from '@uniswap/sdk-core'
import JSBI from 'jsbi'
-import { PENDING_ORDERS_BUFFER, ZERO_FRACTION } from 'legacy/constants'
-import { ONE_HUNDRED_PERCENT } from 'legacy/constants/misc'
-import { AppDispatch } from 'legacy/state'
-import { Order, updateOrder, UpdateOrderParams as UpdateOrderParamsAction } from 'legacy/state/orders/actions'
-import { OUT_OF_MARKET_PRICE_DELTA_PERCENTAGE } from 'legacy/state/orders/consts'
-import { UpdateOrderParams } from 'legacy/state/orders/hooks'
-import { serializeToken } from 'legacy/state/user/hooks'
-
-import { buildPriceFromCurrencyAmounts } from 'modules/utils/orderUtils/buildPriceFromCurrencyAmounts'
-
import { getIsComposableCowParentOrder } from 'utils/orderUtils/getIsComposableCowParentOrder'
import { getOrderSurplus } from 'utils/orderUtils/getOrderSurplus'
+import { Order, updateOrder, UpdateOrderParams as UpdateOrderParamsAction } from './actions'
+import { OUT_OF_MARKET_PRICE_DELTA_PERCENTAGE } from './consts'
+import { UpdateOrderParams } from './hooks'
+
+import { AppDispatch } from '../index'
+import { serializeToken } from '../user/hooks'
+
export type OrderTransitionStatus =
| 'unknown'
| 'fulfilled'
diff --git a/apps/cowswap-frontend/src/legacy/state/price/actions.ts b/apps/cowswap-frontend/src/legacy/state/price/actions.ts
index 0d4d8bfe8e..10457c4fcf 100644
--- a/apps/cowswap-frontend/src/legacy/state/price/actions.ts
+++ b/apps/cowswap-frontend/src/legacy/state/price/actions.ts
@@ -2,9 +2,8 @@ import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
import { createAction } from '@reduxjs/toolkit'
-import { LegacyFeeQuoteParams } from 'api/gnosisProtocol/legacy/types'
-
import { QuoteInformationObject } from './reducer'
+import { LegacyFeeQuoteParams } from './types'
export type UpdateQuoteParams = Omit
diff --git a/apps/cowswap-frontend/src/legacy/state/price/hooks.ts b/apps/cowswap-frontend/src/legacy/state/price/hooks.ts
index f8b611598c..798c0e7bd9 100644
--- a/apps/cowswap-frontend/src/legacy/state/price/hooks.ts
+++ b/apps/cowswap-frontend/src/legacy/state/price/hooks.ts
@@ -4,11 +4,6 @@ import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
import { useDispatch, useSelector } from 'react-redux'
-import { AppDispatch, AppState } from 'legacy/state'
-import { useSwapState } from 'legacy/state/swap/hooks'
-
-import { useWalletInfo } from 'modules/wallet'
-
import {
updateQuote,
UpdateQuoteParams,
@@ -22,6 +17,8 @@ import {
} from './actions'
import { QuoteInformationObject, QuotesMap } from './reducer'
+import { AppDispatch, AppState } from '../index'
+
type GetNewQuoteCallback = (params: GetQuoteParams) => void
type RefreshQuoteCallback = (params: RefreshQuoteParams) => void
type AddPriceCallback = (params: UpdateQuoteParams) => void
@@ -77,16 +74,6 @@ export const useGetQuoteAndStatus = (params: QuoteParams): UseGetQuoteAndStatus
return { quote, isGettingNewQuote, isRefreshingQuote }
}
-// syntactic sugar for not needing to pass swapstate
-export function useIsQuoteRefreshing() {
- const { chainId } = useWalletInfo()
- const {
- INPUT: { currencyId },
- } = useSwapState()
- const { isRefreshingQuote } = useGetQuoteAndStatus({ token: currencyId, chainId })
- return isRefreshingQuote
-}
-
export const useGetNewQuote = (): GetNewQuoteCallback => {
const dispatch = useDispatch()
return useCallback((params: GetQuoteParams) => dispatch(getNewQuote(params)), [dispatch])
diff --git a/apps/cowswap-frontend/src/legacy/state/price/middleware.ts b/apps/cowswap-frontend/src/legacy/state/price/middleware.ts
index 7632c2ba63..43cc24900d 100644
--- a/apps/cowswap-frontend/src/legacy/state/price/middleware.ts
+++ b/apps/cowswap-frontend/src/legacy/state/price/middleware.ts
@@ -1,10 +1,11 @@
-import { Middleware, isAnyOf } from '@reduxjs/toolkit'
+import { initialPriceLoadAnalytics } from '@cowprotocol/analytics'
-import { initialPriceLoadAnalytics } from 'legacy/components/analytics'
-import { AppState } from 'legacy/state'
+import { Middleware, isAnyOf } from '@reduxjs/toolkit'
import * as PriceActions from './actions'
+import { AppState } from '../index'
+
const isUpdateQuoteAction = isAnyOf(PriceActions.updateQuote)
export const priceMiddleware: Middleware, AppState> = (store) => (next) => (action) => {
diff --git a/apps/cowswap-frontend/src/legacy/state/price/reducer.ts b/apps/cowswap-frontend/src/legacy/state/price/reducer.ts
index 73f9c2bf8b..1751d9522c 100644
--- a/apps/cowswap-frontend/src/legacy/state/price/reducer.ts
+++ b/apps/cowswap-frontend/src/legacy/state/price/reducer.ts
@@ -4,16 +4,17 @@ import { OrderKind } from '@cowprotocol/cow-sdk'
import { createReducer, PayloadAction, current } from '@reduxjs/toolkit'
import { FeeInformation, PriceInformation } from 'types'
-import { Writable } from 'legacy/types'
-
-import { LegacyFeeQuoteParams } from 'api/gnosisProtocol/legacy/types'
-
import { updateQuote, setQuoteError, getNewQuote, refreshQuote, QuoteError } from './actions'
+import { LegacyFeeQuoteParams } from './types'
import { PrefillStateRequired } from '../orders/reducer'
// API Doc: https://protocol-rinkeby.dev.gnosisdev.com/api
+type Writable = {
+ -readonly [K in keyof T]: T[K]
+}
+
export const EMPTY_FEE = {
feeAsCurrency: undefined,
amount: '0',
diff --git a/apps/cowswap-frontend/src/api/gnosisProtocol/legacy/types.ts b/apps/cowswap-frontend/src/legacy/state/price/types.ts
similarity index 77%
rename from apps/cowswap-frontend/src/api/gnosisProtocol/legacy/types.ts
rename to apps/cowswap-frontend/src/legacy/state/price/types.ts
index 59f74cd80c..49094cc816 100644
--- a/apps/cowswap-frontend/src/api/gnosisProtocol/legacy/types.ts
+++ b/apps/cowswap-frontend/src/legacy/state/price/types.ts
@@ -1,9 +1,17 @@
-import { SupportedChainId as ChainId, PriceQuality } from '@cowprotocol/cow-sdk'
-import { EnrichedOrder } from '@cowprotocol/cow-sdk'
+import { AppData, AppDataHash, EnrichedOrder, PriceQuality, SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
-import { FeeInformation, PriceInformation } from 'types'
+type GpPriceStrategy = 'COWSWAP' | 'LEGACY'
-import { GpPriceStrategy } from 'legacy/state/gas/atoms'
+interface PriceInformation {
+ token: string
+ amount: string | null
+ quoteId?: number
+}
+
+export interface FeeInformation {
+ expirationDate: string
+ amount: string
+}
interface FeeQuoteParams extends Pick {
amount: string
@@ -38,6 +46,8 @@ export interface LegacyFeeQuoteParams extends FeeQuoteParams {
priceQuality: PriceQuality
isBestQuote?: boolean
isEthFlow: boolean
+ appData?: AppData
+ appDataHash?: AppDataHash
}
export type LegacyPriceQuoteParams = Omit & {
diff --git a/apps/cowswap-frontend/src/legacy/state/profile/hooks.tsx b/apps/cowswap-frontend/src/legacy/state/profile/hooks.tsx
index 07704d829e..c8d83b3c2b 100644
--- a/apps/cowswap-frontend/src/legacy/state/profile/hooks.tsx
+++ b/apps/cowswap-frontend/src/legacy/state/profile/hooks.tsx
@@ -1,9 +1,9 @@
import { useCallback } from 'react'
-import { useAppDispatch, useAppSelector } from 'legacy/state/hooks'
-
import { closeAnnouncement } from './actions'
+import { useAppDispatch, useAppSelector } from '../hooks'
+
export function useAnnouncementVisible(contentHash?: string): boolean {
const announcementVisible = useAppSelector((state) => state.profile.announcementVisible)
diff --git a/apps/cowswap-frontend/src/legacy/state/swap/TradeGp.ts b/apps/cowswap-frontend/src/legacy/state/swap/TradeGp.ts
index 66ea956c4d..d98caa57cd 100644
--- a/apps/cowswap-frontend/src/legacy/state/swap/TradeGp.ts
+++ b/apps/cowswap-frontend/src/legacy/state/swap/TradeGp.ts
@@ -1,9 +1,17 @@
-import { CurrencyAmount, Currency, TradeType, Price, Percent } from '@uniswap/sdk-core'
+import { ONE_FRACTION } from '@cowprotocol/common-const'
+import { CanonicalMarketParams, getCanonicalMarket } from '@cowprotocol/common-utils'
+import { Currency, CurrencyAmount, Percent, Price, TradeType } from '@uniswap/sdk-core'
-import { FeeInformation, PriceInformation } from 'types'
+interface PriceInformation {
+ token: string
+ amount: string | null
+ quoteId?: number
+}
-import { ONE_FRACTION } from 'legacy/constants/misc'
-import { CanonicalMarketParams, getCanonicalMarket } from 'legacy/utils/misc'
+interface FeeInformation {
+ expirationDate: string
+ amount: string
+}
export type FeeForTrade = { feeAsCurrency: CurrencyAmount } & Pick
@@ -86,7 +94,7 @@ export default class TradeGp {
* The output amount for the trade assuming no slippage.
*/
readonly outputAmount: CurrencyAmount
- readonly outputAmountWithoutFee?: CurrencyAmount
+ readonly outputAmountWithoutFee: CurrencyAmount
/**
* Trade fee
*/
diff --git a/apps/cowswap-frontend/src/legacy/state/swap/actions.ts b/apps/cowswap-frontend/src/legacy/state/swap/actions.ts
index 200de24486..8c0b06d0c9 100644
--- a/apps/cowswap-frontend/src/legacy/state/swap/actions.ts
+++ b/apps/cowswap-frontend/src/legacy/state/swap/actions.ts
@@ -1,9 +1,6 @@
import { createAction } from '@reduxjs/toolkit'
-export enum Field {
- INPUT = 'INPUT',
- OUTPUT = 'OUTPUT',
-}
+import { Field } from '../types'
export interface ReplaceOnlyTradeRawStatePayload {
readonly chainId: number | null
diff --git a/apps/cowswap-frontend/src/legacy/state/swap/extension.ts b/apps/cowswap-frontend/src/legacy/state/swap/extension.ts
index d6cfdf4f0b..15d82fc17d 100644
--- a/apps/cowswap-frontend/src/legacy/state/swap/extension.ts
+++ b/apps/cowswap-frontend/src/legacy/state/swap/extension.ts
@@ -3,10 +3,10 @@ import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core'
import JSBI from 'jsbi'
-import { QuoteInformationObject } from 'legacy/state/price/reducer'
-
import TradeGp, { _constructTradePrice } from './TradeGp'
+import { QuoteInformationObject } from '../price/reducer'
+
interface TradeParams {
parsedAmount?: CurrencyAmount
inputCurrency?: Currency | null
diff --git a/apps/cowswap-frontend/src/legacy/state/swap/reducer.ts b/apps/cowswap-frontend/src/legacy/state/swap/reducer.ts
index 994ea43f08..6b7b0fe0a7 100644
--- a/apps/cowswap-frontend/src/legacy/state/swap/reducer.ts
+++ b/apps/cowswap-frontend/src/legacy/state/swap/reducer.ts
@@ -1,12 +1,11 @@
+import { NATIVE_CURRENCY_BUY_TOKEN, WRAPPED_NATIVE_CURRENCY } from '@cowprotocol/common-const'
+import { parsedQueryString } from '@cowprotocol/common-hooks'
+import { getIsNativeToken, getIsWrapOrUnwrap } from '@cowprotocol/common-utils'
import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
import { createReducer } from '@reduxjs/toolkit'
-import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants'
-import { WRAPPED_NATIVE_CURRENCY } from 'legacy/constants/tokens'
-import { parsedQueryString } from 'legacy/hooks/useParsedQueryString'
import {
- Field,
replaceOnlyTradeRawState,
replaceSwapState,
selectCurrency,
@@ -14,13 +13,11 @@ import {
setRecipientAddress,
switchCurrencies,
typeInput,
-} from 'legacy/state/swap/actions'
-
-import { getIsNativeToken } from 'utils/getIsNativeToken'
-import { getIsWrapOrUnwrap } from 'utils/getIsWrapOrUnwrap'
-
+} from './actions'
import { queryParametersToSwapState } from './utils'
+import { Field } from '../types'
+
export interface SwapState {
// Mod: added chainId
chainId: number | null
diff --git a/apps/cowswap-frontend/src/legacy/state/swap/trade.test.ts b/apps/cowswap-frontend/src/legacy/state/swap/trade.test.ts
index 2e1e27ef02..e0209d8d12 100644
--- a/apps/cowswap-frontend/src/legacy/state/swap/trade.test.ts
+++ b/apps/cowswap-frontend/src/legacy/state/swap/trade.test.ts
@@ -1,11 +1,9 @@
+import { DEFAULT_PRECISION, LONG_PRECISION, WRAPPED_NATIVE_CURRENCY as WETH } from '@cowprotocol/common-const'
import { OrderKind } from '@cowprotocol/cow-sdk'
import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
import { parseUnits } from '@ethersproject/units'
import { CurrencyAmount, Fraction, Price, Currency, Percent, Token, TradeType } from '@uniswap/sdk-core'
-import { DEFAULT_PRECISION, LONG_PRECISION } from 'legacy/constants'
-import { WRAPPED_NATIVE_CURRENCY as WETH } from 'legacy/constants/tokens'
-
import { stringToCurrency } from './extension'
import Trade, { _constructTradePrice } from './TradeGp'
import TradeGp from './TradeGp'
diff --git a/apps/cowswap-frontend/src/legacy/state/swap/utils.ts b/apps/cowswap-frontend/src/legacy/state/swap/utils.ts
index 503ecd6f26..43bdd3004b 100644
--- a/apps/cowswap-frontend/src/legacy/state/swap/utils.ts
+++ b/apps/cowswap-frontend/src/legacy/state/swap/utils.ts
@@ -1,14 +1,14 @@
+import { TOKEN_SHORTHANDS, WRAPPED_NATIVE_CURRENCY } from '@cowprotocol/common-const'
+import { isAddress } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { Currency } from '@uniswap/sdk-core'
import { ParsedQs } from 'qs'
-import { TOKEN_SHORTHANDS, WRAPPED_NATIVE_CURRENCY } from 'legacy/constants/tokens'
-import { isAddress } from 'legacy/utils'
-
-import { Field } from './actions'
import { SwapState } from './reducer'
+import { Field } from '../types'
+
export function isWrappingTrade(
sellCurrency: Currency | null | undefined,
buyCurrency: Currency | null | undefined,
diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/types.ts b/apps/cowswap-frontend/src/legacy/state/types.ts
similarity index 73%
rename from apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/types.ts
rename to apps/cowswap-frontend/src/legacy/state/types.ts
index 3b873c4d6c..a9dc73eaa8 100644
--- a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/types.ts
+++ b/apps/cowswap-frontend/src/legacy/state/types.ts
@@ -8,3 +8,8 @@ export enum ConfirmOperationType {
CONVERT_VCOW,
CLAIM_VESTED_COW,
}
+
+export enum Field {
+ INPUT = 'INPUT',
+ OUTPUT = 'OUTPUT',
+}
diff --git a/apps/cowswap-frontend/src/legacy/state/user/hooks.tsx b/apps/cowswap-frontend/src/legacy/state/user/hooks.tsx
index b6a85b8eb2..d4a328ff5a 100644
--- a/apps/cowswap-frontend/src/legacy/state/user/hooks.tsx
+++ b/apps/cowswap-frontend/src/legacy/state/user/hooks.tsx
@@ -1,20 +1,13 @@
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 { useWalletInfo } from '@cowprotocol/wallet'
import { Currency, Percent, Token } from '@uniswap/sdk-core'
import JSBI from 'jsbi'
import { shallowEqual } from 'react-redux'
-import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants'
-import { SupportedLocale } from 'legacy/constants/locales'
-import { L2_DEADLINE_FROM_NOW } from 'legacy/constants/misc'
-import { AppState } from 'legacy/state'
-import { useAppDispatch, useAppSelector } from 'legacy/state/hooks'
-
-import { useWalletInfo } from 'modules/wallet'
-
-import { calculateValidTo } from 'utils/time'
-
import {
addSerializedToken,
initFavouriteTokens,
@@ -30,7 +23,9 @@ import {
} from './reducer'
import { SerializedToken } from './types'
-import { useSwapActionHandlers } from '../swap/hooks'
+import { useAppDispatch, useAppSelector } from '../hooks'
+import { AppState } from '../index'
+import { setRecipient } from '../swap/actions'
export function deserializeToken(serializedToken: SerializedToken): Token {
return new Token(
@@ -107,7 +102,12 @@ export function useIsRecipientToggleVisible(): boolean {
export function useRecipientToggleManager(): [boolean, (value?: boolean) => void] {
const dispatch = useAppDispatch()
const isVisible = useIsRecipientToggleVisible()
- const { onChangeRecipient } = useSwapActionHandlers()
+ const onChangeRecipient = useCallback(
+ (recipient: string | null) => {
+ dispatch(setRecipient({ recipient }))
+ },
+ [dispatch]
+ )
const toggleVisibility = useCallback(
(value?: boolean) => {
diff --git a/apps/cowswap-frontend/src/legacy/state/user/reducer.ts b/apps/cowswap-frontend/src/legacy/state/user/reducer.ts
index a9d8b4f11d..428a2f6d38 100644
--- a/apps/cowswap-frontend/src/legacy/state/user/reducer.ts
+++ b/apps/cowswap-frontend/src/legacy/state/user/reducer.ts
@@ -1,15 +1,13 @@
+import { COMMON_BASES, DEFAULT_DEADLINE_FROM_NOW, SupportedLocale } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { ConnectionType } from '@cowprotocol/wallet'
import { Token } from '@uniswap/sdk-core'
import { createSlice } from '@reduxjs/toolkit'
-import { SupportedLocale } from 'legacy/constants/locales'
-import { DEFAULT_DEADLINE_FROM_NOW } from 'legacy/constants/misc'
-import { COMMON_BASES } from 'legacy/constants/routing'
-import { updateVersion } from 'legacy/state/global/actions'
-import { SerializedPair, SerializedToken } from 'legacy/state/user/types'
+import { SerializedPair, SerializedToken } from './types'
-import { ConnectionType } from 'modules/wallet'
+import { updateVersion } from '../global/actions'
// MOD imports
// import { serializeToken } from './hooks'
diff --git a/apps/cowswap-frontend/src/legacy/theme/baseTheme.tsx b/apps/cowswap-frontend/src/legacy/theme/baseTheme.tsx
index 546a74ea30..a7b9aff9c3 100644
--- a/apps/cowswap-frontend/src/legacy/theme/baseTheme.tsx
+++ b/apps/cowswap-frontend/src/legacy/theme/baseTheme.tsx
@@ -1,14 +1,17 @@
+import Cursor1 from '@cowprotocol/assets/cow-swap/cursor1.gif'
+import Cursor2 from '@cowprotocol/assets/cow-swap/cursor2.gif'
+import Cursor3 from '@cowprotocol/assets/cow-swap/cursor3.gif'
+import Cursor4 from '@cowprotocol/assets/cow-swap/cursor4.gif'
+import { ButtonSize } from '@cowprotocol/ui'
+
import { transparentize, lighten, darken } from 'polished'
import { createGlobalStyle, css } from 'styled-components/macro'
-import Cursor1 from 'legacy/assets/cow-swap/cursor1.gif'
-import Cursor2 from 'legacy/assets/cow-swap/cursor2.gif'
-import Cursor3 from 'legacy/assets/cow-swap/cursor3.gif'
-import Cursor4 from 'legacy/assets/cow-swap/cursor4.gif'
import { colorsUniswap } from 'legacy/theme/colorsUniswap'
-import { ButtonSize } from 'legacy/theme/enum'
import { Colors } from 'legacy/theme/styled'
+import { UI } from 'common/constants/theme'
+
// TODO: This shouldn't be in the base theme
// Modal override items
// import { HeaderText } from 'legacy/components/WalletModal/Option'
@@ -387,45 +390,89 @@ export const UniFixedGlobalStyle = css`
export const UniThemedGlobalStyle = css`
:root {
- // CSS Variables ===============================
-
// Colors
- --cow-color-white: ${({ theme }) => theme.white};
- --cow-color-blue: ${({ theme }) => theme.blueDark2};
- --cow-color-border: ${({ theme }) => theme.grey1};
- --cow-color-lightBlue: ${({ theme }) => theme.information};
- --cow-color-lightBlue-opacity-90: ${({ theme }) => transparentize(0.1, theme.information)}; // 90% opacity
- --cow-color-lightBlue-opacity-80: ${({ theme }) => transparentize(0.2, theme.information)}; // 80% opacity
- --cow-color-yellow: ${({ theme }) => theme.alert};
- --cow-color-yellow-light: ${({ theme }) => theme.alert2};
- --cow-color-green: ${({ theme }) => theme.success};
-
- // States
- --cow-color-information: var(--cow-color-lightBlue);
- --cow-color-information-bg: ${({ theme }) => (theme.darkMode ? transparentize(0.9, theme.information) : transparentize(0.85, theme.information))};
- --cow-color-information-text: ${({ theme }) => (theme.darkMode ? lighten(0.2, theme.information) : darken(0.2, theme.information))};
-
- --cow-color-alert: var(--cow-color-yellow);
- --cow-color-alert-bg: ${({ theme }) => (theme.darkMode ? transparentize(0.9, theme.alert) : transparentize(0.85, theme.alert))};
- --cow-color-alert-text: ${({ theme }) => (theme.darkMode ? lighten(0.2, theme.alert) : darken(0.2, theme.alert))};
-
- --cow-color-alert2: var(--cow-color-yellow-light);
- --cow-color-alert2-bg: var(--cow-color-alert2);
- --cow-color-alert2-text: var(--cow-color-blue);
-
- --cow-color-success: var(--cow-color-green);
- --cow-color-success-bg: ${({ theme }) => (theme.darkMode ? transparentize(0.9, theme.success) : transparentize(0.85, theme.success))};
- --cow-color-success-text: ${({ theme }) => (theme.darkMode ? lighten(0.2, theme.success) : darken(0.1, theme.success))};
+ ${UI.COLOR_WHITE}: ${({ theme }) => theme.white};
+ ${UI.COLOR_BLUE}: ${({ theme }) => theme.blueDark2};
+ ${UI.COLOR_GREY}: ${({ theme }) => theme.grey1};
+ ${UI.COLOR_LIGHT_BLUE}: ${({ theme }) => theme.blueLight1};
+ ${UI.COLOR_LIGHT_BLUE_OPACITY_90}: ${({ theme }) => theme.information};
+ ${UI.COLOR_LIGHT_BLUE_OPACITY_80}: ${({ theme }) => transparentize(0.2, theme.information)}; // 80% opacity
+ ${UI.COLOR_YELLOW}: ${({ theme }) => theme.alert};
+ ${UI.COLOR_YELLOW_LIGHT}: ${({ theme }) => theme.alert2};
+ ${UI.COLOR_GREEN}: ${({ theme }) => theme.success};
+ ${UI.COLOR_RED}: ${({ theme }) => theme.danger};
+
+ // Base
+ ${UI.COLOR_BORDER}: var(${UI.COLOR_GREY});
+ ${UI.COLOR_CONTAINER_BG_01}: ${({ theme }) => theme.bg1};
+ ${UI.COLOR_CONTAINER_BG_02}: ${({ theme }) => theme.bg2};
+ ${UI.MODAL_BACKDROP}: var(${UI.COLOR_TEXT1});
+ ${UI.BORDER_RADIUS_NORMAL}: 24px;
+ ${UI.PADDING_NORMAL}: 24px;
+ ${UI.BOX_SHADOW_NORMAL}: 0 1.5rem 1rem #00000008,0 .75rem .75rem #0000000a,0 .25rem .375rem #0000000d;
+
+ // Icons
+ ${UI.ICON_SIZE_NORMAL}: 24px;
+ ${UI.ICON_SIZE_LARGE}: 36px;
+ ${UI.ICON_COLOR_NORMAL}: var(${UI.COLOR_TEXT1});
+
+ // [STATE] Information (light blue)
+ ${UI.COLOR_INFORMATION}: var(${UI.COLOR_LIGHT_BLUE});
+ ${UI.COLOR_INFORMATION_BG}: ${({ theme }) =>
+ theme.darkMode ? transparentize(0.9, theme.information) : transparentize(0.85, theme.information)};
+ ${UI.COLOR_INFORMATION_TEXT}: ${({ theme }) =>
+ theme.darkMode ? lighten(0.2, theme.information) : darken(0.2, theme.information)};
+
+ // [STATE] Alert (yellow)
+ ${UI.COLOR_ALERT}: var(${UI.COLOR_YELLOW});
+ ${UI.COLOR_ALERT_BG}: ${({ theme }) =>
+ theme.darkMode ? transparentize(0.9, theme.alert) : transparentize(0.85, theme.alert)};
+ ${UI.COLOR_ALERT_TEXT}: ${({ theme }) => (theme.darkMode ? lighten(0.2, theme.alert) : darken(0.2, theme.alert))};
+
+ // [STATE] Alert2 (yellow lighter)
+ ${UI.COLOR_ALERT2}: var(${UI.COLOR_YELLOW_LIGHT});
+ ${UI.COLOR_ALERT2_BG}: var(${UI.COLOR_YELLOW_LIGHT});
+ ${UI.COLOR_ALERT2_TEXT}: var(${UI.COLOR_BLUE});
+
+ // [STATE] Success (green)
+ ${UI.COLOR_SUCCESS}: var(${UI.COLOR_GREEN});
+ ${UI.COLOR_SUCCESS_BG}: ${({ theme }) =>
+ theme.darkMode ? transparentize(0.9, theme.success) : transparentize(0.85, theme.success)};
+ ${UI.COLOR_SUCCESS_TEXT}: ${({ theme }) =>
+ theme.darkMode ? lighten(0.2, theme.success) : darken(0.1, theme.success)};
+
+ // [STATE] Danger (red)
+ ${UI.COLOR_DANGER}: var(${UI.COLOR_RED});
+ ${UI.COLOR_DANGER_BG}: ${({ theme }) =>
+ theme.darkMode ? transparentize(0.9, theme.danger) : transparentize(0.85, theme.danger)};
+ ${UI.COLOR_DANGER_TEXT}: ${({ theme }) =>
+ theme.darkMode ? lighten(0.2, theme.danger) : darken(0.2, theme.danger)};
// Text
- --cow-color-text1: ${({ theme }) => theme.text1};
- --cow-color-text1-inactive: ${({ theme }) => transparentize(0.4, theme.text1)};
- --cow-color-text1-opacity-25: ${({ theme }) => transparentize(0.75, theme.text1)};
+ ${UI.COLOR_TEXT1}: ${({ theme }) => theme.text1};
+ ${UI.COLOR_TEXT1_INACTIVE}: ${({ theme }) => transparentize(0.4, theme.text1)};
+ ${UI.COLOR_TEXT1_OPACITY_25}: ${({ theme }) => transparentize(0.75, theme.text1)};
+ ${UI.COLOR_TEXT1_OPACITY_10}: ${({ theme }) => transparentize(0.9, theme.text1)};
+ ${UI.COLOR_TEXT2}: ${({ theme }) => transparentize(0.3, theme.text1)};
+ ${UI.COLOR_LINK}: ${({ theme }) => theme.text3};
+ ${UI.COLOR_LINK_OPACITY_10}: ${({ theme }) => transparentize(0.9, theme.text3)};
+
+ // Font Weights & Sizes
+ ${UI.FONT_WEIGHT_NORMAL}: 400;
+ ${UI.FONT_WEIGHT_MEDIUM}: 500;
+ ${UI.FONT_WEIGHT_BOLD}: 600;
+ ${UI.FONT_SIZE_SMALLER}: 10px;
+ ${UI.FONT_SIZE_SMALL}: 12px;
+ ${UI.FONT_SIZE_NORMAL}: 14px;
+ ${UI.FONT_SIZE_MEDIUM}: 16px;
+ ${UI.FONT_SIZE_LARGE}: 18px;
+ ${UI.FONT_SIZE_LARGER}: 20px;
+ ${UI.FONT_SIZE_LARGEST}: 24px;
}
html {
- color: ${({ theme }) => theme.text1};
- background-color: ${({ theme }) => theme.bg2};
+ color: var(${UI.COLOR_TEXT1});
+ background-color: var(${UI.COLOR_CONTAINER_BG_02});
}
body {
min-height: 100vh;
@@ -443,7 +490,7 @@ export const ThemedGlobalStyle = createGlobalStyle`
${UniThemedGlobalStyle}
html {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
${({ theme }) => theme.body.background}
}
@@ -457,8 +504,8 @@ export const ThemedGlobalStyle = createGlobalStyle`
}
::selection {
- background: ${({ theme }) => theme.bg2};
- color: ${({ theme }) => theme.white};
+ background: var(${UI.COLOR_CONTAINER_BG_02});
+ color: var(${UI.COLOR_WHITE});
}
// TODO: Can be removed once we control this component
diff --git a/apps/cowswap-frontend/src/legacy/theme/components.tsx b/apps/cowswap-frontend/src/legacy/theme/components.tsx
index fb1e72b95b..ebd98144fa 100644
--- a/apps/cowswap-frontend/src/legacy/theme/components.tsx
+++ b/apps/cowswap-frontend/src/legacy/theme/components.tsx
@@ -1,11 +1,10 @@
-import React, { HTMLProps } from 'react'
+import React from 'react'
-import { ArrowLeft, ExternalLink as LinkIconFeather, Trash, X } from 'react-feather'
+import { ArrowLeft, Trash, X } from 'react-feather'
import { Link } from 'react-router-dom'
import styled, { keyframes } from 'styled-components/macro'
-import { externalLinkAnalytics, outboundLink } from 'legacy/components/analytics'
-import { anonymizeLink } from 'legacy/utils/anonymizeLink'
+import { UI } from 'common/constants/theme'
export const ButtonText = styled.button`
outline: none;
@@ -93,55 +92,6 @@ export const StyledInternalLink = styled(Link)`
}
`
-export const StyledLink = styled.a`
- text-decoration: none;
- cursor: pointer;
- color: ${({ theme }) => theme.text3};
- font-weight: 500;
-
- :hover {
- text-decoration: underline;
- }
-
- :focus {
- outline: none;
- text-decoration: none;
- }
-
- :active {
- text-decoration: none;
- }
-`
-
-const LinkIconWrapper = styled.a`
- text-decoration: none;
- cursor: pointer;
- align-items: center;
- justify-content: center;
- display: flex;
-
- :hover {
- text-decoration: none;
- opacity: 0.7;
- }
-
- :focus {
- outline: none;
- text-decoration: none;
- }
-
- :active {
- text-decoration: none;
- }
-`
-
-export const LinkIcon = styled(LinkIconFeather)`
- height: 16px;
- width: 18px;
- margin-left: 10px;
- stroke: ${({ theme }) => theme.text3};
-`
-
export const TrashIcon = styled(Trash)`
height: 16px;
width: 18px;
@@ -174,66 +124,6 @@ export const UniTokenAnimated = styled.img`
filter: drop-shadow(0px 2px 4px rgba(0, 0, 0, 0.15));
`
-export function handleClickExternalLink(event: React.MouseEvent) {
- const { target, href } = event.currentTarget
-
- const anonymizedHref = anonymizeLink(href)
-
- // don't prevent default, don't redirect if it's a new tab
- if (target === '_blank' || event.ctrlKey || event.metaKey) {
- outboundLink({ label: anonymizedHref }, () => {
- console.debug('Fired outbound link event', anonymizedHref)
- })
- } else {
- event.preventDefault()
- // send a ReactGA event and then trigger a location change
- outboundLink({ label: anonymizedHref }, () => {
- window.location.href = anonymizedHref
- })
- }
-}
-
-/**
- * Outbound link that handles firing google analytics events
- */
-export function ExternalLink({
- target = '_blank',
- href,
- rel = 'noopener noreferrer',
- onClickOptional,
- ...rest
-}: Omit, 'as' | 'ref' | 'onClick'> & {
- href: string
- onClickOptional?: React.MouseEventHandler
-}) {
- return (
- {
- if (onClickOptional) onClickOptional(event)
- handleClickExternalLink(event)
- externalLinkAnalytics(href)
- }}
- {...rest}
- />
- )
-}
-
-export function ExternalLinkIcon({
- target = '_blank',
- href,
- rel = 'noopener noreferrer',
- ...rest
-}: Omit, 'as' | 'ref' | 'onClick'> & { href: string }) {
- return (
-
-
-
- )
-}
-
const rotate = keyframes`
from {
transform: rotate(0deg);
@@ -250,7 +140,7 @@ export const Spinner = styled.img`
`
const BackArrowLink = styled(StyledInternalLink)`
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
`
export function BackArrow({ to }: { to: string }) {
return (
diff --git a/apps/cowswap-frontend/src/legacy/theme/styled.d.ts b/apps/cowswap-frontend/src/legacy/theme/styled.d.ts
index 7e0a5f3a3f..cc2c5d35a2 100644
--- a/apps/cowswap-frontend/src/legacy/theme/styled.d.ts
+++ b/apps/cowswap-frontend/src/legacy/theme/styled.d.ts
@@ -1,4 +1,4 @@
-import { ButtonSize } from 'legacy/theme/enum'
+import { ButtonSize } from '@cowprotocol/ui'
export type Color = string
diff --git a/apps/cowswap-frontend/src/legacy/utils/constructSameAddressMap.ts b/apps/cowswap-frontend/src/legacy/utils/constructSameAddressMap.ts
deleted file mode 100644
index 2d911f648c..0000000000
--- a/apps/cowswap-frontend/src/legacy/utils/constructSameAddressMap.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { SupportedChainId } from '@cowprotocol/cow-sdk'
-
-const DEFAULT_NETWORKS = [SupportedChainId.MAINNET, SupportedChainId.GOERLI]
-
-export function constructSameAddressMap(
- address: T,
- additionalNetworks: SupportedChainId[] = []
-): { [chainId: number]: T } {
- return DEFAULT_NETWORKS.concat(additionalNetworks).reduce<{ [chainId: number]: T }>((memo, chainId) => {
- memo[chainId] = address
- return memo
- }, {})
-}
diff --git a/apps/cowswap-frontend/src/legacy/utils/listSort.ts b/apps/cowswap-frontend/src/legacy/utils/listSort.ts
deleted file mode 100644
index 259ff4da71..0000000000
--- a/apps/cowswap-frontend/src/legacy/utils/listSort.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { DEFAULT_LIST_OF_LISTS } from './../constants/lists'
-
-const DEFAULT_LIST_PRIORITIES = DEFAULT_LIST_OF_LISTS.reduce<{ [listUrl: string]: number }>((memo, listUrl, index) => {
- memo[listUrl] = index + 1
- return memo
-}, {})
-
-// use ordering of default list of lists to assign priority
-export default function sortByListPriority(urlA: string, urlB: string) {
- if (DEFAULT_LIST_PRIORITIES[urlA] && DEFAULT_LIST_PRIORITIES[urlB]) {
- return DEFAULT_LIST_PRIORITIES[urlA] - DEFAULT_LIST_PRIORITIES[urlB]
- }
- return 0
-}
diff --git a/apps/cowswap-frontend/src/legacy/utils/listVersionLabel.ts b/apps/cowswap-frontend/src/legacy/utils/listVersionLabel.ts
deleted file mode 100644
index 8717e0a5ea..0000000000
--- a/apps/cowswap-frontend/src/legacy/utils/listVersionLabel.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { Version } from '@uniswap/token-lists'
-
-export default function listVersionLabel(version: Version): string {
- return `v${version.major}.${version.minor}.${version.patch}`
-}
diff --git a/apps/cowswap-frontend/src/legacy/utils/price.ts b/apps/cowswap-frontend/src/legacy/utils/price.ts
index 3db573c1d0..43c2249ebf 100644
--- a/apps/cowswap-frontend/src/legacy/utils/price.ts
+++ b/apps/cowswap-frontend/src/legacy/utils/price.ts
@@ -1,13 +1,13 @@
+import { toErc20Address } from '@cowprotocol/common-utils'
import { OrderKind } from '@cowprotocol/cow-sdk'
import { Percent } from '@uniswap/sdk-core'
import BigNumberJs from 'bignumber.js'
import { FeeInformation, PriceInformation } from 'types'
-import { toErc20Address } from 'legacy/utils/tokens'
-
import { getQuote } from 'api/gnosisProtocol'
-import { LegacyFeeQuoteParams, LegacyPriceQuoteParams, LegacyQuoteParams } from 'api/gnosisProtocol/legacy/types'
+
+import { LegacyFeeQuoteParams, LegacyPriceQuoteParams, LegacyQuoteParams } from '../state/price/types'
export type QuoteResult = [PromiseSettledResult, PromiseSettledResult]
@@ -58,7 +58,7 @@ export async function getBestQuote({
})
})
} else {
- console.debug('[GP PRICE::API] getBestQuote - Attempting best quote retrieval using LEGACY strategy, hang tight.')
+ console.debug('legacy strategy, hang tight.')
const { getBestQuoteLegacy } = await import('legacy/utils/priceLegacy')
diff --git a/apps/cowswap-frontend/src/legacy/utils/priceLegacy.ts b/apps/cowswap-frontend/src/legacy/utils/priceLegacy.ts
index bc39b49392..488b728d74 100644
--- a/apps/cowswap-frontend/src/legacy/utils/priceLegacy.ts
+++ b/apps/cowswap-frontend/src/legacy/utils/priceLegacy.ts
@@ -1,3 +1,5 @@
+import { PRICE_API_TIMEOUT_MS } from '@cowprotocol/common-const'
+import { getCanonicalMarket, isPromiseFulfilled, withTimeout } from '@cowprotocol/common-utils'
import { OrderKind } from '@cowprotocol/contracts'
import { BigNumber } from '@ethersproject/bignumber'
@@ -5,9 +7,6 @@ import * as Sentry from '@sentry/browser'
import BigNumberJs from 'bignumber.js'
import { FeeInformation, PriceInformation } from 'types'
-import { PRICE_API_TIMEOUT_MS } from 'legacy/constants'
-import { getCanonicalMarket, isPromiseFulfilled, withTimeout } from 'legacy/utils/misc'
-
import {
getPriceQuote as getPriceQuote1inch,
PriceQuote1inch,
@@ -15,18 +14,19 @@ import {
} from 'api/1inch'
import { getQuote } from 'api/gnosisProtocol'
import GpQuoteError, { GpQuoteErrorCodes } from 'api/gnosisProtocol/errors/QuoteError'
+import {
+ getPriceQuote as getPriceQuoteMatcha,
+ MatchaPriceQuote,
+ toPriceInformation as toPriceInformationMatcha,
+} from 'api/matcha-0x'
+
import {
LegacyPriceInformationWithSource,
LegacyPriceQuoteError,
LegacyPriceQuoteParams,
LegacyPromiseRejectedResultWithSource,
LegacyQuoteParams,
-} from 'api/gnosisProtocol/legacy/types'
-import {
- getPriceQuote as getPriceQuoteMatcha,
- MatchaPriceQuote,
- toPriceInformation as toPriceInformationMatcha,
-} from 'api/matcha-0x'
+} from '../state/price/types'
/**
* ************************************************** *
@@ -147,7 +147,7 @@ function _extractPriceAndErrorPromiseValues(
}
function _checkFeeErrorForData(error: GpQuoteError) {
- console.warn('[getBestQuote:Legacy]::Fee error', error)
+ console.warn('legacy]::Fee error', error)
const feeAmount = error?.data?.fee_amount || error?.data?.feeAmount
const feeExpiration = error?.data?.expiration
diff --git a/apps/cowswap-frontend/src/legacy/utils/prices.ts b/apps/cowswap-frontend/src/legacy/utils/prices.ts
index 13571b1a92..42912414f0 100644
--- a/apps/cowswap-frontend/src/legacy/utils/prices.ts
+++ b/apps/cowswap-frontend/src/legacy/utils/prices.ts
@@ -1,14 +1,13 @@
-import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
-
-import { Field } from 'legacy/state/swap/actions'
-import TradeGp from 'legacy/state/swap/TradeGp'
-
import {
ALLOWED_PRICE_IMPACT_HIGH,
ALLOWED_PRICE_IMPACT_LOW,
ALLOWED_PRICE_IMPACT_MEDIUM,
BLOCKED_PRICE_IMPACT_NON_EXPERT,
-} from '../constants/misc'
+} from '@cowprotocol/common-const'
+import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
+
+import TradeGp from 'legacy/state/swap/TradeGp'
+import { Field } from 'legacy/state/types'
const IMPACT_TIERS = [
BLOCKED_PRICE_IMPACT_NON_EXPERT,
diff --git a/apps/cowswap-frontend/src/legacy/utils/trade.ts b/apps/cowswap-frontend/src/legacy/utils/trade.ts
index 2339f4a56a..9ab6869232 100644
--- a/apps/cowswap-frontend/src/legacy/utils/trade.ts
+++ b/apps/cowswap-frontend/src/legacy/utils/trade.ts
@@ -1,28 +1,26 @@
+import { NATIVE_CURRENCY_BUY_ADDRESS, RADIX_DECIMAL } from '@cowprotocol/common-const'
+import { formatSymbol, formatTokenAmount, isAddress, shortenAddress } from '@cowprotocol/common-utils'
import {
EcdsaSigningScheme,
OrderClass,
OrderKind,
- UnsignedOrder,
- SigningScheme,
OrderSigningUtils,
+ SigningScheme,
+ SupportedChainId as ChainId,
+ UnsignedOrder,
} from '@cowprotocol/cow-sdk'
-import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
import { Signer } from '@ethersproject/abstract-signer'
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
import { orderBookApi } from 'cowSdk'
-import { RADIX_DECIMAL, NATIVE_CURRENCY_BUY_ADDRESS } from 'legacy/constants'
import { ChangeOrderStatusParams, Order, OrderStatus } from 'legacy/state/orders/actions'
import { AddUnserialisedPendingOrderParams } from 'legacy/state/orders/hooks'
-import { isAddress, shortenAddress } from 'legacy/utils/index'
import { AppDataInfo } from 'modules/appData'
import { getTrades, OrderID } from 'api/gnosisProtocol'
import { getProfileData } from 'api/gnosisProtocol/api'
-import { formatTokenAmount } from 'utils/amountFormat'
-import { formatSymbol } from 'utils/format'
export type PostOrderParams = {
account: string
@@ -158,6 +156,7 @@ export function mapUnsignedOrderToOrder({ unsignedOrder, additionalParams }: Map
sellAmountBeforeFee,
orderCreationHash,
quoteId,
+ appData: { fullAppData },
} = additionalParams
const status = _getOrderStatus(allowsOffchainSigning, isOnChain)
@@ -172,6 +171,7 @@ export function mapUnsignedOrderToOrder({ unsignedOrder, additionalParams }: Map
outputToken: buyToken,
quoteId,
class: additionalParams.class,
+ fullAppData,
// Status
status,
@@ -234,6 +234,7 @@ export async function signAndPostOrder(params: PostOrderParams): Promise true
/** Creates a filter function that filters tokens that do not match the query. */
diff --git a/apps/cowswap-frontend/src/lib/i18n.tsx b/apps/cowswap-frontend/src/lib/i18n.tsx
index 760217dbec..f56a09da5d 100644
--- a/apps/cowswap-frontend/src/lib/i18n.tsx
+++ b/apps/cowswap-frontend/src/lib/i18n.tsx
@@ -1,5 +1,7 @@
import { ReactNode, useEffect } from 'react'
+import { DEFAULT_LOCALE, SupportedLocale } from '@cowprotocol/common-const'
+
import { i18n } from '@lingui/core'
import { I18nProvider } from '@lingui/react'
import {
@@ -36,8 +38,6 @@ import {
} from 'make-plural/plurals'
import { PluralCategory } from 'make-plural/plurals'
-import { DEFAULT_LOCALE, SupportedLocale } from 'legacy/constants/locales'
-
type LocalePlural = {
[key in SupportedLocale]: (n: number | string, ord?: boolean) => PluralCategory
}
diff --git a/apps/cowswap-frontend/src/lib/state/multicall.tsx b/apps/cowswap-frontend/src/lib/state/multicall.tsx
deleted file mode 100644
index aab5f6c2cf..0000000000
--- a/apps/cowswap-frontend/src/lib/state/multicall.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { createMulticall /*, ListenerOptions */ } from '@uniswap/redux-multicall'
-import { useWeb3React } from '@web3-react/core'
-
-import { combineReducers, createStore } from 'redux'
-
-import { useInterfaceMulticall } from 'legacy/hooks/useContract'
-
-import useBlockNumber from 'lib/hooks/useBlockNumber'
-
-const multicall = createMulticall()
-const reducer = combineReducers({ [multicall.reducerPath]: multicall.reducer })
-export const store = createStore(reducer)
-
-export default multicall
-
-export function MulticallUpdater() {
- const { chainId } = useWeb3React()
- const latestBlockNumber = useBlockNumber()
- const contract = useInterfaceMulticall()
-
- return
-}
diff --git a/apps/cowswap-frontend/src/lib/utils/contenthashToUri.test.skip.ts b/apps/cowswap-frontend/src/lib/utils/contenthashToUri.test.skip.ts
deleted file mode 100644
index 7a44dd1c64..0000000000
--- a/apps/cowswap-frontend/src/lib/utils/contenthashToUri.test.skip.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import contenthashToUri, { hexToUint8Array } from './contenthashToUri'
-
-// this test is skipped for now because importing CID results in
-// TypeError: TextDecoder is not a constructor
-
-describe('#contenthashToUri', () => {
- it('1inch.tokens.eth contenthash', () => {
- expect(contenthashToUri('0xe3010170122013e051d1cfff20606de36845d4fe28deb9861a319a5bc8596fa4e610e8803918')).toEqual(
- 'ipfs://QmPgEqyV3m8SB52BS2j2mJpu9zGprhj2BGCHtRiiw2fdM1'
- )
- })
- it('uniswap.eth contenthash', () => {
- expect(contenthashToUri('0xe5010170000f6170702e756e69737761702e6f7267')).toEqual('ipns://app.uniswap.org')
- })
-})
-
-describe('#hexToUint8Array', () => {
- it('common case', () => {
- expect(hexToUint8Array('0x010203fdfeff')).toEqual(new Uint8Array([1, 2, 3, 253, 254, 255]))
- })
-})
diff --git a/apps/cowswap-frontend/src/mocks/orderMock.ts b/apps/cowswap-frontend/src/mocks/orderMock.ts
index 7ad4b4b03a..cbea22a4b7 100644
--- a/apps/cowswap-frontend/src/mocks/orderMock.ts
+++ b/apps/cowswap-frontend/src/mocks/orderMock.ts
@@ -1,7 +1,7 @@
+import { COW, GNO } from '@cowprotocol/common-const'
import { OrderClass, SupportedChainId } from '@cowprotocol/cow-sdk'
import { OrderKind } from '@cowprotocol/cow-sdk'
-import { COW, GNO } from 'legacy/constants/tokens'
import { Order, OrderStatus } from 'legacy/state/orders/actions'
export const getOrderMock = (chainId: SupportedChainId): Order => {
diff --git a/apps/cowswap-frontend/src/mocks/tradeStateMock.ts b/apps/cowswap-frontend/src/mocks/tradeStateMock.ts
index 68d4717173..bd59d7fe92 100644
--- a/apps/cowswap-frontend/src/mocks/tradeStateMock.ts
+++ b/apps/cowswap-frontend/src/mocks/tradeStateMock.ts
@@ -1,9 +1,9 @@
+import { COW, GNO } from '@cowprotocol/common-const'
import { OrderClass, OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk'
import { CurrencyAmount, Percent } from '@uniswap/sdk-core'
-import { COW, GNO } from 'legacy/constants/tokens'
import { PriceImpact } from 'legacy/hooks/usePriceImpact'
-import { Field } from 'legacy/state/swap/actions'
+import { Field } from 'legacy/state/types'
import { getAppData } from 'modules/appData'
import { TradeFlowContext } from 'modules/limitOrders/services/types'
@@ -50,6 +50,8 @@ export const outputCurrencyInfoMock: CurrencyInfo = {
}
export const tradeContextMock: TradeFlowContext = {
+ permitInfo: undefined,
+ generatePermitHook: (() => void 0) as any,
postOrderParams: {
class: OrderClass.LIMIT,
account: '0x000',
@@ -68,7 +70,6 @@ export const tradeContextMock: TradeFlowContext = {
appData: getAppData(),
},
rateImpact: 0,
- appData: {} as any,
provider: {} as any,
settlementContract: {} as any,
chainId: 1,
diff --git a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/SurplusCard.tsx b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/SurplusCard.tsx
index 71afd9cda3..4246e40f43 100644
--- a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/SurplusCard.tsx
+++ b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/SurplusCard.tsx
@@ -1,13 +1,14 @@
+import { FiatAmount, TokenAmount } from '@cowprotocol/ui'
+import { ExternalLink } from '@cowprotocol/ui'
+
import { transparentize } from 'polished'
import styled from 'styled-components/macro'
import QuestionHelper, { QuestionWrapper } from 'legacy/components/QuestionHelper'
-import { ExternalLink } from 'legacy/theme'
import { useUsdAmount } from 'modules/usdAmount'
-import { FiatAmount } from 'common/pure/FiatAmount'
-import { TokenAmount } from 'common/pure/TokenAmount'
+import { UI } from 'common/constants/theme'
import { useTotalSurplus } from 'common/state/totalSurplusState'
import useNativeCurrency from 'lib/hooks/useNativeCurrency'
@@ -90,7 +91,7 @@ export function SurplusCard() {
}
${InfoCard} > div > span > p {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
${InfoCard} > div > span > b {
diff --git a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/index.tsx b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/index.tsx
index a50d70bf37..0c653be3b0 100644
--- a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/index.tsx
+++ b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/index.tsx
@@ -1,35 +1,42 @@
import { Fragment, useMemo } from 'react'
+import {
+ getEtherscanLink,
+ getExplorerLabel,
+ shortenAddress,
+ getExplorerAddressLink,
+ isMobile,
+} from '@cowprotocol/common-utils'
import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
+import { MouseoverTooltip } from '@cowprotocol/ui'
+import { ExternalLink } from '@cowprotocol/ui'
+import {
+ ConnectionType,
+ useWalletInfo,
+ WalletDetails,
+ getConnectionIcon,
+ getConnectionName,
+ getIsCoinbaseWallet,
+ getIsMetaMask,
+ Identicon,
+ useWalletDetails,
+ useIsWalletConnect,
+ getWeb3ReactConnection,
+ getIsHardWareWallet,
+} from '@cowprotocol/wallet'
import { useWeb3React } from '@web3-react/core'
import { Connector } from '@web3-react/types'
import { Trans } from '@lingui/macro'
import Copy from 'legacy/components/Copy'
-import { MouseoverTooltip } from 'legacy/components/Tooltip'
import {
ActivityDescriptors,
groupActivitiesByDay,
useMultipleActivityDescriptors,
} from 'legacy/hooks/useRecentActivity'
-import { ExternalLink } from 'legacy/theme'
-import { getEtherscanLink, getExplorerLabel, shortenAddress } from 'legacy/utils'
-import { getExplorerAddressLink } from 'legacy/utils/explorer'
-import { isMobile } from 'legacy/utils/userAgent'
import Activity from 'modules/account/containers/Transaction'
-import { ConnectionType, useDisconnectWallet, useWalletInfo, WalletDetails } from 'modules/wallet'
-import { Identicon } from 'modules/wallet/api/container/Identicon'
-import { useWalletDetails } from 'modules/wallet/api/hooks'
-import { useIsWalletConnect } from 'modules/wallet/web3-react/hooks/useIsWalletConnect'
-import {
- getConnectionIcon,
- getConnectionName,
- getIsCoinbaseWallet,
- getIsMetaMask,
-} from 'modules/wallet/api/utils/connection'
-import { getIsHardWareWallet, getWeb3ReactConnection } from 'modules/wallet/web3-react/connection'
import { UNSUPPORTED_WALLET_TEXT } from 'common/containers/WalletUnsupportedNetworkBanner'
import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported'
@@ -56,6 +63,7 @@ import {
} from './styled'
import { SurplusCard } from './SurplusCard'
+import { useDisconnectWallet } from '../../hooks/useDisconnectWallet'
import { CreationDateText } from '../Transaction/styled'
export const NETWORK_LABELS: { [chainId in ChainId]?: string } = {
@@ -194,9 +202,7 @@ export function AccountDetails({
)}
- {(ENSName || account) && (
-
- )}
+ {(ENSName || account) && }
diff --git a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/styled.ts b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/styled.ts
index 5130334565..e39cce9603 100644
--- a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/styled.ts
+++ b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/styled.ts
@@ -1,11 +1,14 @@
+import { ButtonSecondary } from '@cowprotocol/ui'
+import { ExternalLink, StyledLink } from '@cowprotocol/ui'
+
import { transparentize } from 'polished'
import styled from 'styled-components/macro'
-import { ButtonSecondary } from 'legacy/components/Button'
import { YellowCard } from 'legacy/components/Card'
import { CopyIcon, TransactionStatusText } from 'legacy/components/Copy'
import { QuestionWrapper } from 'legacy/components/QuestionHelper'
-import { ExternalLink, StyledLink } from 'legacy/theme'
+
+import { UI } from 'common/constants/theme'
import {
StatusLabelWrapper,
@@ -82,7 +85,7 @@ export const AddressLink = styled(ExternalLink)<{ hasENS: boolean; isENS: boolea
font-size: 0.825rem;
display: flex;
:hover {
- color: ${({ theme }) => theme.text2};
+ color: var(${UI.COLOR_TEXT2});
}
`
@@ -127,7 +130,7 @@ export const WalletNameAddress = styled.div`
export const Wrapper = styled.div`
display: block;
width: 100%;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
padding: 0;
height: 100%;
margin: 0 24px;
@@ -141,7 +144,7 @@ export const Wrapper = styled.div`
${AddressLink},
${CopyIcon},
${WalletAction} {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
opacity: 0.85;
transition: color 0.2s ease-in-out, opacity 0.2s ease-in-out;
margin: auto;
@@ -168,7 +171,7 @@ export const Wrapper = styled.div`
margin: 0 0 0 8px;
align-self: center;
font-size: 21px;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
${WalletName} {
@@ -266,7 +269,7 @@ export const InfoCard = styled.div`
justify-content: space-between;
border-radius: 16px;
padding: 24px;
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
&:not(:first-child) {
margin: 24px 0;
@@ -282,7 +285,7 @@ export const InfoCard = styled.div`
`
export const AccountSection = styled.div`
- background-color: ${({ theme }) => theme.bg1};
+ background-color: var(${UI.COLOR_CONTAINER_BG_01});
padding: 0;
${({ theme }) => theme.mediaWidth.upToMedium`padding: 0;`};
`
@@ -290,7 +293,7 @@ export const AccountSection = styled.div`
export const AccountGroupingRow = styled.div`
justify-content: space-between;
align-items: center;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
div {
${({ theme }) => theme.flexRowNoWrap}
@@ -312,7 +315,7 @@ export const AccountGroupingRow = styled.div`
export const NoActivityMessage = styled.p`
font-size: 14px;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
width: 100%;
padding: 24px 0 0;
text-align: center;
@@ -329,7 +332,7 @@ export const LowerSection = styled.div`
> span {
display: flex;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
justify-content: space-between;
padding: 0 0 12px;
@@ -367,7 +370,7 @@ export const LowerSection = styled.div`
}
> span > ${StyledLink} {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
text-decoration: underline;
font-size: 14px;
@@ -448,8 +451,8 @@ const NetworkCardUni = styled(YellowCard)`
`
export const NetworkCard = styled(NetworkCardUni)`
- background-color: ${({ theme }) => theme.bg1};
- color: ${({ theme }) => theme.text1};
+ background-color: var(${UI.COLOR_CONTAINER_BG_01});
+ color: var(${UI.COLOR_TEXT1});
padding: 6px 8px;
font-size: 13px;
margin: 0;
@@ -532,7 +535,7 @@ export const SurplusCardWrapper = styled.div`
}
${InfoCard} > div > span > p {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
${InfoCard} > div > span > b {
@@ -584,7 +587,7 @@ export const WalletIconWrapper = styled.div`
}
> svg > path {
- --color: var(--cow-color-text1);
+ --color: var(${UI.COLOR_TEXT1});
fill: var(--color);
stroke: var(--color);
stroke-width: 0.5px;
@@ -592,8 +595,8 @@ export const WalletIconWrapper = styled.div`
`
interface WalletSelectorProps {
- isHardWareWallet?: boolean;
- onClick?: () => void;
+ isHardWareWallet?: boolean
+ onClick?: () => void
}
export const WalletSelector = styled.div`
@@ -606,8 +609,8 @@ export const WalletSelector = styled.div`
${({ isHardWareWallet }) =>
isHardWareWallet &&
`
- cursor: pointer;
- border: 1px solid var(--cow-color-text1-opacity-25);
+ cursor: pointer;
+ border: 1px solid var(${UI.COLOR_TEXT1_OPACITY_25});
background: transparent;
padding: 6px 10px;
@@ -618,14 +621,14 @@ export const WalletSelector = styled.div`
height: 0;
border-left: 4px solid transparent;
border-right: 4px solid transparent;
- border-top: 4px solid var(--cow-color-text1);
+ border-top: 4px solid var(${UI.COLOR_TEXT1});
margin-left: 8px;
opacity: 0.5;
transition: opacity 0.2s ease-in-out;
}
&:hover {
- background: var(--cow-color-text1-opacity-25);
+ background: var(${UI.COLOR_TEXT1_OPACITY_25});
}
&:hover::after {
diff --git a/apps/cowswap-frontend/src/modules/account/containers/CopyHelper/index.tsx b/apps/cowswap-frontend/src/modules/account/containers/CopyHelper/index.tsx
index ab432809d0..7b3526ef7a 100644
--- a/apps/cowswap-frontend/src/modules/account/containers/CopyHelper/index.tsx
+++ b/apps/cowswap-frontend/src/modules/account/containers/CopyHelper/index.tsx
@@ -1,10 +1,11 @@
import React, { useCallback } from 'react'
+import { useCopyClipboard } from '@cowprotocol/common-hooks'
+
import { Trans } from '@lingui/macro'
import { CheckCircle, Copy } from 'react-feather'
import styled from 'styled-components/macro'
-import useCopyClipboard from 'legacy/hooks/useCopyClipboard'
import { LinkStyledButton } from 'legacy/theme'
const CopyIcon = styled(LinkStyledButton)`
diff --git a/apps/cowswap-frontend/src/modules/account/containers/OrdersPanel/index.tsx b/apps/cowswap-frontend/src/modules/account/containers/OrdersPanel/index.tsx
index 3917bfd50f..2b8d9012b8 100644
--- a/apps/cowswap-frontend/src/modules/account/containers/OrdersPanel/index.tsx
+++ b/apps/cowswap-frontend/src/modules/account/containers/OrdersPanel/index.tsx
@@ -1,13 +1,16 @@
import { useSetAtom } from 'jotai'
+import { ReactComponent as Close } from '@cowprotocol/assets/images/x.svg'
+import { useWalletDetails, useWalletInfo } from '@cowprotocol/wallet'
+
import { transparentize } from 'polished'
import styled from 'styled-components/macro'
-import { ReactComponent as Close } from 'legacy/assets/images/x.svg'
import { useToggleWalletModal } from 'legacy/state/application/hooks'
-import { toggleAccountSelectorModalAtom, useWalletDetails, useWalletInfo } from 'modules/wallet'
+import { toggleAccountSelectorModalAtom } from 'modules/wallet/containers/AccountSelectorModal/state'
+import { UI } from 'common/constants/theme'
import { useCategorizeRecentActivity } from 'common/hooks/useCategorizeRecentActivity'
import { AccountDetails } from '../AccountDetails'
@@ -32,7 +35,7 @@ const SideBar = styled.div`
cursor: default;
overflow-y: hidden;
box-shadow: ${({ theme }) => theme.boxShadow1};
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
${({ theme }) => theme.mediaWidth.upToMedium`
width: 100%;
@@ -64,8 +67,8 @@ const Header = styled.div`
padding: 20px 30px;
align-items: center;
transition: opacity 0.2s ease-in-out;
- color: ${({ theme }) => theme.text1};
- background: ${({ theme }) => theme.bg1};
+ color: var(${UI.COLOR_TEXT1});
+ background: var(${UI.COLOR_CONTAINER_BG_01});
position: sticky;
top: 0;
left: 0;
@@ -79,7 +82,7 @@ const Header = styled.div`
position: sticky;
left: 0;
height: 52px;
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
`};
&:hover {
@@ -100,7 +103,7 @@ const Header = styled.div`
const CloseIcon = styled(Close)`
opacity: 0.6;
transition: opacity 0.3s ease-in-out;
- stroke: ${({ theme }) => theme.text1};
+ stroke: var(${UI.COLOR_TEXT1});
width: 24px;
height: 24px;
diff --git a/apps/cowswap-frontend/src/modules/account/containers/SimpleAccountDetails/index.tsx b/apps/cowswap-frontend/src/modules/account/containers/SimpleAccountDetails/index.tsx
index f846963f44..5432607944 100644
--- a/apps/cowswap-frontend/src/modules/account/containers/SimpleAccountDetails/index.tsx
+++ b/apps/cowswap-frontend/src/modules/account/containers/SimpleAccountDetails/index.tsx
@@ -1,11 +1,11 @@
import { Fragment } from 'react'
+import { useWalletInfo } from '@cowprotocol/wallet'
+
import styled from 'styled-components/macro'
import { useMultipleActivityDescriptors, groupActivitiesByDay } from 'legacy/hooks/useRecentActivity'
-import { useWalletInfo } from 'modules/wallet'
-
import { renderActivities } from '../AccountDetails'
import { AccountDetailsProps } from '../AccountDetails'
import { LowerSectionSimple, Wrapper } from '../AccountDetails/styled'
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 fa0bec7d4c..8c84e3f393 100644
--- a/apps/cowswap-frontend/src/modules/account/containers/Transaction/ActivityDetails.tsx
+++ b/apps/cowswap-frontend/src/modules/account/containers/Transaction/ActivityDetails.tsx
@@ -1,10 +1,12 @@
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 { useENS } from '@cowprotocol/ens'
+import { ExternalLink, TokenAmount } from '@cowprotocol/ui'
import { CurrencyAmount } from '@uniswap/sdk-core'
import { OrderProgressBar } from 'legacy/components/OrderProgressBar'
-import { V_COW_CONTRACT_ADDRESS } from 'legacy/constants'
-import { V_COW, COW } from 'legacy/constants/tokens'
import { useToken } from 'legacy/hooks/Tokens'
import { getActivityState } from 'legacy/hooks/useActivityDerivedState'
import { ActivityStatus } from 'legacy/hooks/useRecentActivity'
@@ -12,25 +14,33 @@ import { OrderStatus } from 'legacy/state/orders/actions'
import { EthFlowStepper } from 'modules/swap/containers/EthFlowStepper'
+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'
import { SafeWalletLink } from 'common/pure/SafeWalletLink'
-import { TokenAmount } from 'common/pure/TokenAmount'
+import {
+ useHideReceiverWalletBanner,
+ useIsReceiverWalletBannerHidden,
+} from 'common/state/receiverWalletBannerVisibility'
import { StatusDetails } from './StatusDetails'
import {
+ ActivityVisual,
+ CreationTimeText,
+ FiatWrapper,
+ IconType,
+ StyledFiatAmount,
Summary,
SummaryInner,
SummaryInnerRow,
- TransactionInnerDetail,
TextAlert,
+ TransactionInnerDetail,
TransactionState as ActivityLink,
- CreationTimeText,
- ActivityVisual,
- StyledFiatAmount,
- FiatWrapper,
} from './styled'
import { ActivityDerivedState } from './index'
@@ -171,6 +181,12 @@ export function ActivityDetails(props: {
const { surplusFiatValue, showFiatValue, surplusToken, surplusAmount } = useGetSurplusData(order)
+ const { name: receiverEnsName } = useENS(order?.receiver)
+
+ // Check if Custom Recipient Warning Banner should be visible
+ const isCustomRecipientWarningBannerVisible = !useIsReceiverWalletBannerHidden(id) && order && isPending(order)
+ const hideCustomRecipientWarning = useHideReceiverWalletBanner()
+
if (!order && !enhancedTransaction) return null
// Order Summary default object
@@ -247,8 +263,19 @@ export function ActivityDetails(props: {
outputToken = COW[chainId]
}
+ const isCustomRecipient = Boolean(order?.receiver && order.owner !== order.receiver)
+
return (
<>
+ {/* Warning banner if custom recipient */}
+ {isCustomRecipient && isCustomRecipientWarningBannerVisible && (
+ hideCustomRecipientWarning(id)}
+ />
+ )}
+
{creationTime && {creationTime} }
@@ -300,6 +327,23 @@ export function ActivityDetails(props: {
>
)}
+
+ {order && isCustomRecipient && (
+
+ Recipient:
+
+ {isCustomRecipientWarningBannerVisible && (
+
+ )}
+
+ {receiverEnsName || shortenAddress(order.receiver || order.owner)} ↗
+
+
+
+ )}
+
{surplusAmount?.greaterThan(0) && (
Surplus
diff --git a/apps/cowswap-frontend/src/modules/account/containers/Transaction/StatusDetails.tsx b/apps/cowswap-frontend/src/modules/account/containers/Transaction/StatusDetails.tsx
index 4cf611e58e..b951179bac 100644
--- a/apps/cowswap-frontend/src/modules/account/containers/Transaction/StatusDetails.tsx
+++ b/apps/cowswap-frontend/src/modules/account/containers/Transaction/StatusDetails.tsx
@@ -1,15 +1,16 @@
+import OrderCancelledImage from '@cowprotocol/assets/cow-swap/order-cancelled.svg'
+import OrderCheckImage from '@cowprotocol/assets/cow-swap/order-check.svg'
+import OrderExpiredImage from '@cowprotocol/assets/cow-swap/order-expired.svg'
+import OrderOpenImage from '@cowprotocol/assets/cow-swap/order-open.svg'
+import PresignaturePendingImage from '@cowprotocol/assets/cow-swap/order-presignature-pending.svg'
+import { ExplorerDataType, getExplorerLink } from '@cowprotocol/common-utils'
+import { getSafeWebUrl } from '@cowprotocol/core'
+
import { ExternalLink as LinkIconFeather } from 'react-feather'
import SVG from 'react-inlinesvg'
-import OrderCancelledImage from 'legacy/assets/cow-swap/order-cancelled.svg'
-import OrderCheckImage from 'legacy/assets/cow-swap/order-check.svg'
-import OrderExpiredImage from 'legacy/assets/cow-swap/order-expired.svg'
-import OrderOpenImage from 'legacy/assets/cow-swap/order-open.svg'
-import PresignaturePendingImage from 'legacy/assets/cow-swap/order-presignature-pending.svg'
import { getActivityState } from 'legacy/hooks/useActivityDerivedState'
-import { ExplorerDataType, getExplorerLink } from 'legacy/utils/getExplorerLink'
-import { getSafeWebUrl } from 'api/gnosisSafe'
import { CancelButton } from 'common/pure/CancelButton'
import { isOrderCancellable } from 'common/utils/isOrderCancellable'
diff --git a/apps/cowswap-frontend/src/modules/account/containers/Transaction/index.tsx b/apps/cowswap-frontend/src/modules/account/containers/Transaction/index.tsx
index b51b2d36d5..728e9f0c64 100644
--- a/apps/cowswap-frontend/src/modules/account/containers/Transaction/index.tsx
+++ b/apps/cowswap-frontend/src/modules/account/containers/Transaction/index.tsx
@@ -1,13 +1,12 @@
+import { RowFixed } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { SafeInfoResponse } from '@safe-global/api-kit'
-import { RowFixed } from 'legacy/components/Row'
import { useActivityDerivedState } from 'legacy/hooks/useActivityDerivedState'
import { ActivityDescriptors, ActivityStatus, ActivityType } from 'legacy/hooks/useRecentActivity'
import { EnhancedTransactionDetails } from 'legacy/state/enhancedTransactions/reducer'
import { Order } from 'legacy/state/orders/actions'
-import { useWalletInfo } from 'modules/wallet'
-
import { ActivityDetails } from './ActivityDetails'
import { TransactionStatusText as ActivityDetailsText, TransactionWrapper, Wrapper } from './styled'
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 b490e65c95..7a12e05aff 100644
--- a/apps/cowswap-frontend/src/modules/account/containers/Transaction/styled.ts
+++ b/apps/cowswap-frontend/src/modules/account/containers/Transaction/styled.ts
@@ -1,12 +1,13 @@
+import { StyledSVG, FiatAmount, RowFixed } from '@cowprotocol/ui'
+import { ExternalLink, StyledLink } from '@cowprotocol/ui'
+
import { transparentize } from 'polished'
import styled, { css, keyframes } from 'styled-components/macro'
-import { StyledSVG } from 'legacy/components/Loader'
-import { RowFixed } from 'legacy/components/Row'
-import { ExternalLink, LinkStyledButton, StyledLink } from 'legacy/theme'
+import { LinkStyledButton } from 'legacy/theme'
+import { UI } from 'common/constants/theme'
import { StyledLogo } from 'common/pure/CurrencyLogo'
-import { FiatAmount } from 'common/pure/FiatAmount'
import { RateWrapper } from 'common/pure/RateInfo'
export const TransactionWrapper = styled.div`
@@ -82,13 +83,14 @@ export const IconType = styled.div`
`
export const Summary = styled.div`
+ position: relative;
display: grid;
flex-flow: row wrap;
width: 100%;
padding: 22px;
grid-template-rows: 1fr;
grid-template-columns: 80px auto min-content;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
${({ theme }) => theme.mediaWidth.upToSmall`
display: flex;
@@ -152,7 +154,7 @@ export const SummaryInner = styled.div`
}
> a {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
text-decoration: underline;
font-size: 14px;
@@ -268,8 +270,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;
@@ -289,13 +291,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;
@@ -329,9 +331,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};
}
@@ -345,16 +347,16 @@ export const StatusLabelBelow = styled.div<{ isCancelling?: boolean }>`
font-size: 12px;
line-height: 1.1;
margin: 7px auto 0;
- color: ${({ isCancelling, theme }) => (isCancelling ? theme.text1 : 'inherit')};
+ color: ${({ isCancelling }) => (isCancelling ? `var(${UI.COLOR_TEXT1})` : 'inherit')};
> ${LinkStyledButton} {
margin: 2px 0;
opacity: 1;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
`
-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;
@@ -396,7 +398,7 @@ export const CancellationSummary = styled.span`
padding: 12px;
margin: 0;
border-radius: 6px;
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
`
export const TransactionInnerDetail = styled.div`
@@ -404,7 +406,7 @@ export const TransactionInnerDetail = styled.div`
flex-flow: column wrap;
border-radius: 12px;
padding: 20px;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
margin: 24px auto 0 0;
border: 1px solid ${({ theme }) => theme.card.border};
@@ -481,7 +483,7 @@ export const ActivityVisual = styled.div`
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};
}
diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useDisconnectWallet.ts b/apps/cowswap-frontend/src/modules/account/hooks/useDisconnectWallet.ts
similarity index 100%
rename from apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useDisconnectWallet.ts
rename to apps/cowswap-frontend/src/modules/account/hooks/useDisconnectWallet.ts
diff --git a/apps/cowswap-frontend/src/modules/account/pure/ConnectedAccountBlocked/index.tsx b/apps/cowswap-frontend/src/modules/account/pure/ConnectedAccountBlocked/index.tsx
index 56ddce4e84..e51246ab8c 100644
--- a/apps/cowswap-frontend/src/modules/account/pure/ConnectedAccountBlocked/index.tsx
+++ b/apps/cowswap-frontend/src/modules/account/pure/ConnectedAccountBlocked/index.tsx
@@ -1,10 +1,12 @@
+import { useTheme } from '@cowprotocol/common-hooks'
+import { ExternalLink } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import { AlertOctagon } from 'react-feather'
import styled from 'styled-components/macro'
import Column from 'legacy/components/Column'
-import useTheme from 'legacy/hooks/useTheme'
-import { ExternalLink, ThemedText } from 'legacy/theme'
+import { ThemedText } from 'legacy/theme'
import { CopyHelper } from 'modules/account/containers/CopyHelper'
diff --git a/apps/cowswap-frontend/src/modules/advancedOrders/containers/AdvancedOrdersWidget/index.tsx b/apps/cowswap-frontend/src/modules/advancedOrders/containers/AdvancedOrdersWidget/index.tsx
index 3eacbd0b76..e2f1e20f9e 100644
--- a/apps/cowswap-frontend/src/modules/advancedOrders/containers/AdvancedOrdersWidget/index.tsx
+++ b/apps/cowswap-frontend/src/modules/advancedOrders/containers/AdvancedOrdersWidget/index.tsx
@@ -3,7 +3,7 @@ import { PropsWithChildren, ReactNode } from 'react'
import { OrderKind } from '@cowprotocol/cow-sdk'
-import { Field } from 'legacy/state/swap/actions'
+import { Field } from 'legacy/state/types'
import { useAdvancedOrdersActions } from 'modules/advancedOrders/hooks/useAdvancedOrdersActions'
import { useAdvancedOrdersDerivedState } from 'modules/advancedOrders/hooks/useAdvancedOrdersDerivedState'
diff --git a/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useAdvancedOrdersActions.ts b/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useAdvancedOrdersActions.ts
index 871cb922e5..9df7020b55 100644
--- a/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useAdvancedOrdersActions.ts
+++ b/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useAdvancedOrdersActions.ts
@@ -1,10 +1,10 @@
import { useSetAtom } from 'jotai'
import { useCallback } from 'react'
+import { changeSwapAmountAnalytics } from '@cowprotocol/analytics'
import { Currency } from '@uniswap/sdk-core'
-import { changeSwapAmountAnalytics } from 'legacy/components/analytics'
-import { Field } from 'legacy/state/swap/actions'
+import { Field } from 'legacy/state/types'
import { useNavigateOnCurrencySelection } from 'modules/trade/hooks/useNavigateOnCurrencySelection'
import { useSwitchTokensPlaces } from 'modules/trade/hooks/useSwitchTokensPlaces'
diff --git a/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useAdvancedOrdersDerivedState.ts b/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useAdvancedOrdersDerivedState.ts
index b58e60be28..01bf0817c3 100644
--- a/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useAdvancedOrdersDerivedState.ts
+++ b/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useAdvancedOrdersDerivedState.ts
@@ -1,11 +1,12 @@
import { useAtomValue, useSetAtom } from 'jotai'
import { useEffect } from 'react'
+import { TradeType } from 'modules/trade'
import { useBuildTradeDerivedState } from 'modules/trade/hooks/useBuildTradeDerivedState'
import {
- AdvancedOrdersDerivedState,
advancedOrdersAtom,
+ AdvancedOrdersDerivedState,
advancedOrdersDerivedStateAtom,
} from '../state/advancedOrdersAtom'
@@ -21,6 +22,6 @@ export function useFillAdvancedOrdersDerivedState() {
const isUnlocked = rawState.isUnlocked
useEffect(() => {
- updateDerivedState({ ...derivedState, isUnlocked })
+ updateDerivedState({ ...derivedState, isUnlocked, tradeType: TradeType.ADVANCED_ORDERS })
}, [derivedState, isUnlocked, updateDerivedState])
}
diff --git a/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useComposableCowContract.ts b/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useComposableCowContract.ts
index e4ad17f9fc..3d85e43969 100644
--- a/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useComposableCowContract.ts
+++ b/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useComposableCowContract.ts
@@ -1,8 +1,6 @@
-import { ComposableCoW, ComposableCoWAbi } from '@cowswap/abis'
-
-import { useContract } from 'legacy/hooks/useContract'
-
-import { useWalletInfo } from 'modules/wallet'
+import { ComposableCoW, ComposableCoWAbi } from '@cowprotocol/abis'
+import { useContract } from '@cowprotocol/common-hooks'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { COMPOSABLE_COW_ADDRESS } from '../const'
diff --git a/apps/cowswap-frontend/src/modules/advancedOrders/state/advancedOrdersAtom.ts b/apps/cowswap-frontend/src/modules/advancedOrders/state/advancedOrdersAtom.ts
index 854f1c0153..b0244edc12 100644
--- a/apps/cowswap-frontend/src/modules/advancedOrders/state/advancedOrdersAtom.ts
+++ b/apps/cowswap-frontend/src/modules/advancedOrders/state/advancedOrdersAtom.ts
@@ -1,10 +1,9 @@
import { atom } from 'jotai'
import { atomWithStorage } from 'jotai/utils'
+import { getJotaiIsolatedStorage } from '@cowprotocol/core'
import { OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk'
-import { getJotaiIsolatedStorage } from 'jotaiStore'
-
import { DEFAULT_TRADE_DERIVED_STATE, TradeDerivedState } from 'modules/trade/types/TradeDerivedState'
import { ExtendedTradeRawState, getDefaultTradeRawState } from 'modules/trade/types/TradeRawState'
diff --git a/apps/cowswap-frontend/src/modules/advancedOrders/state/advancedOrdersSettingsAtom.ts b/apps/cowswap-frontend/src/modules/advancedOrders/state/advancedOrdersSettingsAtom.ts
index afe566f91d..5d6e2626c5 100644
--- a/apps/cowswap-frontend/src/modules/advancedOrders/state/advancedOrdersSettingsAtom.ts
+++ b/apps/cowswap-frontend/src/modules/advancedOrders/state/advancedOrdersSettingsAtom.ts
@@ -1,7 +1,7 @@
import { atom } from 'jotai'
import { atomWithStorage } from 'jotai/utils'
-import { getJotaiIsolatedStorage } from 'jotaiStore'
+import { getJotaiIsolatedStorage } from '@cowprotocol/core'
export interface AdvancedOrdersSettingsState {
readonly showRecipient: boolean
diff --git a/apps/cowswap-frontend/src/modules/appData/hooks.ts b/apps/cowswap-frontend/src/modules/appData/hooks.ts
index 9e935d697f..389cca11d7 100644
--- a/apps/cowswap-frontend/src/modules/appData/hooks.ts
+++ b/apps/cowswap-frontend/src/modules/appData/hooks.ts
@@ -1,13 +1,11 @@
import { useAtomValue, useSetAtom } from 'jotai'
import { useMemo } from 'react'
-import { DEFAULT_APP_CODE, SAFE_APP_CODE } from 'legacy/constants'
+import { DEFAULT_APP_CODE, SAFE_APP_CODE } from '@cowprotocol/common-const'
+import { isInjectedWidget } from '@cowprotocol/common-utils'
+import { useIsSafeApp } from '@cowprotocol/wallet'
-import { useIsSafeApp } from 'modules/wallet'
-
-import { isInjectedWidget } from 'common/utils/isInjectedWidget'
-
-import { addAppDataToUploadQueueAtom, appDataInfoAtom } from './state/atoms'
+import { addAppDataToUploadQueueAtom, appDataHooksAtom, appDataInfoAtom } from './state/atoms'
import { AppDataInfo } from './types'
import { injectedWidgetMetaDataAtom } from '../injectedWidget/state/injectedWidgetMetaDataAtom'
@@ -39,3 +37,11 @@ export function useAppCode(): string | null {
export function useUploadAppData() {
return useSetAtom(addAppDataToUploadQueueAtom)
}
+
+export function useUpdateAppDataHooks() {
+ return useSetAtom(appDataHooksAtom)
+}
+
+export function useAppDataHooks() {
+ return useAtomValue(appDataHooksAtom)
+}
diff --git a/apps/cowswap-frontend/src/modules/appData/index.ts b/apps/cowswap-frontend/src/modules/appData/index.ts
index 36898fa27a..770057cc7d 100644
--- a/apps/cowswap-frontend/src/modules/appData/index.ts
+++ b/apps/cowswap-frontend/src/modules/appData/index.ts
@@ -1,4 +1,7 @@
export { getAppData } from './utils/fullAppData'
-export * from './updater/AppDataInfoUpdater'
+export * from './updater/AppDataUpdater'
export { useAppData, useUploadAppData } from './hooks'
+export { updateHooksOnAppData, buildAppData } from './utils/buildAppData'
+export { buildAppDataHooks } from './utils/buildAppDataHooks'
+export * from './utils/getAppDataHooks'
export type { AppDataInfo, UploadAppDataParams } from './types'
diff --git a/apps/cowswap-frontend/src/modules/appData/state/atoms.ts b/apps/cowswap-frontend/src/modules/appData/state/atoms.ts
index 209a16a279..73480a7f20 100644
--- a/apps/cowswap-frontend/src/modules/appData/state/atoms.ts
+++ b/apps/cowswap-frontend/src/modules/appData/state/atoms.ts
@@ -4,6 +4,7 @@ import { atomWithStorage } from 'jotai/utils'
import { buildDocFilterFn, buildInverseDocFilterFn } from './utils'
import {
+ AppDataHooks,
AppDataInfo,
AppDataPendingToUpload,
RemoveAppDataFromUploadQueueParams,
@@ -93,3 +94,8 @@ export const removeAppDataFromUploadQueueAtom = atom(
set(appDataUploadQueueAtom, () => get(appDataUploadQueueAtom).filter(buildInverseDocFilterFn(chainId, orderId)))
}
)
+
+/**
+ * In memory atom for storing the current appData hooks info
+ */
+export const appDataHooksAtom = atom(undefined)
diff --git a/apps/cowswap-frontend/src/modules/appData/types.tsx b/apps/cowswap-frontend/src/modules/appData/types.tsx
index 52be631151..521c348b62 100644
--- a/apps/cowswap-frontend/src/modules/appData/types.tsx
+++ b/apps/cowswap-frontend/src/modules/appData/types.tsx
@@ -1,4 +1,4 @@
-import { LatestAppDataDocVersion, createOrderClassMetadata } from '@cowprotocol/app-data'
+import { latest, LatestAppDataDocVersion } from '@cowprotocol/app-data'
import { CowEnv, SupportedChainId } from '@cowprotocol/cow-sdk'
export type AppDataInfo = {
@@ -21,7 +21,7 @@ export type AppDataKeyParams = {
export type AppDataRecord = AppDataInfo & AppDataUploadStatus & AppDataKeyParams
-export type AppDataOrderClass = Parameters[0]['orderClass']
+export type AppDataOrderClass = latest.OrderClass['orderClass']
export type AppDataPendingToUpload = Array
@@ -30,3 +30,11 @@ export type UploadAppDataParams = AppDataKeyParams & {
}
export type UpdateAppDataOnUploadQueueParams = AppDataKeyParams & Partial
export type RemoveAppDataFromUploadQueueParams = AppDataKeyParams
+
+export type AppDataHooks = latest.OrderInteractionHooks
+
+export type PreHooks = latest.PreHooks
+
+export type PostHooks = latest.PostHooks
+
+export type AppDataRootSchema = latest.AppDataRootSchema
diff --git a/apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts b/apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts
new file mode 100644
index 0000000000..d0a7060837
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts
@@ -0,0 +1,25 @@
+import { useEffect, useRef } from 'react'
+
+import { useAccountAgnosticPermitHookData } from 'modules/permit'
+
+import { useUpdateAppDataHooks } from '../hooks'
+import { buildAppDataHooks } from '../utils/buildAppDataHooks'
+
+export function AppDataHooksUpdater(): null {
+ const updateAppDataHooks = useUpdateAppDataHooks()
+ const permitHookData = useAccountAgnosticPermitHookData()
+
+ // To avoid dumb re-renders
+ const ref = useRef(permitHookData)
+ ref.current = permitHookData
+ const stableRef = JSON.stringify(permitHookData)
+
+ useEffect(() => {
+ if (stableRef) {
+ const hooks = buildAppDataHooks(ref.current ? [ref.current] : undefined)
+ updateAppDataHooks(hooks)
+ }
+ }, [stableRef, updateAppDataHooks])
+
+ return null
+}
diff --git a/apps/cowswap-frontend/src/modules/appData/updater/useAppDataUpdater.ts b/apps/cowswap-frontend/src/modules/appData/updater/AppDataInfoUpdater.ts
similarity index 88%
rename from apps/cowswap-frontend/src/modules/appData/updater/useAppDataUpdater.ts
rename to apps/cowswap-frontend/src/modules/appData/updater/AppDataInfoUpdater.ts
index 255269f497..e9cb72f06f 100644
--- a/apps/cowswap-frontend/src/modules/appData/updater/useAppDataUpdater.ts
+++ b/apps/cowswap-frontend/src/modules/appData/updater/AppDataInfoUpdater.ts
@@ -7,7 +7,7 @@ import { UtmParams } from 'modules/utm'
import { useAppCode } from '../hooks'
import { appDataInfoAtom } from '../state/atoms'
-import { AppDataOrderClass } from '../types'
+import { AppDataHooks, AppDataOrderClass } from '../types'
import { buildAppData, BuildAppDataParams } from '../utils/buildAppData'
import { getAppData } from '../utils/fullAppData'
@@ -16,13 +16,14 @@ export type UseAppDataParams = {
slippageBips: string
orderClass: AppDataOrderClass
utm: UtmParams | undefined
+ hooks?: AppDataHooks
}
/**
* Fetches and updates appDataInfo whenever a dependency changes
* The hook can be called only from an updater
*/
-export function useAppDataUpdater({ chainId, slippageBips, orderClass, utm }: UseAppDataParams): void {
+export function AppDataInfoUpdater({ chainId, slippageBips, orderClass, utm, hooks }: UseAppDataParams): void {
// AppDataInfo, from Jotai
const setAppDataInfo = useSetAtom(appDataInfoAtom)
@@ -36,7 +37,7 @@ export function useAppDataUpdater({ chainId, slippageBips, orderClass, utm }: Us
return
}
- const params: BuildAppDataParams = { chainId, slippageBips, appCode, orderClass, utm }
+ const params: BuildAppDataParams = { chainId, slippageBips, appCode, orderClass, utm, hooks }
const updateAppData = async (): Promise => {
try {
@@ -51,7 +52,7 @@ export function useAppDataUpdater({ chainId, slippageBips, orderClass, utm }: Us
}
updateAppData()
- }, [appCode, chainId, setAppDataInfo, slippageBips, orderClass, utm])
+ }, [appCode, chainId, setAppDataInfo, slippageBips, orderClass, utm, hooks])
}
function getEnvByClass(orderClass: string): CowEnv | undefined {
if (orderClass === 'twap') {
diff --git a/apps/cowswap-frontend/src/modules/appData/updater/AppDataInfoUpdater.tsx b/apps/cowswap-frontend/src/modules/appData/updater/AppDataUpdater.tsx
similarity index 52%
rename from apps/cowswap-frontend/src/modules/appData/updater/AppDataInfoUpdater.tsx
rename to apps/cowswap-frontend/src/modules/appData/updater/AppDataUpdater.tsx
index 26b2bdf2c7..481b8b96ae 100644
--- a/apps/cowswap-frontend/src/modules/appData/updater/AppDataInfoUpdater.tsx
+++ b/apps/cowswap-frontend/src/modules/appData/updater/AppDataUpdater.tsx
@@ -1,14 +1,15 @@
import React from 'react'
+import { percentToBips } from '@cowprotocol/common-utils'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Percent } from '@uniswap/sdk-core'
-import { percentToBips } from 'legacy/utils/misc'
-
import { useUtm } from 'modules/utm'
-import { useWalletInfo } from 'modules/wallet'
-import { UseAppDataParams, useAppDataUpdater } from './useAppDataUpdater'
+import { AppDataHooksUpdater } from './AppDataHooksUpdater'
+import { AppDataInfoUpdater, UseAppDataParams } from './AppDataInfoUpdater'
+import { useAppDataHooks } from '../hooks'
import { AppDataOrderClass } from '../types'
interface AppDataUpdaterProps {
@@ -21,14 +22,18 @@ export const AppDataUpdater = React.memo(({ slippage, orderClass }: AppDataUpdat
const slippageBips = percentToBips(slippage)
const utm = useUtm()
+ const hooks = useAppDataHooks()
if (!chainId) return null
- return
+ return (
+
+ )
})
const AppDataUpdaterMemo = React.memo((params: UseAppDataParams) => {
- useAppDataUpdater(params)
+ AppDataHooksUpdater()
+ AppDataInfoUpdater(params)
return null
})
diff --git a/apps/cowswap-frontend/src/modules/appData/utils/buildAppData.ts b/apps/cowswap-frontend/src/modules/appData/utils/buildAppData.ts
index 1bccca5c4c..0239246bd0 100644
--- a/apps/cowswap-frontend/src/modules/appData/utils/buildAppData.ts
+++ b/apps/cowswap-frontend/src/modules/appData/utils/buildAppData.ts
@@ -1,13 +1,13 @@
+import { stringifyDeterministic } from '@cowprotocol/app-data'
+import { environmentName } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { metadataApiSDK } from 'cowSdk'
import { keccak256, toUtf8Bytes } from 'ethers/lib/utils'
-import { environmentName } from 'legacy/utils/environments'
-
import { UtmParams } from 'modules/utm'
-import { AppDataOrderClass } from '../types'
+import { AppDataHooks, AppDataInfo, AppDataOrderClass, AppDataRootSchema } from '../types'
export type BuildAppDataParams = {
appCode: string
@@ -16,6 +16,15 @@ export type BuildAppDataParams = {
orderClass: AppDataOrderClass
referrerAccount?: string
utm: UtmParams | undefined
+ hooks?: AppDataHooks
+}
+
+async function generateAppDataFromDoc(
+ doc: AppDataRootSchema
+): Promise> {
+ const fullAppData = await stringifyDeterministic(doc)
+ const appDataKeccak256 = toKeccak256(fullAppData)
+ return { fullAppData, appDataKeccak256 }
}
export async function buildAppData({
@@ -23,22 +32,23 @@ export async function buildAppData({
slippageBips,
referrerAccount,
appCode,
- orderClass,
- utm: utmParams,
-}: BuildAppDataParams) {
+ orderClass: orderClassName,
+ utm,
+ hooks,
+}: BuildAppDataParams): Promise {
const referrerParams =
referrerAccount && chainId === SupportedChainId.MAINNET ? { address: referrerAccount } : undefined
const quoteParams = { slippageBips }
- const orderClassParams = { orderClass }
+ const orderClass = { orderClass: orderClassName }
const doc = await metadataApiSDK.generateAppDataDoc({
- appDataParams: { appCode, environment: environmentName },
- metadataParams: { referrerParams, quoteParams, orderClassParams, utmParams },
+ appCode,
+ environment: environmentName,
+ metadata: { referrer: referrerParams, quote: quoteParams, orderClass, utm, hooks },
})
- const fullAppData = JSON.stringify(doc)
- const appDataKeccak256 = toKeccak256(fullAppData)
+ const { fullAppData, appDataKeccak256 } = await generateAppDataFromDoc(doc)
return { doc, fullAppData, appDataKeccak256 }
}
@@ -46,3 +56,27 @@ export async function buildAppData({
export function toKeccak256(fullAppData: string) {
return keccak256(toUtf8Bytes(fullAppData))
}
+
+export async function updateHooksOnAppData(appData: AppDataInfo, hooks: AppDataHooks | undefined): Promise {
+ const { doc } = appData
+
+ const newDoc = {
+ ...doc,
+ metadata: {
+ ...doc.metadata,
+ hooks,
+ },
+ }
+
+ if (!hooks) {
+ delete newDoc.metadata.hooks
+ }
+
+ const { fullAppData, appDataKeccak256 } = await generateAppDataFromDoc(newDoc)
+
+ return {
+ doc: newDoc,
+ fullAppData,
+ appDataKeccak256,
+ }
+}
diff --git a/apps/cowswap-frontend/src/modules/appData/utils/buildAppDataHooks.ts b/apps/cowswap-frontend/src/modules/appData/utils/buildAppDataHooks.ts
new file mode 100644
index 0000000000..a03512a3ae
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/appData/utils/buildAppDataHooks.ts
@@ -0,0 +1,15 @@
+import { AppDataHooks, PostHooks, PreHooks } from '../types'
+
+export function buildAppDataHooks(
+ preInteractionHooks?: PreHooks,
+ postInteractionHooks?: PostHooks
+): AppDataHooks | undefined {
+ if (!preInteractionHooks && !postInteractionHooks) {
+ return undefined
+ }
+
+ return {
+ ...(preInteractionHooks ? { pre: preInteractionHooks } : undefined),
+ ...(postInteractionHooks ? { post: postInteractionHooks } : undefined),
+ }
+}
diff --git a/apps/cowswap-frontend/src/modules/appData/utils/decodeAppData.ts b/apps/cowswap-frontend/src/modules/appData/utils/decodeAppData.ts
new file mode 100644
index 0000000000..b9aba4974c
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/appData/utils/decodeAppData.ts
@@ -0,0 +1,24 @@
+import { AnyAppDataDocVersion } from '@cowprotocol/app-data'
+
+import { Nullish } from 'types'
+
+/**
+ * Decode appData from a string to a AnyAppDataDocVersion instance
+ * Keep in mind it can be a valid JSON but not necessarily a valid AppDataDoc
+ *
+ * Returns undefined if the given appData is not a valid JSON
+ */
+export function decodeAppData(appData: Nullish): AnyAppDataDocVersion | undefined {
+ if (!appData) {
+ return undefined
+ }
+
+ try {
+ // TODO: returned value can be a valid JSON but not necessarily a valid AppDataDoc
+ return JSON.parse(appData)
+ } catch (e) {
+ console.info(`[decodeAppData] given appData is not a valid JSON`, appData)
+
+ return undefined
+ }
+}
diff --git a/apps/cowswap-frontend/src/modules/appData/utils/fullAppData.ts b/apps/cowswap-frontend/src/modules/appData/utils/fullAppData.ts
index eb801f6436..08cdc6fac3 100644
--- a/apps/cowswap-frontend/src/modules/appData/utils/fullAppData.ts
+++ b/apps/cowswap-frontend/src/modules/appData/utils/fullAppData.ts
@@ -1,4 +1,4 @@
-import { environmentName } from 'legacy/utils/environments'
+import { environmentName } from '@cowprotocol/common-utils'
import { AppDataInfo } from '../types'
import { toKeccak256 } from '../utils/buildAppData'
diff --git a/apps/cowswap-frontend/src/modules/appData/utils/getAppDataHooks.ts b/apps/cowswap-frontend/src/modules/appData/utils/getAppDataHooks.ts
new file mode 100644
index 0000000000..7aa825789e
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/appData/utils/getAppDataHooks.ts
@@ -0,0 +1,21 @@
+import { AnyAppDataDocVersion } from '@cowprotocol/app-data'
+
+import { Nullish } from 'types'
+
+import { decodeAppData } from './decodeAppData'
+
+import { AppDataHooks } from '../types'
+
+/**
+ * Get hooks from fullAppData, which can be JSON stringified or the instance
+ *
+ * Returns undefined if the fullAppData is falsy or if there are no hooks
+ */
+export function getAppDataHooks(fullAppData: Nullish): AppDataHooks | undefined {
+ const decodedAppData = typeof fullAppData === 'string' ? decodeAppData(fullAppData) : fullAppData
+
+ if (!decodedAppData || !('hooks' in decodedAppData.metadata)) return undefined
+
+ // TODO: this requires app-data v0.9.0. Might not work for newer versions...
+ return decodedAppData.metadata.hooks as AppDataHooks
+}
diff --git a/apps/cowswap-frontend/src/modules/application/containers/App/RoutesApp.tsx b/apps/cowswap-frontend/src/modules/application/containers/App/RoutesApp.tsx
index 6e83f67b24..588f1828d7 100644
--- a/apps/cowswap-frontend/src/modules/application/containers/App/RoutesApp.tsx
+++ b/apps/cowswap-frontend/src/modules/application/containers/App/RoutesApp.tsx
@@ -1,10 +1,11 @@
import { lazy, ReactNode, Suspense } from 'react'
+import { DISCORD_LINK, DOCS_LINK, DUNE_DASHBOARD_LINK, TWITTER_LINK } from '@cowprotocol/common-const'
+import { Loader } from '@cowprotocol/ui'
+
import { Navigate, Route, Routes } from 'react-router-dom'
import { Loading } from 'legacy/components/FlashingLoading'
-import Loader from 'legacy/components/Loader'
-import { DISCORD_LINK, DOCS_LINK, DUNE_DASHBOARD_LINK, TWITTER_LINK } from 'legacy/constants'
import { RedirectPathToSwapOnly, RedirectToPath } from 'legacy/pages/Swap/redirects'
import { Routes as RoutesEnum, RoutesValues } from 'common/constants/routes'
@@ -35,9 +36,6 @@ const EthFlowFaq = lazy(() => import(/* webpackChunkName: "eth_flow_faq" */ 'pag
const AccountTokensOverview = lazy(() => import(/* webpackChunkName: "tokens_overview" */ 'pages/Account/Tokens'))
const AccountNotFound = lazy(() => import(/* webpackChunkName: "affiliate" */ 'pages/error/NotFound'))
-// Misc
-const KitchenSink = lazy(() => import(/* webpackChunkName: "kitchen_sink" */ 'pages/KitchenSink'))
-
function createRedirectExternal(url: string) {
return () => {
window.location.replace(url)
@@ -68,7 +66,6 @@ const lazyRoutes: LazyRouteProps[] = [
{ route: RoutesEnum.PRIVACY_POLICY, element: },
{ route: RoutesEnum.COOKIE_POLICY, element: },
{ route: RoutesEnum.TERMS_CONDITIONS, element: },
- { route: RoutesEnum.KITCHEN_SINK, element: },
]
export function RoutesApp() {
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 306481a0c5..557ee7d30d 100644
--- a/apps/cowswap-frontend/src/modules/application/containers/App/Updaters.tsx
+++ b/apps/cowswap-frontend/src/modules/application/containers/App/Updaters.tsx
@@ -1,31 +1,34 @@
-import ApplicationUpdater from 'legacy/state/application/updater'
-import EnhancedTransactionUpdater from 'legacy/state/enhancedTransactions/updater'
+import { WalletUpdater } from '@cowprotocol/wallet'
+
import { GasPriceStrategyUpdater } from 'legacy/state/gas/gas-price-strategy-updater'
-import GasUpdater from 'legacy/state/gas/updater'
-import ListsUpdater from 'legacy/state/lists/updater'
-import LogsUpdater from 'legacy/state/logs/updater'
-import {
- CancelledOrdersUpdater,
- ExpiredOrdersUpdater,
- GpOrdersUpdater,
- PendingOrdersUpdater,
- UnfillableOrdersUpdater,
-} from 'legacy/state/orders/updaters'
-import { SpotPricesUpdater } from 'legacy/state/orders/updaters/SpotPricesUpdater'
-import FeesUpdater from 'legacy/state/price/updater'
-import SentryUpdater from 'legacy/state/sentry/updater'
-import UserUpdater from 'legacy/state/user/updater'
+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 { WalletUpdater, HwAccountIndexUpdater } from 'modules/wallet'
import { TotalSurplusUpdater } from 'common/state/totalSurplusState'
+import { ApplicationUpdater } from 'common/updaters/ApplicationUpdater'
+import { CancelReplaceTxUpdater } from 'common/updaters/CancelReplaceTxUpdater'
+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,
+ ExpiredOrdersUpdater,
+ GpOrdersUpdater,
+ PendingOrdersUpdater,
+ UnfillableOrdersUpdater,
+} from 'common/updaters/orders'
+import { SpotPricesUpdater } from 'common/updaters/orders/SpotPricesUpdater'
+import { SentryUpdater } from 'common/updaters/SentryUpdater'
import { ThemeFromUrlUpdater } from 'common/updaters/ThemeFromUrlUpdater'
-import { MulticallUpdater } from 'lib/state/multicall'
+import { UserUpdater } from 'common/updaters/UserUpdater'
export function Updaters() {
return (
@@ -36,7 +39,8 @@ export function Updaters() {
-
+
+
diff --git a/apps/cowswap-frontend/src/modules/application/containers/App/index.tsx b/apps/cowswap-frontend/src/modules/application/containers/App/index.tsx
index cd5f7727d4..9af824dfc5 100644
--- a/apps/cowswap-frontend/src/modules/application/containers/App/index.tsx
+++ b/apps/cowswap-frontend/src/modules/application/containers/App/index.tsx
@@ -1,23 +1,22 @@
-import { initializeAnalytics } from 'legacy/components/AmplitudeAnalytics'
-import { useAnalyticsReporter } from 'legacy/components/analytics'
+import { isInjectedWidget } from '@cowprotocol/common-utils'
+
import ErrorBoundary from 'legacy/components/ErrorBoundary'
import Footer from 'legacy/components/Footer'
import Header from 'legacy/components/Header'
import URLWarning from 'legacy/components/Header/URLWarning'
import TopLevelModals from 'legacy/components/TopLevelModals'
-import ApeModeQueryParamReader from 'legacy/hooks/useApeModeQueryParamReader'
import DarkModeQueryParamReader from 'legacy/theme'
import { useInitializeUtm } from 'modules/utm'
-import { isInjectedWidget } from 'common/utils/isInjectedWidget'
import RedirectAnySwapAffectedUsers from 'pages/error/AnySwapAffectedUsers/RedirectAnySwapAffectedUsers'
import { RoutesApp } from './RoutesApp'
import * as styledEl from './styled'
+import { useAnalyticsReporter } from '../../../../common/hooks/useAnalyticsReporter'
+
export function App() {
- initializeAnalytics()
useAnalyticsReporter()
useInitializeUtm()
@@ -27,7 +26,6 @@ export function App() {
-
diff --git a/apps/cowswap-frontend/src/modules/application/containers/PageTitle/index.tsx b/apps/cowswap-frontend/src/modules/application/containers/PageTitle/index.tsx
index 1ede20b483..05a566bf39 100644
--- a/apps/cowswap-frontend/src/modules/application/containers/PageTitle/index.tsx
+++ b/apps/cowswap-frontend/src/modules/application/containers/PageTitle/index.tsx
@@ -1,6 +1,6 @@
-import { Helmet } from 'react-helmet'
+import { APP_TITLE } from '@cowprotocol/common-const'
-import { APP_TITLE } from 'legacy/constants'
+import { Helmet } from 'react-helmet'
type PageTitleProps = {
title?: string
diff --git a/apps/cowswap-frontend/src/modules/application/containers/TradeWidgetLinks/index.tsx b/apps/cowswap-frontend/src/modules/application/containers/TradeWidgetLinks/index.tsx
index 2aebee6968..71eba2d6cc 100644
--- a/apps/cowswap-frontend/src/modules/application/containers/TradeWidgetLinks/index.tsx
+++ b/apps/cowswap-frontend/src/modules/application/containers/TradeWidgetLinks/index.tsx
@@ -12,15 +12,15 @@ import { FeatureGuard } from 'common/containers/FeatureGuard'
import * as styledEl from './styled'
interface MenuItemConfig {
- route: RoutesValues;
- label: string;
- featureGuard?: string;
- onClick?: () => void;
- badgeText?: string;
- badgeType?: BadgeType;
+ route: RoutesValues
+ label: string
+ featureGuard?: string
+ onClick?: () => void
+ badgeText?: string
+ badgeType?: BadgeType
}
-export type BadgeType = 'information' | 'success' | 'alert' | 'alert2' | 'default';
+export type BadgeType = 'information' | 'success' | 'alert' | 'alert2' | 'default'
const MENU_ITEMS: MenuItemConfig[] = [
{ route: Routes.SWAP, label: 'Swap' },
@@ -28,15 +28,14 @@ const MENU_ITEMS: MenuItemConfig[] = [
{
route: Routes.ADVANCED_ORDERS,
label: 'TWAP',
- featureGuard: 'advancedOrdersEnabled',
badgeText: 'NEW!',
- badgeType: 'alert2'
+ badgeType: 'alert2',
},
]
interface TradeWidgetLinksProps {
- highlightedBadgeText?: string;
- highlightedBadgeType?: BadgeType;
+ highlightedBadgeText?: string
+ highlightedBadgeType?: BadgeType
}
export function TradeWidgetLinks({ highlightedBadgeText, highlightedBadgeType }: TradeWidgetLinksProps) {
@@ -45,21 +44,21 @@ export function TradeWidgetLinks({ highlightedBadgeText, highlightedBadgeType }:
const buildMenuItem = useCallback(
(item: MenuItemConfig) => {
- const routePath = parameterizeTradeRoute(tradeContext, item.route);
-
- const isActive = !!matchPath(location.pathname, routePath);
-
+ const routePath = parameterizeTradeRoute(tradeContext, item.route)
+
+ const isActive = !!matchPath(location.pathname, routePath)
+
const menuItem = (
-
- );
-
+ )
+
return item.featureGuard ? (
{menuItem}
@@ -69,17 +68,23 @@ export function TradeWidgetLinks({ highlightedBadgeText, highlightedBadgeType }:
)
},
[location.pathname, tradeContext, highlightedBadgeText, highlightedBadgeType]
- );
+ )
return {MENU_ITEMS.map(buildMenuItem)}
}
-const MenuItem = ({ routePath, item, isActive, badgeText, badgeType }: {
- routePath: string;
- item: MenuItemConfig;
- isActive: boolean;
- badgeText?: string;
- badgeType?: BadgeType;
+const MenuItem = ({
+ routePath,
+ item,
+ isActive,
+ badgeText,
+ badgeType,
+}: {
+ routePath: string
+ item: MenuItemConfig
+ isActive: boolean
+ badgeText?: string
+ badgeType?: BadgeType
}) => (
diff --git a/apps/cowswap-frontend/src/modules/application/containers/TradeWidgetLinks/styled.ts b/apps/cowswap-frontend/src/modules/application/containers/TradeWidgetLinks/styled.ts
index 7bbd4a0e52..660e51fe25 100644
--- a/apps/cowswap-frontend/src/modules/application/containers/TradeWidgetLinks/styled.ts
+++ b/apps/cowswap-frontend/src/modules/application/containers/TradeWidgetLinks/styled.ts
@@ -2,22 +2,24 @@ import { transparentize } from 'polished'
import { NavLink } from 'react-router-dom'
import styled, { css } from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
import { BadgeType } from '.'
const badgeBackgrounds: Record = {
- information: 'var(--cow-color-information-bg)',
- alert: 'var(--cow-color-alert-bg)',
- alert2: 'var(--cow-color-alert2-bg)',
- success: 'var(--cow-color-success-bg)',
+ information: `var(${UI.COLOR_INFORMATION_BG})`,
+ alert: `var(${UI.COLOR_ALERT_BG})`,
+ alert2: `var(${UI.COLOR_ALERT2_BG})`,
+ success: `var(${UI.COLOR_SUCCESS_BG})`,
default: 'transparent', // text only
};
const badgeColors: Record = {
- information: 'var(--cow-color-information-text)',
- alert: 'var(--cow-color-alert-text)',
- alert2: 'var(--cow-color-alert2-text)',
- success: 'var(--cow-color-success-text)',
- default: 'var(--cow-color-text1-inactive)', // text only
+ information: `var(${UI.COLOR_INFORMATION_TEXT})`,
+ alert: `var(${UI.COLOR_ALERT_TEXT})`,
+ alert2: `var(${UI.COLOR_ALERT2_TEXT})`,
+ success: `var(${UI.COLOR_SUCCESS_TEXT})`,
+ default: `var(${UI.COLOR_TEXT1_INACTIVE})`, // text only
};
export const Badge = styled.div<{ type?: BadgeType }>`
@@ -82,13 +84,13 @@ export const MenuItem = styled.div<{ isActive?: boolean }>`
background: transparent;
transition: background 0.2 ease-in-out;
- ${({ isActive, theme }) =>
+ ${({ isActive }) =>
isActive &&
css`
- background: ${theme.grey1};
+ background: var(${UI.COLOR_GREY});
${Link} {
- color: ${theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
${Link} > ${Badge} {
diff --git a/apps/cowswap-frontend/src/modules/application/pure/Page/index.tsx b/apps/cowswap-frontend/src/modules/application/pure/Page/index.tsx
index 72dda63979..e57911bff9 100644
--- a/apps/cowswap-frontend/src/modules/application/pure/Page/index.tsx
+++ b/apps/cowswap-frontend/src/modules/application/pure/Page/index.tsx
@@ -7,6 +7,8 @@ import { WithClassName } from 'legacy/types'
import { Widget } from 'modules/application/pure/Widget'
+import { UI } from 'common/constants/theme'
+
export const PageWrapper = styled(Widget)`
padding: 0 24px 24px;
max-width: ${({ theme }) => theme.appBody.maxWidth.content};
@@ -16,7 +18,7 @@ export const PageWrapper = styled(Widget)`
export const Title = styled.h1`
font-size: 32px;
margin: 24px 0;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
text-shadow: ${({ theme }) => theme.textShadow1};
font-weight: 500;
@@ -170,7 +172,7 @@ export const GdocsListStyle = css`
ol {
margin: 24px 0;
padding: 12px 48px;
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
border-radius: 12px;
> li {
diff --git a/apps/cowswap-frontend/src/modules/application/pure/Widget/index.tsx b/apps/cowswap-frontend/src/modules/application/pure/Widget/index.tsx
index bc476793c1..42bd2a222a 100644
--- a/apps/cowswap-frontend/src/modules/application/pure/Widget/index.tsx
+++ b/apps/cowswap-frontend/src/modules/application/pure/Widget/index.tsx
@@ -2,8 +2,10 @@ import styled from 'styled-components/macro'
import { BodyWrapper as BodyWrapperMod } from 'legacy/pages/AppBody'
+import { UI } from 'common/constants/theme'
+
const Wrapper = styled(BodyWrapperMod)`
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
border: 0;
border-radius: 16px;
box-shadow: ${({ theme }) => theme.boxShadow1};
diff --git a/apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx b/apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx
index b37ccdba8e..2ec8e3ab9f 100644
--- a/apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx
+++ b/apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx
@@ -2,17 +2,19 @@ import { useAtom, useAtomValue } from 'jotai'
import { useSetAtom } from 'jotai'
import { useCallback, useMemo, useRef, useState } from 'react'
+import { openFortuneCookieAnalytics, shareFortuneTwitterAnalytics } from '@cowprotocol/analytics'
+import fortuneCookieImage from '@cowprotocol/assets/cow-swap/fortune-cookie.png'
+import twitterImage from '@cowprotocol/assets/cow-swap/twitter.svg'
+import { useInterval } from '@cowprotocol/common-hooks'
+import { addBodyClass, removeBodyClass } from '@cowprotocol/common-utils'
+import { ExternalLink } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import { X } from 'react-feather'
import SVG from 'react-inlinesvg'
import styled from 'styled-components/macro'
-import fortuneCookieImage from 'legacy/assets/cow-swap/fortune-cookie.png'
-import twitterImage from 'legacy/assets/cow-swap/twitter.svg'
-import { openFortuneCookieAnalytics, shareFortuneTwitterAnalytics } from 'legacy/components/analytics/events/cowFortune'
import Confetti from 'legacy/components/Confetti'
-import { ExternalLink } from 'legacy/theme'
-import { addBodyClass, removeBodyClass } from 'legacy/utils/toggleBodyClass'
import { useOpenRandomFortune } from 'modules/fortune/hooks/useOpenRandomFortune'
import { lastCheckedFortuneAtom } from 'modules/fortune/state/checkedFortunesListAtom'
@@ -22,7 +24,7 @@ import {
updateOpenFortuneAtom,
} from 'modules/fortune/state/fortuneStateAtom'
-import useInterval from 'lib/hooks/useInterval'
+import { UI } from 'common/constants/theme'
import { SuccessBanner } from 'pages/Claim/styled'
const FortuneButton = styled.div<{ isDailyFortuneChecked: boolean }>`
@@ -119,7 +121,7 @@ const FortuneBanner = styled.div`
left: 0;
bottom: 0;
z-index: 501;
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
padding: 0;
animation: open 0.3s ease-in-out forwards;
overflow: hidden;
@@ -182,7 +184,7 @@ const FortuneTitle = styled.h2`
font-size: 21px;
text-align: center;
font-weight: 700;
- color: ${({ theme }) => theme.text2};
+ color: var(${UI.COLOR_TEXT2});
> i {
font-size: 16px;
@@ -226,7 +228,7 @@ const FortuneText = styled.h3`
&:before,
&:after {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
font-size: 100px;
position: absolute;
z-index: 1;
@@ -242,11 +244,11 @@ const FortuneContent = styled.div`
align-items: center;
width: 100%;
max-width: 500px;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
`
const StyledExternalLink = styled(ExternalLink)`
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
border-radius: 24px;
`
@@ -255,7 +257,7 @@ const HeaderElement = styled.div`
align-items: center;
justify-content: space-between;
width: 100%;
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
position: fixed;
padding: 0 16px;
top: 0;
@@ -282,7 +284,7 @@ const StyledCloseIcon = styled(X)`
}
> line {
- stroke: ${({ theme }) => theme.text1};
+ stroke: var(${UI.COLOR_TEXT1});
}
`
diff --git a/apps/cowswap-frontend/src/modules/fortune/hooks/useOpenRandomFortune.ts b/apps/cowswap-frontend/src/modules/fortune/hooks/useOpenRandomFortune.ts
index a1ef978284..aa60fabcc1 100644
--- a/apps/cowswap-frontend/src/modules/fortune/hooks/useOpenRandomFortune.ts
+++ b/apps/cowswap-frontend/src/modules/fortune/hooks/useOpenRandomFortune.ts
@@ -2,13 +2,13 @@ import { useAtom, useAtomValue } from 'jotai'
import { useSetAtom } from 'jotai'
import { useCallback } from 'react'
+import { getRandomInt } from '@cowprotocol/common-utils'
+
import { CheckedFortunesList, checkedFortunesListAtom } from 'modules/fortune/state/checkedFortunesListAtom'
import { fortunesListAtom } from 'modules/fortune/state/fortunesListAtom'
import { updateOpenFortuneAtom } from 'modules/fortune/state/fortuneStateAtom'
import { FortuneItem } from 'modules/fortune/types'
-import { getRandomInt } from 'utils/getRandomInt'
-
function getRandomFortuneFromList(items: FortuneItem[], checkedFortunes: CheckedFortunesList): FortuneItem | null {
const list = items.filter((item) => !checkedFortunes[item.id])
const index = getRandomInt(0, list.length - 1)
diff --git a/apps/cowswap-frontend/src/modules/fortune/state/fortunesListAtom.ts b/apps/cowswap-frontend/src/modules/fortune/state/fortunesListAtom.ts
index 8f4003c8cc..e19fa38250 100644
--- a/apps/cowswap-frontend/src/modules/fortune/state/fortunesListAtom.ts
+++ b/apps/cowswap-frontend/src/modules/fortune/state/fortunesListAtom.ts
@@ -1,7 +1,7 @@
import { atom } from 'jotai'
import { loadable } from 'jotai/utils'
-import { RAW_CODE_LINK } from 'legacy/constants'
+import { RAW_CODE_LINK } from '@cowprotocol/common-const'
import { FortuneItem } from 'modules/fortune/types'
diff --git a/apps/cowswap-frontend/src/modules/injectedWidget/updaters/InjectedWidgetUpdater.ts b/apps/cowswap-frontend/src/modules/injectedWidget/updaters/InjectedWidgetUpdater.ts
index 51572471e2..54c63dd2a7 100644
--- a/apps/cowswap-frontend/src/modules/injectedWidget/updaters/InjectedWidgetUpdater.ts
+++ b/apps/cowswap-frontend/src/modules/injectedWidget/updaters/InjectedWidgetUpdater.ts
@@ -1,9 +1,9 @@
import { useSetAtom } from 'jotai'
import { useCallback, useEffect, useRef } from 'react'
-import { useNavigate } from 'react-router-dom'
+import { deepEqual } from '@cowprotocol/common-utils'
-import { deepEqual } from 'utils/deepEqual'
+import { useNavigate } from 'react-router-dom'
import { injectedWidgetMetaDataAtom } from '../state/injectedWidgetMetaDataAtom'
import { injectedWidgetParamsAtom } from '../state/injectedWidgetParamsAtom'
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 7416a35a79..7c8fa13f95 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersConfirmModal/index.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersConfirmModal/index.tsx
@@ -1,7 +1,8 @@
-import { useAtom } from 'jotai'
-import { useAtomValue } from 'jotai'
+import { useAtom, useAtomValue } from 'jotai'
import React from 'react'
+import { TokenSymbol } from '@cowprotocol/ui'
+
import { PriceImpact } from 'legacy/hooks/usePriceImpact'
import { LimitOrdersWarnings } from 'modules/limitOrders/containers/LimitOrdersWarnings'
@@ -15,10 +16,8 @@ import { limitRateAtom } from 'modules/limitOrders/state/limitRateAtom'
import { partiallyFillableOverrideAtom } from 'modules/limitOrders/state/partiallyFillableOverride'
import { TradeConfirmation, TradeConfirmModal, useTradeConfirmActions } from 'modules/trade'
-import { useFeatureFlags } from 'common/hooks/featureFlags/useFeatureFlags'
import { useRateInfoParams } from 'common/hooks/useRateInfoParams'
import { CurrencyPreviewInfo } from 'common/pure/CurrencyAmountPreview'
-import { TokenSymbol } from 'common/pure/TokenSymbol'
import { LOW_RATE_THRESHOLD_PERCENT } from '../../const/trade'
import { LimitOrdersDetails } from '../../pure/LimitOrdersDetails'
@@ -38,7 +37,6 @@ export function LimitOrdersConfirmModal(props: LimitOrdersConfirmModalProps) {
const executionPrice = useAtomValue(executionPriceAtom)
const limitRateState = useAtomValue(limitRateAtom)
const partiallyFillableOverride = useAtom(partiallyFillableOverrideAtom)
- const { partialFillsEnabled } = useFeatureFlags()
const { amount: inputAmount } = inputCurrencyInfo
const { amount: outputAmount } = outputCurrencyInfo
@@ -83,7 +81,6 @@ export function LimitOrdersConfirmModal(props: LimitOrdersConfirmModalProps) {
settingsState={settingsState}
executionPrice={executionPrice}
partiallyFillableOverride={partiallyFillableOverride}
- featurePartialFillsEnabled={partialFillsEnabled}
/>
>
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWarnings/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWarnings/index.tsx
index 865d955012..c82bd3c577 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWarnings/index.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWarnings/index.tsx
@@ -1,7 +1,8 @@
-import { useSetAtom } from 'jotai'
-import { useAtomValue } from 'jotai'
+import { useAtomValue, useSetAtom } from 'jotai'
import React, { useCallback, useEffect } from 'react'
+import { isFractionFalsy } from '@cowprotocol/common-utils'
+import { useIsSafeViaWc, useWalletInfo } from '@cowprotocol/wallet'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import styled from 'styled-components/macro'
@@ -16,20 +17,21 @@ import {
updateLimitOrdersWarningsAtom,
} from 'modules/limitOrders/state/limitOrdersWarningsAtom'
import { useTradePriceImpact } from 'modules/trade'
+import { useDerivedTradeState } from 'modules/trade/hooks/useDerivedTradeState'
import { NoImpactWarning } from 'modules/trade/pure/NoImpactWarning'
import { TradeFormValidation, useGetTradeFormValidation } from 'modules/tradeFormValidation'
import { useTradeQuote } from 'modules/tradeQuote'
-import { useIsSafeViaWc, useWalletInfo } from 'modules/wallet'
import { HIGH_FEE_WARNING_PERCENTAGE } from 'common/constants/common'
import { useShouldZeroApprove } from 'common/hooks/useShouldZeroApprove'
import {
+ BannerOrientation,
BundleTxApprovalBanner,
BundleTxSafeWcBanner,
+ CustomRecipientWarningBanner,
SmallVolumeWarningBanner,
} from 'common/pure/InlineBanner/banners'
import { ZeroApprovalWarning } from 'common/pure/ZeroApprovalWarning'
-import { isFractionFalsy } from 'utils/isFractionFalsy'
import { calculatePercentageInRelationToReference } from 'utils/orderUtils/calculatePercentageInRelationToReference'
import { RateImpactWarning } from '../../pure/RateImpactWarning'
@@ -103,13 +105,17 @@ export function LimitOrdersWarnings(props: LimitOrdersWarningsProps) {
isSafeViaWc &&
primaryFormValidation === TradeFormValidation.ApproveRequired
+ const { state } = useDerivedTradeState()
+ const showRecipientWarning = isConfirmScreen && state?.recipient && account !== state.recipient
+
const isVisible =
showPriceImpactWarning ||
rateImpact < 0 ||
showHighFeeWarning ||
showApprovalBundlingBanner ||
showSafeWcBundlingBanner ||
- shouldZeroApprove
+ shouldZeroApprove ||
+ showRecipientWarning
// Reset price impact flag when there is no price impact
useEffect(() => {
@@ -135,6 +141,7 @@ export function LimitOrdersWarnings(props: LimitOrdersWarningsProps) {
return isVisible ? (
+ {showRecipientWarning && }
{showZeroApprovalWarning && }
{showPriceImpactWarning && (
{
isRateLoading,
widgetActions,
partiallyFillableOverride,
- featurePartialFillsEnabled,
showRecipient,
isExpertMode,
recipient,
@@ -169,7 +165,7 @@ const LimitOrders = React.memo((props: LimitOrdersProps) => {
return isRateLoading
}, [isRateLoading, inputCurrency, outputCurrency])
- const isPartiallyFillable = featurePartialFillsEnabled && settingsState.partialFillsEnabled
+ const isPartiallyFillable = settingsState.partialFillsEnabled
const updateLimitOrdersState = useSetAtom(updateLimitOrdersRawStateAtom)
@@ -220,7 +216,6 @@ const LimitOrders = React.memo((props: LimitOrdersProps) => {
)}
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/limitOrdersPropsChecker.ts b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/limitOrdersPropsChecker.ts
index c2f0aa9d54..c35fd1d766 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/limitOrdersPropsChecker.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/limitOrdersPropsChecker.ts
@@ -1,3 +1,4 @@
+import { areFractionsEqual, genericPropsChecker, getAddress } from '@cowprotocol/common-utils'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import { PriceImpact } from 'legacy/hooks/usePriceImpact'
@@ -10,9 +11,6 @@ import { TradeFormValidation } from 'modules/tradeFormValidation'
import { CurrencyInfo } from 'common/pure/CurrencyInputPanel/types'
import { RateInfoParams } from 'common/pure/RateInfo'
-import { areFractionsEqual } from 'utils/areFractionsEqual'
-import { genericPropsChecker } from 'utils/genericPropsChecker'
-import { getAddress } from 'utils/getAddress'
import { LimitOrdersFormState } from '../../hooks/useLimitOrdersFormState'
@@ -27,7 +25,6 @@ export interface LimitOrdersProps {
recipient: string | null
partiallyFillableOverride: PartiallyFillableOverrideDispatcherType
- featurePartialFillsEnabled: boolean
rateInfoParams: RateInfoParams
priceImpact: PriceImpact
@@ -50,7 +47,6 @@ export function limitOrdersPropsChecker(a: LimitOrdersProps, b: LimitOrdersProps
a.recipient === b.recipient &&
a.widgetActions === b.widgetActions &&
a.partiallyFillableOverride[0] === b.partiallyFillableOverride[0] &&
- a.featurePartialFillsEnabled === b.featurePartialFillsEnabled &&
checkRateInfoParams(a.rateInfoParams, b.rateInfoParams) &&
checkPriceImpact(a.priceImpact, b.priceImpact) &&
checkTradeFlowContext(a.tradeContext, b.tradeContext) &&
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/RateInput/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/containers/RateInput/index.tsx
index a89744eeea..f7cd7ede74 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/containers/RateInput/index.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/RateInput/index.tsx
@@ -1,9 +1,12 @@
import { useAtomValue, useSetAtom } from 'jotai'
import { useCallback, useEffect, useMemo, useState } from 'react'
+import { formatInputAmount, getAddress, isFractionFalsy } from '@cowprotocol/common-utils'
+import { TokenSymbol, Loader } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
+
import { RefreshCw } from 'react-feather'
-import Loader from 'legacy/components/Loader'
import QuestionHelper from 'legacy/components/QuestionHelper'
import { useLimitOrdersDerivedState } from 'modules/limitOrders/hooks/useLimitOrdersDerivedState'
@@ -14,15 +17,10 @@ import { HeadingText } from 'modules/limitOrders/pure/RateInput/HeadingText'
import { executionPriceAtom } from 'modules/limitOrders/state/executionPriceAtom'
import { limitRateAtom, updateLimitRateAtom } from 'modules/limitOrders/state/limitRateAtom'
import { toFraction } from 'modules/limitOrders/utils/toFraction'
-import { useWalletInfo } from 'modules/wallet'
import { ordersTableFeatures } from 'common/constants/featureFlags'
import { ExecutionPrice } from 'common/pure/ExecutionPrice'
-import { TokenSymbol } from 'common/pure/TokenSymbol'
import { getQuoteCurrency, getQuoteCurrencyByStableCoin } from 'common/services/getQuoteCurrency'
-import { formatInputAmount } from 'utils/amountFormat'
-import { getAddress } from 'utils/getAddress'
-import { isFractionFalsy } from 'utils/isFractionFalsy'
import * as styledEl from './styled'
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/RateInput/styled.ts b/apps/cowswap-frontend/src/modules/limitOrders/containers/RateInput/styled.ts
index 170eee1146..41610c6005 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/containers/RateInput/styled.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/RateInput/styled.ts
@@ -1,11 +1,14 @@
+import { Loader } from '@cowprotocol/ui'
+
import { transparentize } from 'polished'
import styled from 'styled-components/macro'
-import Loader from 'legacy/components/Loader'
import Input from 'legacy/components/NumericalInput'
+import { UI } from 'common/constants/theme'
+
export const Wrapper = styled.div`
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
border-radius: 16px;
padding: 10px 16px;
flex: 1 1 70%;
@@ -30,8 +33,8 @@ export const Header = styled.div`
`
export const MarketPriceButton = styled.button`
- background: ${({ theme }) => theme.bg1};
- color: ${({ theme }) => theme.text1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
+ color: var(${UI.COLOR_TEXT1});
white-space: nowrap;
border: none;
font-weight: 500;
@@ -82,7 +85,7 @@ export const ActiveCurrency = styled.button`
`
export const ActiveSymbol = styled.span`
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
font-size: 13px;
font-weight: 500;
text-align: right;
@@ -91,8 +94,8 @@ export const ActiveSymbol = styled.span`
export const ActiveIcon = styled.div`
--size: 20px;
- background-color: ${({ theme }) => theme.bg1};
- color: ${({ theme }) => theme.text1};
+ background-color: var(${UI.COLOR_CONTAINER_BG_01});
+ color: var(${UI.COLOR_TEXT1});
width: var(--size);
min-width: var(--size);
height: var(--size);
@@ -117,7 +120,7 @@ export const EstimatedRate = styled.div`
font-size: 13px;
border-radius: 0 0 16px 16px;
font-weight: 400;
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
border: 2px solid ${({ theme }) => theme.grey1};
> b {
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/SettingsWidget/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/containers/SettingsWidget/index.tsx
index b76eba69e7..12a9079572 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/containers/SettingsWidget/index.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/SettingsWidget/index.tsx
@@ -1,12 +1,10 @@
-import { useSetAtom } from 'jotai'
-import { useAtomValue } from 'jotai'
+import { useAtomValue, useSetAtom } from 'jotai'
import React, { useCallback, useState } from 'react'
import { Menu, MenuItem } from '@reach/menu-button'
import { ExpertModeIndicator, MenuContent, SettingsButton, SettingsIcon } from 'modules/trade/pure/Settings'
-import { useFeatureFlags } from 'common/hooks/featureFlags/useFeatureFlags'
import { ExpertModeModal } from 'common/pure/ExpertModeModal'
import { Settings } from '../../pure/Settings'
@@ -20,7 +18,6 @@ export function SettingsWidget() {
const settingsState = useAtomValue(limitOrdersSettingsAtom)
const updateSettingsState = useSetAtom(updateLimitOrdersSettingsAtom)
const [showExpertConfirm, setShowExpertConfirm] = useState(false)
- const { partialFillsEnabled } = useFeatureFlags()
const onStateChanged = useCallback(
(state: Partial) => {
@@ -60,11 +57,7 @@ export function SettingsWidget() {
void 0}>
-
+
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useGetInitialPrice.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useGetInitialPrice.ts
index 54809b697a..cee5622916 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useGetInitialPrice.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useGetInitialPrice.ts
@@ -1,19 +1,18 @@
import { useEffect, useState } from 'react'
+import { useIsWindowVisible } from '@cowprotocol/common-hooks'
+import { getAddress } from '@cowprotocol/common-utils'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Currency, Fraction } from '@uniswap/sdk-core'
import * as Sentry from '@sentry/browser'
import ms from 'ms.macro'
import { useAsyncMemo } from 'use-async-memo'
-import useIsWindowVisible from 'legacy/hooks/useIsWindowVisible'
-
import { useLimitOrdersDerivedState } from 'modules/limitOrders/hooks/useLimitOrdersDerivedState'
import { parsePrice } from 'modules/limitOrders/utils/parsePrice'
-import { useWalletInfo } from 'modules/wallet'
import { getNativePrice } from 'api/gnosisProtocol'
-import { getAddress } from 'utils/getAddress'
type PriceResult = number | Error | undefined
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.test.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.test.ts
index 43660a406d..d0e2ea1b75 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.test.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.test.ts
@@ -1,5 +1,7 @@
import { useAtomValue, useSetAtom } from 'jotai'
+import { useIsBundlingSupported } from '@cowprotocol/wallet'
+
import { renderHook } from '@testing-library/react-hooks'
import { PriceImpact } from 'legacy/hooks/usePriceImpact'
@@ -9,7 +11,6 @@ import { safeBundleFlow } from 'modules/limitOrders/services/safeBundleFlow'
import { tradeFlow } from 'modules/limitOrders/services/tradeFlow'
import { TradeFlowContext } from 'modules/limitOrders/services/types'
-import { useIsTxBundlingEnabled } from 'common/hooks/featureFlags/useIsTxBundlingEnabled'
import { useNeedsApproval } from 'common/hooks/useNeedsApproval'
import { TradeAmounts } from 'common/types'
import { withModalProvider } from 'utils/withModalProvider'
@@ -25,15 +26,30 @@ jest.mock('modules/limitOrders/services/safeBundleFlow')
jest.mock('modules/limitOrders/hooks/useSafeBundleFlowContext')
jest.mock('common/hooks/useNeedsApproval')
-jest.mock('common/hooks/featureFlags/useIsTxBundlingEnabled')
-jest.mock('legacy/components/analytics/hooks/useAnalyticsReporter.ts')
+jest.mock('@cowprotocol/wallet', () => {
+ const actual = jest.requireActual('@cowprotocol/wallet')
+
+ return new Proxy(actual, {
+ get: (target, property) => {
+ switch (property) {
+ case 'useIsBundlingSupported': {
+ return jest.fn()
+ }
+ default: {
+ return target[property]
+ }
+ }
+ },
+ })
+})
+jest.mock('common/hooks/useAnalyticsReporter')
const mockTradeFlow = tradeFlow as jest.MockedFunction
const mockSafeBundleFlow = safeBundleFlow as jest.MockedFunction
const mockUseSafeBundleFlowContext = useSafeBundleFlowContext as jest.MockedFunction
const mockUseNeedsApproval = useNeedsApproval as jest.MockedFunction
-const mockUseIsTxBundlingEnabled = useIsTxBundlingEnabled as jest.MockedFunction
+const mockIsBundlingSupported = useIsBundlingSupported as jest.MockedFunction
const tradeContextMock = { postOrderParams: { partiallyFillable: true } } as any as TradeFlowContext
const priceImpactMock: PriceImpact = {
@@ -57,6 +73,9 @@ const tradeConfirmActions: TradeConfirmActions = {
onOpen() {
console.log('onOpen')
},
+ requestPermitSignature() {
+ console.log('requestPermitSignature')
+ },
}
describe('useHandleOrderPlacement', () => {
@@ -65,7 +84,7 @@ describe('useHandleOrderPlacement', () => {
mockSafeBundleFlow.mockImplementation(() => Promise.resolve(''))
mockUseSafeBundleFlowContext.mockImplementation(() => null)
mockUseNeedsApproval.mockImplementation(() => false)
- mockUseIsTxBundlingEnabled.mockImplementation(() => false)
+ mockIsBundlingSupported.mockImplementation(() => true)
})
it('When a limit order placed, then the recipient value should be deleted', async () => {
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.ts
index fed0708c3b..7cdf093500 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.ts
@@ -1,5 +1,4 @@
-import { useAtom } from 'jotai'
-import { useSetAtom } from 'jotai'
+import { useAtom, useSetAtom } from 'jotai'
import { useCallback } from 'react'
import { PriceImpact } from 'legacy/hooks/usePriceImpact'
@@ -31,15 +30,16 @@ export function useHandleOrderPlacement(
const safeBundleFlowContext = useSafeBundleFlowContext(tradeContext)
const isSafeBundle = useIsSafeApprovalBundle(tradeContext?.postOrderParams.inputAmount)
- const beforeTrade = useCallback(() => {
+ const beforePermit = useCallback(() => {
if (!tradeContext) return
- const tradeAmounts: TradeAmounts = {
- inputAmount: tradeContext.postOrderParams.inputAmount,
- outputAmount: tradeContext.postOrderParams.outputAmount,
- }
+ tradeConfirmActions.requestPermitSignature(buildTradeAmounts(tradeContext))
+ }, [tradeConfirmActions, tradeContext])
- tradeConfirmActions.onSign(tradeAmounts)
+ const beforeTrade = useCallback(() => {
+ if (!tradeContext) return
+
+ tradeConfirmActions.onSign(buildTradeAmounts(tradeContext))
}, [tradeContext, tradeConfirmActions])
const tradeFn = useCallback(async () => {
@@ -63,8 +63,9 @@ export function useHandleOrderPlacement(
tradeContext.postOrderParams.partiallyFillable =
partiallyFillableOverride ?? tradeContext.postOrderParams.partiallyFillable
- return tradeFlow(tradeContext, priceImpact, settingsState, confirmPriceImpactWithoutFee, beforeTrade)
+ return tradeFlow(tradeContext, priceImpact, settingsState, confirmPriceImpactWithoutFee, beforePermit, beforeTrade)
}, [
+ beforePermit,
beforeTrade,
confirmPriceImpactWithoutFee,
isSafeBundle,
@@ -95,3 +96,10 @@ export function useHandleOrderPlacement(
})
}, [tradeFn, tradeConfirmActions, updateLimitOrdersState, setPartiallyFillableOverride])
}
+
+function buildTradeAmounts(tradeContext: TradeFlowContext): TradeAmounts {
+ return {
+ inputAmount: tradeContext.postOrderParams.inputAmount,
+ outputAmount: tradeContext.postOrderParams.outputAmount,
+ }
+}
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useIsSafeApprovalBundle.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useIsSafeApprovalBundle.ts
index aad313adb9..fd92f776ac 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useIsSafeApprovalBundle.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useIsSafeApprovalBundle.ts
@@ -1,13 +1,13 @@
+import { useIsBundlingSupported } from '@cowprotocol/wallet'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import { Nullish } from 'types'
-import { useIsTxBundlingEnabled } from 'common/hooks/featureFlags/useIsTxBundlingEnabled'
import { useNeedsApproval } from 'common/hooks/useNeedsApproval'
export function useIsSafeApprovalBundle(amount: Nullish>): boolean {
const needsApproval = useNeedsApproval(amount)
- const isTxBundlingEnabled = useIsTxBundlingEnabled()
+ const isBundlingSupported = useIsBundlingSupported()
- return isTxBundlingEnabled && needsApproval
+ return isBundlingSupported && needsApproval
}
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useLimitOrdersDerivedState.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useLimitOrdersDerivedState.ts
index 3d9b624b36..061a285f8e 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useLimitOrdersDerivedState.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useLimitOrdersDerivedState.ts
@@ -2,10 +2,11 @@ import { useAtomValue, useSetAtom } from 'jotai'
import { useEffect } from 'react'
import {
- limitOrdersRawStateAtom,
LimitOrdersDerivedState,
limitOrdersDerivedStateAtom,
+ limitOrdersRawStateAtom,
} from 'modules/limitOrders/state/limitOrdersRawStateAtom'
+import { TradeType } from 'modules/trade'
import { useBuildTradeDerivedState } from 'modules/trade/hooks/useBuildTradeDerivedState'
export function useLimitOrdersDerivedState(): LimitOrdersDerivedState {
@@ -20,6 +21,6 @@ export function useFillLimitOrdersDerivedState() {
const derivedState = useBuildTradeDerivedState(limitOrdersRawStateAtom)
useEffect(() => {
- updateDerivedState({ ...derivedState, isUnlocked })
+ updateDerivedState({ ...derivedState, isUnlocked, tradeType: TradeType.LIMIT_ORDER })
}, [derivedState, updateDerivedState, isUnlocked])
}
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useLimitOrdersFormState.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useLimitOrdersFormState.ts
index ee996f4d13..0343726766 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useLimitOrdersFormState.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useLimitOrdersFormState.ts
@@ -1,12 +1,12 @@
import { useAtomValue } from 'jotai'
+import { isFractionFalsy } from '@cowprotocol/common-utils'
import { Currency, CurrencyAmount, Fraction } from '@uniswap/sdk-core'
import { limitRateAtom } from 'modules/limitOrders/state/limitRateAtom'
import { useTradeQuote } from 'modules/tradeQuote'
import { useSafeMemo } from 'common/hooks/useSafeMemo'
-import { isFractionFalsy } from 'utils/isFractionFalsy'
import { useLimitOrdersDerivedState } from './useLimitOrdersDerivedState'
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useSafeBundleFlowContext.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useSafeBundleFlowContext.ts
index 1d33afccf9..dcdf51a474 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useSafeBundleFlowContext.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useSafeBundleFlowContext.ts
@@ -1,7 +1,7 @@
-import { useTokenContract } from 'legacy/hooks/useContract'
+import { useTokenContract } from '@cowprotocol/common-hooks'
+import { useSafeAppsSdk } from '@cowprotocol/wallet'
import { SafeBundleFlowContext, TradeFlowContext } from 'modules/limitOrders/services/types'
-import { useSafeAppsSdk } from 'modules/wallet/web3-react/hooks/useSafeAppsSdk'
import { useTradeSpenderAddress } from 'common/hooks/useTradeSpenderAddress'
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useSetupLimitOrderAmountsFromUrl.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useSetupLimitOrderAmountsFromUrl.ts
index 90cd978d61..a94c20fb14 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useSetupLimitOrderAmountsFromUrl.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useSetupLimitOrderAmountsFromUrl.ts
@@ -1,6 +1,9 @@
import { useSetAtom } from 'jotai'
import { useCallback, useLayoutEffect, useMemo } from 'react'
+import { tryParseCurrencyAmount } from '@cowprotocol/common-utils'
+import { FractionUtils } from '@cowprotocol/common-utils'
+import { getIntOrFloat } from '@cowprotocol/common-utils'
import { OrderKind } from '@cowprotocol/cow-sdk'
import { Price } from '@uniswap/sdk-core'
@@ -12,10 +15,6 @@ import { useLimitOrdersDerivedState } from 'modules/limitOrders/hooks/useLimitOr
import { useUpdateActiveRate } from 'modules/limitOrders/hooks/useUpdateActiveRate'
import { TRADE_URL_BUY_AMOUNT_KEY, TRADE_URL_SELL_AMOUNT_KEY } from 'modules/trade/const/tradeUrl'
-import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount'
-import { FractionUtils } from 'utils/fractionUtils'
-import { getIntOrFloat } from 'utils/getIntOrFloat'
-
/**
* Parse sell/buy amount from URL and apply to Limit orders widget
* Example:
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts
index ce62a2556f..488fa09af8 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts
@@ -1,22 +1,24 @@
import { useAtomValue } from 'jotai'
+import { GP_VAULT_RELAYER } from '@cowprotocol/common-const'
+import { useGP2SettlementContract } from '@cowprotocol/common-hooks'
import { OrderClass } from '@cowprotocol/cow-sdk'
+import { useGnosisSafeInfo, useWalletDetails, useWalletInfo } from '@cowprotocol/wallet'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { useDispatch } from 'react-redux'
-import { useGP2SettlementContract } from 'legacy/hooks/useContract'
import { AppDispatch } from 'legacy/state'
import { useAppData } from 'modules/appData'
import { useRateImpact } from 'modules/limitOrders/hooks/useRateImpact'
import { TradeFlowContext } from 'modules/limitOrders/services/types'
import { limitOrdersSettingsAtom } from 'modules/limitOrders/state/limitOrdersSettingsAtom'
+import { useGeneratePermitHook, useIsTokenPermittable } from 'modules/permit'
+import { useEnoughBalanceAndAllowance } from 'modules/tokens'
+import { TradeType } from 'modules/trade'
import { useTradeQuote } from 'modules/tradeQuote'
-import { useGnosisSafeInfo, useWalletDetails, useWalletInfo } from 'modules/wallet'
-
-import { useFeatureFlags } from 'common/hooks/featureFlags/useFeatureFlags'
import { useLimitOrdersDerivedState } from './useLimitOrdersDerivedState'
@@ -32,7 +34,15 @@ export function useTradeFlowContext(): TradeFlowContext | null {
const quoteState = useTradeQuote()
const rateImpact = useRateImpact()
const settingsState = useAtomValue(limitOrdersSettingsAtom)
- const { partialFillsEnabled } = useFeatureFlags()
+ const permitInfo = useIsTokenPermittable(state.inputCurrency, TradeType.LIMIT_ORDER)
+
+ const checkAllowanceAddress = GP_VAULT_RELAYER[chainId]
+ const { enoughAllowance } = useEnoughBalanceAndAllowance({
+ account,
+ amount: state.slippageAdjustedSellAmount || undefined,
+ checkAllowanceAddress,
+ })
+ const generatePermitHook = useGeneratePermitHook()
if (
!chainId ||
@@ -56,8 +66,7 @@ export function useTradeFlowContext(): TradeFlowContext | null {
const feeAmount = CurrencyAmount.fromRawAmount(state.inputCurrency, 0)
const quoteId = quoteState.response?.id || undefined
- // Depends on the feature flag to allow partial fills or not
- const partiallyFillable = partialFillsEnabled && settingsState.partialFillsEnabled
+ const partiallyFillable = settingsState.partialFillsEnabled
return {
chainId,
@@ -66,8 +75,9 @@ export function useTradeFlowContext(): TradeFlowContext | null {
isGnosisSafeWallet,
dispatch,
provider,
- appData,
rateImpact,
+ permitInfo: !enoughAllowance ? permitInfo : undefined,
+ generatePermitHook,
postOrderParams: {
class: OrderClass.LIMIT,
kind: state.orderKind,
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useUpdateCurrencyAmount.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useUpdateCurrencyAmount.ts
index bbc2ede726..17b695c8f9 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useUpdateCurrencyAmount.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useUpdateCurrencyAmount.ts
@@ -1,17 +1,17 @@
import { useSetAtom } from 'jotai'
import { useCallback } from 'react'
+import { FractionUtils } from '@cowprotocol/common-utils'
import { OrderKind } from '@cowprotocol/cow-sdk'
import { Fraction } from '@uniswap/sdk-core'
import { Writeable } from 'types'
-import { Field } from 'legacy/state/swap/actions'
+import { Field } from 'legacy/state/types'
import { useLimitOrdersDerivedState } from 'modules/limitOrders/hooks/useLimitOrdersDerivedState'
import { LimitOrdersRawState, updateLimitOrdersRawStateAtom } from 'modules/limitOrders/state/limitOrdersRawStateAtom'
-import { FractionUtils } from 'utils/fractionUtils'
import { calculateAmountForRate } from 'utils/orderUtils/calculateAmountForRate'
type CurrencyAmountProps = {
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/DeadlineSelector/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/DeadlineSelector/index.tsx
index be050ea38d..25fb8a440e 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/pure/DeadlineSelector/index.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/DeadlineSelector/index.tsx
@@ -1,11 +1,11 @@
import { ChangeEventHandler, useCallback, useEffect, useMemo, useRef, useState } from 'react'
+import { ButtonPrimary, ButtonSecondary } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import { Menu } from '@reach/menu-button'
import { ChevronDown } from 'react-feather'
-import { ButtonPrimary, ButtonSecondary } from 'legacy/components/Button'
-
import {
calculateMinMax,
formatDateToLocalTime,
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/DeadlineSelector/styled.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/DeadlineSelector/styled.tsx
index 6c89ca55be..28a6f9e1ef 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/pure/DeadlineSelector/styled.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/DeadlineSelector/styled.tsx
@@ -3,8 +3,10 @@ import { transparentize } from 'polished'
import { X } from 'react-feather'
import styled from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
export const Wrapper = styled.div<{ inline?: boolean; minHeight?: string }>`
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
border-radius: 16px;
padding: 10px 16px;
min-height: ${({ minHeight }) => minHeight || '80px'};
@@ -38,7 +40,7 @@ export const Label = styled.span`
`
export const Current = styled(MenuButton)<{ $custom?: boolean }>`
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
font-size: ${({ $custom }) => ($custom ? '12px' : '100%')};
letter-spacing: ${({ $custom }) => ($custom ? '-0.3px' : '0')};
font-weight: 500;
@@ -75,7 +77,7 @@ export const Current = styled(MenuButton)<{ $custom?: boolean }>`
export const ListWrapper = styled(MenuList)`
display: block;
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
box-shadow: ${({ theme }) => theme.boxShadow2};
margin: 15px 0 0 0;
padding: 10px 15px;
@@ -88,7 +90,7 @@ export const ListWrapper = styled(MenuList)`
`
export const ListItem = styled(MenuItem)`
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
background: none;
border: 0;
outline: none;
@@ -111,17 +113,17 @@ export const CustomInput = styled.input`
border-radius: 8px;
width: 100%;
border: 1px solid ${({ theme }) => transparentize(0.7, theme.text1)};
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
padding: 4px 8px;
outline: 0;
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
&::-webkit-calendar-picker-indicator {
filter: ${({ theme }) => (theme.darkMode ? 'invert(1)' : 'invert(0)')};
}
&::-webkit-datetime-edit {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
&::-webkit-datetime-edit[disabled] {
@@ -177,7 +179,7 @@ export const ModalContent = styled.div`
align-items: flex-start;
justify-content: center;
padding: 16px;
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
border-radius: 12px;
`
@@ -193,6 +195,6 @@ export const CloseIcon = styled(X)`
}
> line {
- stroke: ${({ theme }) => theme.text1};
+ stroke: var(${UI.COLOR_TEXT1});
}
`
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/ExecutionPriceTooltip/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/ExecutionPriceTooltip/index.tsx
index cbefe4f3ea..f31603ba88 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/pure/ExecutionPriceTooltip/index.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/ExecutionPriceTooltip/index.tsx
@@ -1,11 +1,10 @@
+import { FiatAmount, TokenAmount } from '@cowprotocol/ui'
import { Currency, CurrencyAmount, Fraction, Price } from '@uniswap/sdk-core'
import { useUsdAmount } from 'modules/usdAmount'
import { ExecutionPrice } from 'common/pure/ExecutionPrice'
-import { FiatAmount } from 'common/pure/FiatAmount'
import { RateTooltipHeader } from 'common/pure/OrderExecutionStatusList'
-import { TokenAmount } from 'common/pure/TokenAmount'
import { convertAmountToCurrency } from 'utils/orderUtils/calculateExecutionPrice'
import * as styledEl from './styled'
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/ExecutionPriceTooltip/styled.ts b/apps/cowswap-frontend/src/modules/limitOrders/pure/ExecutionPriceTooltip/styled.ts
index beea28b1ad..fa195df8dd 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/pure/ExecutionPriceTooltip/styled.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/ExecutionPriceTooltip/styled.ts
@@ -1,12 +1,14 @@
import { transparentize } from 'polished'
import styled from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
export const FeeTooltipWrapper = styled.div`
display: flex;
flex-flow: column wrap;
align-items: center;
justify-content: center;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
`
export const FeeItem = styled.div<{ highlighted?: boolean; borderTop?: boolean }>`
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/InfoBanner/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/InfoBanner/index.tsx
index d41eb8b05b..b65af754c7 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/pure/InfoBanner/index.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/InfoBanner/index.tsx
@@ -1,10 +1,10 @@
import { useState, useEffect } from 'react'
+import AlertIcon from '@cowprotocol/assets/cow-swap/alert-circle.svg'
+
import SVG from 'react-inlinesvg'
import { HashLink } from 'react-router-hash-link'
-import AlertIcon from 'legacy/assets/cow-swap/alert-circle.svg'
-
import * as styledEl from './styled'
export function InfoBanner() {
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/InfoBanner/styled.ts b/apps/cowswap-frontend/src/modules/limitOrders/pure/InfoBanner/styled.ts
index fe70965313..8c51cd42aa 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/pure/InfoBanner/styled.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/InfoBanner/styled.ts
@@ -2,6 +2,8 @@ import { transparentize, lighten } from 'polished'
import { X } from 'react-feather'
import styled from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
export const InfoPopup = styled.div`
display: flex;
position: relative;
@@ -34,7 +36,7 @@ export const InfoPopup = styled.div`
}
.content > a {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
text-decoration: underline;
&::after {
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx
index 776d046c24..66d3058a37 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx
@@ -1,12 +1,9 @@
import { SetStateAction } from 'jotai'
-import { SupportedChainId } from '@cowprotocol/cow-sdk'
-import { OrderKind } from '@cowprotocol/cow-sdk'
-import { OrderClass } from '@cowprotocol/cow-sdk'
+import { COW, GNO } from '@cowprotocol/common-const'
+import { OrderClass, OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk'
import { CurrencyAmount } from '@uniswap/sdk-core'
-import { COW, GNO } from 'legacy/constants/tokens'
-
import { getAppData } from 'modules/appData'
import { defaultLimitOrdersSettings } from 'modules/limitOrders/state/limitOrdersSettingsAtom'
import { initLimitRateState } from 'modules/limitOrders/state/limitRateAtom'
@@ -19,6 +16,8 @@ const inputCurrency = COW[SupportedChainId.MAINNET]
const outputCurrency = GNO[SupportedChainId.MAINNET]
const tradeContext: TradeFlowContext = {
+ permitInfo: undefined,
+ generatePermitHook: () => Promise.resolve(undefined),
postOrderParams: {
class: OrderClass.LIMIT,
account: '0x000',
@@ -37,7 +36,6 @@ const tradeContext: TradeFlowContext = {
appData: getAppData(),
},
rateImpact: 0,
- appData: {} as any,
provider: {} as any,
settlementContract: {} as any,
chainId: 1,
@@ -63,7 +61,6 @@ const Fixtures = {
executionPrice={null}
limitRateState={initLimitRateState()}
partiallyFillableOverride={[true, (_?: SetStateAction) => void 0]}
- featurePartialFillsEnabled
/>
),
}
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.tsx
index 91644315f6..a201d11707 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.tsx
@@ -1,14 +1,16 @@
import React, { useMemo, useState } from 'react'
+import ArrowDownImage from '@cowprotocol/assets/cow-swap/arrowDownRight.svg'
+import { DEFAULT_DATE_FORMAT } from '@cowprotocol/common-const'
+import { formatInputAmount } from '@cowprotocol/common-utils'
+import { isAddress, shortenAddress } from '@cowprotocol/common-utils'
import { Currency, Price } from '@uniswap/sdk-core'
import SVG from 'react-inlinesvg'
import styled from 'styled-components/macro'
-import ArrowDownImage from 'legacy/assets/cow-swap/arrowDownRight.svg'
import { InfoIcon } from 'legacy/components/InfoIcon'
import QuestionHelper from 'legacy/components/QuestionHelper'
-import { isAddress, shortenAddress } from 'legacy/utils'
import { ExecutionPriceTooltip } from 'modules/limitOrders/pure/ExecutionPriceTooltip'
import { OrderType } from 'modules/limitOrders/pure/OrderType'
@@ -19,17 +21,16 @@ import { PartiallyFillableOverrideDispatcherType } from 'modules/limitOrders/sta
import { calculateLimitOrdersDeadline } from 'modules/limitOrders/utils/calculateLimitOrdersDeadline'
import { ordersTableFeatures } from 'common/constants/featureFlags'
-import { DEFAULT_DATE_FORMAT } from 'common/constants/intl'
+import { UI } from 'common/constants/theme'
import { ExecutionPrice } from 'common/pure/ExecutionPrice'
import { RateInfoParams } from 'common/pure/RateInfo'
-import { formatInputAmount } from 'utils/amountFormat'
import * as styledEl from './styled'
const Wrapper = styled.div`
font-size: 13px;
font-weight: 400;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
padding: 8px;
`
@@ -37,7 +38,7 @@ const ArrowDownRight = styled.div`
display: flex;
opacity: 0.3;
margin: 0 3px 0 0;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
`
export interface LimitOrdersDetailsProps {
rateInfoParams: RateInfoParams
@@ -46,19 +47,11 @@ export interface LimitOrdersDetailsProps {
executionPrice: Price | null
limitRateState: LimitRateState
partiallyFillableOverride: PartiallyFillableOverrideDispatcherType
- featurePartialFillsEnabled: boolean
}
export function LimitOrdersDetails(props: LimitOrdersDetailsProps) {
- const {
- executionPrice,
- tradeContext,
- settingsState,
- rateInfoParams,
- limitRateState,
- partiallyFillableOverride,
- featurePartialFillsEnabled,
- } = props
+ const { executionPrice, tradeContext, settingsState, rateInfoParams, limitRateState, partiallyFillableOverride } =
+ props
const { account, recipient, recipientAddressOrName, partiallyFillable } = tradeContext.postOrderParams
const { feeAmount, activeRate, marketRate } = limitRateState
@@ -135,11 +128,7 @@ export function LimitOrdersDetails(props: LimitOrdersDetailsProps) {
Active
*/}
-
+
{recipientAddressOrName && recipient !== account && (
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/styled.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/styled.tsx
index 4d77475eab..5cb898a3ef 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/styled.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/styled.tsx
@@ -2,6 +2,7 @@ import styled from 'styled-components/macro'
import { QuestionWrapper } from 'legacy/components/QuestionHelper'
+import { UI } from 'common/constants/theme'
import { RateInfo } from 'common/pure/RateInfo'
export const DetailsRow = styled.div`
@@ -41,7 +42,7 @@ export const DetailsRow = styled.div`
export const StyledRateInfo = styled(RateInfo)`
font-size: 13px;
font-weight: 400;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
min-height: 24px;
gap: 3px;
`
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/index.tsx
index 153fd3e834..cc33942ac7 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/index.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/index.tsx
@@ -1,6 +1,7 @@
+import IMAGE_CARET_DOWN from '@cowprotocol/assets/cow-swap/carret-down.svg'
+
import { Menu } from '@reach/menu-button'
-import IMAGE_CARET_DOWN from 'legacy/assets/cow-swap/carret-down.svg'
import { InfoIcon } from 'legacy/components/InfoIcon'
import { DetailsRow } from 'modules/limitOrders/pure/LimitOrdersDetails/styled'
@@ -10,7 +11,6 @@ import * as styledEl from './styled'
export type OrderTypeProps = {
isPartiallyFillable: boolean
- featurePartialFillsEnabled: boolean
partiallyFillableOverride: PartiallyFillableOverrideDispatcherType
className?: string
}
@@ -41,11 +41,7 @@ export function OrderType(props: OrderTypeProps) {
const LABELS = ['Partially fillable', 'Fill or kill']
-function OrderTypePicker({
- isPartiallyFillable,
- featurePartialFillsEnabled,
- partiallyFillableOverride,
-}: OrderTypeProps) {
+function OrderTypePicker({ isPartiallyFillable, partiallyFillableOverride }: OrderTypeProps) {
const [override, setOverride] = partiallyFillableOverride
const showPartiallyFillable = override ?? isPartiallyFillable
@@ -53,21 +49,18 @@ function OrderTypePicker({
const [labelText] = showPartiallyFillable ? LABELS : [...LABELS].reverse()
const onSelect = (label: string) => setOverride(label === LABELS[0])
- const disabled = !featurePartialFillsEnabled
return (
{({ isExpanded }: { isExpanded: boolean }) => (
-
+
{labelText}
- {!disabled && (
-
- )}
+
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/styled.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/styled.tsx
index 7bc48d569f..1360ee5f78 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/styled.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/styled.tsx
@@ -3,12 +3,14 @@ import { transparentize } from 'polished'
import SVG from 'react-inlinesvg'
import styled from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
export const Wrapper = styled.div`
position: relative;
`
export const LabelText = styled.span`
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
transition: color 0.15s ease-in-out;
`
@@ -19,7 +21,7 @@ export const StyledSVG = styled(SVG)`
height: var(--size);
> path {
- fill: ${({ theme }) => theme.text1};
+ fill: var(${UI.COLOR_TEXT1});
transition: fill 0.15s ease-in-out;
}
@@ -54,7 +56,7 @@ export const StyledMenuButton = styled(MenuButton)`
export const StyledMenuList = styled(MenuList)`
box-shadow: 0 4px 8px 0 ${({ theme }) => transparentize(0.95, theme.shadow1)};
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
border-radius: 8px;
z-index: 2;
min-width: 100%;
@@ -67,7 +69,7 @@ export const StyledMenuList = styled(MenuList)`
export const StyledMenuItem = styled(MenuItem)`
padding: 6px 12px;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
font-size: 13px;
cursor: pointer;
border-radius: 8px;
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactIndicator/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactIndicator/index.cosmos.tsx
index b37a7bb897..1a960c2370 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactIndicator/index.cosmos.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactIndicator/index.cosmos.tsx
@@ -1,4 +1,4 @@
-import { GNO_GNOSIS_CHAIN } from 'legacy/utils/gnosis_chain/constants'
+import { GNO_GNOSIS_CHAIN } from '@cowprotocol/common-const'
import { RateImpactIndicator } from './index'
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactIndicator/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactIndicator/index.tsx
index c6eef7184d..b91dec12ad 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactIndicator/index.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactIndicator/index.tsx
@@ -1,13 +1,13 @@
+import { TokenSymbol } from '@cowprotocol/ui'
+import { MouseoverTooltipContent } from '@cowprotocol/ui'
import { Currency } from '@uniswap/sdk-core'
import { AlertTriangle } from 'react-feather'
import styled from 'styled-components/macro'
-import { MouseoverTooltipContent } from 'legacy/components/Tooltip'
-
import { LOW_RATE_THRESHOLD_PERCENT } from 'modules/limitOrders/const/trade'
-import { TokenSymbol } from 'common/pure/TokenSymbol'
+import { UI } from 'common/constants/theme'
interface RateImpactProps {
rateImpact: number
@@ -21,8 +21,8 @@ const PercentBox = styled.span<{ isPositive: boolean; isTooLowRate: boolean }>`
display: inline-flex;
align-items: center;
gap: 2px;
- color: ${({ isPositive, isTooLowRate, theme }) =>
- isPositive ? theme.success : isTooLowRate ? theme.danger : theme.text1};
+ color: ${({ isPositive, isTooLowRate }) =>
+ isPositive ? `var(${UI.COLOR_SUCCESS})` : isTooLowRate ? `var(${UI.COLOR_DANGER})` : `var(${UI.COLOR_TEXT1})`};
`
const ImpactTooltip = styled.span`
display: block;
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactWarning/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactWarning/index.cosmos.tsx
index 2f8500fc93..234e81092a 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactWarning/index.cosmos.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactWarning/index.cosmos.tsx
@@ -1,7 +1,6 @@
+import { COW } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
-import { COW } from 'legacy/constants/tokens'
-
import { RateImpactWarning } from './index'
const Fixtures = {
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactWarning/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactWarning/index.tsx
index 3a831ed7fc..0b62777663 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactWarning/index.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactWarning/index.tsx
@@ -1,3 +1,4 @@
+import { TokenSymbol } from '@cowprotocol/ui'
import { Currency } from '@uniswap/sdk-core'
import { transparentize, lighten, darken } from 'polished'
@@ -6,7 +7,7 @@ import styled from 'styled-components/macro'
import { LOW_RATE_THRESHOLD_PERCENT } from 'modules/limitOrders/const/trade'
-import { TokenSymbol } from 'common/pure/TokenSymbol'
+import { UI } from 'common/constants/theme'
interface RateImpactAcknowledge {
withAcknowledge: boolean
@@ -41,7 +42,7 @@ const ReadMoreLink = styled.a`
text-decoration: underline;
&:hover {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
`
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/index.cosmos.tsx
index 99857c61ee..df49f8cc0c 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/index.cosmos.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/index.cosmos.tsx
@@ -8,7 +8,6 @@ const defaultProps: SettingsProps = {
deadlineMilliseconds: 200_000,
customDeadlineTimestamp: null,
},
- featurePartialFillsEnabled: true,
onStateChanged(state) {
console.log('Settings state changed: ', state)
},
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/index.tsx
index 4fcbca9924..6f5dbe5f3c 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/index.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/index.tsx
@@ -4,11 +4,10 @@ import { LimitOrdersSettingsState } from '../../state/limitOrdersSettingsAtom'
export interface SettingsProps {
state: LimitOrdersSettingsState
- featurePartialFillsEnabled: boolean
onStateChanged: (state: Partial) => void
}
-export function Settings({ state, featurePartialFillsEnabled, onStateChanged }: SettingsProps) {
+export function Settings({ state, onStateChanged }: SettingsProps) {
const { expertMode, showRecipient, partialFillsEnabled } = state
return (
@@ -41,8 +40,7 @@ export function Settings({ state, featurePartialFillsEnabled, onStateChanged }:
amount.
>
}
- disabled={!featurePartialFillsEnabled}
- value={featurePartialFillsEnabled && partialFillsEnabled}
+ value={partialFillsEnabled}
toggle={() => onStateChanged({ partialFillsEnabled: !partialFillsEnabled })}
/>
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/styled.ts b/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/styled.ts
deleted file mode 100644
index aea0048814..0000000000
--- a/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/styled.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { transparentize } from 'polished'
-import styled from 'styled-components/macro'
-
-export const SettingsTitle = styled.h3`
- font-weight: 600;
- font-size: 14px;
- color: ${({ theme }) => theme.text1};
- margin: 0 0 12px 0;
-`
-
-export const SettingsContainer = styled.div`
- margin: 12px 0 0;
- padding: 16px;
- border-radius: 12px;
- box-shadow: ${({ theme }) => theme.boxShadow2};
- border: 1px solid ${({ theme }) => transparentize(0.95, theme.white)};
- background: ${({ theme }) => theme.bg1};
- color: ${({ theme }) => theme.text1};
-`
-
-export const SettingsBox = styled.div<{ disabled: boolean }>`
- display: flex;
- justify-content: space-between;
- margin-bottom: 10px;
-
- :last-child {
- margin-bottom: 0;
- }
-
- opacity: ${({ disabled }) => (disabled ? '0.7' : '1')};
- pointer-events: ${({ disabled }) => (disabled ? 'none' : '')};
-`
-
-export const SettingsBoxTitle = styled.div`
- display: flex;
- align-items: center;
- font-weight: 400;
- color: ${({ theme }) => theme.text1};
- font-size: 14px;
- opacity: 0.85;
- margin-right: 2rem;
-`
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts b/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts
index fcd22122d1..e6c7baf500 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts
@@ -9,10 +9,10 @@ import { LOW_RATE_THRESHOLD_PERCENT } from 'modules/limitOrders/const/trade'
import { PriceImpactDeclineError, TradeFlowContext } from 'modules/limitOrders/services/types'
import { LimitOrdersSettingsState } from 'modules/limitOrders/state/limitOrdersSettingsAtom'
import { calculateLimitOrdersDeadline } from 'modules/limitOrders/utils/calculateLimitOrdersDeadline'
+import { handlePermit } from 'modules/permit'
import { presignOrderStep } from 'modules/swap/services/swapFlow/steps/presignOrderStep'
import { addPendingOrderStep } from 'modules/trade/utils/addPendingOrderStep'
-import { tradeFlowAnalytics } from 'modules/trade/utils/analytics'
-import { SwapFlowAnalyticsContext } from 'modules/trade/utils/analytics'
+import { SwapFlowAnalyticsContext, tradeFlowAnalytics } from 'modules/trade/utils/analytics'
import { logTradeFlow } from 'modules/trade/utils/logger'
import { getSwapErrorMessage } from 'modules/trade/utils/swapErrorHelper'
@@ -21,9 +21,22 @@ export async function tradeFlow(
priceImpact: PriceImpact,
settingsState: LimitOrdersSettingsState,
confirmPriceImpactWithoutFee: (priceImpact: Percent) => Promise,
- beforeTrade?: () => void
+ beforePermit: () => void,
+ beforeTrade: () => void
): Promise {
- const { account, recipientAddressOrName, sellToken, buyToken } = params.postOrderParams
+ const {
+ postOrderParams,
+ rateImpact,
+ permitInfo,
+ provider,
+ chainId,
+ allowsOffchainSigning,
+ settlementContract,
+ dispatch,
+ isGnosisSafeWallet,
+ generatePermitHook,
+ } = params
+ const { account, recipientAddressOrName, sellToken, buyToken, appData } = postOrderParams
const marketLabel = [sellToken.symbol, buyToken.symbol].join(',')
const swapFlowAnalyticsContext: SwapFlowAnalyticsContext = {
account,
@@ -34,64 +47,76 @@ export async function tradeFlow(
}
logTradeFlow('LIMIT ORDER FLOW', 'STEP 1: confirm price impact')
- const isTooLowRate = params.rateImpact < LOW_RATE_THRESHOLD_PERCENT
+ const isTooLowRate = rateImpact < LOW_RATE_THRESHOLD_PERCENT
if (!isTooLowRate && priceImpact.priceImpact && !(await confirmPriceImpactWithoutFee(priceImpact.priceImpact))) {
throw new PriceImpactDeclineError()
}
- logTradeFlow('LIMIT ORDER FLOW', 'STEP 2: send transaction')
- tradeFlowAnalytics.trade(swapFlowAnalyticsContext)
- beforeTrade?.()
-
const validTo = calculateLimitOrdersDeadline(settingsState)
try {
- logTradeFlow('LIMIT ORDER FLOW', 'STEP 3: sign and post order')
+ logTradeFlow('LIMIT ORDER FLOW', 'STEP 2: handle permit')
+ if (permitInfo) beforePermit()
+
+ postOrderParams.appData = await handlePermit({
+ permitInfo,
+ inputToken: sellToken,
+ account,
+ appData,
+ generatePermitHook,
+ })
+
+ logTradeFlow('LIMIT ORDER FLOW', 'STEP 3: send transaction')
+ tradeFlowAnalytics.trade(swapFlowAnalyticsContext)
+
+ beforeTrade()
+
+ logTradeFlow('LIMIT ORDER FLOW', 'STEP 4: sign and post order')
const { id: orderId, order } = await signAndPostOrder({
- ...params.postOrderParams,
- signer: params.provider.getSigner(),
+ ...postOrderParams,
+ signer: provider.getSigner(),
validTo,
})
- logTradeFlow('LIMIT ORDER FLOW', 'STEP 4: add pending order step')
+ logTradeFlow('LIMIT ORDER FLOW', 'STEP 5: add pending order step')
addPendingOrderStep(
{
id: orderId,
- chainId: params.chainId,
+ chainId: chainId,
order: {
...order,
- isHidden: !params.allowsOffchainSigning,
+ isHidden: !allowsOffchainSigning,
},
},
- params.dispatch
+ dispatch
)
- logTradeFlow('LIMIT ORDER FLOW', 'STEP 5: presign order (optional)')
- const presignTx = await (params.allowsOffchainSigning
+ logTradeFlow('LIMIT ORDER FLOW', 'STEP 6: presign order (optional)')
+ const presignTx = await (allowsOffchainSigning
? Promise.resolve(null)
- : presignOrderStep(orderId, params.settlementContract))
+ : presignOrderStep(orderId, settlementContract))
- logTradeFlow('LIMIT ORDER FLOW', 'STEP 6: unhide SC order (optional)')
+ logTradeFlow('LIMIT ORDER FLOW', 'STEP 7: unhide SC order (optional)')
if (presignTx) {
partialOrderUpdate(
{
- chainId: params.chainId,
+ chainId,
order: {
id: order.id,
- presignGnosisSafeTxHash: params.isGnosisSafeWallet ? presignTx.hash : undefined,
+ presignGnosisSafeTxHash: isGnosisSafeWallet ? presignTx.hash : undefined,
isHidden: false,
},
},
- params.dispatch
+ dispatch
)
}
- logTradeFlow('LIMIT ORDER FLOW', 'STEP 7: Sign order')
+ logTradeFlow('LIMIT ORDER FLOW', 'STEP 8: Sign order')
tradeFlowAnalytics.sign(swapFlowAnalyticsContext)
return orderId
} catch (error: any) {
- logTradeFlow('LIMIT ORDER FLOW', 'STEP 8: ERROR: ', error)
+ logTradeFlow('LIMIT ORDER FLOW', 'STEP 9: ERROR: ', error)
const swapErrorMessage = getSwapErrorMessage(error)
tradeFlowAnalytics.error(error, swapErrorMessage, swapFlowAnalyticsContext)
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/services/types.ts b/apps/cowswap-frontend/src/modules/limitOrders/services/types.ts
index 709933594a..71d0f022e0 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/services/types.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/services/types.ts
@@ -1,12 +1,12 @@
+import { Erc20, GPv2Settlement } from '@cowprotocol/abis'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
-import { Erc20, GPv2Settlement } from '@cowswap/abis'
import { Web3Provider } from '@ethersproject/providers'
import SafeAppsSDK from '@safe-global/safe-apps-sdk'
import { AppDispatch } from 'legacy/state'
import { PostOrderParams } from 'legacy/utils/trade'
-import { AppDataInfo } from 'modules/appData'
+import { GeneratePermitHook, IsTokenPermittableResult } from 'modules/permit'
export interface TradeFlowContext {
// signer changes creates redundant re-renders
@@ -16,10 +16,11 @@ export interface TradeFlowContext {
chainId: SupportedChainId
dispatch: AppDispatch
rateImpact: number
- appData: AppDataInfo
provider: Web3Provider
allowsOffchainSigning: boolean
isGnosisSafeWallet: boolean
+ permitInfo: IsTokenPermittableResult
+ generatePermitHook: GeneratePermitHook
}
export interface SafeBundleFlowContext extends TradeFlowContext {
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/state/limitOrdersRawStateAtom.ts b/apps/cowswap-frontend/src/modules/limitOrders/state/limitOrdersRawStateAtom.ts
index fbec1895e0..c0d8afc079 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/state/limitOrdersRawStateAtom.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/state/limitOrdersRawStateAtom.ts
@@ -1,10 +1,9 @@
import { atom } from 'jotai'
import { atomWithStorage } from 'jotai/utils'
+import { getJotaiIsolatedStorage } from '@cowprotocol/core'
import { OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk'
-import { getJotaiIsolatedStorage } from 'jotaiStore'
-
import { DEFAULT_TRADE_DERIVED_STATE, TradeDerivedState } from 'modules/trade/types/TradeDerivedState'
import { ExtendedTradeRawState, getDefaultTradeRawState } from 'modules/trade/types/TradeRawState'
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/state/limitOrdersSettingsAtom.ts b/apps/cowswap-frontend/src/modules/limitOrders/state/limitOrdersSettingsAtom.ts
index 634d9ebd86..5241831bd5 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/state/limitOrdersSettingsAtom.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/state/limitOrdersSettingsAtom.ts
@@ -1,7 +1,8 @@
import { atom } from 'jotai'
import { atomWithStorage } from 'jotai/utils'
-import { getJotaiIsolatedStorage } from 'jotaiStore'
+import { getJotaiIsolatedStorage } from '@cowprotocol/core'
+
import { Milliseconds, Timestamp } from 'types'
import { defaultLimitOrderDeadline } from 'modules/limitOrders/pure/DeadlineSelector/deadlines'
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/state/limitRateAtom.ts b/apps/cowswap-frontend/src/modules/limitOrders/state/limitRateAtom.ts
index 5887799588..66f79dd58c 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/state/limitRateAtom.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/state/limitRateAtom.ts
@@ -1,9 +1,8 @@
import { atom } from 'jotai'
+import { atomWithPartialUpdate } from '@cowprotocol/common-utils'
import { Currency, CurrencyAmount, Fraction } from '@uniswap/sdk-core'
-import { atomWithPartialUpdate } from 'utils/jotai/atomWithPartialUpdate'
-
export interface LimitRateState {
readonly isLoading: boolean
readonly isLoadingMarketRate: boolean
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/updaters/InitialPriceUpdater/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/updaters/InitialPriceUpdater/index.tsx
index aa6161f7db..4a7f8d6480 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/updaters/InitialPriceUpdater/index.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/updaters/InitialPriceUpdater/index.tsx
@@ -1,9 +1,9 @@
import { useSetAtom } from 'jotai'
import { useLayoutEffect, useState } from 'react'
-import { Writeable } from 'types'
+import { usePrevious } from '@cowprotocol/common-hooks'
-import usePrevious from 'legacy/hooks/usePrevious'
+import { Writeable } from 'types'
import { useGetInitialPrice } from 'modules/limitOrders/hooks/useGetInitialPrice'
import { useUpdateActiveRate } from 'modules/limitOrders/hooks/useUpdateActiveRate'
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/updaters/QuoteObserverUpdater/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/updaters/QuoteObserverUpdater/index.tsx
index ecfba21327..75fcfa3997 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/updaters/QuoteObserverUpdater/index.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/updaters/QuoteObserverUpdater/index.tsx
@@ -1,14 +1,13 @@
import { useSetAtom } from 'jotai'
import { useEffect } from 'react'
+import { FractionUtils } from '@cowprotocol/common-utils'
import { CurrencyAmount, Percent, Price } from '@uniswap/sdk-core'
import { updateLimitRateAtom } from 'modules/limitOrders/state/limitRateAtom'
import { useDerivedTradeState } from 'modules/trade/hooks/useDerivedTradeState'
import { useTradeQuote } from 'modules/tradeQuote'
-import { FractionUtils } from 'utils/fractionUtils'
-
export const LIMIT_ORDERS_PRICE_SLIPPAGE = new Percent(1, 10) // 0.1%
export function QuoteObserverUpdater() {
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/utils/calculateLimitOrdersDeadline.ts b/apps/cowswap-frontend/src/modules/limitOrders/utils/calculateLimitOrdersDeadline.ts
index 6e74aef9d2..d6a120a074 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/utils/calculateLimitOrdersDeadline.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/utils/calculateLimitOrdersDeadline.ts
@@ -1,9 +1,9 @@
+import { calculateValidTo } from '@cowprotocol/common-utils'
+
import { Timestamp } from 'types'
import { LimitOrdersSettingsState } from 'modules/limitOrders/state/limitOrdersSettingsAtom'
-import { calculateValidTo } from 'utils/time'
-
export function calculateLimitOrdersDeadline(settingsState: LimitOrdersSettingsState): Timestamp {
return settingsState.customDeadlineTimestamp
? settingsState.customDeadlineTimestamp
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/utils/parsePrice.ts b/apps/cowswap-frontend/src/modules/limitOrders/utils/parsePrice.ts
index 1e38742387..75ba2cafc5 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/utils/parsePrice.ts
+++ b/apps/cowswap-frontend/src/modules/limitOrders/utils/parsePrice.ts
@@ -1,7 +1,6 @@
+import { DEFAULT_DECIMALS } from '@cowprotocol/common-const'
import { Currency } from '@uniswap/sdk-core'
-import { DEFAULT_DECIMALS } from 'legacy/constants'
-
/**
* @deprecated use rawToTokenAmount
*/
diff --git a/apps/cowswap-frontend/src/modules/mainMenu/constants/mainMenu.tsx b/apps/cowswap-frontend/src/modules/mainMenu/constants/mainMenu.tsx
index abf730ceb5..d7f223602f 100644
--- a/apps/cowswap-frontend/src/modules/mainMenu/constants/mainMenu.tsx
+++ b/apps/cowswap-frontend/src/modules/mainMenu/constants/mainMenu.tsx
@@ -1,21 +1,26 @@
-import { Globe } from 'react-feather'
-
-import IMAGE_CODE from 'legacy/assets/cow-swap/code.svg'
-import IMAGE_COOKIE_POLICY from 'legacy/assets/cow-swap/cookie-policy.svg'
-import IMAGE_DISCORD from 'legacy/assets/cow-swap/discord.svg'
-import IMAGE_DOCS from 'legacy/assets/cow-swap/doc.svg'
-import IMAGE_GAME from 'legacy/assets/cow-swap/game.gif'
-import IMAGE_INFO from 'legacy/assets/cow-swap/info.svg'
-import IMAGE_SLICER from 'legacy/assets/cow-swap/ninja-cow.png'
-import IMAGE_PIE from 'legacy/assets/cow-swap/pie.svg'
-import IMAGE_PRIVACY_POLICY from 'legacy/assets/cow-swap/privacy-policy.svg'
-import IMAGE_TERMS_AND_CONDITIONS from 'legacy/assets/cow-swap/terms-and-conditions.svg'
-import IMAGE_TWITTER from 'legacy/assets/cow-swap/twitter.svg'
-import { CONTRACTS_CODE_LINK, DISCORD_LINK, DOCS_LINK, DUNE_DASHBOARD_LINK, TWITTER_LINK } from 'legacy/constants'
-import { ExternalLink } from 'legacy/theme'
-import { getExplorerBaseUrl } from 'legacy/utils/explorer'
+import IMAGE_CODE from '@cowprotocol/assets/cow-swap/code.svg'
+import IMAGE_COOKIE_POLICY from '@cowprotocol/assets/cow-swap/cookie-policy.svg'
+import IMAGE_DISCORD from '@cowprotocol/assets/cow-swap/discord.svg'
+import IMAGE_DOCS from '@cowprotocol/assets/cow-swap/doc.svg'
+import IMAGE_GAME from '@cowprotocol/assets/cow-swap/game.gif'
+import IMAGE_INFO from '@cowprotocol/assets/cow-swap/info.svg'
+import IMAGE_SLICER from '@cowprotocol/assets/cow-swap/ninja-cow.png'
+import IMAGE_PIE from '@cowprotocol/assets/cow-swap/pie.svg'
+import IMAGE_PRIVACY_POLICY from '@cowprotocol/assets/cow-swap/privacy-policy.svg'
+import IMAGE_TERMS_AND_CONDITIONS from '@cowprotocol/assets/cow-swap/terms-and-conditions.svg'
+import IMAGE_TWITTER from '@cowprotocol/assets/cow-swap/twitter.svg'
+import {
+ CONTRACTS_CODE_LINK,
+ DISCORD_LINK,
+ DOCS_LINK,
+ DUNE_DASHBOARD_LINK,
+ TWITTER_LINK,
+} from '@cowprotocol/common-const'
+import { getExplorerBaseUrl } from '@cowprotocol/common-utils'
+import { ExternalLink } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
-import { useWalletInfo } from 'modules/wallet'
+import { Globe } from 'react-feather'
import { Routes } from 'common/constants/routes'
@@ -60,6 +65,12 @@ export const MAIN_MENU: MenuTreeItem[] = [
title: 'Limit orders',
url: Routes.LIMIT_ORDER,
},
+ {
+ id: MainMenuItemId.ADVANCED_ORDERS,
+ kind: MenuItemKind.PARAMETRIZED_LINK,
+ title: 'TWAP orders',
+ url: Routes.ADVANCED_ORDERS,
+ },
],
},
],
diff --git a/apps/cowswap-frontend/src/modules/mainMenu/hooks.ts b/apps/cowswap-frontend/src/modules/mainMenu/hooks.ts
deleted file mode 100644
index 7612906103..0000000000
--- a/apps/cowswap-frontend/src/modules/mainMenu/hooks.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { useMemo } from 'react'
-
-import { useIsAdvancedOrdersEnabled } from 'common/hooks/useIsAdvancedOrdersEnabled'
-
-import { MenuTreeItem } from './types'
-import { buildMainMenuTreeItems } from './utils'
-
-export function useMenuItems(): MenuTreeItem[] {
- const isAdvancedOrdersEnabled = !!useIsAdvancedOrdersEnabled()
-
- return useMemo(() => buildMainMenuTreeItems({ isAdvancedOrdersEnabled }), [isAdvancedOrdersEnabled])
-}
diff --git a/apps/cowswap-frontend/src/modules/mainMenu/index.ts b/apps/cowswap-frontend/src/modules/mainMenu/index.ts
index 52c64f81db..28508e16a2 100644
--- a/apps/cowswap-frontend/src/modules/mainMenu/index.ts
+++ b/apps/cowswap-frontend/src/modules/mainMenu/index.ts
@@ -1,4 +1,2 @@
export * from './constants/mainMenu'
export * from './types'
-export * from './utils'
-export * from './hooks'
diff --git a/apps/cowswap-frontend/src/modules/mainMenu/pure/MenuTree/index.tsx b/apps/cowswap-frontend/src/modules/mainMenu/pure/MenuTree/index.tsx
index 04bf386858..b5ba054f26 100644
--- a/apps/cowswap-frontend/src/modules/mainMenu/pure/MenuTree/index.tsx
+++ b/apps/cowswap-frontend/src/modules/mainMenu/pure/MenuTree/index.tsx
@@ -1,27 +1,30 @@
+import IMAGE_MOON from '@cowprotocol/assets/cow-swap/moon.svg'
+import IMAGE_SUN from '@cowprotocol/assets/cow-swap/sun.svg'
+import { ExternalLink as ExternalLinkComponent } from '@cowprotocol/ui'
+
import SVG from 'react-inlinesvg'
-import IMAGE_MOON from 'legacy/assets/cow-swap/moon.svg'
-import IMAGE_SUN from 'legacy/assets/cow-swap/sun.svg'
import { HeaderLinks as Wrapper, StyledNavLink } from 'legacy/components/Header/styled'
import MenuDropdown from 'legacy/components/MenuDropdown'
import { MenuSection, MenuTitle } from 'legacy/components/MenuDropdown/styled'
-import { ExternalLink as ExternalLinkComponent } from 'legacy/theme/components'
import {
- DropDownItem,
- ParametrizedLink,
CustomItem,
+ DropDownItem,
ExternalLink,
InternalLink,
MainMenuContext,
MenuItemKind,
MenuLink,
MenuTreeItem,
+ ParametrizedLink,
} from 'modules/mainMenu/types'
import { parameterizeTradeRoute } from 'modules/trade/utils/parameterizeTradeRoute'
import { RoutesValues } from 'common/constants/routes'
+import { MAIN_MENU } from '../../constants/mainMenu'
+
// Assets
// TODO: decompose the file
@@ -164,12 +167,12 @@ function MenuItemWithDropDown(props: MenuItemWithDropDownProps) {
}
export interface MenuTreeProps {
- items: MenuTreeItem[]
+ items?: MenuTreeItem[]
context: MainMenuContext
isMobileMenuOpen: boolean
}
-export function MenuTree({ items, isMobileMenuOpen, context }: MenuTreeProps) {
+export function MenuTree({ items = MAIN_MENU, isMobileMenuOpen, context }: MenuTreeProps) {
return (
{items.map((menuItem, index) => {
diff --git a/apps/cowswap-frontend/src/modules/mainMenu/utils.ts b/apps/cowswap-frontend/src/modules/mainMenu/utils.ts
deleted file mode 100644
index 4cb760db8b..0000000000
--- a/apps/cowswap-frontend/src/modules/mainMenu/utils.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import cloneDeep from 'clone-deep'
-
-import { Routes } from 'common/constants/routes'
-
-import { MAIN_MENU } from './constants/mainMenu'
-import { DropDownItem, MainMenuItemId, MenuItemKind, MenuTreeItem } from './types'
-
-const ADVANCED_ORDERS_MENU_TITLE = 'TWAP orders'
-
-export type BuildMainMenuTreeItemsParams = {
- isAdvancedOrdersEnabled: boolean
-}
-
-export function buildMainMenuTreeItems({ isAdvancedOrdersEnabled }: BuildMainMenuTreeItemsParams): MenuTreeItem[] {
- if (!isAdvancedOrdersEnabled) {
- return MAIN_MENU
- }
-
- // Make a deep copy to avoid mutating original
- const mainMenuCopy = cloneDeep(MAIN_MENU)
-
- // Assume trade menu is at the first position
- const [tradeMenu] = mainMenuCopy
-
- // Add to the bottom of the list
- ;(tradeMenu as DropDownItem).items[0].links.push({
- id: MainMenuItemId.ADVANCED_ORDERS,
- kind: MenuItemKind.PARAMETRIZED_LINK,
- title: ADVANCED_ORDERS_MENU_TITLE,
- url: Routes.ADVANCED_ORDERS,
- })
-
- return mainMenuCopy
-}
diff --git a/apps/cowswap-frontend/src/modules/operations/bundle/buildApproveTx.ts b/apps/cowswap-frontend/src/modules/operations/bundle/buildApproveTx.ts
index 7a2e6ac24b..abd22db931 100644
--- a/apps/cowswap-frontend/src/modules/operations/bundle/buildApproveTx.ts
+++ b/apps/cowswap-frontend/src/modules/operations/bundle/buildApproveTx.ts
@@ -1,4 +1,4 @@
-import { Erc20 } from '@cowswap/abis'
+import { Erc20 } from '@cowprotocol/abis'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import { estimateApprove } from 'common/hooks/useApproveCallback'
diff --git a/apps/cowswap-frontend/src/modules/operations/bundle/buildPresignTx.ts b/apps/cowswap-frontend/src/modules/operations/bundle/buildPresignTx.ts
index 49f9fcc256..d4157a7d5b 100644
--- a/apps/cowswap-frontend/src/modules/operations/bundle/buildPresignTx.ts
+++ b/apps/cowswap-frontend/src/modules/operations/bundle/buildPresignTx.ts
@@ -1,4 +1,4 @@
-import { GPv2Settlement } from '@cowswap/abis'
+import { GPv2Settlement } from '@cowprotocol/abis'
export type BuildPresignTxParams = {
orderId: string
diff --git a/apps/cowswap-frontend/src/modules/operations/bundle/buildWrapTx.ts b/apps/cowswap-frontend/src/modules/operations/bundle/buildWrapTx.ts
index e0d9e9d577..0adeb8e0c2 100644
--- a/apps/cowswap-frontend/src/modules/operations/bundle/buildWrapTx.ts
+++ b/apps/cowswap-frontend/src/modules/operations/bundle/buildWrapTx.ts
@@ -1,4 +1,4 @@
-import { Weth } from '@cowswap/abis'
+import { Weth } from '@cowprotocol/abis'
export type BuildWrapTxParams = {
wrappedNativeContract: Weth
diff --git a/apps/cowswap-frontend/src/modules/orders/hooks/useSWROrdersRequest.ts b/apps/cowswap-frontend/src/modules/orders/hooks/useSWROrdersRequest.ts
index 49f4fe2d97..d3fada025a 100644
--- a/apps/cowswap-frontend/src/modules/orders/hooks/useSWROrdersRequest.ts
+++ b/apps/cowswap-frontend/src/modules/orders/hooks/useSWROrdersRequest.ts
@@ -1,8 +1,7 @@
import { useMemo } from 'react'
-import { AMOUNT_OF_ORDERS_TO_FETCH } from 'legacy/constants'
-
-import { useWalletInfo } from 'modules/wallet'
+import { AMOUNT_OF_ORDERS_TO_FETCH } from '@cowprotocol/common-const'
+import { useWalletInfo } from '@cowprotocol/wallet'
export function useSWROrdersRequest(): { owner: string; limit: number } | null {
const { account } = useWalletInfo()
diff --git a/apps/cowswap-frontend/src/modules/orders/hooks/useSWRProdOrders.ts b/apps/cowswap-frontend/src/modules/orders/hooks/useSWRProdOrders.ts
index da01743db6..0e438f14bf 100644
--- a/apps/cowswap-frontend/src/modules/orders/hooks/useSWRProdOrders.ts
+++ b/apps/cowswap-frontend/src/modules/orders/hooks/useSWRProdOrders.ts
@@ -1,14 +1,12 @@
import { useMemo } from 'react'
+import { GP_ORDER_UPDATE_INTERVAL } from '@cowprotocol/common-const'
+import { isBarnBackendEnv } from '@cowprotocol/common-utils'
import { EnrichedOrder } from '@cowprotocol/cow-sdk'
+import { useWalletInfo } from '@cowprotocol/wallet'
import useSWR from 'swr'
-import { GP_ORDER_UPDATE_INTERVAL } from 'legacy/constants'
-import { isBarnBackendEnv } from 'legacy/utils/environments'
-
-import { useWalletInfo } from 'modules/wallet'
-
import { getOrders } from 'api/gnosisProtocol'
import { useApiOrders } from './useApiOrders'
diff --git a/apps/cowswap-frontend/src/modules/orders/hooks/useTokensForOrdersList.ts b/apps/cowswap-frontend/src/modules/orders/hooks/useTokensForOrdersList.ts
index e3e42c175d..5d1174e575 100644
--- a/apps/cowswap-frontend/src/modules/orders/hooks/useTokensForOrdersList.ts
+++ b/apps/cowswap-frontend/src/modules/orders/hooks/useTokensForOrdersList.ts
@@ -1,12 +1,13 @@
import { useCallback, useRef } from 'react'
+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, TokenWithLogo } from 'modules/tokensList/state/tokensListAtom'
-import { useWalletInfo } from 'modules/wallet'
+import { TokensByAddress } from 'modules/tokensList/state/tokensListAtom'
+import { TokenWithLogo } from 'modules/tokensList/types'
import { getTokenFromMapping } from 'utils/orderUtils/getTokenFromMapping'
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/containers/MultipleCancellationMenu/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/containers/MultipleCancellationMenu/index.tsx
index cb738c2a21..760b94f5b9 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/containers/MultipleCancellationMenu/index.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/containers/MultipleCancellationMenu/index.tsx
@@ -1,12 +1,13 @@
import { useAtomValue, useSetAtom } from 'jotai'
import { useCallback, useEffect } from 'react'
+import { useWalletDetails } from '@cowprotocol/wallet'
+
import { transparentize } from 'polished'
import { Trash2 } from 'react-feather'
import styled from 'styled-components/macro'
-import { useWalletDetails } from 'modules/wallet'
-
+import { UI } from 'common/constants/theme'
import { useMultipleOrdersCancellation } from 'common/hooks/useMultipleOrdersCancellation'
import { ordersToCancelAtom, updateOrdersToCancelAtom } from 'common/hooks/useMultipleOrdersCancellation/state'
import { isOrderOffChainCancellable } from 'common/utils/isOrderOffChainCancellable'
@@ -61,7 +62,7 @@ const ActionButton = styled.button`
const TextButton = styled.button`
display: inline-block;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
font-size: 13px;
padding: 5px 10px;
cursor: pointer;
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersReceiptModal/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersReceiptModal/index.tsx
index e13b1738ed..4cc7b9f947 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersReceiptModal/index.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersReceiptModal/index.tsx
@@ -1,13 +1,12 @@
+import { useENS } from '@cowprotocol/ens'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { CurrencyAmount } from '@uniswap/sdk-core'
import JSBI from 'jsbi'
-import useENS from 'legacy/hooks/useENS'
-
import { PendingOrdersPrices } from 'modules/orders/state/pendingOrdersPricesAtom'
import { ReceiptModal } from 'modules/ordersTable/pure/ReceiptModal'
import { useTwapOrderById, useTwapOrderByChildId } from 'modules/twap'
-import { useWalletInfo } from 'modules/wallet'
import { calculatePrice } from 'utils/orderUtils/calculatePrice'
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useGetOrdersToCheckPendingPermit.ts b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useGetOrdersToCheckPendingPermit.ts
new file mode 100644
index 0000000000..444c72662b
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useGetOrdersToCheckPendingPermit.ts
@@ -0,0 +1,34 @@
+import { useMemo } from 'react'
+
+import { SupportedChainId } from '@cowprotocol/cow-sdk'
+
+import { BalancesAndAllowances } from 'modules/tokens'
+
+import { ParsedOrder } from 'utils/orderUtils/parseOrder'
+
+import { OrdersTableList } from './useOrdersTableList'
+
+import { getOrderParams } from '../../../pure/OrdersTableContainer/utils/getOrderParams'
+import { isParsedOrder } from '../../../utils/orderTableGroupUtils'
+
+export function useGetOrdersToCheckPendingPermit(
+ ordersList: OrdersTableList,
+ chainId: SupportedChainId,
+ balancesAndAllowances: BalancesAndAllowances
+) {
+ return useMemo(() => {
+ // Pick only the pending orders
+ return ordersList.pending.reduce((acc: ParsedOrder[], item) => {
+ // Only do it for regular orders (not TWAP)
+ if (isParsedOrder(item)) {
+ const { hasEnoughAllowance } = getOrderParams(chainId, balancesAndAllowances, item)
+
+ // Only if the order has not enough allowance
+ if (hasEnoughAllowance === false) {
+ acc.push(item)
+ }
+ }
+ return acc
+ }, [])
+ }, [balancesAndAllowances, chainId, ordersList.pending])
+}
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useOrdersTableList.ts b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useOrdersTableList.ts
index d42302c4f1..186e89fe5e 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useOrdersTableList.ts
+++ b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useOrdersTableList.ts
@@ -3,7 +3,7 @@ import { useMemo } from 'react'
import { Order, PENDING_STATES } from 'legacy/state/orders/actions'
import { groupOrdersTable } from '../../../utils/groupOrdersTable'
-import { getParsedOrderFromItem, isParsedOrder, OrderTableItem } from '../../../utils/orderTableGroupUtils'
+import { getParsedOrderFromTableItem, isParsedOrder, OrderTableItem } from '../../../utils/orderTableGroupUtils'
export interface OrdersTableList {
pending: OrderTableItem[]
@@ -11,8 +11,8 @@ export interface OrdersTableList {
}
const ordersSorter = (a: OrderTableItem, b: OrderTableItem) => {
- const aCreationTime = getParsedOrderFromItem(a).creationTime
- const bCreationTime = getParsedOrderFromItem(b).creationTime
+ const aCreationTime = getParsedOrderFromTableItem(a).creationTime
+ const bCreationTime = getParsedOrderFromTableItem(b).creationTime
return bCreationTime.getTime() - aCreationTime.getTime()
}
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useOrdersTableTokenApprove.test.ts b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useOrdersTableTokenApprove.test.ts
index bb3b468d14..c93d059593 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useOrdersTableTokenApprove.test.ts
+++ b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useOrdersTableTokenApprove.test.ts
@@ -1,8 +1,8 @@
import { useEffect } from 'react'
-import { renderHook } from '@testing-library/react-hooks'
+import { WETH_GOERLI } from '@cowprotocol/common-const'
-import { WETH_GOERLI } from 'legacy/utils/goerli/constants'
+import { renderHook } from '@testing-library/react-hooks'
import { useTradeApproveCallback } from 'common/containers/TradeApprove'
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/index.tsx
index 2c196c3808..d98cc04619 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/index.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/index.tsx
@@ -1,10 +1,12 @@
import { useAtomValue, useSetAtom } from 'jotai'
import { useCallback, useEffect, useMemo } from 'react'
+import { GP_VAULT_RELAYER } from '@cowprotocol/common-const'
+import { useIsSafeViaWc, useWalletDetails, useWalletInfo } from '@cowprotocol/wallet'
+
import { useLocation, useNavigate } from 'react-router-dom'
import styled from 'styled-components/macro'
-import { GP_VAULT_RELAYER } from 'legacy/constants'
import { Order } from 'legacy/state/orders/actions'
import { pendingOrdersPricesAtom } from 'modules/orders/state/pendingOrdersPricesAtom'
@@ -15,20 +17,22 @@ import { OrdersReceiptModal } from 'modules/ordersTable/containers/OrdersReceipt
import { useSelectReceiptOrder } from 'modules/ordersTable/containers/OrdersReceiptModal/hooks'
import { OrderActions } from 'modules/ordersTable/pure/OrdersTableContainer/types'
import { buildOrdersTableUrl, parseOrdersTableUrl } from 'modules/ordersTable/utils/buildOrdersTableUrl'
+import { PendingPermitUpdater, useGetOrdersPermitStatus } from 'modules/permit'
import { useBalancesAndAllowances } from 'modules/tokens'
-import { useIsSafeViaWc, useWalletDetails, useWalletInfo } from 'modules/wallet'
import { useCancelOrder } from 'common/hooks/useCancelOrder'
+import { useCategorizeRecentActivity } from 'common/hooks/useCategorizeRecentActivity'
import { ordersToCancelAtom, updateOrdersToCancelAtom } from 'common/hooks/useMultipleOrdersCancellation/state'
import { CancellableOrder } from 'common/utils/isOrderCancellable'
import { ParsedOrder } from 'utils/orderUtils/parseOrder'
+import { useGetOrdersToCheckPendingPermit } from './hooks/useGetOrdersToCheckPendingPermit'
import { OrdersTableList, useOrdersTableList } from './hooks/useOrdersTableList'
import { useOrdersTableTokenApprove } from './hooks/useOrdersTableTokenApprove'
import { useValidatePageUrlParams } from './hooks/useValidatePageUrlParams'
import { OrdersTableContainer, TabOrderTypes } from '../../pure/OrdersTableContainer'
-import { getParsedOrderFromItem, OrderTableItem, tableItemsToOrders } from '../../utils/orderTableGroupUtils'
+import { getParsedOrderFromTableItem, OrderTableItem, tableItemsToOrders } from '../../utils/orderTableGroupUtils'
function getOrdersListByIndex(ordersList: OrdersTableList, id: string): OrderTableItem[] {
return id === OPEN_TAB.id ? ordersList.pending : ordersList.history
@@ -71,6 +75,7 @@ export function OrdersTableWidget({
const getSpotPrice = useGetSpotPrice()
const selectReceiptOrder = useSelectReceiptOrder()
const isSafeViaWc = useIsSafeViaWc()
+ const ordersPermitStatus = useGetOrdersPermitStatus()
const spender = useMemo(() => (chainId ? GP_VAULT_RELAYER[chainId] : undefined), [chainId])
@@ -99,11 +104,12 @@ export function OrdersTableWidget({
const tokens = useMemo(() => {
const pendingOrders = isOpenOrdersTab ? ordersList.pending : []
- return pendingOrders.map((item) => getParsedOrderFromItem(item).inputToken)
+ return pendingOrders.map((item) => getParsedOrderFromTableItem(item).inputToken)
}, [isOpenOrdersTab, ordersList.pending])
// Get effective balance
const balancesAndAllowances = useBalancesAndAllowances({ account, spender, tokens })
+ const { pendingActivity } = useCategorizeRecentActivity()
const toggleOrdersForCancellation = useCallback(
(orders: ParsedOrder[]) => {
@@ -145,8 +151,11 @@ export function OrdersTableWidget({
useValidatePageUrlParams(orders.length, currentTabId, currentPageNumber)
+ const ordersToCheckPendingPermit = useGetOrdersToCheckPendingPermit(ordersList, chainId, balancesAndAllowances)
+
return (
<>
+
{isOpenOrdersTab && orders.length && }
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/EstimatedExecutionPrice.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/EstimatedExecutionPrice.tsx
index 01d725a782..a1e9a5ab86 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/EstimatedExecutionPrice.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/EstimatedExecutionPrice.tsx
@@ -1,18 +1,17 @@
import { useContext } from 'react'
+import AlertTriangle from '@cowprotocol/assets/cow-swap/alert.svg'
+import { ZERO_FRACTION } from '@cowprotocol/common-const'
+import { SymbolElement, TokenAmount, TokenAmountProps } from '@cowprotocol/ui'
+import { MouseoverTooltipContent } from '@cowprotocol/ui'
import { Currency, CurrencyAmount, Fraction, Percent } from '@uniswap/sdk-core'
import { darken, transparentize } from 'polished'
import SVG from 'react-inlinesvg'
import styled, { ThemeContext } from 'styled-components/macro'
-import AlertTriangle from 'legacy/assets/cow-swap/alert.svg'
-import { MouseoverTooltipContent } from 'legacy/components/Tooltip'
-import { ZERO_FRACTION } from 'legacy/constants'
-
import { HIGH_FEE_WARNING_PERCENTAGE } from 'common/constants/common'
import { calculateOrderExecutionStatus, ExecuteIndicator } from 'common/pure/OrderExecutionStatusList'
-import { SymbolElement, TokenAmount, TokenAmountProps } from 'common/pure/TokenAmount'
import * as styledEl from './styled'
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/OrderContextMenu.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/OrderContextMenu.tsx
index 08f2b3c49d..2ebd2ab942 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/OrderContextMenu.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/OrderContextMenu.tsx
@@ -5,6 +5,8 @@ import { transparentize } from 'polished'
import { FileText, Link2, MoreVertical, Trash2 } from 'react-feather'
import styled, { ThemeContext } from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
export const ContextMenuButton = styled(MenuButton)`
background: none;
border: 0;
@@ -26,7 +28,7 @@ export const ContextMenuButton = styled(MenuButton)`
}
`
export const ContextMenuList = styled(MenuList)`
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
border-radius: 12px;
overflow: hidden;
position: relative;
@@ -47,7 +49,7 @@ export const ContextMenuItem = styled(MenuItem)<{ $red?: boolean }>`
align-items: center;
font-size: 15px;
font-weight: 500;
- color: ${({ theme, $red }) => ($red ? theme.danger : theme.text1)};
+ color: ${({ theme, $red }) => ($red ? `var(${UI.COLOR_DANGER})` : theme.text1)};
&:hover {
background: ${({ theme }) => transparentize(0.8, theme.text3)};
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 e02fd5057d..e71f7ff25d 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
@@ -1,17 +1,17 @@
import React, { useCallback, useContext, useEffect, useState } from 'react'
+import AlertTriangle from '@cowprotocol/assets/cow-swap/alert.svg'
+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 { Loader, TokenAmount, TokenSymbol } from '@cowprotocol/ui'
import { Currency, CurrencyAmount, Percent, Price } from '@uniswap/sdk-core'
import SVG from 'react-inlinesvg'
import { ThemeContext } from 'styled-components/macro'
-import AlertTriangle from 'legacy/assets/cow-swap/alert.svg'
-import Loader from 'legacy/components/Loader'
-import { ZERO_FRACTION } from 'legacy/constants'
-import useTimeAgo from 'legacy/hooks/useTimeAgo'
import { CREATING_STATES, OrderStatus } from 'legacy/state/orders/actions'
-import { getEtherscanLink } from 'legacy/utils'
import { PendingOrderPrices } from 'modules/orders/state/pendingOrdersPricesAtom'
import { EstimatedExecutionPrice } from 'modules/ordersTable/pure/OrdersTableContainer/OrderRow/EstimatedExecutionPrice'
@@ -30,11 +30,8 @@ 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 { TokenAmount } from 'common/pure/TokenAmount'
-import { TokenSymbol } from 'common/pure/TokenSymbol'
import { getQuoteCurrency } from 'common/services/getQuoteCurrency'
import { isOrderCancellable } from 'common/utils/isOrderCancellable'
-import { getAddress } from 'utils/getAddress'
import { calculatePercentageInRelationToReference } from 'utils/orderUtils/calculatePercentageInRelationToReference'
import { calculatePriceDifference, PriceDifference } from 'utils/orderUtils/calculatePriceDifference'
import { getIsComposableCowParentOrder } from 'utils/orderUtils/getIsComposableCowParentOrder'
@@ -151,6 +148,7 @@ export interface OrderRowProps {
orderParams: OrderParams
onClick: () => void
orderActions: OrderActions
+ hasValidPendingPermit?: boolean | undefined
children?: JSX.Element
}
@@ -167,6 +165,7 @@ export function OrderRow({
prices,
spotPrice,
children,
+ hasValidPendingPermit,
}: OrderRowProps) {
const { buyAmount, rateInfoParams, hasEnoughAllowance, hasEnoughBalance, chainId } = orderParams
const { creationTime, expirationTime, status } = order
@@ -177,7 +176,7 @@ export function OrderRow({
const showCancellationModal = orderActions.getShowCancellationModal(order)
const withWarning =
- (hasEnoughBalance === false || hasEnoughAllowance === false) &&
+ (hasEnoughBalance === false || (hasEnoughAllowance === false && hasValidPendingPermit === false)) &&
// show the warning only for pending and scheduled orders
(status === OrderStatus.PENDING || status === OrderStatus.SCHEDULED)
const theme = useContext(ThemeContext)
@@ -360,7 +359,7 @@ export function OrderRow({
{hasEnoughBalance === false && (
)}
- {hasEnoughAllowance === false && (
+ {hasEnoughAllowance === false && hasValidPendingPermit === false && (
orderActions.approveOrderToken(order.inputToken)}
symbol={inputTokenSymbol}
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 2c566846b8..a335e391df 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
@@ -3,6 +3,7 @@ import styled from 'styled-components/macro'
import QuestionHelper from 'legacy/components/QuestionHelper'
+import { UI } from 'common/constants/theme'
import { RateWrapper } from 'common/pure/RateInfo'
export const WarningIndicator = styled.button<{ hasBackground?: boolean }>`
@@ -297,7 +298,7 @@ export const ToggleExpandButton = styled.div<{ isCollapsed?: boolean }>`
margin: 0 0 0 6px;
cursor: pointer;
outline: none;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
transition: color 0.2s ease-out;
position: relative;
height: var(--height);
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx
index 4e34e84f23..b9d87eadb5 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx
@@ -1,5 +1,6 @@
-import React, { useCallback, useState, useEffect, useMemo, useRef } from 'react'
+import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
+import iconOrderExecution from '@cowprotocol/assets/cow-swap/orderExecution.svg'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { Currency, Price } from '@uniswap/sdk-core'
@@ -10,23 +11,23 @@ import SVG from 'react-inlinesvg'
import { useLocation } from 'react-router-dom'
import styled from 'styled-components/macro'
-import iconOrderExecution from 'legacy/assets/cow-swap/orderExecution.svg'
-import { QuestionWrapper } from 'legacy/components/QuestionHelper'
-import QuestionHelper from 'legacy/components/QuestionHelper'
+import QuestionHelper, { QuestionWrapper } from 'legacy/components/QuestionHelper'
import { PendingOrdersPrices } from 'modules/orders/state/pendingOrdersPricesAtom'
import { SpotPricesKeyParams } from 'modules/orders/state/spotPricesAtom'
import { ORDERS_TABLE_PAGE_SIZE } from 'modules/ordersTable/const/tabs'
import {
+ CheckboxCheckmark,
TableHeader,
TableRowCheckbox,
TableRowCheckboxWrapper,
- CheckboxCheckmark,
} from 'modules/ordersTable/pure/OrdersTableContainer/styled'
import { OrderActions } from 'modules/ordersTable/pure/OrdersTableContainer/types'
+import { OrdersPermitStatus } from 'modules/permit'
import { BalancesAndAllowances } from 'modules/tokens'
import { ordersTableFeatures } from 'common/constants/featureFlags'
+import { UI } from 'common/constants/theme'
import { OrderExecutionStatusList, RateTooltipHeader } from 'common/pure/OrderExecutionStatusList'
import { InvertRateControl } from 'common/pure/RateInfo'
import { CancellableOrder } from 'common/utils/isOrderCancellable'
@@ -39,7 +40,7 @@ import { getOrderParams } from './utils/getOrderParams'
import { buildOrdersTableUrl } from '../../utils/buildOrdersTableUrl'
import {
- getParsedOrderFromItem,
+ getParsedOrderFromTableItem,
isParsedOrder,
OrderTableItem,
tableItemsToOrders,
@@ -150,7 +151,7 @@ const StyledCloseIcon = styled(X)`
}
> line {
- stroke: ${({ theme }) => theme.text1};
+ stroke: var(${UI.COLOR_TEXT1});
}
`
@@ -205,6 +206,7 @@ export interface OrdersTableProps {
balancesAndAllowances: BalancesAndAllowances
getSpotPrice: (params: SpotPricesKeyParams) => Price | null
orderActions: OrderActions
+ ordersPermitStatus: OrdersPermitStatus
}
export function OrdersTable({
@@ -218,6 +220,7 @@ export function OrdersTable({
getSpotPrice,
orderActions,
currentPageNumber,
+ ordersPermitStatus,
}: OrdersTableProps) {
const location = useLocation()
const [isRateInverted, setIsRateInverted] = useState(false)
@@ -260,14 +263,14 @@ export function OrdersTable({
}, [showOrdersExplainerBanner])
const cancellableOrders = useMemo(
- () => ordersPage.filter((item) => isOrderOffChainCancellable(getParsedOrderFromItem(item))),
+ () => ordersPage.filter((item) => isOrderOffChainCancellable(getParsedOrderFromTableItem(item))),
[ordersPage]
)
const allOrdersSelected = useMemo(() => {
if (!cancellableOrders.length) return false
- return cancellableOrders.every((item) => selectedOrdersMap[getParsedOrderFromItem(item).id])
+ return cancellableOrders.every((item) => selectedOrdersMap[getParsedOrderFromTableItem(item).id])
}, [cancellableOrders, selectedOrdersMap])
const getPageUrl = useCallback((index: number) => buildOrdersTableUrl(location, { pageNumber: index }), [location])
@@ -399,7 +402,7 @@ export function OrdersTable({
{ordersPage.map((item) => {
- const { inputToken, outputToken } = getParsedOrderFromItem(item)
+ const { inputToken, outputToken } = getParsedOrderFromTableItem(item)
const spotPrice = getSpotPrice({
chainId: chainId as SupportedChainId,
sellTokenAddress: inputToken.address,
@@ -409,6 +412,10 @@ export function OrdersTable({
if (isParsedOrder(item)) {
const order = item
+ const orderParams = getOrderParams(chainId, balancesAndAllowances, order)
+
+ const hasValidPendingPermit = ordersPermitStatus[order.id]
+
return (
orderActions.selectReceiptOrder(order)}
+ hasValidPendingPermit={hasValidPendingPermit}
/>
)
} else {
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTablePagination.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTablePagination.tsx
index e4519ba642..e5e7519a93 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTablePagination.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTablePagination.tsx
@@ -2,6 +2,8 @@ import { transparentize } from 'polished'
import { Link } from 'react-router-dom'
import styled, { css } from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
export interface OrdersTablePaginationProps {
getPageUrl?(index: number): Partial<{ pathname: string; search: string }>
onPageChange?(index: number): void
@@ -28,7 +30,7 @@ const PaginationBox = styled.div`
const pageButtonStyles = css<{ $active?: boolean }>`
background: ${({ theme, $active }) => ($active ? transparentize(0.9, theme.text3) : 'transparent')};
- color: ${({ theme, $active }) => ($active ? theme.text1 : transparentize(0.2, theme.text1))};
+ color: ${({ theme, $active }) => ($active ? `var(${UI.COLOR_TEXT1})` : transparentize(0.2, theme.text1))};
border: 0;
outline: 0;
padding: 5px 10px;
@@ -39,8 +41,8 @@ const pageButtonStyles = css<{ $active?: boolean }>`
text-decoration: none;
&:hover {
- background: ${({ theme }) => theme.bg1};
- color: ${({ theme }) => theme.text1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
+ color: var(${UI.COLOR_TEXT1});
}
`
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTabs.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTabs.tsx
index 0b228fe113..b12867c0bf 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTabs.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTabs.tsx
@@ -5,6 +5,8 @@ import styled from 'styled-components/macro'
import { buildOrdersTableUrl } from 'modules/ordersTable/utils/buildOrdersTableUrl'
+import { UI } from 'common/constants/theme'
+
import { OrderTab } from '../../const/tabs'
const Tabs = styled.div`
@@ -24,7 +26,7 @@ const Tabs = styled.div`
const TabButton = styled(Link)<{ active: string }>`
display: inline-block;
background: ${({ theme, active }) => (active === 'true' ? transparentize(0.88, theme.text3) : 'transparent')};
- color: ${({ theme, active }) => (active === 'true' ? theme.text1 : transparentize(0.2, theme.text1))};
+ color: ${({ theme, active }) => (active === 'true' ? `var(${UI.COLOR_TEXT1})` : transparentize(0.2, theme.text1))};
font-weight: ${({ active }) => (active === 'true' ? '600' : '400')};
text-decoration: none;
font-size: 13px;
@@ -39,8 +41,8 @@ const TabButton = styled(Link)<{ active: string }>`
`};
&:hover {
- background: ${({ theme }) => theme.bg1};
- color: ${({ theme }) => theme.text1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
+ color: var(${UI.COLOR_TEXT1});
}
`
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.cosmos.tsx
index a35075a79b..0288e07a25 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.cosmos.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.cosmos.tsx
@@ -53,6 +53,7 @@ const orderActions: OrderActions = {
export default (
null}
orderActions={orderActions}
orderType={TabOrderTypes.LIMIT}
+ ordersPermitStatus={{}}
/>
)
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.tsx
index 5370596d2c..dcde2ae431 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.tsx
@@ -1,16 +1,15 @@
import { ReactNode } from 'react'
+import cowMeditatingV2 from '@cowprotocol/assets/cow-swap/meditating-cow-v2.svg'
+import imageConnectWallet from '@cowprotocol/assets/cow-swap/wallet-plus.svg'
+import { ExternalLink } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import { transparentize } from 'polished'
import SVG from 'react-inlinesvg'
import styled from 'styled-components/macro'
-import cowMeditatingV2 from 'legacy/assets/cow-swap/meditating-cow-v2.svg'
-import imageConnectWallet from 'legacy/assets/cow-swap/wallet-plus.svg'
-import { ExternalLink } from 'legacy/theme'
-
-import { Wrapper as Web3StatusWrapper } from 'modules/wallet/api/pure/Web3StatusInner/styled'
-import { Web3Status } from 'modules/wallet/web3-react/containers/Web3Status'
+import { Web3Status } from 'modules/wallet/containers/Web3Status'
import { CowSwapSafeAppLink } from 'common/pure/CowSwapSafeAppLink'
@@ -85,10 +84,6 @@ const Content = styled.div`
text-align: center;
color: ${({ theme }) => transparentize(0.3, theme.text1)};
}
-
- ${Web3StatusWrapper} {
- margin: 0 auto;
- }
`
const Header = styled.div`
@@ -144,6 +139,7 @@ export interface OrdersProps extends OrdersTabsProps, OrdersTableProps {
isOpenOrdersTab: boolean
isSafeViaWc: boolean
displayOrdersOnlyForSafeApp: boolean
+ pendingActivities: string[]
children?: ReactNode
orderType: TabOrderTypes
}
@@ -170,6 +166,8 @@ export function OrdersTableContainer({
getSpotPrice,
children,
orderType,
+ pendingActivities,
+ ordersPermitStatus,
}: OrdersProps) {
const content = () => {
if (!isWalletConnected) {
@@ -188,7 +186,7 @@ export function OrdersTableContainer({
-
+
)
}
@@ -236,6 +234,7 @@ export function OrdersTableContainer({
balancesAndAllowances={balancesAndAllowances}
getSpotPrice={getSpotPrice}
orderActions={orderActions}
+ ordersPermitStatus={ordersPermitStatus}
/>
)
}
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/orders.mock.ts b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/orders.mock.ts
index 89c9e45e14..742785a504 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/orders.mock.ts
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/orders.mock.ts
@@ -1,8 +1,8 @@
+import { COW, DAI, GNO, USDC } from '@cowprotocol/common-const'
+import { WETH_GOERLI } from '@cowprotocol/common-const'
import { OrderKind, OrderClass } from '@cowprotocol/cow-sdk'
-import { COW, DAI, GNO, USDC } from 'legacy/constants/tokens'
import { OrderStatus } from 'legacy/state/orders/actions'
-import { WETH_GOERLI } from 'legacy/utils/goerli/constants'
import { ParsedOrder, parseOrder } from 'utils/orderUtils/parseOrder'
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/styled.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/styled.tsx
index bfa9c7de84..bc97fc4c2a 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/styled.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/styled.tsx
@@ -1,6 +1,7 @@
import { transparentize } from 'polished'
import styled from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
import { RateWrapper } from 'common/pure/RateInfo'
export const TableHeader = styled.div<{ isOpenOrdersTab: boolean; isRowSelectable: boolean }>`
@@ -118,7 +119,7 @@ export const TableRowCheckbox = styled.input`
outline: 0;
&:checked {
- background-color: ${({ theme }) => theme.text1};
+ background-color: var(${UI.COLOR_TEXT1});
}
&:checked + ${CheckboxCheckmark}::after {
@@ -126,7 +127,7 @@ export const TableRowCheckbox = styled.input`
}
&:indeterminate {
- border-color: ${({ theme }) => theme.text1};
+ border-color: var(${UI.COLOR_TEXT1});
}
&:indeterminate + ${CheckboxCheckmark}::after {
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 8968e26a34..afda0bf5fd 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
@@ -1,10 +1,10 @@
+import { isEnoughAmount } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { Currency, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core'
import { BalancesAndAllowances } from 'modules/tokens'
import { RateInfoParams } from 'common/pure/RateInfo'
-import { isEnoughAmount } from 'utils/isEnoughAmount'
import { ParsedOrder } from 'utils/orderUtils/parseOrder'
export interface OrderParams {
@@ -23,8 +23,8 @@ export function getOrderParams(
balancesAndAllowances: BalancesAndAllowances,
order: ParsedOrder
): OrderParams {
- const sellAmount = CurrencyAmount.fromRawAmount(order.inputToken, order.sellAmount.toString())
- const buyAmount = CurrencyAmount.fromRawAmount(order.outputToken, order.buyAmount.toString())
+ const sellAmount = CurrencyAmount.fromRawAmount(order.inputToken, order.sellAmount)
+ const buyAmount = CurrencyAmount.fromRawAmount(order.outputToken, order.buyAmount)
const rateInfoParams: RateInfoParams = {
chainId,
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/CurrencyField.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/CurrencyField.tsx
index 05b1f2a7b5..ddb834a39e 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/CurrencyField.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/CurrencyField.tsx
@@ -1,7 +1,7 @@
+import { TokenAmount } from '@cowprotocol/ui'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { CurrencySelectButton } from 'common/pure/CurrencySelectButton'
-import { TokenAmount } from 'common/pure/TokenAmount'
import * as styledEl from './styled'
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/DateField.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/DateField.tsx
index 38642583fe..63ae1693af 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/DateField.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/DateField.tsx
@@ -1,6 +1,6 @@
-import { format } from 'date-fns'
+import { useTimeAgo } from '@cowprotocol/common-hooks'
-import useTimeAgo from 'legacy/hooks/useTimeAgo'
+import { format } from 'date-fns'
import * as styledEl from './styled'
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/FeeField.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/FeeField.tsx
index 7786024f61..eed9c96389 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/FeeField.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/FeeField.tsx
@@ -1,6 +1,6 @@
+import { TokenAmount } from '@cowprotocol/ui'
import { CurrencyAmount } from '@uniswap/sdk-core'
-import { TokenAmount } from 'common/pure/TokenAmount'
import { ParsedOrder } from 'utils/orderUtils/parseOrder'
import * as styledEl from './styled'
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/FilledField.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/FilledField.tsx
index 5c2752ac09..866e6c7e93 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/FilledField.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/FilledField.tsx
@@ -1,8 +1,9 @@
// Code based on https://github.com/cowprotocol/explorer/blob/develop/src/components/orders/FilledProgress/index.tsx
+import { TokenAmount } from '@cowprotocol/ui'
+
import { ProgressBarWrapper, ProgressBar } from 'modules/ordersTable/pure/OrdersTableContainer/OrderRow/styled'
-import { TokenAmount } from 'common/pure/TokenAmount'
import { getFilledAmounts } from 'utils/orderUtils/getFilledAmounts'
import { ParsedOrder } from 'utils/orderUtils/parseOrder'
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/IdField.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/IdField.tsx
index 73eef077b1..4947ceeda0 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/IdField.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/IdField.tsx
@@ -1,7 +1,6 @@
+import { getEtherscanLink } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
-
-import { ExternalLink } from 'legacy/theme'
-import { getEtherscanLink } from 'legacy/utils'
+import { ExternalLink } from '@cowprotocol/ui'
import * as styledEl from './styled'
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/PriceField.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/PriceField.tsx
index 9a6b7a469d..9e53548174 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/PriceField.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/PriceField.tsx
@@ -1,7 +1,7 @@
+import { TokenAmount } from '@cowprotocol/ui'
+import { TokenSymbol } from '@cowprotocol/ui'
import { Fraction } from '@uniswap/sdk-core'
-import { TokenAmount } from 'common/pure/TokenAmount'
-import { TokenSymbol } from 'common/pure/TokenSymbol'
import { ParsedOrder } from 'utils/orderUtils/parseOrder'
import * as styledEl from './styled'
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/SurplusField.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/SurplusField.tsx
index 7cd1495a1b..235ec3282c 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/SurplusField.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/SurplusField.tsx
@@ -1,7 +1,7 @@
import { OrderKind } from '@cowprotocol/cow-sdk'
+import { TokenAmount } from '@cowprotocol/ui'
import { CurrencyAmount } from '@uniswap/sdk-core'
-import { TokenAmount } from 'common/pure/TokenAmount'
import { ParsedOrder } from 'utils/orderUtils/parseOrder'
import * as styledEl from './styled'
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/fields/SafeTxFields.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/fields/SafeTxFields.tsx
index 93a75c77f2..00eea420be 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/fields/SafeTxFields.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/fields/SafeTxFields.tsx
@@ -1,9 +1,8 @@
+import safeLogo from '@cowprotocol/assets/cow-swap/safe-logo.svg'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import styled from 'styled-components/macro'
-import safeLogo from 'modules/wallet/api/assets/safe-logo.svg'
-
import { SafeWalletLink } from 'common/pure/SafeWalletLink'
import { FieldLabel } from '../FieldLabel'
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/index.tsx
index 512aae78c7..609ac01159 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/index.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/index.tsx
@@ -1,15 +1,23 @@
+import { ExplorerDataType, getExplorerLink, shortenAddress } from '@cowprotocol/common-utils'
import { OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk'
+import { ExternalLink } from '@cowprotocol/ui'
import { CurrencyAmount, Fraction, Token } from '@uniswap/sdk-core'
import { OrderStatus } from 'legacy/state/orders/actions'
-import { CloseIcon, ExternalLink } from 'legacy/theme'
-import { shortenAddress } from 'legacy/utils'
-import { ExplorerDataType, getExplorerLink } from 'legacy/utils/getExplorerLink'
+import { CloseIcon } from 'legacy/theme'
import { TwapOrderItem } from 'modules/twap/types'
+import { UI } from 'common/constants/theme'
+import { isPending } from 'common/hooks/useCategorizeRecentActivity'
+import { Icon, IconType } from 'common/pure/Icon'
import { InlineBanner } from 'common/pure/InlineBanner'
+import { BannerOrientation, CustomRecipientWarningBanner } from 'common/pure/InlineBanner/banners'
import { CowModal } from 'common/pure/Modal'
+import {
+ useHideReceiverWalletBanner,
+ useIsReceiverWalletBannerHidden,
+} from 'common/state/receiverWalletBannerVisibility'
import { getSellAmountWithFee } from 'utils/orderUtils/getSellAmountWithFee'
import { ParsedOrder } from 'utils/orderUtils/parseOrder'
@@ -88,6 +96,14 @@ export function ReceiptModal({
estimatedExecutionPrice,
receiverEnsName,
}: ReceiptProps) {
+ // Check if Custom Recipient Warning Banner should be visible
+ const isCustomRecipientWarningBannerVisible = !useIsReceiverWalletBannerHidden(order.id)
+ const hideCustomRecipientWarning = useHideReceiverWalletBanner()
+
+ const isCustomRecipient = Boolean(order.receiver && order.owner !== order.receiver)
+
+ const showCustomRecipientBanner = isCustomRecipient && isCustomRecipientWarningBannerVisible && isPending(order)
+
if (!order || !chainId) {
return null
}
@@ -108,7 +124,7 @@ export function ReceiptModal({
{twapOrder && (
-
+
{isTwapPartOrder
? `Part of a ${twapOrder.order.n}-part TWAP order split`
@@ -123,6 +139,15 @@ export function ReceiptModal({
+ {/* If custom recipient show warning banner */}
+ {showCustomRecipientBanner && (
+ hideCustomRecipientWarning(order.id)}
+ />
+ )}
+
@@ -132,8 +157,11 @@ export function ReceiptModal({
+ {showCustomRecipientBanner && (
+
+ )}
- {receiverEnsName || shortenAddress(order.receiver)}
+ {receiverEnsName || shortenAddress(order.receiver)} ↗
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/styled.ts b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/styled.ts
index 836c5be695..0c829b2b09 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/styled.ts
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/styled.ts
@@ -1,9 +1,11 @@
+import { AutoRow } from '@cowprotocol/ui'
+
import styled from 'styled-components/macro'
-import { AutoRow } from 'legacy/components/Row'
+import { UI } from 'common/constants/theme'
export const Wrapper = styled.div`
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
width: 100%;
margin: 0 0 14px;
overflow-y: auto;
@@ -24,7 +26,7 @@ export const Header = styled.div`
justify-content: space-between;
align-items: center;
padding: 0 16px 16px;
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
position: sticky;
top: 0;
left: 0;
@@ -69,7 +71,7 @@ export const Field = styled.div`
justify-content: space-between;
align-items: center;
padding: 12px 16px;
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
width: 100%;
font-size: 13px;
@@ -80,6 +82,10 @@ export const Field = styled.div`
&:last-child {
border-radius: 0 0 16px 16px;
}
+
+ > div {
+ display: flex;
+ }
`
export const CurrencyField = styled.div`
@@ -88,7 +94,7 @@ export const CurrencyField = styled.div`
flex-direction: column;
align-items: flex-start;
padding: 16px;
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
width: 100%;
border-radius: 16px;
margin: 0 0 10px;
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/utils/orderTableGroupUtils.ts b/apps/cowswap-frontend/src/modules/ordersTable/utils/orderTableGroupUtils.ts
index 621ed72dd2..2f4db047ae 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/utils/orderTableGroupUtils.ts
+++ b/apps/cowswap-frontend/src/modules/ordersTable/utils/orderTableGroupUtils.ts
@@ -7,10 +7,11 @@ export interface OrderTableGroup {
export type OrderTableItem = OrderTableGroup | ParsedOrder
-export const isParsedOrder = (item: OrderTableItem): item is ParsedOrder => item.hasOwnProperty('creationTime')
+export const isParsedOrder = (item: OrderTableItem): item is ParsedOrder => !('children' in item)
-export const getParsedOrderFromItem = (item: OrderTableItem): ParsedOrder => (isParsedOrder(item) ? item : item.parent)
+export const getParsedOrderFromTableItem = (item: OrderTableItem): ParsedOrder =>
+ isParsedOrder(item) ? item : item.parent
export function tableItemsToOrders(items: OrderTableItem[]): ParsedOrder[] {
- return items.map(getParsedOrderFromItem)
+ return items.map(getParsedOrderFromTableItem)
}
diff --git a/apps/cowswap-frontend/src/modules/permit/const.ts b/apps/cowswap-frontend/src/modules/permit/const.ts
new file mode 100644
index 0000000000..516059f1f3
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/permit/const.ts
@@ -0,0 +1,33 @@
+import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { MaxUint256 } from '@ethersproject/constants'
+import { Wallet } from '@ethersproject/wallet'
+
+import ms from 'ms.macro'
+
+import { TradeType } from '../trade'
+
+// PK used only for signing permit requests for quoting and identifying token 'permittability'
+// Do not use or try to send funds to it. Or do. It'll be your funds 🤷
+const PERMIT_PK = '0xc58a2a421ca71ca57ae698f1c32feeb0b0ccb434da0b8089d88d80fb918f3f9d' // address: 0xFf65D1DfCF256cf4A8D5F2fb8e70F936606B7474
+
+export const PERMIT_SIGNER = new Wallet(PERMIT_PK)
+
+export const PERMIT_GAS_LIMIT_MIN: Record = {
+ 1: 55_000,
+ 100: 55_000,
+ 5: 36_000,
+}
+
+export const DEFAULT_PERMIT_GAS_LIMIT = '80000'
+
+export const DEFAULT_PERMIT_VALUE = MaxUint256.toString()
+
+export const DEFAULT_PERMIT_DURATION = ms`5 years`
+
+export const ORDER_TYPE_SUPPORTS_PERMIT: Record = {
+ [TradeType.SWAP]: true,
+ [TradeType.LIMIT_ORDER]: true,
+ [TradeType.ADVANCED_ORDERS]: false,
+}
+
+export const PENDING_ORDER_PERMIT_CHECK_INTERVAL = ms`1min`
diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts
new file mode 100644
index 0000000000..458cbe3e21
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts
@@ -0,0 +1,54 @@
+import { useEffect, useState } from 'react'
+
+import { Token } from '@uniswap/sdk-core'
+
+import { useDerivedTradeState } from 'modules/trade'
+
+import { useSafeMemo } from 'common/hooks/useSafeMemo'
+
+import { useGeneratePermitHook } from './useGeneratePermitHook'
+import { useIsTokenPermittable } from './useIsTokenPermittable'
+
+import { GeneratePermitHookParams, PermitHookData } from '../types'
+
+/**
+ * Returns PermitHookData using an account agnostic signer if inputCurrency is permittable
+ *
+ * Internally checks whether the token is permittable
+ *
+ * If not permittable or not able to tell, returns undefined
+ */
+export function useAccountAgnosticPermitHookData(): PermitHookData | undefined {
+ const params = useGeneratePermitHookParams()
+ const generatePermitHook = useGeneratePermitHook()
+
+ const [data, setData] = useState(undefined)
+
+ useEffect(() => {
+ if (!params) {
+ setData(undefined)
+
+ return
+ }
+
+ generatePermitHook(params).then(setData)
+ }, [generatePermitHook, params])
+
+ return data
+}
+
+function useGeneratePermitHookParams(): GeneratePermitHookParams | undefined {
+ const { state } = useDerivedTradeState()
+ const { inputCurrency, tradeType } = state || {}
+
+ const permitInfo = useIsTokenPermittable(inputCurrency, tradeType)
+
+ return useSafeMemo(() => {
+ if (!inputCurrency || !permitInfo) return undefined
+
+ return {
+ inputToken: inputCurrency as Token,
+ permitInfo,
+ }
+ }, [inputCurrency, permitInfo])
+}
diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useCheckHasValidPendingPermit.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useCheckHasValidPendingPermit.ts
new file mode 100644
index 0000000000..6197865e15
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/permit/hooks/useCheckHasValidPendingPermit.ts
@@ -0,0 +1,121 @@
+import { useCallback } from 'react'
+
+import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { useWalletInfo } from '@cowprotocol/wallet'
+import { Web3Provider } from '@ethersproject/providers'
+import { useWeb3React } from '@web3-react/core'
+
+import { DAI_PERMIT_SELECTOR, Eip2612PermitUtils, EIP_2612_PERMIT_SELECTOR } from '@1inch/permit-signed-approvals-utils'
+
+import { getAppDataHooks } from 'modules/appData'
+
+import { ParsedOrder } from 'utils/orderUtils/parseOrder'
+
+import { CheckHasValidPendingPermit } from '../types'
+import { getPermitUtilsInstance } from '../utils/getPermitUtilsInstance'
+
+export function useCheckHasValidPendingPermit(): CheckHasValidPendingPermit {
+ const { chainId } = useWalletInfo()
+ const { provider } = useWeb3React()
+
+ return useCallback(
+ async (order: ParsedOrder): Promise => {
+ if (!provider) {
+ // Missing required params, we can't tell
+ return undefined
+ }
+
+ return checkHasValidPendingPermit(order, provider, chainId)
+ },
+ [chainId, provider]
+ )
+}
+
+async function checkHasValidPendingPermit(
+ order: ParsedOrder,
+ provider: Web3Provider,
+ chainId: SupportedChainId
+): Promise {
+ const { fullAppData, partiallyFillable, executionData } = order
+ const preHooks = getAppDataHooks(fullAppData)?.pre
+
+ if (
+ // No hooks === no permit
+ !preHooks ||
+ // Permit is only executed for partially fillable orders in the first execution
+ // Thus, if there is any amount executed, partiallyFillable permit is no longer valid
+ (partiallyFillable && executionData.filledAmount.gt('0'))
+ ) {
+ // These cases we know for sure permit isn't valid or there is no permit
+ return false
+ }
+
+ const eip2162Utils = getPermitUtilsInstance(chainId, provider, order.owner)
+
+ const tokenAddress = order.inputToken.address
+ const tokenName = order.inputToken.name || tokenAddress
+
+ const checkedHooks = await Promise.all(
+ preHooks.map(({ callData }) =>
+ checkIsSingleCallDataAValidPermit(order, chainId, eip2162Utils, tokenAddress, tokenName, callData)
+ )
+ )
+
+ const validPermits = checkedHooks.filter((v) => v !== undefined)
+
+ if (!validPermits.length) {
+ // No permits means no preHook permits, we can say that there is no valid permit
+ return false
+ }
+
+ // Only when all permits are valid, then the order permits are still valid
+ return validPermits.every(Boolean)
+}
+
+async function checkIsSingleCallDataAValidPermit(
+ order: ParsedOrder,
+ chainId: SupportedChainId,
+ eip2162Utils: Eip2612PermitUtils,
+ tokenAddress: string,
+ tokenName: string,
+ callData: string
+): Promise {
+ const params = { chainId, tokenName, tokenAddress, callData }
+
+ let recoverPermitOwnerPromise: Promise | undefined = undefined
+
+ // If pre-hook doesn't start with either selector, it's not a permit
+ if (callData.startsWith(EIP_2612_PERMIT_SELECTOR)) {
+ recoverPermitOwnerPromise = eip2162Utils.recoverPermitOwnerFromCallData({
+ ...params,
+ // I don't know why this was removed, ok?
+ // We added it back on buildPermitCallData.ts
+ // But it looks like this is needed 🤷
+ // Check the test for this method https://github.com/1inch/permit-signed-approvals-utils/blob/master/src/eip-2612-permit.test.ts#L85-L106
+ callData: callData.replace(EIP_2612_PERMIT_SELECTOR, '0x'),
+ })
+ } else if (callData.startsWith(DAI_PERMIT_SELECTOR)) {
+ recoverPermitOwnerPromise = eip2162Utils.recoverDaiLikePermitOwnerFromCallData({
+ ...params,
+ callData: callData.replace(DAI_PERMIT_SELECTOR, '0x'),
+ })
+ }
+
+ if (!recoverPermitOwnerPromise) {
+ // The callData doesn't match any known permit type
+ return undefined
+ }
+
+ try {
+ const recoveredOwner = await recoverPermitOwnerPromise
+
+ // Permit is valid when recovered owner matches order owner
+ return recoveredOwner.toLowerCase() === order.owner.toLowerCase()
+ } catch (e) {
+ console.debug(
+ `[checkHasValidPendingPermit] Failed to check permit validity for order ${order.id} with callData ${callData}`,
+ e
+ )
+ return false
+ }
+}
diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts
new file mode 100644
index 0000000000..82edb237c0
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts
@@ -0,0 +1,73 @@
+import { useAtomValue, useSetAtom } from 'jotai'
+import { useCallback } from 'react'
+
+import { useWalletInfo } from '@cowprotocol/wallet'
+import { useWeb3React } from '@web3-react/core'
+
+import {
+ getPermitCacheAtom,
+ staticPermitCacheAtom,
+ storePermitCacheAtom,
+ userPermitCacheAtom,
+} from '../state/permitCacheAtom'
+import { GeneratePermitHook, GeneratePermitHookParams, PermitHookData } from '../types'
+import { generatePermitHook } from '../utils/generatePermitHook'
+import { getPermitUtilsInstance } from '../utils/getPermitUtilsInstance'
+
+/**
+ * Hook that returns callback to generate permit hook data
+ */
+export function useGeneratePermitHook(): GeneratePermitHook {
+ const getCachedPermit = useSetAtom(getPermitCacheAtom)
+ const storePermit = useSetAtom(storePermitCacheAtom)
+
+ // Warming up stored atoms
+ //
+ // For some reason, atoms start always in the default state (`{}`) on load,
+ // even if localStorage contains data, wiping previously saved data.
+ // Here we force an individual read of each atom, which does populate them properly
+ useAtomValue(staticPermitCacheAtom)
+ useAtomValue(userPermitCacheAtom)
+
+ const { chainId } = useWalletInfo()
+ const { provider } = useWeb3React()
+
+ return useCallback(
+ async (params: GeneratePermitHookParams): Promise => {
+ const { inputToken, account, permitInfo } = params
+
+ if (!provider) {
+ return
+ }
+
+ const eip2162Utils = getPermitUtilsInstance(chainId, provider, account)
+
+ // Always get the nonce for the real account, to know whether the cache should be invalidated
+ // Static account should never need to pre-check the nonce as it'll never change once cached
+ const nonce = account ? await eip2162Utils.getTokenNonce(inputToken.address, account) : undefined
+
+ const permitParams = { chainId, tokenAddress: inputToken.address, account, nonce }
+
+ const cachedPermit = getCachedPermit(permitParams)
+
+ if (cachedPermit) {
+ return cachedPermit
+ }
+
+ const hookData = await generatePermitHook({
+ chainId,
+ inputToken,
+ provider,
+ permitInfo,
+ eip2162Utils,
+ account,
+ nonce,
+ })
+
+ storePermit({ ...permitParams, hookData })
+
+ return hookData
+ },
+ [storePermit, chainId, getCachedPermit, provider]
+ )
+}
diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts
new file mode 100644
index 0000000000..b804d3aaf5
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts
@@ -0,0 +1,97 @@
+import { useAtomValue, useSetAtom } from 'jotai'
+import { useEffect, useMemo } from 'react'
+
+import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { useWalletInfo } from '@cowprotocol/wallet'
+import { Currency } from '@uniswap/sdk-core'
+import { useWeb3React } from '@web3-react/core'
+
+import { Nullish } from 'types'
+
+import { TradeType } from 'modules/trade'
+
+import { useIsPermitEnabled } from 'common/hooks/featureFlags/useIsPermitEnabled'
+
+import { ORDER_TYPE_SUPPORTS_PERMIT } from '../const'
+import { addPermitInfoForTokenAtom, permittableTokensAtom } from '../state/permittableTokensAtom'
+import { IsTokenPermittableResult } from '../types'
+import { checkIsTokenPermittable } from '../utils/checkIsTokenPermittable'
+
+/**
+ * Checks whether the token is permittable, and caches the result on localStorage
+ *
+ * When it is, returned type is `{type: 'dai'|'permit', gasLimit: number}
+ * When it is not, returned type is `false`
+ * When it is unknown, returned type is `undefined`
+ *
+ */
+export function useIsTokenPermittable(
+ token: Nullish,
+ tradeType: Nullish
+): IsTokenPermittableResult {
+ const { chainId } = useWalletInfo()
+ const { provider } = useWeb3React()
+
+ const lowerCaseAddress = token?.wrapped?.address?.toLowerCase()
+ const isNative = token?.isNative
+ const tokenName = token?.name || lowerCaseAddress || ''
+
+ // Avoid building permit info in the first place if order type is not supported
+ const isPermitSupported = !!tradeType && ORDER_TYPE_SUPPORTS_PERMIT[tradeType]
+
+ const isPermitEnabled = useIsPermitEnabled(chainId) && isPermitSupported
+
+ const addPermitInfo = useAddPermitInfo()
+ const permitInfo = usePermitInfo(chainId, isPermitEnabled ? lowerCaseAddress : undefined)
+
+ useEffect(() => {
+ if (!chainId || !isPermitEnabled || !lowerCaseAddress || !provider || permitInfo !== undefined || isNative) {
+ return
+ }
+
+ checkIsTokenPermittable({ tokenAddress: lowerCaseAddress, tokenName, chainId, provider }).then((result) => {
+ if (!result) {
+ // When falsy, we know it doesn't support permit. Cache it.
+ addPermitInfo({ chainId, tokenAddress: lowerCaseAddress, permitInfo: false })
+ } else if ('error' in result) {
+ // When error, we don't know. Log and don't cache.
+ console.debug(
+ `useIsTokenPermittable: failed to check whether token ${lowerCaseAddress} is permittable: ${result.error}`
+ )
+ } else {
+ // Otherwise, we know it is permittable. Cache it.
+ addPermitInfo({ chainId, tokenAddress: lowerCaseAddress, permitInfo: result })
+ }
+ })
+ }, [addPermitInfo, chainId, isNative, isPermitEnabled, lowerCaseAddress, permitInfo, provider, tokenName])
+
+ if (isNative) {
+ return false
+ }
+ // TODO: add an updater for this
+ return permitInfo
+}
+
+/**
+ * Returns a callback for adding PermitInfo for a given token
+ */
+function useAddPermitInfo() {
+ return useSetAtom(addPermitInfoForTokenAtom)
+}
+
+/**
+ * Returns whether a token is permittable.
+ *
+ * When it is, returned type is `{type: 'dai'|'permit', gasLimit: number}`
+ * When it is not, returned type is `false`
+ * When it is unknown, returned type is `undefined`
+ */
+function usePermitInfo(chainId: SupportedChainId, tokenAddress: string | undefined): IsTokenPermittableResult {
+ const permittableTokens = useAtomValue(permittableTokensAtom)
+
+ return useMemo(() => {
+ if (!tokenAddress) return undefined
+
+ return permittableTokens[chainId][tokenAddress.toLowerCase()]
+ }, [chainId, permittableTokens, tokenAddress])
+}
diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useOrdersPermitStatus.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useOrdersPermitStatus.ts
new file mode 100644
index 0000000000..b61aba3797
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/permit/hooks/useOrdersPermitStatus.ts
@@ -0,0 +1,7 @@
+import { useAtomValue } from 'jotai'
+
+import { ordersPermitStatusAtom } from '../state/ordersPermitStatusAtom'
+
+export function useGetOrdersPermitStatus() {
+ return useAtomValue(ordersPermitStatusAtom)
+}
diff --git a/apps/cowswap-frontend/src/modules/permit/index.ts b/apps/cowswap-frontend/src/modules/permit/index.ts
new file mode 100644
index 0000000000..9de2b7724e
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/permit/index.ts
@@ -0,0 +1,7 @@
+export * from './hooks/useAccountAgnosticPermitHookData'
+export * from './hooks/useGeneratePermitHook'
+export * from './hooks/useIsTokenPermittable'
+export * from './hooks/useOrdersPermitStatus'
+export * from './types'
+export * from './updaters/PendingPermitUpdater'
+export * from './utils/handlePermit'
diff --git a/apps/cowswap-frontend/src/modules/permit/state/ordersPermitStatusAtom.ts b/apps/cowswap-frontend/src/modules/permit/state/ordersPermitStatusAtom.ts
new file mode 100644
index 0000000000..cf132cefc3
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/permit/state/ordersPermitStatusAtom.ts
@@ -0,0 +1,9 @@
+import { atom } from 'jotai'
+
+import { atomWithPartialUpdate } from '@cowprotocol/common-utils'
+
+import { OrdersPermitStatus } from '../types'
+
+export const { atom: ordersPermitStatusAtom, updateAtom: updateOrdersPermitStatusAtom } = atomWithPartialUpdate(
+ atom({})
+)
diff --git a/apps/cowswap-frontend/src/modules/permit/state/permitCacheAtom.ts b/apps/cowswap-frontend/src/modules/permit/state/permitCacheAtom.ts
new file mode 100644
index 0000000000..aac142e2a1
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/permit/state/permitCacheAtom.ts
@@ -0,0 +1,106 @@
+import { atom } from 'jotai'
+import { atomWithStorage } from 'jotai/utils'
+
+import {
+ CachedPermitData,
+ GetPermitCacheParams,
+ PermitCache,
+ PermitCacheKeyParams,
+ StorePermitCacheParams,
+} from '../types'
+
+/**
+ * Atom that stores permit data for static permit requests.
+ * Should never change once it has been created.
+ * Used exclusively for quote requests
+ */
+export const staticPermitCacheAtom = atomWithStorage('staticPermitCache:v0', {})
+
+/**
+ * Atom that stores permit data for user permit requests.
+ * Should be updated whenever the permit nonce is updated.
+ * Used exclusively for order requests
+ */
+export const userPermitCacheAtom = atomWithStorage('userPermitCache:v0', {})
+
+/**
+ * Atom to add/update permit cache data
+ *
+ * Input depends on the target type of cache: static or user
+ */
+export const storePermitCacheAtom = atom(null, (get, set, params: StorePermitCacheParams) => {
+ const atomToUpdate = params.account ? userPermitCacheAtom : staticPermitCacheAtom
+
+ const key = buildKey(params)
+
+ const dataToCache: CachedPermitData = {
+ hookData: params.hookData,
+ nonce: params.nonce,
+ }
+
+ set(atomToUpdate, (permitCache) => ({ ...permitCache, [key]: JSON.stringify(dataToCache) }))
+})
+
+/**
+ * Atom to get the cached permit data.
+ *
+ * Returns either undefined when no cache or cache is outdated, or the cached permit hook data.
+ *
+ * When cache is outdated, it will remove the cache key from the target cache.
+ * For this reason it's a writable atom.
+ */
+export const getPermitCacheAtom = atom(null, (get, set, params: GetPermitCacheParams) => {
+ const atomToUpdate = params.account ? userPermitCacheAtom : staticPermitCacheAtom
+
+ const permitCache = get(atomToUpdate)
+ const key = buildKey(params)
+ const cachedData = permitCache[key]
+
+ if (!cachedData) {
+ return undefined
+ }
+
+ try {
+ const { hookData, nonce: storedNonce }: CachedPermitData = JSON.parse(cachedData)
+
+ if (params.account !== undefined) {
+ // User type permit cache, check the nonce
+
+ const inputNonce = params.nonce
+
+ if (storedNonce !== undefined && inputNonce !== undefined && storedNonce < inputNonce) {
+ // When both nonces exist and storedNonce < inputNonce, data is outdated
+
+ // Remove cache key
+ set(atomToUpdate, removePermitCacheBuilder(key))
+
+ return undefined
+ }
+ }
+
+ // Cache hit for both static and user permit types
+ return hookData
+ } catch (e) {
+ // Failed to parse stored data, clear cache and return nothing
+
+ set(atomToUpdate, removePermitCacheBuilder(key))
+
+ console.info(`[getPermitCacheAtom] failed to parse stored data`, cachedData, e)
+
+ return undefined
+ }
+})
+
+function buildKey({ chainId, tokenAddress, account }: PermitCacheKeyParams) {
+ const base = `${chainId}-${tokenAddress.toLowerCase()}`
+
+ return account ? `${base}-${account.toLowerCase()}` : base
+}
+
+const removePermitCacheBuilder = (key: string) => (permitCache: PermitCache) => {
+ const newPermitCache = { ...permitCache }
+
+ delete newPermitCache[key]
+
+ return newPermitCache
+}
diff --git a/apps/cowswap-frontend/src/modules/permit/state/permittableTokensAtom.ts b/apps/cowswap-frontend/src/modules/permit/state/permittableTokensAtom.ts
new file mode 100644
index 0000000000..daf8a9de07
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/permit/state/permittableTokensAtom.ts
@@ -0,0 +1,33 @@
+import { atom } from 'jotai'
+import { atomWithStorage } from 'jotai/utils'
+
+import { SupportedChainId } from '@cowprotocol/cow-sdk'
+
+import { AddPermitTokenParams, PermittableTokens } from '../types'
+
+/**
+ * Atom that stores the permittable tokens info for each chain on localStorage.
+ * It's meant to be shared across different tabs, thus no special storage handling.
+ *
+ * Contains either the permit info with `type` and `gasLimit` when supported or
+ * `false` when not supported
+ */
+export const permittableTokensAtom = atomWithStorage('permittableTokens:v0', {
+ [SupportedChainId.MAINNET]: {},
+ [SupportedChainId.GOERLI]: {},
+ [SupportedChainId.GNOSIS_CHAIN]: {},
+})
+
+/**
+ * Helper derived atom to add a permit info for a token for a given chain
+ */
+export const addPermitInfoForTokenAtom = atom(
+ null,
+ (get, set, { chainId, tokenAddress, permitInfo }: AddPermitTokenParams) => {
+ const permittableTokens = { ...get(permittableTokensAtom) }
+
+ permittableTokens[chainId][tokenAddress.toLowerCase()] = permitInfo
+
+ set(permittableTokensAtom, permittableTokens)
+ }
+)
diff --git a/apps/cowswap-frontend/src/modules/permit/types.ts b/apps/cowswap-frontend/src/modules/permit/types.ts
new file mode 100644
index 0000000000..d1cc15571f
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/permit/types.ts
@@ -0,0 +1,100 @@
+import { latest } from '@cowprotocol/app-data'
+import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { Web3Provider } from '@ethersproject/providers'
+import { Token } from '@uniswap/sdk-core'
+
+import { Eip2612PermitUtils } from '@1inch/permit-signed-approvals-utils'
+
+import { AppDataInfo } from 'modules/appData'
+
+import { ParsedOrder } from 'utils/orderUtils/parseOrder'
+
+export type PermitType = 'dai-like' | 'eip-2612'
+
+export type SupportedPermitInfo = {
+ type: PermitType
+ gasLimit: number
+}
+type UnsupportedPermitInfo = false
+export type PermitInfo = SupportedPermitInfo | UnsupportedPermitInfo
+
+export type PermittableTokens = Record>
+
+export type IsTokenPermittableResult = PermitInfo | undefined
+
+export type AddPermitTokenParams = {
+ chainId: SupportedChainId
+ tokenAddress: string
+ permitInfo: PermitInfo
+}
+
+export type PermitHookParams = {
+ inputToken: Token
+ chainId: SupportedChainId
+ permitInfo: SupportedPermitInfo
+ provider: Web3Provider
+ eip2162Utils: Eip2612PermitUtils
+ account?: string | undefined
+ nonce?: number | undefined
+}
+
+export type GeneratePermitHookParams = Pick
+
+export type GeneratePermitHook = (params: GeneratePermitHookParams) => Promise
+
+export type HandlePermitParams = Omit & {
+ permitInfo: IsTokenPermittableResult
+ appData: AppDataInfo
+ generatePermitHook: GeneratePermitHook
+}
+
+export type PermitHookData = latest.CoWHook
+
+type FailedToIdentify = { error: string }
+
+export type EstimatePermitResult =
+ // When it's a permittable token:
+ | SupportedPermitInfo
+ // When something failed:
+ | FailedToIdentify
+ // When it's not permittable:
+ | UnsupportedPermitInfo
+
+type BasePermitCallDataParams = {
+ eip2162Utils: Eip2612PermitUtils
+}
+export type BuildEip2162PermitCallDataParams = BasePermitCallDataParams & {
+ callDataParams: Parameters
+}
+export type BuildDaiLikePermitCallDataParams = BasePermitCallDataParams & {
+ callDataParams: Parameters
+}
+
+export type CheckIsTokenPermittableParams = {
+ tokenAddress: string
+ tokenName: string
+ chainId: SupportedChainId
+ provider: Web3Provider
+}
+
+export type PermitCache = Record
+
+export type CachedPermitData = {
+ hookData: PermitHookData
+ nonce: number | undefined
+}
+
+export type PermitCacheKeyParams = {
+ chainId: SupportedChainId
+ tokenAddress: string
+ account: string | undefined
+ nonce: number | undefined
+}
+
+export type StorePermitCacheParams = PermitCacheKeyParams & { hookData: PermitHookData }
+
+export type GetPermitCacheParams = PermitCacheKeyParams
+
+export type CheckHasValidPendingPermit = (order: ParsedOrder) => Promise
+
+export type OrdersPermitStatus = Record
diff --git a/apps/cowswap-frontend/src/modules/permit/updaters/PendingPermitUpdater.ts b/apps/cowswap-frontend/src/modules/permit/updaters/PendingPermitUpdater.ts
new file mode 100644
index 0000000000..b286652ed9
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/permit/updaters/PendingPermitUpdater.ts
@@ -0,0 +1,39 @@
+import { useSetAtom } from 'jotai'
+import { useEffect, useRef } from 'react'
+
+import { ParsedOrder } from 'utils/orderUtils/parseOrder'
+
+import { PENDING_ORDER_PERMIT_CHECK_INTERVAL } from '../const'
+import { useCheckHasValidPendingPermit } from '../hooks/useCheckHasValidPendingPermit'
+import { updateOrdersPermitStatusAtom } from '../state/ordersPermitStatusAtom'
+
+export type PendingPermitUpdaterProps = {
+ orders: ParsedOrder[]
+}
+
+export function PendingPermitUpdater({ orders }: PendingPermitUpdaterProps): null {
+ const ordersRef = useRef(orders)
+ ordersRef.current = orders
+
+ const checkHasValidPendingPermit = useCheckHasValidPendingPermit()
+ const updateOrdersPermitStatus = useSetAtom(updateOrdersPermitStatusAtom)
+
+ useEffect(() => {
+ const checkOrders = () => {
+ console.debug(`UpdatePendingPermit: checking orders`, ordersRef.current.length)
+ ordersRef.current.forEach((order) => {
+ checkHasValidPendingPermit(order).then((status) => {
+ console.debug(`UpdatePendingPermit: checked order ${order.id} with status ${status}`)
+ updateOrdersPermitStatus({ [order.id]: status })
+ })
+ })
+ }
+
+ checkOrders()
+ const interval = setInterval(checkOrders, PENDING_ORDER_PERMIT_CHECK_INTERVAL)
+
+ return () => clearInterval(interval)
+ }, [checkHasValidPendingPermit, updateOrdersPermitStatus])
+
+ return null
+}
diff --git a/apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts b/apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts
new file mode 100644
index 0000000000..67d5ddcca0
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts
@@ -0,0 +1,26 @@
+import { DAI_PERMIT_SELECTOR, EIP_2612_PERMIT_SELECTOR } from '@1inch/permit-signed-approvals-utils'
+
+import { BuildDaiLikePermitCallDataParams, BuildEip2162PermitCallDataParams } from '../types'
+
+export async function buildEip2162PermitCallData({
+ eip2162Utils,
+ callDataParams,
+}: BuildEip2162PermitCallDataParams): Promise {
+ const callData = await eip2162Utils.buildPermitCallData(...callDataParams)
+
+ // For some reason, the method above removes the permit selector prefix
+ // https://github.com/1inch/permit-signed-approvals-utils/blob/master/src/eip-2612-permit.utils.ts#L92
+ // Adding it back
+ return callData.replace('0x', EIP_2612_PERMIT_SELECTOR)
+}
+
+export async function buildDaiLikePermitCallData({
+ eip2162Utils,
+ callDataParams,
+}: BuildDaiLikePermitCallDataParams): Promise {
+ const callData = await eip2162Utils.buildDaiLikePermitCallData(...callDataParams)
+
+ // Same as above, but for dai like
+ // https://github.com/1inch/permit-signed-approvals-utils/blob/master/src/eip-2612-permit.utils.ts#L140
+ return callData.replace('0x', DAI_PERMIT_SELECTOR)
+}
diff --git a/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts b/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts
new file mode 100644
index 0000000000..8093044c24
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts
@@ -0,0 +1,186 @@
+import { GP_VAULT_RELAYER, NATIVE_CURRENCY_BUY_ADDRESS } from '@cowprotocol/common-const'
+import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import type { Web3Provider } from '@ethersproject/providers'
+
+import { DAI_LIKE_PERMIT_TYPEHASH, Eip2612PermitUtils } from '@1inch/permit-signed-approvals-utils'
+
+import { buildDaiLikePermitCallData, buildEip2162PermitCallData } from './buildPermitCallData'
+import { getPermitDeadline } from './getPermitDeadline'
+import { getPermitUtilsInstance } from './getPermitUtilsInstance'
+
+import { DEFAULT_PERMIT_VALUE, PERMIT_GAS_LIMIT_MIN, PERMIT_SIGNER } from '../const'
+import { CheckIsTokenPermittableParams, EstimatePermitResult, PermitType } from '../types'
+
+const EIP_2162_PERMIT_PARAMS = {
+ value: DEFAULT_PERMIT_VALUE,
+ nonce: 0,
+ deadline: getPermitDeadline(),
+}
+
+const DAI_LIKE_PERMIT_PARAMS = {
+ allowed: true,
+ nonce: 0,
+ expiry: getPermitDeadline(),
+}
+
+const REQUESTS_CACHE: Record> = {}
+
+export async function checkIsTokenPermittable(params: CheckIsTokenPermittableParams): Promise {
+ const { tokenAddress, chainId } = params
+ if (NATIVE_CURRENCY_BUY_ADDRESS.toLowerCase() === tokenAddress.toLowerCase()) {
+ // We shouldn't call this for the native token, but just in case
+ return false
+ }
+
+ const key = `${chainId}-${tokenAddress.toLowerCase()}`
+
+ const cached = REQUESTS_CACHE[key]
+
+ if (cached) {
+ return cached
+ }
+
+ const request = actuallyCheckTokenIsPermittable(params)
+
+ REQUESTS_CACHE[key] = request
+
+ return request
+}
+
+async function actuallyCheckTokenIsPermittable(params: CheckIsTokenPermittableParams): Promise {
+ const { tokenAddress, tokenName, chainId, provider } = params
+
+ const spender = GP_VAULT_RELAYER[chainId]
+
+ const eip2612PermitUtils = getPermitUtilsInstance(chainId, provider)
+
+ const owner = PERMIT_SIGNER.address
+
+ let nonce: number
+
+ try {
+ nonce = await eip2612PermitUtils.getTokenNonce(tokenAddress, owner)
+ } catch (e) {
+ if (e === 'nonce not supported' || e.message === 'nonce is NaN') {
+ console.debug(`[checkTokenIsPermittable] Not a permittable token ${tokenAddress}`, e?.message || e)
+ // Here we know it's not supported, return false
+ // See https://github.com/1inch/permit-signed-approvals-utils/blob/b190197a45c3289867ee4e6da93f10dea51ef276/src/eip-2612-permit.utils.ts#L309
+ // and https://github.com/1inch/permit-signed-approvals-utils/blob/b190197a45c3289867ee4e6da93f10dea51ef276/src/eip-2612-permit.utils.ts#L325
+ return false
+ }
+ console.debug(`[checkTokenIsPermittable] Failed to get nonce for ${tokenAddress}`, e)
+
+ // Otherwise, it might have been a network issue or another temporary failure, return error
+ return { error: e.message || e.toString() }
+ }
+
+ const baseParams: BaseParams = {
+ chainId,
+ eip2612PermitUtils,
+ nonce,
+ spender,
+ tokenAddress,
+ tokenName,
+ walletAddress: owner,
+ }
+
+ try {
+ // Try to estimate with eip-2612 first
+ return await estimateTokenPermit({ ...baseParams, type: 'eip-2612', provider })
+ } catch (e) {
+ // Not eip-2612, try dai-like
+ console.debug(`[checkTokenIsPermittable] Failed to estimate eip-2612 permit for ${tokenAddress}`, e)
+ try {
+ return await estimateTokenPermit({ ...baseParams, type: 'dai-like', provider })
+ } catch (e) {
+ // Not dai-like either, return error
+ console.debug(`[checkTokenIsPermittable] Failed to estimate dai-like permit for ${tokenAddress}`, e)
+ return { error: e.message || e.toString() }
+ }
+ }
+}
+
+type BaseParams = {
+ tokenAddress: string
+ tokenName: string
+ chainId: SupportedChainId
+ walletAddress: string
+ spender: string
+ eip2612PermitUtils: Eip2612PermitUtils
+ nonce: number
+}
+
+type EstimateParams = BaseParams & {
+ type: PermitType
+ provider: Web3Provider
+}
+
+async function estimateTokenPermit(params: EstimateParams): Promise {
+ const { provider, chainId, walletAddress, tokenAddress, type } = params
+
+ const getCallDataFn = type === 'eip-2612' ? getEip2612CallData : getDaiLikeCallData
+
+ const data = await getCallDataFn(params)
+
+ if (!data) {
+ return false
+ }
+
+ const estimatedGas = await provider.estimateGas({
+ data,
+ from: walletAddress,
+ to: tokenAddress,
+ })
+
+ const gasLimit = estimatedGas.toNumber()
+
+ return gasLimit > PERMIT_GAS_LIMIT_MIN[chainId]
+ ? {
+ gasLimit,
+ type,
+ }
+ : false
+}
+
+async function getEip2612CallData(params: BaseParams): Promise {
+ const { eip2612PermitUtils, walletAddress, spender, nonce, chainId, tokenName, tokenAddress } = params
+ return buildEip2162PermitCallData({
+ eip2162Utils: eip2612PermitUtils,
+ callDataParams: [
+ {
+ ...EIP_2162_PERMIT_PARAMS,
+ owner: walletAddress,
+ spender,
+ nonce,
+ },
+ +chainId,
+ tokenName,
+ tokenAddress,
+ ],
+ })
+}
+
+async function getDaiLikeCallData(params: BaseParams): Promise {
+ const { eip2612PermitUtils, tokenAddress, walletAddress, spender, nonce, chainId, tokenName } = params
+
+ const permitTypeHash = await eip2612PermitUtils.getPermitTypeHash(tokenAddress)
+
+ if (permitTypeHash === DAI_LIKE_PERMIT_TYPEHASH) {
+ return buildDaiLikePermitCallData({
+ eip2162Utils: eip2612PermitUtils,
+ callDataParams: [
+ {
+ ...DAI_LIKE_PERMIT_PARAMS,
+ holder: walletAddress,
+ spender,
+ nonce,
+ },
+ chainId as number,
+ tokenName,
+ tokenAddress,
+ ],
+ })
+ }
+
+ return false
+}
diff --git a/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts b/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts
new file mode 100644
index 0000000000..7d781342aa
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts
@@ -0,0 +1,124 @@
+import { GP_VAULT_RELAYER } from '@cowprotocol/common-const'
+import { Web3Provider } from '@ethersproject/providers'
+
+import { buildDaiLikePermitCallData, buildEip2162PermitCallData } from './buildPermitCallData'
+import { getPermitDeadline } from './getPermitDeadline'
+
+import { DEFAULT_PERMIT_GAS_LIMIT, DEFAULT_PERMIT_VALUE, PERMIT_SIGNER } from '../const'
+import { PermitHookData, PermitHookParams } from '../types'
+
+const REQUESTS_CACHE: { [permitKey: string]: Promise } = {}
+
+export async function generatePermitHook(params: PermitHookParams): Promise {
+ const permitKey = getCacheKey(params)
+
+ const cachedRequest = REQUESTS_CACHE[permitKey]
+
+ if (cachedRequest) {
+ try {
+ return await cachedRequest
+ } catch (e) {
+ console.debug(`[generatePermitHookWith] cached request failed`, e)
+ delete REQUESTS_CACHE[permitKey]
+ }
+ }
+
+ const request = generatePermitHookRaw(params).then((permitHookData) => {
+ // Remove consumed request to avoid stale data
+ delete REQUESTS_CACHE[permitKey]
+
+ return permitHookData
+ })
+
+ REQUESTS_CACHE[permitKey] = request
+
+ return request
+}
+
+async function generatePermitHookRaw(params: PermitHookParams): Promise {
+ const { inputToken, chainId, permitInfo, provider, account, eip2162Utils, nonce: preFetchedNonce } = params
+ const tokenAddress = inputToken.address
+ const tokenName = inputToken.name || tokenAddress
+
+ const owner = account || PERMIT_SIGNER.address
+
+ // Only fetch the nonce in case it wasn't pre-fetched before
+ // That's the case for static account
+ const nonce = preFetchedNonce === undefined ? await eip2162Utils.getTokenNonce(tokenAddress, owner) : preFetchedNonce
+
+ const spender = GP_VAULT_RELAYER[chainId]
+ const deadline = getPermitDeadline()
+ const value = DEFAULT_PERMIT_VALUE
+
+ const callData =
+ permitInfo.type === 'eip-2612'
+ ? await buildEip2162PermitCallData({
+ eip2162Utils,
+ callDataParams: [
+ {
+ owner,
+ spender,
+ value,
+ nonce,
+ deadline,
+ },
+ chainId as number,
+ tokenName,
+ tokenAddress,
+ ],
+ })
+ : await buildDaiLikePermitCallData({
+ eip2162Utils,
+ callDataParams: [
+ {
+ holder: owner,
+ spender,
+ allowed: true,
+ value,
+ nonce,
+ expiry: deadline,
+ },
+ chainId as number,
+ tokenName,
+ tokenAddress,
+ ],
+ })
+
+ const gasLimit = await calculateGasLimit(callData, owner, tokenAddress, provider, !!account)
+
+ return {
+ target: tokenAddress,
+ callData,
+ gasLimit,
+ }
+}
+
+async function calculateGasLimit(
+ data: string,
+ from: string,
+ to: string,
+ provider: Web3Provider,
+ isUserAccount: boolean
+): Promise {
+ try {
+ // Query the actual gas estimate
+ const actual = await provider.estimateGas({ data, from, to })
+
+ // Add 10% to actual value to account for minor differences with real account
+ // Do not add it if this is the real user's account
+ const gasLimit = !isUserAccount ? actual.add(actual.div(10)) : actual
+
+ // Pick the biggest between estimated and default
+ return gasLimit.gt(DEFAULT_PERMIT_GAS_LIMIT) ? gasLimit.toString() : DEFAULT_PERMIT_GAS_LIMIT
+ } catch (e) {
+ console.debug(`[calculatePermitGasLimit] Failed to estimateGas, using default`, e)
+
+ return DEFAULT_PERMIT_GAS_LIMIT
+ }
+}
+
+function getCacheKey(params: PermitHookParams): string {
+ const { inputToken, chainId, account } = params
+
+ return `${inputToken.address.toLowerCase()}-${chainId}${account ? `-${account.toLowerCase()}` : ''}`
+}
diff --git a/apps/cowswap-frontend/src/modules/permit/utils/getPermitDeadline.ts b/apps/cowswap-frontend/src/modules/permit/utils/getPermitDeadline.ts
new file mode 100644
index 0000000000..3c05ad4eeb
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/permit/utils/getPermitDeadline.ts
@@ -0,0 +1,5 @@
+import { DEFAULT_PERMIT_DURATION } from '../const'
+
+export function getPermitDeadline() {
+ return Math.ceil((Date.now() + DEFAULT_PERMIT_DURATION) / 1000)
+}
diff --git a/apps/cowswap-frontend/src/modules/permit/utils/getPermitUtilsInstance.ts b/apps/cowswap-frontend/src/modules/permit/utils/getPermitUtilsInstance.ts
new file mode 100644
index 0000000000..daeba06d33
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/permit/utils/getPermitUtilsInstance.ts
@@ -0,0 +1,51 @@
+import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import type { Web3Provider } from '@ethersproject/providers'
+
+import { Eip2612PermitUtils } from '@1inch/permit-signed-approvals-utils'
+
+import { PermitProviderConnector } from 'modules/wallet/utils/PermitProviderConnector'
+
+import { PERMIT_SIGNER } from '../const'
+
+/**
+ * Cache by network. Here we don't care about the provider as a static account will be used for the signature
+ */
+const CHAIN_UTILS_CACHE = new Map()
+/**
+ * Cache by provider. Here we cache per provider as each account should have its own instance
+ */
+const PROVIDER_UTILS_CACHE = new Map()
+
+export function getPermitUtilsInstance(
+ chainId: SupportedChainId,
+ provider: Web3Provider,
+ account?: string | undefined
+): Eip2612PermitUtils {
+ const chainCache = CHAIN_UTILS_CACHE.get(chainId)
+
+ if (!account && chainCache) {
+ return chainCache
+ }
+ const providerCacheKey = `${chainId}-${account}`
+ const providerCache = PROVIDER_UTILS_CACHE.get(providerCacheKey)
+
+ if (providerCache) {
+ return providerCache
+ }
+
+ const web3ProviderConnector = new PermitProviderConnector(provider, account ? undefined : PERMIT_SIGNER)
+ const eip2612PermitUtils = new Eip2612PermitUtils(web3ProviderConnector)
+
+ if (!account) {
+ console.log(`[getPermitUtilsInstance] Set cached chain utils for chain ${chainId}`, eip2612PermitUtils)
+ CHAIN_UTILS_CACHE.set(chainId, eip2612PermitUtils)
+ } else {
+ console.log(
+ `[getPermitUtilsInstance] Set cached provider utils for chain ${chainId}-${account}`,
+ eip2612PermitUtils
+ )
+ PROVIDER_UTILS_CACHE.set(providerCacheKey, eip2612PermitUtils)
+ }
+
+ return eip2612PermitUtils
+}
diff --git a/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts b/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts
new file mode 100644
index 0000000000..38bc18b9c3
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts
@@ -0,0 +1,38 @@
+import { AppDataInfo, buildAppDataHooks, updateHooksOnAppData } from 'modules/appData'
+
+import { HandlePermitParams } from '../types'
+
+/**
+ * Handle token permit
+ *
+ * Will request user signature if needed
+ * Can use cached permit if available
+ *
+ * If not needed, will remove any permit info from appData
+ *
+ * Returns the updated appData
+ */
+export async function handlePermit(params: HandlePermitParams): Promise {
+ const { permitInfo, inputToken, account, appData, generatePermitHook } = params
+
+ if (permitInfo) {
+ // permitInfo will only be set if there's NOT enough allowance
+
+ const permitData = await generatePermitHook({
+ inputToken,
+ account,
+ permitInfo,
+ })
+
+ if (!permitData) {
+ throw new Error(`Unable to generate permit data`)
+ }
+
+ const hooks = buildAppDataHooks([permitData])
+
+ return updateHooksOnAppData(appData, hooks)
+ } else {
+ // Otherwise, remove hooks (if any) from appData to avoid stale data
+ return updateHooksOnAppData(appData, undefined)
+ }
+}
diff --git a/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useEthFlowActions.ts b/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useEthFlowActions.ts
index 557a19e047..0bea93ab97 100644
--- a/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useEthFlowActions.ts
+++ b/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useEthFlowActions.ts
@@ -2,17 +2,18 @@ import { useSetAtom } from 'jotai'
import { useAtomValue } from 'jotai'
import { useMemo } from 'react'
-import { WRAPPED_NATIVE_CURRENCY } from 'legacy/constants/tokens'
+import { WRAPPED_NATIVE_CURRENCY } from '@cowprotocol/common-const'
+import { useWalletInfo } from '@cowprotocol/wallet'
+
import { WrapUnwrapCallback } from 'legacy/hooks/useWrapCallback'
-import { Field } from 'legacy/state/swap/actions'
-import { useDerivedSwapInfo, useSwapActionHandlers } from 'legacy/state/swap/hooks'
+import { Field } from 'legacy/state/types'
import { useSwapConfirmManager } from 'modules/swap/hooks/useSwapConfirmManager'
import { HandleSwapCallback } from 'modules/swap/pure/SwapButtons'
-import { useWalletInfo } from 'modules/wallet'
import { TradeApproveCallback } from 'common/containers/TradeApprove/useTradeApproveCallback'
+import { useDerivedSwapInfo, useSwapActionHandlers } from '../../../hooks/useSwapState'
import { ethFlowContextAtom, updateEthFlowContextAtom } from '../../../state/EthFlow/ethFlowContextAtom'
export interface EthFlowActionCallbacks {
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 489f2f2408..58376d2694 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,15 +1,14 @@
import { useMemo } from 'react'
+import { AVG_APPROVE_COST_GWEI } from '@cowprotocol/common-const'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { BigNumber } from '@ethersproject/bignumber'
import { CurrencyAmount, Currency } from '@uniswap/sdk-core'
import { parseUnits } from 'ethers/lib/utils'
-import { AVG_APPROVE_COST_GWEI } from 'legacy/constants'
import { useGasPrices } from 'legacy/state/gas/hooks'
-import { useWalletInfo } from 'modules/wallet'
-
import { BalanceChecks } from '../../../pure/EthFlow/EthFlowModalContent/EthFlowModalTopContent'
export const MINIMUM_TXS = '10'
diff --git a/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useSetupEthFlow.ts b/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useSetupEthFlow.ts
index 72b41992d7..88c2d2e034 100644
--- a/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useSetupEthFlow.ts
+++ b/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useSetupEthFlow.ts
@@ -1,9 +1,10 @@
import { useAtomValue, useSetAtom } from 'jotai'
import { useEffect, useState } from 'react'
+import { delay } from '@cowprotocol/common-utils'
+
import { ApprovalState } from 'legacy/hooks/useApproveCallback/useApproveCallbackMod'
import { ActivityDescriptors, ActivityStatus } from 'legacy/hooks/useRecentActivity'
-import { delay } from 'legacy/utils/misc'
import { EthFlowActions } from './useEthFlowActions'
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 ab11eed1bf..09af53c8e8 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 { useWalletInfo } from '@cowprotocol/wallet'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import { useSingleActivityDescriptor } from 'legacy/hooks/useRecentActivity'
@@ -14,7 +15,6 @@ import { HandleSwapCallback } from 'modules/swap/pure/SwapButtons'
import { ethFlowContextAtom } from 'modules/swap/state/EthFlow/ethFlowContextAtom'
import { useCurrencyBalances } from 'modules/tokens/hooks/useCurrencyBalance'
import { useWrappedToken } from 'modules/trade/hooks/useWrappedToken'
-import { useWalletInfo } from 'modules/wallet'
import { useTradeApproveCallback, useTradeApproveState } from 'common/containers/TradeApprove'
import { CowModal } from 'common/pure/Modal'
diff --git a/apps/cowswap-frontend/src/modules/swap/containers/EthFlowStepper/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/EthFlowStepper/index.tsx
index e685f0d5a9..46b09bfcb2 100644
--- a/apps/cowswap-frontend/src/modules/swap/containers/EthFlowStepper/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/containers/EthFlowStepper/index.tsx
@@ -1,4 +1,6 @@
-import { NATIVE_CURRENCY_BUY_ADDRESS } from 'legacy/constants'
+import { NATIVE_CURRENCY_BUY_ADDRESS } from '@cowprotocol/common-const'
+import { formatSymbol } from '@cowprotocol/common-utils'
+
import { useAllTransactions } from 'legacy/state/enhancedTransactions/hooks'
import { EnhancedTransactionDetails } from 'legacy/state/enhancedTransactions/reducer'
import { Order, OrderStatus } from 'legacy/state/orders/actions'
@@ -11,7 +13,6 @@ import {
} from 'modules/swap/pure/EthFlow/EthFlowStepper'
import useNativeCurrency from 'lib/hooks/useNativeCurrency'
-import { formatSymbol } from 'utils/format'
type EthFlowStepperProps = {
order: Order | undefined
diff --git a/apps/cowswap-frontend/src/modules/swap/containers/FeesDiscount/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/FeesDiscount/index.tsx
index 603d9a73f7..b25922ad7f 100644
--- a/apps/cowswap-frontend/src/modules/swap/containers/FeesDiscount/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/containers/FeesDiscount/index.tsx
@@ -1,24 +1,27 @@
+import { AutoRow } from '@cowprotocol/ui'
+import { MouseoverTooltipContent } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import { BoxProps, Text } from 'rebass'
import styled, { DefaultTheme } from 'styled-components/macro'
import { SUBSIDY_INFO_MESSAGE } from 'legacy/components/CowSubsidyModal/constants'
-import { AutoRow } from 'legacy/components/Row'
-import { MouseoverTooltipContent } from 'legacy/components/Tooltip'
import useCowBalanceAndSubsidy from 'legacy/hooks/useCowBalanceAndSubsidy'
import { StyledInfoIcon } from 'modules/swap/pure/styled'
import { LowerSectionWrapper } from 'modules/swap/pure/styled'
+import { UI } from 'common/constants/theme'
+
interface FeesDiscountProps extends BoxProps {
theme: DefaultTheme
}
const DarkSpan = styled.span`
padding: 2px 8px;
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
border-radius: 5px;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
transition: background 0.2s ease-in-out, color 0.2s ease-in-out;
&:hover {
diff --git a/apps/cowswap-frontend/src/modules/swap/containers/Row/RowFee/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/Row/RowFee/index.tsx
index 59b641ddeb..52e7136694 100644
--- a/apps/cowswap-frontend/src/modules/swap/containers/Row/RowFee/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/containers/Row/RowFee/index.tsx
@@ -1,5 +1,8 @@
import { useMemo } from 'react'
+import { formatFiatAmount, formatTokenAmount } from '@cowprotocol/common-utils'
+import { FractionUtils } from '@cowprotocol/common-utils'
+import { formatSymbol } from '@cowprotocol/common-utils'
import { Currency, CurrencyAmount, Token, TradeType } from '@uniswap/sdk-core'
import TradeGp from 'legacy/state/swap/TradeGp'
@@ -9,9 +12,6 @@ import { RowFeeContent } from 'modules/swap/pure/Row/RowFeeContent'
import { RowWithShowHelpersProps } from 'modules/swap/pure/Row/types'
import useNativeCurrency from 'lib/hooks/useNativeCurrency'
-import { formatFiatAmount, formatTokenAmount } from 'utils/amountFormat'
-import { formatSymbol } from 'utils/format'
-import { FractionUtils } from 'utils/fractionUtils'
export const GASLESS_FEE_TOOLTIP_MSG =
'On CoW Swap you sign your order (hence no gas costs!). The fees are covering your gas costs already.'
diff --git a/apps/cowswap-frontend/src/modules/swap/containers/Row/RowReceivedAfterSlippage/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/Row/RowReceivedAfterSlippage/index.tsx
index 046ff8937c..f81ee43f1b 100644
--- a/apps/cowswap-frontend/src/modules/swap/containers/Row/RowReceivedAfterSlippage/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/containers/Row/RowReceivedAfterSlippage/index.tsx
@@ -2,8 +2,8 @@ import { useMemo } from 'react'
import { Percent, TradeType } from '@uniswap/sdk-core'
-import { Field } from 'legacy/state/swap/actions'
import TradeGp from 'legacy/state/swap/TradeGp'
+import { Field } from 'legacy/state/types'
import { computeSlippageAdjustedAmounts } from 'legacy/utils/prices'
import { RowReceivedAfterSlippageContent } from 'modules/swap/pure/Row/RowReceivedAfterSlippageContent'
diff --git a/apps/cowswap-frontend/src/modules/swap/containers/Row/RowSlippage/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/Row/RowSlippage/index.tsx
index ffe552649a..e5f9dbcfc9 100644
--- a/apps/cowswap-frontend/src/modules/swap/containers/Row/RowSlippage/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/containers/Row/RowSlippage/index.tsx
@@ -1,5 +1,6 @@
import { useMemo } from 'react'
+import { formatPercent } from '@cowprotocol/common-utils'
import { Percent } from '@uniswap/sdk-core'
import { useToggleSettingsMenu } from 'legacy/state/application/hooks'
@@ -8,7 +9,6 @@ import { useIsEoaEthFlow } from 'modules/swap/hooks/useIsEoaEthFlow'
import { RowSlippageContent } from 'modules/swap/pure/Row/RowSlippageContent'
import useNativeCurrency from 'lib/hooks/useNativeCurrency'
-import { formatPercent } from 'utils/amountFormat'
export interface RowSlippageProps {
allowedSlippage: Percent
diff --git a/apps/cowswap-frontend/src/modules/swap/containers/SetRecipient/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/SetRecipient/index.tsx
index 1583782fa0..55b110aa4b 100644
--- a/apps/cowswap-frontend/src/modules/swap/containers/SetRecipient/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/containers/SetRecipient/index.tsx
@@ -1,10 +1,11 @@
import { useContext } from 'react'
+import { AutoRow } from '@cowprotocol/ui'
+
import { ArrowDown } from 'react-feather'
import { ThemeContext } from 'styled-components/macro'
import { AddressInputPanel } from 'legacy/components/AddressInputPanel'
-import { AutoRow } from 'legacy/components/Row'
import { ArrowWrapper } from 'legacy/components/swap/styleds'
export interface SetRecipientProps {
diff --git a/apps/cowswap-frontend/src/modules/swap/containers/SurplusModalSetup/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/SurplusModalSetup/index.tsx
index cad0a44151..65f41ef968 100644
--- a/apps/cowswap-frontend/src/modules/swap/containers/SurplusModalSetup/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/containers/SurplusModalSetup/index.tsx
@@ -1,8 +1,8 @@
import { useCallback, useEffect } from 'react'
-import { useOrder } from 'legacy/state/orders/hooks'
+import { useWalletInfo } from '@cowprotocol/wallet'
-import { useWalletInfo } from 'modules/wallet'
+import { useOrder } from 'legacy/state/orders/hooks'
import { useGetSurplusData } from 'common/hooks/useGetSurplusFiatValue'
import { CowModal } from 'common/pure/Modal'
diff --git a/apps/cowswap-frontend/src/modules/swap/containers/SwapModals/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/SwapModals/index.tsx
index bfb450a0b3..420510807f 100644
--- a/apps/cowswap-frontend/src/modules/swap/containers/SwapModals/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/containers/SwapModals/index.tsx
@@ -1,10 +1,10 @@
import React from 'react'
+import { genericPropsChecker } from '@cowprotocol/common-utils'
+
import { ConfirmSwapModalSetup, ConfirmSwapModalSetupProps } from 'modules/swap/containers/ConfirmSwapModalSetup'
import { EthFlowModal, EthFlowProps } from 'modules/swap/containers/EthFlow'
-import { genericPropsChecker } from 'utils/genericPropsChecker'
-
import { SurplusModalSetup } from '../SurplusModalSetup'
export interface SwapModalsProps {
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 c3e1bf2ce2..07a12bff92 100644
--- a/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx
@@ -1,20 +1,15 @@
import React, { useMemo, useState } from 'react'
+import { isFractionFalsy } from '@cowprotocol/common-utils'
+import { useIsSafeViaWc, useWalletDetails, useWalletInfo } from '@cowprotocol/wallet'
+
import { NetworkAlert } from 'legacy/components/NetworkAlert/NetworkAlert'
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/swap/actions'
-import {
- useDerivedSwapInfo,
- useHighFeeWarning,
- useIsFeeGreaterThanInput,
- useSwapActionHandlers,
- useSwapState,
- useUnknownImpactWarning,
-} from 'legacy/state/swap/hooks'
+import { Field } from 'legacy/state/types'
import { useExpertModeManager, useUserSlippageTolerance } from 'legacy/state/user/hooks'
import { ConfirmSwapModalSetupProps } from 'modules/swap/containers/ConfirmSwapModalSetup'
@@ -40,15 +35,21 @@ import { TradeWidget, TradeWidgetContainer, useTradePriceImpact } from 'modules/
import { useTradeRouteContext } from 'modules/trade/hooks/useTradeRouteContext'
import { useWrappedToken } from 'modules/trade/hooks/useWrappedToken'
import { useTradeUsdAmounts } from 'modules/usdAmount'
-import { useIsSafeViaWc, useWalletDetails, useWalletInfo } from 'modules/wallet'
import { useRateInfoParams } from 'common/hooks/useRateInfoParams'
import { useShouldZeroApprove } from 'common/hooks/useShouldZeroApprove'
import { CurrencyInfo } from 'common/pure/CurrencyInputPanel/types'
import useNativeCurrency from 'lib/hooks/useNativeCurrency'
-import { isFractionFalsy } from 'utils/isFractionFalsy'
import { useIsSwapEth } from '../../hooks/useIsSwapEth'
+import {
+ useDerivedSwapInfo,
+ useHighFeeWarning,
+ useIsFeeGreaterThanInput,
+ useSwapActionHandlers,
+ useSwapState,
+ useUnknownImpactWarning,
+} from '../../hooks/useSwapState'
const BUTTON_STATES_TO_SHOW_BUNDLE_APPROVAL_BANNER = [
SwapButtonState.ApproveAndSwap,
diff --git a/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/propsChecker.ts b/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/propsChecker.ts
index ff7ed8ff2b..9b292674e1 100644
--- a/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/propsChecker.ts
+++ b/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/propsChecker.ts
@@ -1,11 +1,12 @@
+import { genericPropsChecker } from '@cowprotocol/common-utils'
+import { areFractionsEqual } from '@cowprotocol/common-utils'
+
import { PriceImpact } from 'legacy/hooks/usePriceImpact'
import { SwapFormProps } from 'modules/swap/containers/SwapWidget/types'
import { ReceiveAmountInfo } from 'modules/swap/helpers/tradeReceiveAmount'
import { CurrencyInfo } from 'common/pure/CurrencyInputPanel/types'
-import { areFractionsEqual } from 'utils/areFractionsEqual'
-import { genericPropsChecker } from 'utils/genericPropsChecker'
function isReceiveAmountInfoEqual(prev: ReceiveAmountInfo | null, next: ReceiveAmountInfo | null): boolean {
if (!prev || !next) {
diff --git a/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/types.ts b/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/types.ts
index 059cfabd08..b610f65bd1 100644
--- a/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/types.ts
+++ b/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/types.ts
@@ -2,10 +2,11 @@ import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import { BalanceAndSubsidy } from 'legacy/hooks/useCowBalanceAndSubsidy'
import { PriceImpact } from 'legacy/hooks/usePriceImpact'
-import { SwapActions } from 'legacy/state/swap/hooks'
import { CurrencyInfo } from 'common/pure/CurrencyInputPanel/types'
+import { SwapActions } from '../../hooks/useSwapState'
+
export interface SwapFormProps {
chainId: number | undefined
recipient: string | null
diff --git a/apps/cowswap-frontend/src/modules/swap/containers/TradeBasicDetails/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/TradeBasicDetails/index.tsx
index 9d7893925b..7904ad0440 100644
--- a/apps/cowswap-frontend/src/modules/swap/containers/TradeBasicDetails/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/containers/TradeBasicDetails/index.tsx
@@ -1,8 +1,8 @@
+import { INITIAL_ALLOWED_SLIPPAGE_PERCENT } from '@cowprotocol/common-const'
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import { BoxProps } from 'rebass'
-import { INITIAL_ALLOWED_SLIPPAGE_PERCENT } from 'legacy/constants'
import TradeGp from 'legacy/state/swap/TradeGp'
import { RowFee } from 'modules/swap/containers/Row/RowFee'
diff --git a/apps/cowswap-frontend/src/modules/swap/containers/TradeSummary/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/TradeSummary/index.tsx
index 376e8041a2..b8bb423882 100644
--- a/apps/cowswap-frontend/src/modules/swap/containers/TradeSummary/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/containers/TradeSummary/index.tsx
@@ -1,10 +1,10 @@
+import { useWalletDetails } from '@cowprotocol/wallet'
import { Percent } from '@uniswap/sdk-core'
import TradeGp from 'legacy/state/swap/TradeGp'
import { TradeSummaryContent } from 'modules/swap/pure/TradeSummary'
import { useUsdAmount } from 'modules/usdAmount'
-import { useWalletDetails } from 'modules/wallet'
// Sub-components
diff --git a/apps/cowswap-frontend/src/modules/swap/helpers/getSwapButtonState.ts b/apps/cowswap-frontend/src/modules/swap/helpers/getSwapButtonState.ts
index 7f5b8eb78f..fe2112b2f2 100644
--- a/apps/cowswap-frontend/src/modules/swap/helpers/getSwapButtonState.ts
+++ b/apps/cowswap-frontend/src/modules/swap/helpers/getSwapButtonState.ts
@@ -40,8 +40,7 @@ export interface SwapButtonStateParams {
isReadonlyGnosisSafeUser: boolean
isExpertMode: boolean
isSwapUnsupported: boolean
- isTxBundlingEnabled: boolean
- isEthFlowBundlingEnabled: boolean
+ isBundlingSupported: boolean
quoteError: QuoteError | undefined | null
inputError?: string
approvalState: ApprovalState
@@ -54,6 +53,7 @@ export interface SwapButtonStateParams {
isSmartContractWallet: boolean
isBestQuoteLoading: boolean
wrappedToken: Token
+ isPermitSupported: boolean
}
const quoteErrorToSwapButtonState: { [key in QuoteError]: SwapButtonState | null } = {
@@ -67,12 +67,14 @@ const quoteErrorToSwapButtonState: { [key in QuoteError]: SwapButtonState | null
}
export function getSwapButtonState(input: SwapButtonStateParams): SwapButtonState {
- const { quoteError, approvalState } = input
+ const { quoteError, approvalState, isPermitSupported } = input
// show approve flow when: no error on inputs, not approved or pending, or approved in current session
// never show if price impact is above threshold in non expert mode
const showApproveFlow =
- !input.inputError && (approvalState === ApprovalState.NOT_APPROVED || approvalState === ApprovalState.PENDING)
+ !isPermitSupported &&
+ !input.inputError &&
+ (approvalState === ApprovalState.NOT_APPROVED || approvalState === ApprovalState.PENDING)
const isValid = !input.inputError && input.feeWarningAccepted && input.impactWarningAccepted
const swapBlankState = !input.inputError && !input.trade
@@ -104,12 +106,8 @@ export function getSwapButtonState(input: SwapButtonStateParams): SwapButtonStat
}
if (!input.isNativeIn && showApproveFlow) {
- if (input.isTxBundlingEnabled) {
- // TODO: decide if this should be done re-using the current approval flow state or whether do it custom with bundling
- if (input.isExpertMode) {
- return SwapButtonState.ExpertApproveAndSwap
- }
- return SwapButtonState.ApproveAndSwap
+ if (input.isBundlingSupported) {
+ return input.isExpertMode ? SwapButtonState.ExpertApproveAndSwap : SwapButtonState.ApproveAndSwap
}
return SwapButtonState.NeedApprove
}
@@ -125,7 +123,7 @@ export function getSwapButtonState(input: SwapButtonStateParams): SwapButtonStat
if (input.isNativeIn) {
if (getEthFlowEnabled(input.isSmartContractWallet)) {
return input.isExpertMode ? SwapButtonState.ExpertModeEthFlowSwap : SwapButtonState.RegularEthFlowSwap
- } else if (input.isEthFlowBundlingEnabled) {
+ } else if (input.isBundlingSupported) {
return input.isExpertMode ? SwapButtonState.ExpertWrapAndSwap : SwapButtonState.WrapAndSwap
} else {
return SwapButtonState.SwapWithWrappedToken
diff --git a/apps/cowswap-frontend/src/modules/swap/helpers/tradeReceiveAmount.test.ts b/apps/cowswap-frontend/src/modules/swap/helpers/tradeReceiveAmount.test.ts
index 2bd20f1c70..a1e1da4f79 100644
--- a/apps/cowswap-frontend/src/modules/swap/helpers/tradeReceiveAmount.test.ts
+++ b/apps/cowswap-frontend/src/modules/swap/helpers/tradeReceiveAmount.test.ts
@@ -1,9 +1,9 @@
import { ReactElement } from 'react'
+import { COW, GNO } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { CurrencyAmount, Price, Token, TradeType } from '@uniswap/sdk-core'
-import { COW, GNO } from 'legacy/constants/tokens'
import TradeGp from 'legacy/state/swap/TradeGp'
import { getInputReceiveAmountInfo, getOutputReceiveAmountInfo } from './tradeReceiveAmount'
diff --git a/apps/cowswap-frontend/src/modules/swap/helpers/tradeReceiveAmount.tsx b/apps/cowswap-frontend/src/modules/swap/helpers/tradeReceiveAmount.tsx
index 2ea808af17..aa2627c132 100644
--- a/apps/cowswap-frontend/src/modules/swap/helpers/tradeReceiveAmount.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/helpers/tradeReceiveAmount.tsx
@@ -1,11 +1,10 @@
import { ReactNode } from 'react'
+import { TokenAmount, TokenAmountProps } from '@cowprotocol/ui'
import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core'
import TradeGp from 'legacy/state/swap/TradeGp'
-import { TokenAmount, TokenAmountProps } from 'common/pure/TokenAmount'
-
export interface ReceiveAmountInfo {
type: 'from' | 'to'
amountBeforeFees: ReactNode
diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useBaseSafeBundleFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useBaseSafeBundleFlowContext.ts
index 45f6e06254..a1369547a6 100644
--- a/apps/cowswap-frontend/src/modules/swap/hooks/useBaseSafeBundleFlowContext.ts
+++ b/apps/cowswap-frontend/src/modules/swap/hooks/useBaseSafeBundleFlowContext.ts
@@ -1,12 +1,11 @@
+import { useGP2SettlementContract } from '@cowprotocol/common-hooks'
import { OrderKind } from '@cowprotocol/cow-sdk'
+import { useSafeAppsSdk } from '@cowprotocol/wallet'
import { TradeType } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
-import { useGP2SettlementContract } from 'legacy/hooks/useContract'
-
import { getFlowContext, useBaseFlowContextSetup } from 'modules/swap/hooks/useFlowContext'
import { BaseSafeFlowContext } from 'modules/swap/services/types'
-import { useSafeAppsSdk } from 'modules/wallet/web3-react/hooks/useSafeAppsSdk'
import { useTradeSpenderAddress } from 'common/hooks/useTradeSpenderAddress'
diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useCheckEthFlowOrderExists.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useCheckEthFlowOrderExists.ts
new file mode 100644
index 0000000000..088ad2711b
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/swap/hooks/useCheckEthFlowOrderExists.ts
@@ -0,0 +1,39 @@
+import { useAtomValue } from 'jotai'
+import { useCallback } from 'react'
+
+import { ZERO_ADDRESS } from '@cowprotocol/common-const'
+import { useEthFlowContract } from '@cowprotocol/common-hooks'
+
+import { ethFlowInFlightOrderIdsAtom } from '../state/EthFlow/ethFlowInFlightOrderIdsAtom'
+
+export interface EthFlowOrderExistsCallback {
+ (orderId: string, orderDigest: string): Promise
+}
+
+export function useCheckEthFlowOrderExists(): EthFlowOrderExistsCallback {
+ const ethFlowInFlightOrderIds = useAtomValue(ethFlowInFlightOrderIdsAtom)
+ const ethFlowContract = useEthFlowContract()
+
+ return useCallback(
+ async (orderId: string, orderDigest: string) => {
+ if (ethFlowInFlightOrderIds.includes(orderId)) {
+ return true
+ }
+
+ if (ethFlowContract) {
+ try {
+ const { owner } = await ethFlowContract.callStatic.orders(orderDigest)
+
+ return owner.toLowerCase() !== ZERO_ADDRESS
+ } catch (e) {
+ console.error('Eth-flow order existing check error: ', e)
+
+ return false
+ }
+ }
+
+ return false
+ },
+ [ethFlowInFlightOrderIds, ethFlowContract]
+ )
+}
diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useEthFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useEthFlowContext.ts
index 93adb7d077..7cd8122b69 100644
--- a/apps/cowswap-frontend/src/modules/swap/hooks/useEthFlowContext.ts
+++ b/apps/cowswap-frontend/src/modules/swap/hooks/useEthFlowContext.ts
@@ -1,31 +1,25 @@
-import { useAtomValue, useSetAtom } from 'jotai'
-import { useCallback } from 'react'
+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 { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants'
-import { useEthFlowContract } from 'legacy/hooks/useContract'
import { useTransactionAdder } from 'legacy/state/enhancedTransactions/hooks'
import { FlowType, getFlowContext, useBaseFlowContextSetup } from 'modules/swap/hooks/useFlowContext'
import { EthFlowContext } from 'modules/swap/services/types'
-import {
- addInFlightOrderIdAtom,
- ethFlowInFlightOrderIdsAtom,
-} from 'modules/swap/state/EthFlow/ethFlowInFlightOrderIdsAtom'
+import { addInFlightOrderIdAtom } from 'modules/swap/state/EthFlow/ethFlowInFlightOrderIdsAtom'
+
+import { useCheckEthFlowOrderExists } from './useCheckEthFlowOrderExists'
export function useEthFlowContext(): EthFlowContext | null {
const contract = useEthFlowContract()
const baseProps = useBaseFlowContextSetup()
const addTransaction = useTransactionAdder()
- const ethFlowInFlightOrderIds = useAtomValue(ethFlowInFlightOrderIdsAtom)
const addInFlightOrderId = useSetAtom(addInFlightOrderIdAtom)
- const checkInFlightOrderIdExists = useCallback(
- (orderId: string) => ethFlowInFlightOrderIds.includes(orderId),
- [ethFlowInFlightOrderIds]
- )
+ const checkEthFlowOrderExists = useCheckEthFlowOrderExists()
const baseContext = getFlowContext({
baseProps,
@@ -39,7 +33,7 @@ export function useEthFlowContext(): EthFlowContext | null {
...baseContext,
contract,
addTransaction,
- checkInFlightOrderIdExists,
+ checkEthFlowOrderExists,
addInFlightOrderId,
}
}
diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useFlowContext.ts
index 8e6b4f1af9..5b4f2fd8e0 100644
--- a/apps/cowswap-frontend/src/modules/swap/hooks/useFlowContext.ts
+++ b/apps/cowswap-frontend/src/modules/swap/hooks/useFlowContext.ts
@@ -1,5 +1,10 @@
+import { Erc20, Weth } from '@cowprotocol/abis'
+import { GpEther as ETHER, 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 { Weth } from '@cowswap/abis'
+import { useENSAddress } from '@cowprotocol/ens'
+import { useGnosisSafeInfo, useWalletDetails, useWalletInfo } from '@cowprotocol/wallet'
import { Web3Provider } from '@ethersproject/providers'
import { SafeInfoResponse } from '@safe-global/api-kit'
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
@@ -7,14 +12,9 @@ import { useWeb3React } from '@web3-react/core'
import { useDispatch } from 'react-redux'
-import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants'
-import { GpEther as ETHER } from 'legacy/constants/tokens'
-import { useWETHContract } from 'legacy/hooks/useContract'
-import useENSAddress from 'legacy/hooks/useENSAddress'
import { AppDispatch } from 'legacy/state'
import { useCloseModals } from 'legacy/state/application/hooks'
import { AddOrderCallback, useAddPendingOrder } from 'legacy/state/orders/hooks'
-import { useDerivedSwapInfo, useSwapState } from 'legacy/state/swap/hooks'
import TradeGp from 'legacy/state/swap/TradeGp'
import { useUserTransactionTTL } from 'legacy/state/user/hooks'
import { computeSlippageAdjustedAmounts } from 'legacy/utils/prices'
@@ -27,11 +27,9 @@ import { useIsEoaEthFlow } from 'modules/swap/hooks/useIsEoaEthFlow'
import { SwapConfirmManager, useSwapConfirmManager } from 'modules/swap/hooks/useSwapConfirmManager'
import { BaseFlowContext } from 'modules/swap/services/types'
import { SwapFlowAnalyticsContext } from 'modules/trade/utils/analytics'
-import { useGnosisSafeInfo, useWalletDetails, useWalletInfo } from 'modules/wallet'
-
-import { calculateValidTo } from 'utils/time'
import { useIsSafeEthFlow } from './useIsSafeEthFlow'
+import { useDerivedSwapInfo, useSwapState } from './useSwapState'
const _computeInputAmountForSignature = (params: {
input: CurrencyAmount
@@ -63,6 +61,7 @@ export enum FlowType {
interface BaseFlowContextSetup {
chainId: number | undefined
account: string | undefined
+ sellTokenContract: Erc20 | null
provider: Web3Provider | undefined
trade: TradeGp | undefined
appData: AppDataInfo | null
@@ -109,6 +108,7 @@ export function useBaseFlowContextSetup(): BaseFlowContextSetup {
trade,
allowedSlippage
)
+ const sellTokenContract = useTokenContract(getAddress(inputAmountWithSlippage?.currency) || undefined, true)
const isSafeBundle = useIsSafeApprovalBundle(inputAmountWithSlippage)
const flowType = _getFlowType(isSafeBundle, isEoaEthFlow, isSafeEthFlow)
@@ -116,6 +116,7 @@ export function useBaseFlowContextSetup(): BaseFlowContextSetup {
return {
chainId,
account,
+ sellTokenContract,
provider,
trade,
appData,
@@ -179,6 +180,7 @@ export function getFlowContext({ baseProps, sellToken, kind }: BaseGetFlowContex
uploadAppData,
dispatch,
flowType,
+ sellTokenContract,
} = baseProps
if (
@@ -263,5 +265,6 @@ export function getFlowContext({ baseProps, sellToken, kind }: BaseGetFlowContex
swapConfirmManager,
orderParams,
appDataInfo: appData,
+ sellTokenContract,
}
}
diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useHandleSwap.test.tsx b/apps/cowswap-frontend/src/modules/swap/hooks/useHandleSwap.test.tsx
index cd751a26de..e8c23f5bfb 100644
--- a/apps/cowswap-frontend/src/modules/swap/hooks/useHandleSwap.test.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/hooks/useHandleSwap.test.tsx
@@ -1,8 +1,7 @@
import { renderHook } from '@testing-library/react-hooks'
import { PriceImpact } from 'legacy/hooks/usePriceImpact'
-import { Field } from 'legacy/state/swap/actions'
-import { useSwapActionHandlers } from 'legacy/state/swap/hooks'
+import { Field } from 'legacy/state/types'
import { useSafeBundleApprovalFlowContext } from 'modules/swap/hooks/useSafeBundleApprovalFlowContext'
import { ethFlow } from 'modules/swap/services/ethFlow'
@@ -15,17 +14,18 @@ import { useEthFlowContext } from './useEthFlowContext'
import { useHandleSwap } from './useHandleSwap'
import { useSafeBundleEthFlowContext } from './useSafeBundleEthFlowContext'
import { useSwapFlowContext } from './useSwapFlowContext'
+import { useSwapActionHandlers } from './useSwapState'
+jest.mock('./useSwapState')
jest.mock('./useSwapFlowContext')
jest.mock('./useEthFlowContext')
jest.mock('./useSafeBundleApprovalFlowContext')
jest.mock('./useSafeBundleEthFlowContext')
-jest.mock('legacy/state/swap/hooks')
jest.mock('modules/swap/services/swapFlow')
jest.mock('modules/swap/services/ethFlow')
jest.mock('modules/swap/services/safeBundleFlow')
jest.mock('modules/twap/state/twapOrdersListAtom', () => ({}))
-jest.mock('legacy/components/analytics/hooks/useAnalyticsReporter.ts')
+jest.mock('common/hooks/useAnalyticsReporter')
const mockUseSwapActionHandlers = useSwapActionHandlers as jest.MockedFunction
const mockSwapFlow = swapFlow as jest.MockedFunction
diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useHandleSwap.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useHandleSwap.ts
index 7ecfe2c12e..20dc460162 100644
--- a/apps/cowswap-frontend/src/modules/swap/hooks/useHandleSwap.ts
+++ b/apps/cowswap-frontend/src/modules/swap/hooks/useHandleSwap.ts
@@ -1,8 +1,7 @@
import { useCallback } from 'react'
import { PriceImpact } from 'legacy/hooks/usePriceImpact'
-import { Field } from 'legacy/state/swap/actions'
-import { useSwapActionHandlers } from 'legacy/state/swap/hooks'
+import { Field } from 'legacy/state/types'
import { useSafeBundleApprovalFlowContext } from 'modules/swap/hooks/useSafeBundleApprovalFlowContext'
import { ethFlow } from 'modules/swap/services/ethFlow'
@@ -15,6 +14,7 @@ import { useConfirmPriceImpactWithoutFee } from 'common/hooks/useConfirmPriceImp
import { useEthFlowContext } from './useEthFlowContext'
import { useSafeBundleEthFlowContext } from './useSafeBundleEthFlowContext'
import { useSwapFlowContext } from './useSwapFlowContext'
+import { useSwapActionHandlers } from './useSwapState'
export function useHandleSwap(priceImpactParams: PriceImpact): () => Promise {
const swapFlowContext = useSwapFlowContext()
diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useIsEoaEthFlow.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useIsEoaEthFlow.ts
index 3ee54396d4..5d2a630fe7 100644
--- a/apps/cowswap-frontend/src/modules/swap/hooks/useIsEoaEthFlow.ts
+++ b/apps/cowswap-frontend/src/modules/swap/hooks/useIsEoaEthFlow.ts
@@ -1,6 +1,6 @@
-import { getEthFlowEnabled } from 'modules/swap/helpers/getEthFlowEnabled'
+import { useIsSmartContractWallet } from '@cowprotocol/wallet'
-import { useIsSmartContractWallet } from 'common/hooks/useIsSmartContractWallet'
+import { getEthFlowEnabled } from 'modules/swap/helpers/getEthFlowEnabled'
import { useIsSwapEth } from './useIsSwapEth'
diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useIsSafeEthFlow.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useIsSafeEthFlow.ts
index a108950381..b1badd3a31 100644
--- a/apps/cowswap-frontend/src/modules/swap/hooks/useIsSafeEthFlow.ts
+++ b/apps/cowswap-frontend/src/modules/swap/hooks/useIsSafeEthFlow.ts
@@ -1,10 +1,10 @@
-import { useIsEthFlowBundlingEnabled } from 'common/hooks/featureFlags/useIsEthFlowBundlingEnabled'
+import { useIsBundlingSupported } from '@cowprotocol/wallet'
import { useIsSwapEth } from './useIsSwapEth'
export function useIsSafeEthFlow(): boolean {
const isSwapEth = useIsSwapEth()
- const isEthFlowBundlingEnabled = useIsEthFlowBundlingEnabled()
+ const isBundlingSupported = useIsBundlingSupported()
- return isEthFlowBundlingEnabled && isSwapEth
+ return isBundlingSupported && isSwapEth
}
diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSafeBundleApprovalFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSafeBundleApprovalFlowContext.ts
index 5e6425be86..7fc8ee6a35 100644
--- a/apps/cowswap-frontend/src/modules/swap/hooks/useSafeBundleApprovalFlowContext.ts
+++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSafeBundleApprovalFlowContext.ts
@@ -1,4 +1,4 @@
-import { useTokenContract } from 'legacy/hooks/useContract'
+import { useTokenContract } from '@cowprotocol/common-hooks'
import { FlowType } from 'modules/swap/hooks/useFlowContext'
import { SafeBundleApprovalFlowContext } from 'modules/swap/services/types'
diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSafeBundleEthFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSafeBundleEthFlowContext.ts
index e946713168..65ac47fc2b 100644
--- a/apps/cowswap-frontend/src/modules/swap/hooks/useSafeBundleEthFlowContext.ts
+++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSafeBundleEthFlowContext.ts
@@ -1,4 +1,4 @@
-import { useWETHContract } from 'legacy/hooks/useContract'
+import { useWETHContract } from '@cowprotocol/common-hooks'
import { FlowType } from 'modules/swap/hooks/useFlowContext'
import { SafeBundleEthFlowContext } from 'modules/swap/services/types'
diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSetupSwapAmountsFromUrl.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSetupSwapAmountsFromUrl.ts
index 6e2f09e5d7..a3cb22aa90 100644
--- a/apps/cowswap-frontend/src/modules/swap/hooks/useSetupSwapAmountsFromUrl.ts
+++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSetupSwapAmountsFromUrl.ts
@@ -1,13 +1,14 @@
import { useCallback, useLayoutEffect, useMemo } from 'react'
+import { getIntOrFloat } from '@cowprotocol/common-utils'
+
import { useLocation, useNavigate } from 'react-router-dom'
-import { Field } from 'legacy/state/swap/actions'
-import { useSwapActionHandlers } from 'legacy/state/swap/hooks'
+import { Field } from 'legacy/state/types'
import { TRADE_URL_BUY_AMOUNT_KEY, TRADE_URL_SELL_AMOUNT_KEY } from 'modules/trade/const/tradeUrl'
-import { getIntOrFloat } from 'utils/getIntOrFloat'
+import { useSwapActionHandlers } from './useSwapState'
/**
* Parse sell/buy amount from URL and apply to Swap widget
diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts
index 4ac0493a34..e76de08d48 100644
--- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts
+++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts
@@ -1,13 +1,20 @@
+import {
+ useGnosisSafeInfo,
+ useIsBundlingSupported,
+ useIsSmartContractWallet,
+ useWalletDetails,
+ useWalletInfo,
+} from '@cowprotocol/wallet'
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/swap/actions'
-import { useDerivedSwapInfo, useSwapActionHandlers } from 'legacy/state/swap/hooks'
+import { Field } from 'legacy/state/types'
import { useExpertModeManager } from 'legacy/state/user/hooks'
+import { useIsTokenPermittable } from 'modules/permit'
import { getSwapButtonState } from 'modules/swap/helpers/getSwapButtonState'
import { useEthFlowContext } from 'modules/swap/hooks/useEthFlowContext'
import { useHandleSwap } from 'modules/swap/hooks/useHandleSwap'
@@ -16,18 +23,15 @@ import { useSwapConfirmManager } from 'modules/swap/hooks/useSwapConfirmManager'
import { useSwapFlowContext } from 'modules/swap/hooks/useSwapFlowContext'
import { SwapButtonsContext } from 'modules/swap/pure/SwapButtons'
import useCurrencyBalance from 'modules/tokens/hooks/useCurrencyBalance'
-import { useWrapNativeFlow } from 'modules/trade'
+import { TradeType, useWrapNativeFlow } from 'modules/trade'
import { useIsNativeIn } from 'modules/trade/hooks/useIsNativeInOrOut'
import { useIsWrappedOut } from 'modules/trade/hooks/useIsWrappedInOrOut'
import { useWrappedToken } from 'modules/trade/hooks/useWrappedToken'
-import { useGnosisSafeInfo, useWalletDetails, useWalletInfo } from 'modules/wallet'
import { useTradeApproveState } from 'common/containers/TradeApprove/useTradeApproveState'
-import { useIsEthFlowBundlingEnabled } from 'common/hooks/featureFlags/useIsEthFlowBundlingEnabled'
-import { useIsTxBundlingEnabled } from 'common/hooks/featureFlags/useIsTxBundlingEnabled'
-import { useIsSmartContractWallet } from 'common/hooks/useIsSmartContractWallet'
import { useSafeBundleEthFlowContext } from './useSafeBundleEthFlowContext'
+import { useDerivedSwapInfo, useSwapActionHandlers } from './useSwapState'
export interface SwapButtonInput {
feeWarningAccepted: boolean
@@ -87,16 +91,15 @@ export function useSwapButtonContext(input: SwapButtonInput): SwapButtonsContext
const isReadonlyGnosisSafeUser = gnosisSafeInfo?.isReadOnly || false
const isSwapUnsupported = useIsTradeUnsupported(currencyIn, currencyOut)
const isSmartContractWallet = useIsSmartContractWallet()
- const isTxBundlingEnabled = useIsTxBundlingEnabled()
- const isEthFlowBundlingEnabled = useIsEthFlowBundlingEnabled()
+ const isBundlingSupported = useIsBundlingSupported()
+ const isPermitSupported = !!useIsTokenPermittable(currencyIn, TradeType.SWAP)
const swapButtonState = getSwapButtonState({
account,
isSupportedWallet,
isSmartContractWallet,
isReadonlyGnosisSafeUser,
- isTxBundlingEnabled,
- isEthFlowBundlingEnabled,
+ isBundlingSupported,
isExpertMode,
isSwapUnsupported,
isNativeIn: isNativeInSwap,
@@ -110,6 +113,7 @@ export function useSwapButtonContext(input: SwapButtonInput): SwapButtonsContext
swapCallbackError,
trade,
isBestQuoteLoading,
+ isPermitSupported,
})
return {
diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapConfirmManager.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapConfirmManager.ts
index d771262739..0ba4f9b23c 100644
--- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapConfirmManager.ts
+++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapConfirmManager.ts
@@ -1,75 +1,113 @@
-import { useAtom } from 'jotai'
+import { useSetAtom } from 'jotai'
import { useMemo } from 'react'
import TradeGp from 'legacy/state/swap/TradeGp'
import { useExpertModeManager } from 'legacy/state/user/hooks'
-import { swapConfirmAtom } from 'modules/swap/state/swapConfirmAtom'
+import { swapConfirmAtom, SwapConfirmState } from 'modules/swap/state/swapConfirmAtom'
export interface SwapConfirmManager {
setSwapError(swapErrorMessage: string): void
- openSwapConfirmModal(tradeToConfirm: TradeGp): void
+ openSwapConfirmModal(tradeToConfirm: TradeGp, needsPermitSignature?: boolean): void
acceptRateUpdates(tradeToConfirm: TradeGp): void
closeSwapConfirm(): void
sendTransaction(tradeToConfirm: TradeGp): void
transactionSent(txHash: string): void
+ requestPermitSignature(): void
+ permitSigned(): void
}
export function useSwapConfirmManager(): SwapConfirmManager {
- const [swapConfirmState, setSwapConfirmState] = useAtom(swapConfirmAtom)
+ const setSwapConfirmState = useSetAtom(swapConfirmAtom)
const [isExpertMode] = useExpertModeManager()
return useMemo(
() => ({
setSwapError(swapErrorMessage: string) {
- const state = { ...swapConfirmState, swapErrorMessage }
- console.debug('[Swap confirm state] setSwapError: ', state)
- setSwapConfirmState(state)
+ setSwapConfirmState((prev) => {
+ const state = { ...prev, swapErrorMessage, attemptingTxn: false, permitSignatureState: undefined }
+ console.debug('[Swap confirm state] setSwapError: ', state)
+ return state
+ })
},
openSwapConfirmModal(tradeToConfirm: TradeGp) {
- const state = {
+ const state: SwapConfirmState = {
tradeToConfirm,
attemptingTxn: false,
swapErrorMessage: undefined,
showConfirm: true,
txHash: undefined,
+ permitSignatureState: undefined,
}
console.debug('[Swap confirm state] openSwapConfirmModal: ', state)
setSwapConfirmState(state)
},
acceptRateUpdates(tradeToConfirm: TradeGp) {
- const state = { ...swapConfirmState, tradeToConfirm }
- console.debug('[Swap confirm state] acceptRateUpdates: ', state)
- setSwapConfirmState(state)
+ setSwapConfirmState((prev) => {
+ const state = { ...prev, tradeToConfirm }
+ console.debug('[Swap confirm state] acceptRateUpdates: ', state)
+ return state
+ })
+ },
+ requestPermitSignature() {
+ setSwapConfirmState((prev) => {
+ const state: SwapConfirmState = { ...prev, permitSignatureState: 'requested' }
+ console.debug('[Swap confirm state] requestPermitSignature: ', state)
+ return state
+ })
+ },
+ permitSigned() {
+ setSwapConfirmState((prev) => {
+ // Move to `signed` state only if previous state was `requested` - which means the order is using the permit
+ // Set to `undefined` otherwise
+ const permitSignatureState = prev.permitSignatureState === 'requested' ? 'signed' : undefined
+
+ const state: SwapConfirmState = {
+ ...prev,
+ permitSignatureState,
+ }
+
+ console.debug('[Swap confirm state] permitSigned: ', state)
+
+ return state
+ })
},
closeSwapConfirm() {
- const state = { ...swapConfirmState, showConfirm: false }
- console.debug('[Swap confirm state] closeSwapConfirm: ', state)
- setSwapConfirmState(state)
+ setSwapConfirmState((prev) => {
+ const state = { ...prev, showConfirm: false, permitSignatureState: undefined }
+ console.debug('[Swap confirm state] closeSwapConfirm: ', state)
+ return state
+ })
},
sendTransaction(tradeToConfirm: TradeGp) {
- const state = {
- tradeToConfirm,
- attemptingTxn: true,
- swapErrorMessage: undefined,
- showConfirm: true,
- txHash: undefined,
- }
- console.debug('[Swap confirm state] sendTransaction: ', state)
- setSwapConfirmState(state)
+ setSwapConfirmState((prev) => {
+ const state = {
+ ...prev,
+ tradeToConfirm,
+ attemptingTxn: true,
+ swapErrorMessage: undefined,
+ showConfirm: true,
+ txHash: undefined,
+ }
+ console.debug('[Swap confirm state] sendTransaction: ', state)
+ return state
+ })
},
transactionSent(txHash: string) {
- const state = {
- ...swapConfirmState,
- attemptingTxn: false,
- swapErrorMessage: undefined,
- showConfirm: !isExpertMode,
- txHash,
- }
- console.debug('[Swap confirm state] transactionSent: ', state)
- setSwapConfirmState(state)
+ setSwapConfirmState((prev) => {
+ const state = {
+ ...prev,
+ attemptingTxn: false,
+ swapErrorMessage: undefined,
+ showConfirm: !isExpertMode,
+ txHash,
+ permitSignatureState: undefined,
+ }
+ console.debug('[Swap confirm state] transactionSent: ', state)
+ return state
+ })
},
}),
- [swapConfirmState, setSwapConfirmState, isExpertMode]
+ [setSwapConfirmState, isExpertMode]
)
}
diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapCurrenciesAmounts.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapCurrenciesAmounts.ts
index 60036372c1..9d0c1e51f3 100644
--- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapCurrenciesAmounts.ts
+++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapCurrenciesAmounts.ts
@@ -1,12 +1,13 @@
import { useMemo } from 'react'
import { ParsedAmounts } from 'legacy/hooks/usePriceImpact/types'
-import { Field } from 'legacy/state/swap/actions'
-import { useSwapState } from 'legacy/state/swap/hooks'
-import { useDerivedSwapInfo } from 'legacy/state/swap/hooks'
+import { Field } from 'legacy/state/types'
import { useSafeMemoObject } from 'common/hooks/useSafeMemo'
+import { useSwapState } from './useSwapState'
+import { useDerivedSwapInfo } from './useSwapState'
+
export function useSwapCurrenciesAmounts(): ParsedAmounts {
const { independentField } = useSwapState()
const { v2Trade: trade, parsedAmount } = useDerivedSwapInfo()
diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts
index f8adc0ea86..086e4329ba 100644
--- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts
+++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts
@@ -1,21 +1,34 @@
-import { OrderKind } from '@cowprotocol/cow-sdk'
-import { TradeType } from '@uniswap/sdk-core'
-
-import { useGP2SettlementContract } from 'legacy/hooks/useContract'
+import { GP_VAULT_RELAYER } from '@cowprotocol/common-const'
+import { useGP2SettlementContract } from '@cowprotocol/common-hooks'
+import { OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk'
+import { TradeType as UniTradeType } from '@uniswap/sdk-core'
+import { useGeneratePermitHook, useIsTokenPermittable } from 'modules/permit'
import { FlowType, getFlowContext, useBaseFlowContextSetup } from 'modules/swap/hooks/useFlowContext'
import { SwapFlowContext } from 'modules/swap/services/types'
+import { useEnoughBalanceAndAllowance } from 'modules/tokens'
+import { TradeType } from 'modules/trade'
export function useSwapFlowContext(): SwapFlowContext | null {
const contract = useGP2SettlementContract()
const baseProps = useBaseFlowContextSetup()
+ const sellCurrency = baseProps.trade?.inputAmount?.currency
+ const permitInfo = useIsTokenPermittable(sellCurrency, TradeType.SWAP)
+ const generatePermitHook = useGeneratePermitHook()
+
+ const checkAllowanceAddress = GP_VAULT_RELAYER[baseProps.chainId || SupportedChainId.MAINNET]
+ const { enoughAllowance } = useEnoughBalanceAndAllowance({
+ account: baseProps.account,
+ amount: baseProps.inputAmountWithSlippage,
+ checkAllowanceAddress,
+ })
if (!baseProps.trade) return null
const baseContext = getFlowContext({
baseProps,
sellToken: baseProps.trade.inputAmount.currency.wrapped,
- kind: baseProps.trade.tradeType === TradeType.EXACT_INPUT ? OrderKind.SELL : OrderKind.BUY,
+ kind: baseProps.trade.tradeType === UniTradeType.EXACT_INPUT ? OrderKind.SELL : OrderKind.BUY,
})
if (!contract || !baseContext || baseProps.flowType !== FlowType.REGULAR) return null
@@ -23,5 +36,7 @@ export function useSwapFlowContext(): SwapFlowContext | null {
return {
...baseContext,
contract,
+ permitInfo: !enoughAllowance ? permitInfo : undefined,
+ generatePermitHook,
}
}
diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapRawState.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapRawState.ts
index 481307e5d8..bab6dc5cdb 100644
--- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapRawState.ts
+++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapRawState.ts
@@ -2,10 +2,11 @@ import { useCallback } from 'react'
import { useAppDispatch } from 'legacy/state/hooks'
import { replaceOnlyTradeRawState, ReplaceOnlyTradeRawStatePayload } from 'legacy/state/swap/actions'
-import { useSwapState } from 'legacy/state/swap/hooks'
import { ExtendedTradeRawState, TradeRawState } from 'modules/trade/types/TradeRawState'
+import { useSwapState } from './useSwapState'
+
export function useSwapRawState(): TradeRawState {
const swapState = useSwapState()
diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapSlippage.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapSlippage.ts
index bbb7308b06..1ccd9f92e4 100644
--- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapSlippage.ts
+++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapSlippage.ts
@@ -1,6 +1,6 @@
+import { INITIAL_ALLOWED_SLIPPAGE_PERCENT } from '@cowprotocol/common-const'
import { Percent } from '@uniswap/sdk-core'
-import { INITIAL_ALLOWED_SLIPPAGE_PERCENT } from 'legacy/constants'
import { useUserSlippageToleranceWithDefault } from 'legacy/state/user/hooks'
export function useSwapSlippage(): Percent {
diff --git a/apps/cowswap-frontend/src/legacy/state/swap/hooks.test.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapState.test.ts
similarity index 95%
rename from apps/cowswap-frontend/src/legacy/state/swap/hooks.test.ts
rename to apps/cowswap-frontend/src/modules/swap/hooks/useSwapState.test.ts
index 04ac6376f1..9dbd371abb 100644
--- a/apps/cowswap-frontend/src/legacy/state/swap/hooks.test.ts
+++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapState.test.ts
@@ -1,9 +1,9 @@
import { parse } from 'qs'
-import { Field } from './actions'
-import { queryParametersToSwapState } from './utils'
+import { queryParametersToSwapState } from 'legacy/state/swap/utils'
+import { Field } from 'legacy/state/types'
-jest.mock('legacy/components/analytics/hooks/useAnalyticsReporter.ts')
+jest.mock('common/hooks/useAnalyticsReporter')
describe('hooks', () => {
describe('#queryParametersToSwapState', () => {
diff --git a/apps/cowswap-frontend/src/legacy/state/swap/hooks.tsx b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapState.tsx
similarity index 95%
rename from apps/cowswap-frontend/src/legacy/state/swap/hooks.tsx
rename to apps/cowswap-frontend/src/modules/swap/hooks/useSwapState.tsx
index 835cf5f5c7..c0de1c1112 100644
--- a/apps/cowswap-frontend/src/legacy/state/swap/hooks.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapState.tsx
@@ -1,38 +1,36 @@
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 { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { useENS } from '@cowprotocol/ens'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import { t } from '@lingui/macro'
-import { changeSwapAmountAnalytics, switchTokensAnalytics } from 'legacy/components/analytics'
-import { FEE_SIZE_THRESHOLD } from 'legacy/constants'
import { useCurrency } from 'legacy/hooks/Tokens'
-import useENS from 'legacy/hooks/useENS'
import { PriceImpact } from 'legacy/hooks/usePriceImpact'
import { AppState } from 'legacy/state'
import { useAppDispatch, useAppSelector } from 'legacy/state/hooks'
import { useGetQuoteAndStatus, useQuote } from 'legacy/state/price/hooks'
+import { setRecipient, switchCurrencies, typeInput } from 'legacy/state/swap/actions'
import { stringToCurrency, useTradeExactInWithFee, useTradeExactOutWithFee } from 'legacy/state/swap/extension'
import TradeGp from 'legacy/state/swap/TradeGp'
import { isWrappingTrade } from 'legacy/state/swap/utils'
+import { Field } from 'legacy/state/types'
import { useIsExpertMode } from 'legacy/state/user/hooks'
-import { isAddress } from 'legacy/utils'
-import { registerOnWindow } from 'legacy/utils/misc'
-import { useSwapSlippage } from 'modules/swap/hooks/useSwapSlippage'
import { useCurrencyBalances } from 'modules/tokens/hooks/useCurrencyBalance'
import { useNavigateOnCurrencySelection } from 'modules/trade/hooks/useNavigateOnCurrencySelection'
import { useTradeNavigate } from 'modules/trade/hooks/useTradeNavigate'
-import { useWalletInfo } from 'modules/wallet'
import { useAreThereTokensWithSameSymbol } from 'common/hooks/useAreThereTokensWithSameSymbol'
import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported'
import { useTokenBySymbolOrAddress } from 'common/hooks/useTokenBySymbolOrAddress'
-import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount'
-import { formatSymbol } from 'utils/format'
-import { Field, setRecipient, switchCurrencies, typeInput } from './actions'
+import { useSwapSlippage } from './useSwapSlippage'
export const BAD_RECIPIENT_ADDRESSES: { [address: string]: true } = {
'0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f': true, // v2 factory
@@ -282,9 +280,6 @@ export function useDerivedSwapInfo(): DerivedSwapInfo {
// TODO: rename v2Trade to just "trade" we dont have versions
const v2Trade = isExactIn ? bestTradeExactIn : bestTradeExactOut
- registerOnWindow({ trade: v2Trade })
- // -- MOD --
-
const currencyBalances = useMemo(
() => ({
[Field.INPUT]: relevantTokenBalances[0],
diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useTradePricesUpdate.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useTradePricesUpdate.ts
index 7d809f81e8..a171af0670 100644
--- a/apps/cowswap-frontend/src/modules/swap/hooks/useTradePricesUpdate.ts
+++ b/apps/cowswap-frontend/src/modules/swap/hooks/useTradePricesUpdate.ts
@@ -1,8 +1,12 @@
import { useMemo } from 'react'
-import { LONG_LOAD_THRESHOLD, SHORT_LOAD_THRESHOLD } from 'legacy/constants'
-import useLoadingWithTimeout from 'legacy/hooks/useLoadingWithTimeout'
-import { useIsBestQuoteLoading, useIsQuoteLoading, useIsQuoteRefreshing } from 'legacy/state/price/hooks'
+import { LONG_LOAD_THRESHOLD, SHORT_LOAD_THRESHOLD } from '@cowprotocol/common-const'
+import { useLoadingWithTimeout } from '@cowprotocol/common-hooks'
+import { useWalletInfo } from '@cowprotocol/wallet'
+
+import { useGetQuoteAndStatus, useIsBestQuoteLoading, useIsQuoteLoading } from 'legacy/state/price/hooks'
+
+import { useSwapState } from './useSwapState'
export function useTradePricesUpdate(): boolean {
const isRefreshingQuote = useIsQuoteRefreshing()
@@ -14,3 +18,12 @@ export function useTradePricesUpdate(): boolean {
return useMemo(() => showCowLoader || showQuoteLoader, [showCowLoader, showQuoteLoader])
}
+
+function useIsQuoteRefreshing(): boolean {
+ const { chainId } = useWalletInfo()
+ const {
+ INPUT: { currencyId },
+ } = useSwapState()
+ const { isRefreshingQuote } = useGetQuoteAndStatus({ token: currencyId, chainId })
+ return isRefreshingQuote
+}
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 9d534210a3..4745047b58 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,8 +1,7 @@
+import { GpEther } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { Token } from '@uniswap/sdk-core'
-import { GpEther } from 'legacy/constants/tokens'
-
import { EthFlowBannerContent, EthFlowBannerContentProps } from '.'
const defaultProps: EthFlowBannerContentProps = {
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/index.tsx
index b590076c12..d972e7937d 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/index.tsx
@@ -1,13 +1,12 @@
+import savingsIcon from '@cowprotocol/assets/cow-swap/savings.svg'
+import { MINIMUM_ETH_FLOW_SLIPPAGE, PERCENTAGE_PRECISION } from '@cowprotocol/common-const'
+import { ButtonPrimary } from '@cowprotocol/ui'
import { Currency, Token } from '@uniswap/sdk-core'
import { Trans } from '@lingui/macro'
import { ChevronDown, ChevronUp } from 'react-feather'
import SVG from 'react-inlinesvg'
-import savingsIcon from 'legacy/assets/cow-swap/savings.svg'
-import { ButtonPrimary } from 'legacy/components/Button'
-import { MINIMUM_ETH_FLOW_SLIPPAGE, PERCENTAGE_PRECISION } from 'legacy/constants'
-
import { EthFlowBannerCallbacks } from 'modules/swap/containers/EthFlow/EthFlowBanner'
import * as styledEl from './styleds'
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/styleds.ts b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/styleds.ts
index 99a597f61b..f96c023a53 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/styleds.ts
+++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/styleds.ts
@@ -1,7 +1,9 @@
+import { ButtonPrimary } from '@cowprotocol/ui'
+
import { transparentize } from 'polished'
import styled from 'styled-components/macro'
-import { ButtonPrimary } from 'legacy/components/Button'
+import { UI } from 'common/constants/theme'
export const BannerWrapper = styled.div`
display: flex;
@@ -36,7 +38,7 @@ export const ClosedBannerWrapper = styled.div`
cursor: pointer;
> path {
- fill: ${({ theme }) => theme.text1};
+ fill: var(${UI.COLOR_TEXT1});
}
}
@@ -45,7 +47,7 @@ export const ClosedBannerWrapper = styled.div`
}
&:hover > svg:last-child {
- stroke: ${({ theme }) => theme.text1};
+ stroke: var(${UI.COLOR_TEXT1});
}
`
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowModalContent/ActionButton.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowModalContent/ActionButton.tsx
index 7da6af2af4..9a118dcd73 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowModalContent/ActionButton.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowModalContent/ActionButton.tsx
@@ -1,9 +1,8 @@
+import { Loader, ButtonPrimary } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import styled from 'styled-components/macro'
-import { ButtonPrimary } from 'legacy/components/Button'
-import Loader from 'legacy/components/Loader'
-
const ButtonWrapper = styled.div`
display: flex;
flex-flow: row nowrap;
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowModalContent/EthFlowModalTopContent.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowModalContent/EthFlowModalTopContent.tsx
index be5dba945a..fc0d0a5445 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowModalContent/EthFlowModalTopContent.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowModalContent/EthFlowModalTopContent.tsx
@@ -4,6 +4,8 @@ import styled from 'styled-components/macro'
import { EthFlowState } from 'modules/swap/services/ethFlow/types'
+import { UI } from 'common/constants/theme'
+
const ModalMessage = styled.div`
display: flex;
flex-flow: row wrap;
@@ -25,7 +27,7 @@ const ModalMessage = styled.div`
const LowBalanceMessage = styled(ModalMessage)`
margin: 0 0 10px;
background: ${({ theme }) => (theme.darkMode ? transparentize(0.9, theme.alert) : transparentize(0.85, theme.alert))};
- color: ${({ theme }) => (theme.darkMode ? theme.alert : darken(0.2, theme.alert))};
+ color: ${({ theme }) => (theme.darkMode ? `var(${UI.COLOR_ALERT})` : darken(0.2, theme.alert))};
padding: 16px;
border-radius: 16px;
width: 100%;
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/index.cosmos.tsx
index 1fd39c2845..022dcc648e 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/index.cosmos.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/index.cosmos.tsx
@@ -1,6 +1,7 @@
import 'inter-ui' // TODO: We need to do a cosmos wrapper with the global styles! Will reiterate to remove this line
import { useSelect } from 'react-cosmos/client'
+import styled from 'styled-components/macro'
import { EthFlowStepper, EthFlowStepperProps, SmartOrderStatus } from '.'
@@ -376,6 +377,11 @@ const STEPS_BY_DESCRIPTION = STEPS.reduce<{ [description: string]: EthFlowSteppe
return acc
}, {})
+const Wrapper = styled.div`
+ width: 80%;
+ margin: 20px auto;
+`
+
function Fixture() {
const [stepDescription] = useSelect('steps', {
options: STEPS.map((step) => step.description),
@@ -383,13 +389,13 @@ function Fixture() {
const props = STEPS_BY_DESCRIPTION[stepDescription]
return (
- <>
+
Params
{JSON.stringify(props, null, 2)}
- >
+
)
}
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/index.tsx
index 85f7e02e7c..543dcf6803 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/index.tsx
@@ -3,6 +3,8 @@ import React from 'react'
import { transparentize } from 'polished'
import styled from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
import { StatusIconState } from './StatusIcon'
import { Progress1 } from './steps/Progress1'
import { Progress2 } from './steps/Progress2'
@@ -72,7 +74,7 @@ const Wrapper = styled.div`
width: 100%;
padding: 22px;
border-radius: 0 0 12px 12px;
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
font-size: 15px;
line-height: 1;
@@ -117,7 +119,7 @@ export const Progress = styled.div`
transition: width 0.3s ease-in-out, background 0.2s ease-in-out;
width: ${({ value }) => (value ? `${value}%` : '0%')};
background: ${({ status, theme }) =>
- status === 'error' ? theme.danger : status === 'success' ? theme.success : theme.text3};
+ status === 'error' ? `var(${UI.COLOR_DANGER})` : status === 'success' ? `var(${UI.COLOR_SUCCESS})` : theme.text3};
border-radius: var(--height);
${({ theme }) => theme.mediaWidth.upToSmall`
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step1.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step1.tsx
index 1041c2d8aa..3916be3635 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step1.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step1.tsx
@@ -1,9 +1,9 @@
import React from 'react'
-import Checkmark from 'legacy/assets/cow-swap/checkmark.svg'
-import Exclamation from 'legacy/assets/cow-swap/exclamation.svg'
-import Send from 'legacy/assets/cow-swap/send.svg'
-import X from 'legacy/assets/cow-swap/x.svg'
+import Checkmark from '@cowprotocol/assets/cow-swap/checkmark.svg'
+import Exclamation from '@cowprotocol/assets/cow-swap/exclamation.svg'
+import Send from '@cowprotocol/assets/cow-swap/send.svg'
+import X from '@cowprotocol/assets/cow-swap/x.svg'
import { EthFlowStepperProps, SmartOrderStatus } from '..'
import { StatusIconState } from '../StatusIcon'
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step2.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step2.tsx
index bf5c8137d0..15a3f843f0 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step2.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step2.tsx
@@ -1,9 +1,9 @@
import React, { useMemo } from 'react'
-import Checkmark from 'legacy/assets/cow-swap/checkmark.svg'
-import Exclamation from 'legacy/assets/cow-swap/exclamation.svg'
-import Plus from 'legacy/assets/cow-swap/plus.svg'
-import X from 'legacy/assets/cow-swap/x.svg'
+import Checkmark from '@cowprotocol/assets/cow-swap/checkmark.svg'
+import Exclamation from '@cowprotocol/assets/cow-swap/exclamation.svg'
+import Plus from '@cowprotocol/assets/cow-swap/plus.svg'
+import X from '@cowprotocol/assets/cow-swap/x.svg'
import { EthFlowStepperProps, SmartOrderStatus } from '..'
import { ExplorerLinkStyled, Step, StepProps } from '../Step'
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step3.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step3.tsx
index d7b5871985..61896a3dec 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step3.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step3.tsx
@@ -1,17 +1,19 @@
import React, { useMemo } from 'react'
+import Checkmark from '@cowprotocol/assets/cow-swap/checkmark.svg'
+import Exclamation from '@cowprotocol/assets/cow-swap/exclamation.svg'
+import Finish from '@cowprotocol/assets/cow-swap/finish.svg'
+import Refund from '@cowprotocol/assets/cow-swap/refund.svg'
+
import styled from 'styled-components/macro'
-import Checkmark from 'legacy/assets/cow-swap/checkmark.svg'
-import Exclamation from 'legacy/assets/cow-swap/exclamation.svg'
-import Finish from 'legacy/assets/cow-swap/finish.svg'
-import Refund from 'legacy/assets/cow-swap/refund.svg'
+import { UI } from 'common/constants/theme'
import { EthFlowStepperProps, SmartOrderStatus } from '..'
import { Step, StepProps, ExplorerLinkStyled } from '../Step'
const RefundMessage = styled.span`
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
font-weight: 500;
`
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/WrapCard.cosmos.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/WrapCard.cosmos.tsx
index 38b74f34ea..5a4bf5c5aa 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/WrapCard.cosmos.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/WrapCard.cosmos.tsx
@@ -1,8 +1,7 @@
+import { WRAPPED_NATIVE_CURRENCY as WETH } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { CurrencyAmount } from '@uniswap/sdk-core'
-import { WRAPPED_NATIVE_CURRENCY as WETH } from 'legacy/constants/tokens'
-
import { WrapCard } from 'modules/swap/pure/EthFlow/WrappingPreview/WrapCard'
const WrappedEther = WETH[SupportedChainId.GOERLI]
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 7c7acc9a2d..ec22db099c 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,16 +1,15 @@
+import { CHAIN_INFO, WRAPPED_NATIVE_CURRENCY } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { TokenAmount } from '@cowprotocol/ui'
import { CurrencyAmount, Currency } from '@uniswap/sdk-core'
import styled from 'styled-components/macro'
-import { CHAIN_INFO } from 'legacy/constants/chainInfo'
-import { WRAPPED_NATIVE_CURRENCY } from 'legacy/constants/tokens'
import { WrappedTokenInfo } from 'legacy/state/lists/wrappedTokenInfo'
import * as styledEl from 'modules/swap/pure/EthFlow/WrappingPreview/styled'
import { CurrencyLogo } from 'common/pure/CurrencyLogo'
-import { TokenAmount } from 'common/pure/TokenAmount'
const BackupTokenImg = styled.img.attrs((attrs) => ({ ...attrs, width: '24px' }))`
filter: invert(1);
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 93b00ba3cf..e85f4b6ab5 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
@@ -1,5 +1,7 @@
import styled from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
export const WrapCardWrapper = styled.div`
${({ theme }) => theme.flexColumnNoWrap}
align-items: center;
@@ -38,14 +40,14 @@ export const WrappingPreviewContainer = styled.div`
border: 1px solid ${({ theme }) => theme.bg3};
&:nth-of-type(1) {
- background-color: ${({ theme }) => theme.bg1};
+ background-color: var(${UI.COLOR_CONTAINER_BG_01});
border-radius: 16px 0 0 16px;
border-right: 0;
}
&:nth-of-type(2) {
- color: ${({ theme }) => theme.text1};
- background-color: ${({ theme }) => theme.grey1};
+ color: var(${UI.COLOR_TEXT1});
+ background-color: var(${UI.COLOR_GREY});
border: 1px solid ${({ theme }) => theme.grey1};
border-radius: 0 16px 16px 0;
}
@@ -65,8 +67,8 @@ export const WrappingPreviewContainer = styled.div`
bottom: 0;
right: 0;
margin: auto;
- background: ${({ theme }) => theme.grey1};
- stroke: ${({ theme }) => theme.text1};
+ background: var(${UI.COLOR_GREY});
+ stroke: var(${UI.COLOR_TEXT1});
width: 32px;
height: 32px;
border-radius: 32px;
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/ReceiveAmount/styled.tsx b/apps/cowswap-frontend/src/modules/swap/pure/ReceiveAmount/styled.tsx
index 40319ea55e..94a7f7b9a4 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/ReceiveAmount/styled.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/ReceiveAmount/styled.tsx
@@ -2,6 +2,8 @@ import styled from 'styled-components/macro'
import QuestionHelper from 'legacy/components/QuestionHelper'
+import { UI } from 'common/constants/theme'
+
export const ReceiveAmountBox = styled.div`
display: flex;
justify-content: space-between;
@@ -9,7 +11,7 @@ export const ReceiveAmountBox = styled.div`
border-radius: 0 0 16px 16px;
font-size: 14px;
font-weight: 600;
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
border: 2px solid ${({ theme }) => theme.grey1};
${({ theme }) => theme.mediaWidth.upToSmall`
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/ReceiveAmountInfo/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/ReceiveAmountInfo/index.tsx
index 25cadad0bd..0618a9552f 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/ReceiveAmountInfo/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/ReceiveAmountInfo/index.tsx
@@ -1,5 +1,6 @@
import React from 'react'
+import { TokenSymbol } from '@cowprotocol/ui'
import { Currency } from '@uniswap/sdk-core'
import { Trans } from '@lingui/macro'
@@ -9,8 +10,6 @@ import { BalanceAndSubsidy } from 'legacy/hooks/useCowBalanceAndSubsidy'
import { ReceiveAmountInfo } from 'modules/swap/helpers/tradeReceiveAmount'
import { useIsEoaEthFlow } from 'modules/swap/hooks/useIsEoaEthFlow'
-import { TokenSymbol } from 'common/pure/TokenSymbol'
-
import * as styledEl from './styled'
export interface ReceiveAmountInfoTooltipProps {
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowDeadline/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowDeadline/index.cosmos.tsx
index 70882c2d7d..06633ec398 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowDeadline/index.cosmos.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowDeadline/index.cosmos.tsx
@@ -1,4 +1,4 @@
-import { MINIMUM_ETH_FLOW_DEADLINE_SECONDS } from 'legacy/constants'
+import { MINIMUM_ETH_FLOW_DEADLINE_SECONDS } from '@cowprotocol/common-const'
import { RowDeadlineContent, RowDeadlineProps } from '.'
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowDeadline/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowDeadline/index.tsx
index 53d298f009..2fd4e68630 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowDeadline/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowDeadline/index.tsx
@@ -1,8 +1,8 @@
-import { Trans } from '@lingui/macro'
+import { INPUT_OUTPUT_EXPLANATION, MINIMUM_ETH_FLOW_DEADLINE_SECONDS } from '@cowprotocol/common-const'
+import { RowFixed } from '@cowprotocol/ui'
+import { MouseoverTooltipContent } from '@cowprotocol/ui'
-import { RowFixed } from 'legacy/components/Row'
-import { MouseoverTooltipContent } from 'legacy/components/Tooltip'
-import { INPUT_OUTPUT_EXPLANATION, MINIMUM_ETH_FLOW_DEADLINE_SECONDS } from 'legacy/constants'
+import { Trans } from '@lingui/macro'
import { RowSlippageProps } from 'modules/swap/containers/Row/RowSlippage'
import { ClickableText } from 'modules/swap/pure/Row/RowSlippageContent'
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 eda944b2f3..e843ec7148 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,7 +1,7 @@
+import { COW, GNO } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { CurrencyAmount, TradeType, Price } from '@uniswap/sdk-core'
-import { COW, GNO } from 'legacy/constants/tokens'
import TradeGp from 'legacy/state/swap/TradeGp'
import { RowFeeProps } from 'modules/swap/containers/Row/RowFee'
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowFeeContent/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowFeeContent/index.tsx
index df06abd7ad..37046508e1 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowFeeContent/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowFeeContent/index.tsx
@@ -1,5 +1,5 @@
-import { RowFixed } from 'legacy/components/Row'
-import { MouseoverTooltipContent } from 'legacy/components/Tooltip'
+import { RowFixed } from '@cowprotocol/ui'
+import { MouseoverTooltipContent } from '@cowprotocol/ui'
import { StyledRowBetween, TextWrapper } from 'modules/swap/pure/Row/styled'
import { RowStyleProps, RowWithShowHelpersProps } from 'modules/swap/pure/Row/types'
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowReceivedAfterSlippageContent/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowReceivedAfterSlippageContent/index.cosmos.tsx
index 1e7b790d32..bb9e9357ed 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowReceivedAfterSlippageContent/index.cosmos.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowReceivedAfterSlippageContent/index.cosmos.tsx
@@ -1,7 +1,7 @@
+import { COW, GNO } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { CurrencyAmount, TradeType, Price, Percent } from '@uniswap/sdk-core'
-import { COW, GNO } from 'legacy/constants/tokens'
import TradeGp from 'legacy/state/swap/TradeGp'
import { RowReceivedAfterSlippageProps } from 'modules/swap/containers/Row/RowReceivedAfterSlippage'
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowReceivedAfterSlippageContent/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowReceivedAfterSlippageContent/index.tsx
index d1d772eab2..a3d6f5a7f9 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowReceivedAfterSlippageContent/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowReceivedAfterSlippageContent/index.tsx
@@ -1,17 +1,14 @@
+import { getMinimumReceivedTooltip } from '@cowprotocol/common-utils'
+import { TokenAmount, RowFixed } from '@cowprotocol/ui'
+import { MouseoverTooltipContent } from '@cowprotocol/ui'
import { CurrencyAmount, Currency, TradeType } from '@uniswap/sdk-core'
import { Trans } from '@lingui/macro'
-import { RowFixed } from 'legacy/components/Row'
-import { MouseoverTooltipContent } from 'legacy/components/Tooltip'
-import { getMinimumReceivedTooltip } from 'legacy/utils/tooltips'
-
import { RowReceivedAfterSlippageProps } from 'modules/swap/containers/Row/RowReceivedAfterSlippage'
import { RowStyleProps } from 'modules/swap/pure/Row/types'
import { StyledInfoIcon } from 'modules/swap/pure/styled'
-import { TokenAmount } from 'common/pure/TokenAmount'
-
import { StyledRowBetween, TextWrapper } from '../styled'
export interface RowReceivedAfterSlippageContentProps extends RowReceivedAfterSlippageProps {
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowSlippageContent/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowSlippageContent/index.tsx
index f3245de41e..cae8d10647 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowSlippageContent/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowSlippageContent/index.tsx
@@ -1,10 +1,10 @@
+import { INPUT_OUTPUT_EXPLANATION, MINIMUM_ETH_FLOW_SLIPPAGE, PERCENTAGE_PRECISION } from '@cowprotocol/common-const'
+import { RowFixed } from '@cowprotocol/ui'
+import { MouseoverTooltipContent } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import styled from 'styled-components/macro'
-import { RowFixed } from 'legacy/components/Row'
-import { MouseoverTooltipContent } from 'legacy/components/Tooltip'
-import { INPUT_OUTPUT_EXPLANATION, MINIMUM_ETH_FLOW_SLIPPAGE, PERCENTAGE_PRECISION } from 'legacy/constants'
-
import { RowSlippageProps } from 'modules/swap/containers/Row/RowSlippage'
import { StyledRowBetween, TextWrapper } from 'modules/swap/pure/Row/styled'
import { RowStyleProps } from 'modules/swap/pure/Row/types'
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/Row/styled.ts b/apps/cowswap-frontend/src/modules/swap/pure/Row/styled.ts
index 7be251e7e4..f8fd766a05 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/Row/styled.ts
+++ b/apps/cowswap-frontend/src/modules/swap/pure/Row/styled.ts
@@ -1,9 +1,11 @@
+import { RowBetween, RowFixed } from '@cowprotocol/ui'
+import { MouseoverTooltipContent } from '@cowprotocol/ui'
+
import { transparentize } from 'polished'
import { Text } from 'rebass'
import styled from 'styled-components/macro'
-import { RowBetween, RowFixed } from 'legacy/components/Row'
-import { MouseoverTooltipContent } from 'legacy/components/Tooltip'
+import { UI } from 'common/constants/theme'
import { RowStyleProps } from './types'
@@ -21,7 +23,7 @@ export const StyledRowBetween = styled(RowBetween)`
}
${TextWrapper} {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
font-size: ${({ fontSize = 13 }) => fontSize}px;
font-weight: ${({ fontWeight = 500 }) => fontWeight};
@@ -30,7 +32,7 @@ export const StyledRowBetween = styled(RowBetween)`
font-weight: 400;
&:hover {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
}
@@ -45,6 +47,6 @@ export const StyledRowBetween = styled(RowBetween)`
${StyledMouseoverTooltipContent} {
background-color: ${({ theme }) => theme.bg3};
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
`
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/SwapButton/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/SwapButton/index.tsx
index 7720b3b6d0..1436d521a8 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/SwapButton/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/SwapButton/index.tsx
@@ -1,5 +1,4 @@
-import { ButtonError } from 'legacy/components/Button'
-import { ButtonSize } from 'legacy/theme/enum'
+import { ButtonSize, ButtonError } from '@cowprotocol/ui'
export interface SwapButtonProps {
disabled: boolean
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.cosmos.tsx
index 1ac4344f6a..e38c510c54 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.cosmos.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.cosmos.tsx
@@ -1,9 +1,9 @@
+import { WETH_GOERLI } from '@cowprotocol/common-const'
import { CurrencyAmount } from '@uniswap/sdk-core'
import { useSelect } from 'react-cosmos/client'
-import { Field } from 'legacy/state/swap/actions'
-import { WETH_GOERLI } from 'legacy/utils/goerli/constants'
+import { Field } from 'legacy/state/types'
import { SwapButtonState } from 'modules/swap/helpers/getSwapButtonState'
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 a225e29457..8605cc9de6 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.tsx
@@ -1,26 +1,23 @@
import React, { ReactNode } from 'react'
+import { GpEther } from '@cowprotocol/common-const'
+import { genericPropsChecker } 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'
import { Trans } from '@lingui/macro'
import { Text } from 'rebass'
-import { ButtonError, ButtonPrimary } from 'legacy/components/Button'
import { GreyCard } from 'legacy/components/Card'
import { AutoColumn } from 'legacy/components/Column'
-import { AutoRow } from 'legacy/components/Row'
-import { GpEther } from 'legacy/constants/tokens'
import { WrapUnwrapCallback } from 'legacy/hooks/useWrapCallback'
-import { Field } from 'legacy/state/swap/actions'
-import { ButtonSize } from 'legacy/theme/enum'
+import { Field } from 'legacy/state/types'
import { EthFlowBanner } from 'modules/swap/containers/EthFlow/EthFlowBanner'
import { SwapButtonState } from 'modules/swap/helpers/getSwapButtonState'
import { TradeApproveButton } from 'common/containers/TradeApprove/TradeApproveButton'
-import { TokenSymbol } from 'common/pure/TokenSymbol'
-import { genericPropsChecker } from 'utils/genericPropsChecker'
import * as styledEl from './styled'
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/styled.tsx b/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/styled.tsx
index b650ca0ec7..67b300bd11 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/styled.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/styled.tsx
@@ -1,8 +1,6 @@
-import { Text } from 'rebass'
+import { ButtonSize, ButtonError, RowBetween } from '@cowprotocol/ui'
-import { ButtonError } from 'legacy/components/Button'
-import { RowBetween } from 'legacy/components/Row'
-import { ButtonSize } from 'legacy/theme/enum'
+import { Text } from 'rebass'
import { TradeLoadingButton } from 'common/pure/TradeLoadingButton'
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/index.cosmos.tsx
index aa549df0a8..bbf5431c70 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/index.cosmos.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/index.cosmos.tsx
@@ -1,7 +1,7 @@
+import { COW, GNO } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { CurrencyAmount, TradeType, Price, Percent } from '@uniswap/sdk-core'
-import { COW, GNO } from 'legacy/constants/tokens'
import TradeGp from 'legacy/state/swap/TradeGp'
import { TradeRates, TradeRatesProps } from 'modules/swap/pure/TradeRates/index'
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/index.tsx
index efc3ae3ce3..7a29e549f0 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/index.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/index.tsx
@@ -1,5 +1,6 @@
import React from 'react'
+import { genericPropsChecker } from '@cowprotocol/common-utils'
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import TradeGp from 'legacy/state/swap/TradeGp'
@@ -8,7 +9,6 @@ import { RowDeadline } from 'modules/swap/containers/Row/RowDeadline'
import { TradeBasicDetails } from 'modules/swap/containers/TradeBasicDetails'
import { RateInfoParams } from 'common/pure/RateInfo'
-import { genericPropsChecker } from 'utils/genericPropsChecker'
import * as styledEl from './styled'
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/styled.tsx b/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/styled.tsx
index 20b75dc857..9e03f75df1 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/styled.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/styled.tsx
@@ -4,6 +4,7 @@ import styled from 'styled-components/macro'
import QuestionHelper from 'legacy/components/QuestionHelper'
+import { UI } from 'common/constants/theme'
import { RateInfo } from 'common/pure/RateInfo'
export const Box = styled.div`
@@ -15,7 +16,7 @@ export const Row = styled.div`
justify-content: space-between;
font-size: 13px;
font-weight: 400;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
min-height: 24px;
gap: 3px;
@@ -33,7 +34,7 @@ export const Row = styled.div`
transition: color 0.15s ease-in-out;
&:hover {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
}
@@ -63,8 +64,8 @@ export const Discount = styled.span`
display: flex;
cursor: pointer;
padding: 2px 8px;
- background: ${({ theme }) => theme.grey1};
- color: ${({ theme }) => theme.text1};
+ background: var(${UI.COLOR_GREY});
+ color: var(${UI.COLOR_TEXT1});
border-radius: 5px;
font-weight: 400;
transition: background 0.2s ease-in-out, color 0.2s ease-in-out;
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/TradeSummary/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/swap/pure/TradeSummary/index.cosmos.tsx
index 2569881d99..e6029d9b64 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/TradeSummary/index.cosmos.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/TradeSummary/index.cosmos.tsx
@@ -1,7 +1,7 @@
+import { COW, GNO } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { CurrencyAmount, TradeType, Price, Percent } from '@uniswap/sdk-core'
-import { COW, GNO } from 'legacy/constants/tokens'
import TradeGp from 'legacy/state/swap/TradeGp'
import { TradeSummaryProps } from 'modules/swap/containers/TradeSummary'
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/banners/TwapSuggestionBanner.tsx b/apps/cowswap-frontend/src/modules/swap/pure/banners/TwapSuggestionBanner.tsx
index d8d4033eb3..76f54c9b2e 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/banners/TwapSuggestionBanner.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/banners/TwapSuggestionBanner.tsx
@@ -54,7 +54,7 @@ export function TwapSuggestionBanner({
parameterizeTradeRoute(tradeUrlParams, Routes.ADVANCED_ORDERS) + `?${TRADE_URL_SELL_AMOUNT_KEY}=${sellAmount}`
return (
-
+
Minimize price impact with TWAP
The price impact is {+priceImpact.toFixed(2)}% . Consider breaking up your order using a{' '}
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/styled.tsx b/apps/cowswap-frontend/src/modules/swap/pure/styled.tsx
index 19fe60b682..1c5c48b49a 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/styled.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/styled.tsx
@@ -1,8 +1,10 @@
+import { RowBetween } from '@cowprotocol/ui'
+
import { transparentize } from 'polished'
import { Info } from 'react-feather'
import styled from 'styled-components/macro'
-import { RowBetween } from 'legacy/components/Row'
+import { UI } from 'common/constants/theme'
export const LowerSectionWrapper = styled(RowBetween).attrs((props) => ({
...props,
@@ -26,7 +28,7 @@ export const BottomGrouping = styled.div`
div > svg,
div > svg > path {
- stroke: ${({ theme }) => theme.text2};
+ stroke: var(${UI.COLOR_TEXT2});
}
`
export const LightGreyText = styled.span`
@@ -36,7 +38,7 @@ export const LightGreyText = styled.span`
export const StyledInfoIcon = styled(Info)`
opacity: 0.5;
- stroke: ${({ theme }) => theme.text1};
+ stroke: var(${UI.COLOR_TEXT1});
line-height: 0;
vertical-align: middle;
transition: opacity 0.2s ease-in-out;
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/warnings.tsx b/apps/cowswap-frontend/src/modules/swap/pure/warnings.tsx
index c7720cf4f5..f7720bd985 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/warnings.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/warnings.tsx
@@ -1,5 +1,6 @@
import React from 'react'
+import { genericPropsChecker } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
@@ -12,10 +13,8 @@ import { CompatibilityIssuesWarning } from 'modules/trade/pure/CompatibilityIssu
import { NoImpactWarning } from 'modules/trade/pure/NoImpactWarning'
import { TradeUrlParams } from 'modules/trade/types/TradeRawState'
-import { FeatureGuard } from 'common/containers/FeatureGuard'
import { BundleTxApprovalBanner, BundleTxSafeWcBanner, BundleTxWrapBanner } from 'common/pure/InlineBanner/banners'
import { ZeroApprovalWarning } from 'common/pure/ZeroApprovalWarning'
-import { genericPropsChecker } from 'utils/genericPropsChecker'
import { TwapSuggestionBanner } from './banners/TwapSuggestionBanner'
@@ -97,15 +96,13 @@ export const SwapWarningsTop = React.memo(function (props: SwapWarningsTopProps)
)}
-
-
-
+
>
)
}, genericPropsChecker)
diff --git a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/index.ts b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/index.ts
index ba405d9814..0869204e42 100644
--- a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/index.ts
+++ b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/index.ts
@@ -25,7 +25,7 @@ export async function ethFlow(
appDataInfo,
dispatch,
orderParams: orderParamsOriginal,
- checkInFlightOrderIdExists,
+ checkEthFlowOrderExists,
addInFlightOrderId,
} = ethFlowContext
@@ -40,11 +40,7 @@ export async function ethFlow(
swapConfirmManager.sendTransaction(context.trade)
logTradeFlow('ETH FLOW', 'STEP 3: Get Unique Order Id (prevent collisions)')
- const { orderId, orderParams } = await calculateUniqueOrderId(
- orderParamsOriginal,
- contract,
- checkInFlightOrderIdExists
- )
+ const { orderId, orderParams } = await calculateUniqueOrderId(orderParamsOriginal, contract, checkEthFlowOrderExists)
try {
logTradeFlow('ETH FLOW', 'STEP 4: sign order')
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 fcb7ba2530..669903f979 100644
--- a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/mocks.ts
+++ b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/mocks.ts
@@ -1,8 +1,7 @@
+import { nativeOnChain, WRAPPED_NATIVE_CURRENCY as WETH } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { CurrencyAmount } from '@uniswap/sdk-core'
-import { nativeOnChain, WRAPPED_NATIVE_CURRENCY as WETH } from 'legacy/constants/tokens'
-
import { EthFlowActions } from 'modules/swap/containers/EthFlow/hooks/useEthFlowActions'
import { EthFlowModalContentProps } from 'modules/swap/pure/EthFlow/EthFlowModalContent'
import { BalanceChecks } from 'modules/swap/pure/EthFlow/EthFlowModalContent/EthFlowModalTopContent'
diff --git a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/steps/calculateUniqueOrderId.ts b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/steps/calculateUniqueOrderId.ts
index 7ff21788dd..66e05b9d5c 100644
--- a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/steps/calculateUniqueOrderId.ts
+++ b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/steps/calculateUniqueOrderId.ts
@@ -1,14 +1,15 @@
+import { CoWSwapEthFlow } from '@cowprotocol/abis'
+import { WRAPPED_NATIVE_CURRENCY } from '@cowprotocol/common-const'
+import { MAX_VALID_TO_EPOCH } from '@cowprotocol/common-utils'
import type { Order } from '@cowprotocol/contracts'
import { OrderSigningUtils } from '@cowprotocol/cow-sdk'
-import { CoWSwapEthFlow } from '@cowswap/abis'
import { CurrencyAmount } from '@uniswap/sdk-core'
-import { WRAPPED_NATIVE_CURRENCY } from 'legacy/constants/tokens'
import { getSignOrderParams, PostOrderParams } from 'legacy/utils/trade'
import { logTradeFlow } from 'modules/trade/utils/logger'
-import { MAX_VALID_TO_EPOCH } from 'utils/time'
+import { EthFlowOrderExistsCallback } from '../../../hooks/useCheckEthFlowOrderExists'
export interface UniqueOrderIdResult {
orderId: string
@@ -33,7 +34,7 @@ function incrementFee(params: PostOrderParams): PostOrderParams {
export async function calculateUniqueOrderId(
orderParams: PostOrderParams,
ethFlowContract: CoWSwapEthFlow,
- checkInFlightOrderIdExists: (orderId: string) => boolean
+ checkEthFlowOrderExists: EthFlowOrderExistsCallback
): Promise {
logTradeFlow('ETH FLOW', '[EthFlow::calculateUniqueOrderId] - Calculate unique order Id', orderParams)
const { chainId } = orderParams
@@ -59,11 +60,11 @@ export async function calculateUniqueOrderId(
sellAmount: orderParams.inputAmount.quotient.toString(),
fee: orderParams.feeAmount?.quotient.toString(),
}
- if (checkInFlightOrderIdExists(orderId)) {
+ if (await checkEthFlowOrderExists(orderId, orderDigest)) {
logTradeFlow('ETH FLOW', '[calculateUniqueOrderId] ❌ Collision detected: ' + orderId, logParams)
// Recursive call, increment one fee until we get an unique order Id
- return calculateUniqueOrderId(incrementFee(orderParams), ethFlowContract, checkInFlightOrderIdExists)
+ return calculateUniqueOrderId(incrementFee(orderParams), ethFlowContract, checkEthFlowOrderExists)
}
logTradeFlow('ETH FLOW', '[calculateUniqueOrderId] ✅ Order Id is Unique' + orderId, logParams)
diff --git a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/steps/signEthFlowOrderStep.ts b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/steps/signEthFlowOrderStep.ts
index 1d8f6fa53a..2f905eff00 100644
--- a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/steps/signEthFlowOrderStep.ts
+++ b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/steps/signEthFlowOrderStep.ts
@@ -1,10 +1,10 @@
+import { CoWSwapEthFlow } from '@cowprotocol/abis'
+import { calculateGasMargin } from '@cowprotocol/common-utils'
import { OrderClass, UnsignedOrder } from '@cowprotocol/cow-sdk'
-import { CoWSwapEthFlow } from '@cowswap/abis'
import { ContractTransaction } from '@ethersproject/contracts'
import { NativeCurrency } from '@uniswap/sdk-core'
import { Order } from 'legacy/state/orders/actions'
-import { calculateGasMargin } from 'legacy/utils/calculateGasMargin'
import { getSignOrderParams, mapUnsignedOrderToOrder, PostOrderParams } from 'legacy/utils/trade'
import { ETHFLOW_GAS_LIMIT_DEFAULT } from 'modules/swap/services/ethFlow/const'
diff --git a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/transactionsMocks.ts b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/transactionsMocks.ts
index ba49c9e096..aeac0d9705 100644
--- a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/transactionsMocks.ts
+++ b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/transactionsMocks.ts
@@ -1,4 +1,4 @@
-import store from 'legacy/state'
+import { cowSwapStore } from 'legacy/state'
import { addTransaction, finalizeTransaction } from 'legacy/state/enhancedTransactions/actions'
import { HashType } from 'legacy/state/enhancedTransactions/reducer'
@@ -12,7 +12,7 @@ export const ApproveErrorTxHashMock = '0x138b032570b443508a0a102f1d15949401acf2b
export function mockEthFlowPendingTxs() {
// Wrap transactions
- store.dispatch(
+ cowSwapStore.dispatch(
addTransaction({
hash: WrapPendingTxHashMock,
hashType: HashType.ETHEREUM_TX,
@@ -22,7 +22,7 @@ export function mockEthFlowPendingTxs() {
})
)
- store.dispatch(
+ cowSwapStore.dispatch(
addTransaction({
hash: WrapSuccessfulTxHashMock,
hashType: HashType.ETHEREUM_TX,
@@ -31,7 +31,7 @@ export function mockEthFlowPendingTxs() {
summary: 'Wrap 0.02 WETH to Ether',
})
)
- store.dispatch(
+ cowSwapStore.dispatch(
finalizeTransaction({
hash: WrapSuccessfulTxHashMock,
chainId: 5,
@@ -48,7 +48,7 @@ export function mockEthFlowPendingTxs() {
})
)
- store.dispatch(
+ cowSwapStore.dispatch(
addTransaction({
hash: WrapErrorTxHashMock,
hashType: HashType.ETHEREUM_TX,
@@ -57,7 +57,7 @@ export function mockEthFlowPendingTxs() {
summary: 'Wrap 0.02 WETH to Ether',
})
)
- store.dispatch(
+ cowSwapStore.dispatch(
finalizeTransaction({
hash: WrapErrorTxHashMock,
chainId: 5,
@@ -75,7 +75,7 @@ export function mockEthFlowPendingTxs() {
)
// Approve transactions
- store.dispatch(
+ cowSwapStore.dispatch(
addTransaction({
hash: ApprovePendingTxHashMock,
hashType: HashType.ETHEREUM_TX,
@@ -89,7 +89,7 @@ export function mockEthFlowPendingTxs() {
})
)
- store.dispatch(
+ cowSwapStore.dispatch(
addTransaction({
hash: ApproveSuccessfulTxHashMock,
hashType: HashType.ETHEREUM_TX,
@@ -102,7 +102,7 @@ export function mockEthFlowPendingTxs() {
summary: 'Approve GNO',
})
)
- store.dispatch(
+ cowSwapStore.dispatch(
finalizeTransaction({
hash: ApproveSuccessfulTxHashMock,
chainId: 5,
@@ -119,7 +119,7 @@ export function mockEthFlowPendingTxs() {
})
)
- store.dispatch(
+ cowSwapStore.dispatch(
addTransaction({
hash: ApproveErrorTxHashMock,
hashType: HashType.ETHEREUM_TX,
@@ -132,7 +132,7 @@ export function mockEthFlowPendingTxs() {
summary: 'Approve GNO',
})
)
- store.dispatch(
+ cowSwapStore.dispatch(
finalizeTransaction({
hash: ApproveErrorTxHashMock,
chainId: 5,
diff --git a/apps/cowswap-frontend/src/modules/swap/services/safeBundleFlow/safeBundleEthFlow.ts b/apps/cowswap-frontend/src/modules/swap/services/safeBundleFlow/safeBundleEthFlow.ts
index abcc1d9245..3186cbc225 100644
--- a/apps/cowswap-frontend/src/modules/swap/services/safeBundleFlow/safeBundleEthFlow.ts
+++ b/apps/cowswap-frontend/src/modules/swap/services/safeBundleFlow/safeBundleEthFlow.ts
@@ -1,4 +1,4 @@
-import { Erc20 } from '@cowswap/abis'
+import { Erc20 } from '@cowprotocol/abis'
import { MetaTransactionData } from '@safe-global/safe-core-sdk-types'
import { Percent } from '@uniswap/sdk-core'
diff --git a/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts b/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts
index a23c0e492f..ec49a936b3 100644
--- a/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts
+++ b/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts
@@ -1,16 +1,17 @@
-import { Percent } from '@uniswap/sdk-core'
+import { Percent, Token } from '@uniswap/sdk-core'
import { PriceImpact } from 'legacy/hooks/usePriceImpact'
import { partialOrderUpdate } from 'legacy/state/orders/utils'
import { signAndPostOrder } from 'legacy/utils/trade'
+import { handlePermit } from 'modules/permit'
import { addPendingOrderStep } from 'modules/trade/utils/addPendingOrderStep'
+import { tradeFlowAnalytics } from 'modules/trade/utils/analytics'
import { logTradeFlow } from 'modules/trade/utils/logger'
import { getSwapErrorMessage } from 'modules/trade/utils/swapErrorHelper'
import { presignOrderStep } from './steps/presignOrderStep'
-import { tradeFlowAnalytics } from '../../../trade/utils/analytics'
import { SwapFlowContext } from '../types'
export async function swapFlow(
@@ -23,12 +24,24 @@ export async function swapFlow(
return
}
- logTradeFlow('SWAP FLOW', 'STEP 2: send transaction')
- tradeFlowAnalytics.trade(input.swapFlowAnalyticsContext)
- input.swapConfirmManager.sendTransaction(input.context.trade)
-
try {
- logTradeFlow('SWAP FLOW', 'STEP 3: sign and post order')
+ logTradeFlow('SWAP FLOW', 'STEP 2: handle permit')
+ if (input.permitInfo) input.swapConfirmManager.requestPermitSignature()
+
+ input.orderParams.appData = await handlePermit({
+ appData: input.orderParams.appData,
+ inputToken: input.context.trade.inputAmount.currency as Token,
+ account: input.orderParams.account,
+ permitInfo: input.permitInfo,
+ generatePermitHook: input.generatePermitHook,
+ })
+ input.swapConfirmManager.permitSigned()
+
+ logTradeFlow('SWAP FLOW', 'STEP 3: send transaction')
+ tradeFlowAnalytics.trade(input.swapFlowAnalyticsContext)
+ input.swapConfirmManager.sendTransaction(input.context.trade)
+
+ logTradeFlow('SWAP FLOW', 'STEP 4: sign and post order')
const { id: orderId, order } = await signAndPostOrder(input.orderParams).finally(() => {
input.callbacks.closeModals()
})
@@ -45,12 +58,12 @@ export async function swapFlow(
input.dispatch
)
- logTradeFlow('SWAP FLOW', 'STEP 4: presign order (optional)')
+ logTradeFlow('SWAP FLOW', 'STEP 5: presign order (optional)')
const presignTx = await (input.flags.allowsOffchainSigning
? Promise.resolve(null)
: presignOrderStep(orderId, input.contract))
- logTradeFlow('SWAP FLOW', 'STEP 5: unhide SC order (optional)')
+ logTradeFlow('SWAP FLOW', 'STEP 6: unhide SC order (optional)')
if (presignTx) {
partialOrderUpdate(
{
@@ -65,11 +78,11 @@ export async function swapFlow(
)
}
- logTradeFlow('SWAP FLOW', 'STEP 6: show UI of the successfully sent transaction', orderId)
+ logTradeFlow('SWAP FLOW', 'STEP 7: show UI of the successfully sent transaction', orderId)
input.swapConfirmManager.transactionSent(orderId)
tradeFlowAnalytics.sign(input.swapFlowAnalyticsContext)
} catch (error: any) {
- logTradeFlow('SWAP FLOW', 'STEP 7: ERROR: ', error)
+ logTradeFlow('SWAP FLOW', 'STEP 8: ERROR: ', error)
const swapErrorMessage = getSwapErrorMessage(error)
tradeFlowAnalytics.error(error, swapErrorMessage, input.swapFlowAnalyticsContext)
diff --git a/apps/cowswap-frontend/src/modules/swap/services/swapFlow/steps/presignOrderStep.ts b/apps/cowswap-frontend/src/modules/swap/services/swapFlow/steps/presignOrderStep.ts
index 54e4735871..3705c2df45 100644
--- a/apps/cowswap-frontend/src/modules/swap/services/swapFlow/steps/presignOrderStep.ts
+++ b/apps/cowswap-frontend/src/modules/swap/services/swapFlow/steps/presignOrderStep.ts
@@ -1,9 +1,8 @@
-import { GPv2Settlement } from '@cowswap/abis'
+import { GPv2Settlement } from '@cowprotocol/abis'
+import { calculateGasMargin } from '@cowprotocol/common-utils'
import { BigNumber } from '@ethersproject/bignumber'
import { ContractTransaction } from '@ethersproject/contracts'
-import { calculateGasMargin } from 'legacy/utils/calculateGasMargin'
-
import { logTradeFlow, logTradeFlowError } from 'modules/trade/utils/logger'
// Use a 150K gas as a fallback if there's issue calculating the gas estimation (fixes some issues with some nodes failing to calculate gas costs for SC wallets)
diff --git a/apps/cowswap-frontend/src/modules/swap/services/types.ts b/apps/cowswap-frontend/src/modules/swap/services/types.ts
index e8c963faba..52d3f55a30 100644
--- a/apps/cowswap-frontend/src/modules/swap/services/types.ts
+++ b/apps/cowswap-frontend/src/modules/swap/services/types.ts
@@ -1,5 +1,4 @@
-import { GPv2Settlement, CoWSwapEthFlow } from '@cowswap/abis'
-import { Erc20, Weth } from '@cowswap/abis'
+import { CoWSwapEthFlow, Erc20, GPv2Settlement, Weth } from '@cowprotocol/abis'
import { Web3Provider } from '@ethersproject/providers'
import SafeAppsSDK from '@safe-global/safe-apps-sdk'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
@@ -11,9 +10,11 @@ import TradeGp from 'legacy/state/swap/TradeGp'
import { PostOrderParams } from 'legacy/utils/trade'
import { AppDataInfo, UploadAppDataParams } from 'modules/appData'
+import { GeneratePermitHook, IsTokenPermittableResult } from 'modules/permit'
import { SwapConfirmManager } from 'modules/swap/hooks/useSwapConfirmManager'
import { SwapFlowAnalyticsContext } from 'modules/trade/utils/analytics'
+import { EthFlowOrderExistsCallback } from '../hooks/useCheckEthFlowOrderExists'
import { FlowType } from '../hooks/useFlowContext'
export interface BaseFlowContext {
@@ -33,6 +34,7 @@ export interface BaseFlowContext {
addOrderCallback: AddOrderCallback
uploadAppData: (params: UploadAppDataParams) => void
}
+ sellTokenContract: Erc20 | null
dispatch: AppDispatch
swapFlowAnalyticsContext: SwapFlowAnalyticsContext
swapConfirmManager: SwapConfirmManager
@@ -42,12 +44,14 @@ export interface BaseFlowContext {
export type SwapFlowContext = BaseFlowContext & {
contract: GPv2Settlement
+ permitInfo: IsTokenPermittableResult
+ generatePermitHook: GeneratePermitHook
}
export type EthFlowContext = BaseFlowContext & {
contract: CoWSwapEthFlow
addTransaction: ReturnType
- checkInFlightOrderIdExists: (orderId: string) => boolean
+ checkEthFlowOrderExists: EthFlowOrderExistsCallback
addInFlightOrderId: (orderId: string) => void
}
diff --git a/apps/cowswap-frontend/src/modules/swap/state/EthFlow/updaters/EthFlowDeadlineUpdater.tsx b/apps/cowswap-frontend/src/modules/swap/state/EthFlow/updaters/EthFlowDeadlineUpdater.tsx
index d2990c1112..21ba267bc1 100644
--- a/apps/cowswap-frontend/src/modules/swap/state/EthFlow/updaters/EthFlowDeadlineUpdater.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/state/EthFlow/updaters/EthFlowDeadlineUpdater.tsx
@@ -1,12 +1,12 @@
import { useEffect, useRef } from 'react'
-import { MINIMUM_ETH_FLOW_DEADLINE_SECONDS } from 'legacy/constants'
+import { MINIMUM_ETH_FLOW_DEADLINE_SECONDS } from '@cowprotocol/common-const'
+import { loadJsonFromLocalStorage, setJsonToLocalStorage } from '@cowprotocol/common-utils'
+
import { useUserTransactionTTL } from 'legacy/state/user/hooks'
import { useIsEoaEthFlow } from 'modules/swap/hooks/useIsEoaEthFlow'
-import { loadJsonFromLocalStorage, setJsonToLocalStorage } from 'utils/localStorage'
-
import { DeadlineSettings } from './types'
const LOCAL_STORAGE_KEY = 'UserDeadlineSettings'
diff --git a/apps/cowswap-frontend/src/modules/swap/state/EthFlow/updaters/EthFlowSlippageUpdater.tsx b/apps/cowswap-frontend/src/modules/swap/state/EthFlow/updaters/EthFlowSlippageUpdater.tsx
index 3bdfa52fd9..04abefcc9e 100644
--- a/apps/cowswap-frontend/src/modules/swap/state/EthFlow/updaters/EthFlowSlippageUpdater.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/state/EthFlow/updaters/EthFlowSlippageUpdater.tsx
@@ -1,14 +1,13 @@
import { useEffect, useRef } from 'react'
+import { MINIMUM_ETH_FLOW_SLIPPAGE } from '@cowprotocol/common-const'
+import { loadJsonFromLocalStorage, setJsonToLocalStorage } from '@cowprotocol/common-utils'
import { Percent } from '@uniswap/sdk-core'
-import { MINIMUM_ETH_FLOW_SLIPPAGE } from 'legacy/constants'
import { useSetUserSlippageTolerance, useUserSlippageTolerance } from 'legacy/state/user/hooks'
import { useIsEoaEthFlow } from 'modules/swap/hooks/useIsEoaEthFlow'
-import { loadJsonFromLocalStorage, setJsonToLocalStorage } from 'utils/localStorage'
-
import { SerializedSlippage, SerializedSlippageSettings, Slippage, SlippageSettings } from './types'
const LOCAL_STORAGE_KEY = 'UserSlippageSettings'
diff --git a/apps/cowswap-frontend/src/modules/swap/state/swapConfirmAtom.ts b/apps/cowswap-frontend/src/modules/swap/state/swapConfirmAtom.ts
index c69a80f056..0bd8d19589 100644
--- a/apps/cowswap-frontend/src/modules/swap/state/swapConfirmAtom.ts
+++ b/apps/cowswap-frontend/src/modules/swap/state/swapConfirmAtom.ts
@@ -8,6 +8,7 @@ export interface SwapConfirmState {
attemptingTxn: boolean
swapErrorMessage: string | undefined
txHash: string | undefined
+ permitSignatureState: undefined | 'requested' | 'signed'
}
export const swapConfirmAtom = atom({
@@ -16,4 +17,5 @@ export const swapConfirmAtom = atom({
attemptingTxn: false,
swapErrorMessage: undefined,
txHash: undefined,
+ permitSignatureState: undefined,
})
diff --git a/apps/cowswap-frontend/src/modules/swap/state/useSwapDerivedState.ts b/apps/cowswap-frontend/src/modules/swap/state/useSwapDerivedState.ts
index 365c0a9dfd..51e0f63f12 100644
--- a/apps/cowswap-frontend/src/modules/swap/state/useSwapDerivedState.ts
+++ b/apps/cowswap-frontend/src/modules/swap/state/useSwapDerivedState.ts
@@ -3,15 +3,17 @@ import { useEffect } from 'react'
import { OrderKind } from '@cowprotocol/cow-sdk'
-import { Field } from 'legacy/state/swap/actions'
-import { useDerivedSwapInfo, useSwapState } from 'legacy/state/swap/hooks'
+import { Field } from 'legacy/state/types'
+import { TradeType } from 'modules/trade'
import { useTradeUsdAmounts } from 'modules/usdAmount'
import { useSafeMemoObject } from 'common/hooks/useSafeMemo'
import { SwapDerivedState, swapDerivedStateAtom } from './swapDerivedStateAtom'
+import { useDerivedSwapInfo, useSwapState } from '../hooks/useSwapState'
+
export function useSwapDerivedState(): SwapDerivedState {
return useAtomValue(swapDerivedStateAtom)
}
@@ -48,6 +50,7 @@ export function useFillSwapDerivedState() {
recipient,
recipientAddress,
orderKind: isSellTrade ? OrderKind.SELL : OrderKind.BUY,
+ tradeType: TradeType.SWAP,
})
useEffect(() => {
diff --git a/apps/cowswap-frontend/src/modules/tokens/hooks/useBalancesAndAllowances.ts b/apps/cowswap-frontend/src/modules/tokens/hooks/useBalancesAndAllowances.ts
index 38dcbd6df8..7d16e34069 100644
--- a/apps/cowswap-frontend/src/modules/tokens/hooks/useBalancesAndAllowances.ts
+++ b/apps/cowswap-frontend/src/modules/tokens/hooks/useBalancesAndAllowances.ts
@@ -5,7 +5,7 @@ import { BalancesAndAllowances, BalancesAndAllowancesParams } from '../types'
/**
* Return the balances and allowances of the tokens.
*
- * This hooks is different than the useOnchainBalancesAndAllowance one in the fact that the user might contain some
+ * This hook is different from the useOnchainBalancesAndAllowance one in the fact that the user might contain some
* un-commited transaction that might affect the balances.
*/
export function useBalancesAndAllowances(params: BalancesAndAllowancesParams): BalancesAndAllowances {
diff --git a/apps/cowswap-frontend/src/modules/tokens/hooks/useCurrencyBalance.ts b/apps/cowswap-frontend/src/modules/tokens/hooks/useCurrencyBalance.ts
index dfc031323e..f2a4d6ad19 100644
--- a/apps/cowswap-frontend/src/modules/tokens/hooks/useCurrencyBalance.ts
+++ b/apps/cowswap-frontend/src/modules/tokens/hooks/useCurrencyBalance.ts
@@ -2,17 +2,16 @@
import { useMemo } from 'react'
+import { nativeOnChain } from '@cowprotocol/common-const'
+import { useInterfaceMulticall } from '@cowprotocol/common-hooks'
+import { isAddress } from '@cowprotocol/common-utils'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
import JSBI from 'jsbi'
-import { nativeOnChain } from 'legacy/constants/tokens'
-import { useInterfaceMulticall } from 'legacy/hooks/useContract'
-import { isAddress } from 'legacy/utils'
-
import { useOnchainBalances } from 'modules/tokens'
import { TokenAmounts } from 'modules/tokens'
-import { useWalletInfo } from 'modules/wallet'
import { useSingleContractMultipleData } from 'lib/hooks/multicall'
diff --git a/apps/cowswap-frontend/src/modules/tokens/hooks/useEnoughBalance.ts b/apps/cowswap-frontend/src/modules/tokens/hooks/useEnoughBalance.ts
index cdadded320..e3fb3eeb8e 100644
--- a/apps/cowswap-frontend/src/modules/tokens/hooks/useEnoughBalance.ts
+++ b/apps/cowswap-frontend/src/modules/tokens/hooks/useEnoughBalance.ts
@@ -1,8 +1,7 @@
+import { isEnoughAmount, getAddress } from '@cowprotocol/common-utils'
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
import useNativeCurrency from 'lib/hooks/useNativeCurrency'
-import { getAddress } from 'utils/getAddress'
-import { isEnoughAmount } from 'utils/isEnoughAmount'
import { useBalancesAndAllowances } from './useBalancesAndAllowances'
import { useCurrencyBalances } from './useCurrencyBalance'
@@ -26,12 +25,19 @@ export interface UseEnoughBalanceParams {
checkAllowanceAddress?: string
}
+export type UseEnoughBalanceAndAllowanceResult = {
+ enoughBalance: boolean | undefined
+ enoughAllowance: boolean | undefined
+}
+
+const DEFAULT_BALANCE_AND_ALLOWANCE = { enoughBalance: undefined, enoughAllowance: undefined }
+
/**
* Check if the account has enough balance and optionally allowance
- * @param params Parameters to check balance and optionally the allowance
- * @returns true if the account has enough balance (and allowance if it applies)
+ * @param params UseEnoughBalanceParams to check balance and optionally the allowance
+ * @returns UseEnoughBalanceAndAllowanceResult
*/
-export function useEnoughBalanceAndAllowance(params: UseEnoughBalanceParams): boolean | undefined {
+export function useEnoughBalanceAndAllowance(params: UseEnoughBalanceParams): UseEnoughBalanceAndAllowanceResult {
const { account, amount, checkAllowanceAddress } = params
const isNativeCurrency = amount?.currency.isNative
const token = amount?.currency.wrapped
@@ -75,11 +81,11 @@ export interface EnoughBalanceParams extends Omit
+
+
+ ),
+ importList: (
+
+
+
+ ),
+ loadedLists: (
+
+
+
+ ),
+}
+
+export default Fixtures
diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/index.tsx
new file mode 100644
index 0000000000..2aa322a3d6
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/index.tsx
@@ -0,0 +1,56 @@
+import * as styledEl from './styled'
+
+import { PrimaryInput, PrimaryInputBox } from '../../pure/commonElements'
+import { ImportTokenListItem } from '../../pure/ImportTokenListItem'
+import { LoadedTokenListItem } from '../../pure/LoadedTokenListItem'
+import { TokenListItem } from '../../pure/TokenListItem'
+import { TokenList } from '../../types'
+
+export interface ManageListsProps {
+ lists: TokenList[]
+ loadedLists?: TokenList[]
+ listsToImport?: TokenList[]
+}
+
+export function ManageLists(props: ManageListsProps) {
+ const { lists, loadedLists, listsToImport } = props
+
+ const viewList = (id: string) => {
+ console.log('TODO viewList', id)
+ }
+
+ const removeList = (id: string) => {
+ console.log('TODO removeList', id)
+ }
+
+ const importList = (list: TokenList) => {
+ console.log('TODO importList', list.id)
+ }
+
+ return (
+
+
+
+
+ {!!loadedLists?.length && (
+
+ {loadedLists.map((list) => (
+
+ ))}
+
+ )}
+ {!!listsToImport?.length && (
+
+ {listsToImport.map((list) => (
+
+ ))}
+
+ )}
+
+ {lists.map((list) => (
+
+ ))}
+
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/styled.ts
new file mode 100644
index 0000000000..f84c70adc6
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/styled.ts
@@ -0,0 +1,16 @@
+import styled from 'styled-components/macro'
+
+import { UI } from 'common/constants/theme'
+
+export const Wrapper = styled.div`
+ display: block;
+ width: 100%;
+`
+
+export const ListsContainer = styled.div`
+ padding-bottom: 20px;
+`
+
+export const ImportListsContainer = styled.div`
+ border-bottom: 1px solid var(${UI.COLOR_BORDER});
+`
diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/index.cosmos.tsx
new file mode 100644
index 0000000000..7df1d8115c
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/index.cosmos.tsx
@@ -0,0 +1,19 @@
+import styled from 'styled-components/macro'
+
+import { customTokensMock, listsMock } from '../../mocks'
+
+import { ManageListsAndTokens } from './index'
+
+const Wrapper = styled.div`
+ width: 450px;
+`
+
+const Fixtures = {
+ default: (
+
+
+
+ ),
+}
+
+export default Fixtures
diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/index.tsx
new file mode 100644
index 0000000000..dc8d6234b7
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/index.tsx
@@ -0,0 +1,44 @@
+import { useState } from 'react'
+
+import * as styledEl from './styled'
+
+import { ModalHeader } from '../../pure/ModalHeader'
+import { TokenList, TokenWithLogo } from '../../types'
+import { ManageLists } from '../ManageLists'
+import { ManageTokens } from '../ManageTokens'
+
+export interface ManageListsAndTokensProps {
+ lists: TokenList[]
+ customTokens: TokenWithLogo[]
+}
+
+export function ManageListsAndTokens(props: ManageListsAndTokensProps) {
+ const { lists, customTokens } = props
+
+ const [currentTab, setCurrentTab] = useState<'tokens' | 'lists'>('lists')
+
+ const onBack = () => {
+ console.log('TODO onBack')
+ }
+
+ const onClose = () => {
+ console.log('TODO onClose')
+ }
+
+ return (
+
+
+ Manage
+
+
+ setCurrentTab('lists')}>
+ Lists
+
+ setCurrentTab('tokens')}>
+ Tokens
+
+
+ {currentTab === 'lists' ? : }
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/styled.ts
new file mode 100644
index 0000000000..bc39147ac1
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/styled.ts
@@ -0,0 +1,37 @@
+import styled from 'styled-components/macro'
+
+import { UI } from 'common/constants/theme'
+
+import { blankButtonMixin } from '../../pure/commonElements'
+
+export const Wrapper = styled.div`
+ display: block;
+ width: 100%;
+ background: var(${UI.COLOR_CONTAINER_BG_01});
+ border-radius: 20px;
+`
+
+export const TabsContainer = styled.div`
+ display: flex;
+ flex-direction: row;
+ flex-shrink: 0;
+ margin-top: 10px;
+
+ > button {
+ width: 50%;
+ }
+`
+
+export const Tab = styled.button<{ active$: boolean }>`
+ ${blankButtonMixin};
+
+ color: var(${UI.COLOR_TEXT1});
+ opacity: ${({ active$ }) => (active$ ? 1 : 0.5)};
+ padding: 10px;
+ font-size: 16px;
+ font-weight: 600;
+
+ &:hover {
+ color: var(${UI.COLOR_TEXT2});
+ }
+`
diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/ManageTokens/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageTokens/index.tsx
new file mode 100644
index 0000000000..c35b48b186
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageTokens/index.tsx
@@ -0,0 +1,67 @@
+import { ExplorerDataType, getExplorerLink } from '@cowprotocol/common-utils'
+import { TokenSymbol } from '@cowprotocol/ui'
+
+import { ExternalLink, Trash } from 'react-feather'
+
+import * as styledEl from './styled'
+
+import { PrimaryInput, PrimaryInputBox } from '../../pure/commonElements'
+import { TokenLogo } from '../../pure/TokenLogo'
+import { TokenWithLogo } from '../../types'
+
+export interface ManageTokensProps {
+ tokens: TokenWithLogo[]
+}
+
+export function ManageTokens(props: ManageTokensProps) {
+ const { tokens } = props
+
+ const clearAll = () => {
+ console.log('TODO clearAll')
+ }
+
+ const removeToken = (token: TokenWithLogo) => {
+ console.log('TODO removeToken', token.symbol)
+ }
+
+ return (
+
+
+
+
+
+
+ {tokens.length} Custom Tokens
+ Clear all
+
+
+ {tokens.map((token) => {
+ return (
+
+
+
+
+
+
+
removeToken(token)}>
+
+
+
+
+
+
+
+
+
+ )
+ })}
+
+
Tip: Custom tokens are stored locally in your browser
+
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/ManageTokens/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageTokens/styled.ts
new file mode 100644
index 0000000000..6586717106
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageTokens/styled.ts
@@ -0,0 +1,54 @@
+import styled from 'styled-components/macro'
+
+import { UI } from 'common/constants/theme'
+
+import { blankButtonMixin } from '../../pure/commonElements'
+
+const RowBox = styled.div`
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+`
+
+export const Header = styled(RowBox)`
+ padding: 20px;
+`
+
+export const Title = styled.div`
+ font-weight: 600;
+ opacity: 0.65;
+`
+
+export const LinkButton = styled.button`
+ ${blankButtonMixin};
+
+ font-size: 16px;
+ font-weight: 500;
+ color: var(${UI.COLOR_LINK});
+ margin-left: 10px;
+
+ &:hover {
+ opacity: 0.8;
+ }
+`
+
+export const TokenItem = styled(RowBox)`
+ padding: 0 20px;
+ margin-bottom: 20px;
+`
+
+export const TokenInfo = styled(RowBox)`
+ gap: 10px;
+ font-weight: 600;
+`
+
+export const TipText = styled.div`
+ font-size: 13px;
+ font-weight: 500;
+ color: var(${UI.COLOR_LINK});
+ text-align: center;
+ padding: 20px 0;
+ border-top: 1px solid var(${UI.COLOR_GREY});
+ margin-top: 20px;
+`
diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.cosmos.tsx
new file mode 100644
index 0000000000..651c415fb3
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.cosmos.tsx
@@ -0,0 +1,61 @@
+import { getRandomInt } from '@cowprotocol/common-utils'
+import { CurrencyAmount } from '@uniswap/sdk-core'
+import { Currency } from '@uniswap/sdk-core'
+
+import styled from 'styled-components/macro'
+
+import { allTokensMock, favouriteTokensMock } from '../../mocks'
+
+import { SelectTokenModal } from './index'
+
+const Wrapper = styled.div`
+ width: 450px;
+`
+
+const selectedToken = favouriteTokensMock[0]
+
+const balances = allTokensMock.reduce<{ [key: string]: CurrencyAmount }>((acc, token) => {
+ acc[token.address.toLowerCase()] = CurrencyAmount.fromRawAmount(
+ token,
+ getRandomInt(20_000, 120_000_000) * 10 ** token.decimals
+ )
+
+ return acc
+}, {})
+
+const defaultProps = {
+ selectedToken,
+ balances,
+ allTokens: allTokensMock,
+ favouriteTokens: favouriteTokensMock,
+}
+
+const Fixtures = {
+ default: (
+
+
+
+ ),
+ importByAddress: (
+
+
+
+ ),
+ NoTokenFound: (
+
+
+
+ ),
+ searchFromInactiveLists: (
+
+
+
+ ),
+ searchFromExternalSources: (
+
+
+
+ ),
+}
+
+export default Fixtures
diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.tsx
new file mode 100644
index 0000000000..92defb25f7
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.tsx
@@ -0,0 +1,147 @@
+import { useEffect, useMemo, useState } from 'react'
+
+import { useDebounce, useNetworkName } from '@cowprotocol/common-hooks'
+import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
+
+import { Edit, X } from 'react-feather'
+
+import { searchToken, TokenSearchSource } from './searchToken'
+import * as styledEl from './styled'
+
+import { AllTokensList } from '../../pure/AllTokensList'
+import { IconButton } from '../../pure/commonElements'
+import { FavouriteTokensList } from '../../pure/FavouriteTokensList'
+import { ImportTokenItem } from '../../pure/ImportTokenItem'
+import { TokenSourceTitle } from '../../pure/TokenSourceTitle'
+import { TokenWithLogo } from '../../types'
+export interface SelectTokenModalProps {
+ allTokens: TokenWithLogo[]
+ favouriteTokens: TokenWithLogo[]
+ balances: { [key: string]: CurrencyAmount }
+ selectedToken?: TokenWithLogo
+ defaultInputValue?: string
+}
+
+export function SelectTokenModal(props: SelectTokenModalProps) {
+ const { defaultInputValue = '', favouriteTokens, allTokens, selectedToken, balances } = props
+
+ const networkName = useNetworkName()
+
+ const [isSearchInProgress, setIsSearchInProgress] = useState(false)
+ const [inputValue, setInputValue] = useState(defaultInputValue)
+ const debouncedInputValue = useDebounce(inputValue, 500)
+
+ const [tokensFromBlockChain, setTokensFromBlockChain] = useState([])
+ const [tokensFromInactiveLists, setTokensFromInactiveLists] = useState([])
+ const [tokensFromExternal, setTokensFromExternal] = useState([])
+
+ const importToken = (token: TokenWithLogo) => {
+ console.log('TODO: import token', token)
+ }
+
+ const isTokenNotFound = useMemo(() => {
+ if (isSearchInProgress || !debouncedInputValue) return false
+
+ return tokensFromExternal.length === 0 && tokensFromBlockChain.length === 0 && tokensFromInactiveLists.length === 0
+ }, [debouncedInputValue, isSearchInProgress, tokensFromBlockChain, tokensFromInactiveLists, tokensFromExternal])
+
+ useEffect(() => {
+ if (!debouncedInputValue) return
+
+ setIsSearchInProgress(true)
+ setTokensFromBlockChain([])
+ setTokensFromInactiveLists([])
+ setTokensFromExternal([])
+
+ searchToken(debouncedInputValue)
+ .then((result) => {
+ if (!result) {
+ return
+ }
+
+ const { source, tokens } = result
+
+ if (source === TokenSearchSource.Blockchain) {
+ setTokensFromBlockChain(tokens)
+ return
+ }
+ if (source === TokenSearchSource.InactiveList) {
+ setTokensFromInactiveLists(tokens)
+ return
+ }
+ if (source === TokenSearchSource.External) {
+ setTokensFromExternal(tokens)
+ return
+ }
+ })
+ .finally(() => {
+ setIsSearchInProgress(false)
+ })
+ }, [debouncedInputValue])
+
+ return (
+
+
+ Select a token
+
+
+
+
+
+ setInputValue(e.target.value)}
+ type="text"
+ placeholder="Search name or past address"
+ />
+
+
+
+
+ {isTokenNotFound && (
+ No tokens found for this name in {networkName}
+ )}
+ {tokensFromBlockChain.length > 0 && (
+
+ {tokensFromBlockChain.map((token) => {
+ return
+ })}
+
+ )}
+ {tokensFromInactiveLists.length > 0 && (
+
+
+ Expanded results from inactive Token Lists
+
+
+ {tokensFromInactiveLists.map((token) => {
+ return
+ })}
+
+
+ )}
+ {tokensFromExternal.length > 0 && (
+
+
+ Additional Results from External Sources
+
+
+ {tokensFromExternal.map((token) => {
+ return
+ })}
+
+
+ )}
+ {!debouncedInputValue && (
+
+ )}
+
+
+ Manage Token Lists
+
+
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/mocks.ts b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/mocks.ts
new file mode 100644
index 0000000000..77ed5e8e8e
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/mocks.ts
@@ -0,0 +1,77 @@
+import { TokenWithLogo } from '../../types'
+
+export const allTokensMock: TokenWithLogo[] = [
+ {
+ name: 'Gnosis',
+ chainId: 5,
+ symbol: 'GNO',
+ decimals: 18,
+ address: '0x02abbdbaaa7b1bb64b5c878f7ac17f8dda169532',
+ logoURI:
+ 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6810e776880C02933D47DB1b9fc05908e5386b96/logo.png',
+ },
+ {
+ name: 'Basic Attention Token',
+ chainId: 5,
+ symbol: 'BAT',
+ decimals: 18,
+ address: '0x70cBa46d2e933030E2f274AE58c951C800548AeF',
+ logoURI:
+ 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x0D8775F648430679A709E98d2b0Cb6250d2887EF/logo.png',
+ },
+ {
+ name: 'CoW Protocol Token',
+ chainId: 5,
+ symbol: 'COW',
+ decimals: 18,
+ address: '0x91056D4A53E1faa1A84306D4deAEc71085394bC8',
+ logoURI: 'https://gnosis.mypinata.cloud/ipfs/Qme9B6jRpGtZsRFcPjHvA5T4ugFuL4c3SzWfxyMPa59AMo',
+ },
+ {
+ name: 'USD Coin',
+ chainId: 5,
+ symbol: 'USDC',
+ decimals: 6,
+ address: '0xD87Ba7A50B2E7E660f678A895E4B72E7CB4CCd9C',
+ logoURI:
+ 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png',
+ },
+ {
+ name: 'DAI',
+ chainId: 5,
+ symbol: 'DAI',
+ decimals: 18,
+ address: '0xdc31Ee1784292379Fbb2964b3B9C4124D8F89C60',
+ logoURI:
+ 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png',
+ },
+ {
+ name: '0x',
+ chainId: 5,
+ symbol: 'ZRX',
+ decimals: 18,
+ address: '0xe4E81Fa6B16327D4B78CFEB83AAdE04bA7075165',
+ logoURI:
+ 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png',
+ },
+].map((item) => new TokenWithLogo(item.logoURI, item.chainId, item.address, item.decimals, item.symbol, item.name))
+
+export const favouriteTokensMock: TokenWithLogo[] = [
+ {
+ name: 'Basic Attention Token',
+ chainId: 5,
+ symbol: 'BAT',
+ decimals: 18,
+ address: '0x70cBa46d2e933030E2f274AE58c951C800548AeF',
+ logoURI:
+ 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x0D8775F648430679A709E98d2b0Cb6250d2887EF/logo.png',
+ },
+ {
+ name: 'Polymath Network',
+ chainId: 5,
+ symbol: 'POLY',
+ decimals: 18,
+ address: '0x9e32c0EfF886B6Ccae99350Fd5e7002dCED55F15',
+ logoURI: 'https://assets.coingecko.com/coins/images/2784/thumb/inKkF01.png?1605007034',
+ },
+].map((item) => new TokenWithLogo(item.logoURI, item.chainId, item.address, item.decimals, item.symbol, item.name))
diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/searchToken.ts b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/searchToken.ts
new file mode 100644
index 0000000000..04623a4139
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/searchToken.ts
@@ -0,0 +1,55 @@
+import { TokenWithLogo } from '../../types'
+
+export enum TokenSearchSource {
+ Blockchain = 'Blockchain',
+ External = 'External',
+ InactiveList = 'InactiveList',
+}
+
+type TokenSearchResult = {
+ source: TokenSearchSource
+ tokens: TokenWithLogo[]
+}
+
+// TODO: implement search
+export async function searchToken(input: string): Promise {
+ if (input === '0x252d98fab648203aa33310721bbbddfa8f1b6587') {
+ return {
+ source: TokenSearchSource.Blockchain,
+ tokens: [new TokenWithLogo(undefined, 5, '0x252d98fab648203aa33310721bbbddfa8f1b6587', 18, 'GSUc', 'GSU Coin')],
+ }
+ }
+ if (input === 'cDAI') {
+ return {
+ source: TokenSearchSource.InactiveList,
+ tokens: [
+ new TokenWithLogo(undefined, 5, '0x822397d9a55d0fefd20F5c4bCaB33C5F65bd28Eb', 6, 'cDAI', 'Compound DAI'),
+ ],
+ }
+ }
+ if (input === 'Coo') {
+ return {
+ source: TokenSearchSource.External,
+ tokens: [
+ new TokenWithLogo(
+ 'https://etherscan.io/token/images/indexcoop_new_32.png',
+ 5,
+ '0x0954906da0Bf32d5479e25f46056d22f08464cab',
+ 18,
+ 'INDEX',
+ 'Index DAI'
+ ),
+ new TokenWithLogo(
+ 'https://etherscan.io/token/images/ETH2x-FLI_32.png',
+ 5,
+ '0xAa6E8127831c9DE45ae56bB1b0d4D4Da6e5665BD',
+ 18,
+ 'ETH2x-FLI',
+ 'ETH 2x Flexible Leverage Index'
+ ),
+ ],
+ }
+ }
+
+ return undefined
+}
diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/styled.ts
new file mode 100644
index 0000000000..dc00bb5fb7
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/styled.ts
@@ -0,0 +1,81 @@
+import styled from 'styled-components/macro'
+
+import { UI } from 'common/constants/theme'
+
+import { blankButtonMixin } from '../../pure/commonElements'
+
+export const Wrapper = styled.div`
+ display: flex;
+ flex-direction: column;
+ background: var(${UI.COLOR_CONTAINER_BG_01});
+ border-radius: 20px;
+`
+
+export const Row = styled.div`
+ margin: 0 20px 15px 20px;
+`
+
+export const Header = styled.div`
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ padding: 20px 20px 0 20px;
+ margin-bottom: 15px;
+
+ > h3 {
+ font-size: 16px;
+ font-weight: 500;
+ margin: 0;
+ }
+`
+
+export const SearchInput = styled.input`
+ width: 100%;
+ outline: none;
+ border-radius: 20px;
+ color: var(${UI.COLOR_TEXT1});
+ padding: 16px;
+ border: 1px solid var(${UI.COLOR_GREY});
+ -webkit-appearance: none;
+ transition: border 100ms;
+ background: transparent;
+
+ font-size: 18px;
+
+ ::placeholder {
+ color: var(${UI.COLOR_LINK});
+ }
+
+ :focus {
+ border: 1px solid var(${UI.COLOR_CONTAINER_BG_02});
+ outline: none;
+ }
+`
+
+export const ActionButton = styled.button`
+ ${blankButtonMixin};
+
+ display: flex;
+ width: 100%;
+ align-items: center;
+ flex-direction: row;
+ justify-content: center;
+ gap: 10px;
+ cursor: pointer;
+ padding: 20px 0;
+ margin: 0;
+ font-size: 16px;
+ font-weight: 500;
+ color: var(${UI.COLOR_TEXT1});
+
+ &:hover {
+ opacity: 0.7;
+ }
+`
+
+export const TokenNotFound = styled.div`
+ color: var(${UI.COLOR_LINK});
+ font-weight: 500;
+ padding: 10px 0;
+ text-align: center;
+`
diff --git a/apps/cowswap-frontend/src/modules/tokensList/mocks.ts b/apps/cowswap-frontend/src/modules/tokensList/mocks.ts
new file mode 100644
index 0000000000..016c5e101e
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/mocks.ts
@@ -0,0 +1,130 @@
+import { TokenList, TokenWithLogo } from './types'
+
+export const allTokensMock: TokenWithLogo[] = [
+ {
+ name: 'Gnosis',
+ chainId: 5,
+ symbol: 'GNO',
+ decimals: 18,
+ address: '0x02abbdbaaa7b1bb64b5c878f7ac17f8dda169532',
+ logoURI:
+ 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6810e776880C02933D47DB1b9fc05908e5386b96/logo.png',
+ },
+ {
+ name: 'Basic Attention Token',
+ chainId: 5,
+ symbol: 'BAT',
+ decimals: 18,
+ address: '0x70cBa46d2e933030E2f274AE58c951C800548AeF',
+ logoURI:
+ 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x0D8775F648430679A709E98d2b0Cb6250d2887EF/logo.png',
+ },
+ {
+ name: 'CoW Protocol Token',
+ chainId: 5,
+ symbol: 'COW',
+ decimals: 18,
+ address: '0x91056D4A53E1faa1A84306D4deAEc71085394bC8',
+ logoURI: 'https://gnosis.mypinata.cloud/ipfs/Qme9B6jRpGtZsRFcPjHvA5T4ugFuL4c3SzWfxyMPa59AMo',
+ },
+ {
+ name: 'USD Coin',
+ chainId: 5,
+ symbol: 'USDC',
+ decimals: 6,
+ address: '0xD87Ba7A50B2E7E660f678A895E4B72E7CB4CCd9C',
+ logoURI:
+ 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png',
+ },
+ {
+ name: 'DAI',
+ chainId: 5,
+ symbol: 'DAI',
+ decimals: 18,
+ address: '0xdc31Ee1784292379Fbb2964b3B9C4124D8F89C60',
+ logoURI:
+ 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png',
+ },
+ {
+ name: '0x',
+ chainId: 5,
+ symbol: 'ZRX',
+ decimals: 18,
+ address: '0xe4E81Fa6B16327D4B78CFEB83AAdE04bA7075165',
+ logoURI:
+ 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png',
+ },
+].map((item) => new TokenWithLogo(item.logoURI, item.chainId, item.address, item.decimals, item.symbol, item.name))
+
+export const favouriteTokensMock: TokenWithLogo[] = [
+ {
+ name: 'Basic Attention Token',
+ chainId: 5,
+ symbol: 'BAT',
+ decimals: 18,
+ address: '0x70cBa46d2e933030E2f274AE58c951C800548AeF',
+ logoURI:
+ 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x0D8775F648430679A709E98d2b0Cb6250d2887EF/logo.png',
+ },
+ {
+ name: 'Polymath Network',
+ chainId: 5,
+ symbol: 'POLY',
+ decimals: 18,
+ address: '0x9e32c0EfF886B6Ccae99350Fd5e7002dCED55F15',
+ logoURI: 'https://assets.coingecko.com/coins/images/2784/thumb/inKkF01.png?1605007034',
+ },
+].map((item) => new TokenWithLogo(item.logoURI, item.chainId, item.address, item.decimals, item.symbol, item.name))
+
+export const customTokensMock: TokenWithLogo[] = [
+ {
+ name: 'Tether USD',
+ chainId: 5,
+ symbol: 'USDT',
+ decimals: 6,
+ address: '0x7b77F953e703E80CD97F6911385c0b1ceabC96Bc',
+ logoURI: undefined,
+ },
+ {
+ name: 'Euro Coin',
+ chainId: 5,
+ symbol: 'EUROC',
+ decimals: 6,
+ address: '0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c',
+ logoURI:
+ 'https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c/logo.png',
+ },
+].map((item) => new TokenWithLogo(item.logoURI, item.chainId, item.address, item.decimals, item.symbol, item.name))
+
+export const listsMock: TokenList[] = [
+ {
+ id: '1',
+ name: 'CowSwap Goerli',
+ url: 'https://tokenlists.org/token-list?url=https://raw.githubusercontent.com/cowprotocol/cowswap/develop/apps/cowswap-frontend/src/tokens/goerli-token-list.json',
+ logoUrl: 'https://gnosis.mypinata.cloud/ipfs/Qme9B6jRpGtZsRFcPjHvA5T4ugFuL4c3SzWfxyMPa59AMo',
+ tokensCount: 7,
+ enabled: true,
+ version: 'v0.0.0',
+ },
+ {
+ id: '2',
+ name: 'Compound',
+ url: 'https://tokenlists.org/token-list?url=https://raw.githubusercontent.com/compound-finance/token-list/master/compound.tokenlist.json',
+ logoUrl: 'https://raw.githubusercontent.com/compound-finance/token-list/master/assets/compound-interface.svg',
+ tokensCount: 16,
+ enabled: false,
+ version: 'v0.2.1',
+ },
+]
+
+export const importListsMock: TokenList[] = [
+ {
+ id: '4',
+ name: 'CoW Swap',
+ url: 'https://files.cow.fi/tokens/CowSwap.json',
+ logoUrl: 'https://raw.githubusercontent.com/cowprotocol/token-lists/main/src/public/images/list-logo.png',
+ tokensCount: 113,
+ enabled: true,
+ version: 'v0.0.0',
+ },
+]
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/index.tsx
new file mode 100644
index 0000000000..a687a0b832
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/index.tsx
@@ -0,0 +1,34 @@
+import { TokenAmount } from '@cowprotocol/ui'
+import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
+
+import * as styledEl from './styled'
+
+import { TokenWithLogo } from '../../types'
+import { TokenInfo } from '../TokenInfo'
+
+export interface AllTokensListProps {
+ tokens: TokenWithLogo[]
+ selectedToken?: TokenWithLogo
+ balances: { [key: string]: CurrencyAmount }
+}
+
+export function AllTokensList(props: AllTokensListProps) {
+ const { tokens, selectedToken, balances } = props
+
+ return (
+
+ {tokens.map((token) => {
+ const isTokenSelected = token.address.toLowerCase() === selectedToken?.address.toLowerCase()
+
+ return (
+
+
+
+
+
+
+ )
+ })}
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/styled.ts
new file mode 100644
index 0000000000..27b207ebf1
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/styled.ts
@@ -0,0 +1,33 @@
+import styled from 'styled-components/macro'
+
+import { UI } from 'common/constants/theme'
+
+export const Wrapper = styled.div`
+ border-top: 1px solid var(${UI.COLOR_BORDER});
+ border-bottom: 1px solid var(${UI.COLOR_BORDER});
+`
+
+export const TokenItem = styled.button`
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ width: 100%;
+ background: none;
+ border: 0;
+ outline: none;
+ color: var(${UI.COLOR_TEXT1});
+ cursor: pointer;
+ font-size: 16px;
+ padding: 10px 20px;
+ margin-bottom: 10px;
+ opacity: ${({ disabled }) => (disabled ? 0.5 : 1)};
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+
+ &:hover {
+ background-color: ${({ disabled }) => !disabled && `var(${UI.COLOR_GREY})`};
+ }
+`
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/FavouriteTokensList/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/FavouriteTokensList/index.tsx
new file mode 100644
index 0000000000..cecb000792
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/FavouriteTokensList/index.tsx
@@ -0,0 +1,37 @@
+import { TokenSymbol } from '@cowprotocol/ui'
+
+import { InfoIcon } from 'legacy/components/InfoIcon'
+
+import * as styledEl from './styled'
+
+import { TokenWithLogo } from '../../types'
+
+export interface FavouriteTokensListProps {
+ tokens: TokenWithLogo[]
+ selectedToken?: TokenWithLogo
+}
+
+export function FavouriteTokensList(props: FavouriteTokensListProps) {
+ const { tokens, selectedToken } = props
+
+ return (
+
+
+ Favourite tokens
+
+
+
+ {tokens.map((token) => {
+ const isTokenSelected = token.address.toLowerCase() === selectedToken?.address.toLowerCase()
+
+ return (
+
+
+
+
+ )
+ })}
+
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/FavouriteTokensList/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/FavouriteTokensList/styled.ts
new file mode 100644
index 0000000000..614464bcf1
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/FavouriteTokensList/styled.ts
@@ -0,0 +1,53 @@
+import styled from 'styled-components/macro'
+
+import { UI } from 'common/constants/theme'
+
+export const Header = styled.div`
+ display: flex;
+ gap: 5px;
+ flex-direction: row;
+ align-items: center;
+
+ > h4 {
+ font-size: 14px;
+ font-weight: 500;
+ margin: 0;
+ }
+`
+
+export const TokensList = styled.div`
+ margin: 10px 0;
+`
+
+export const TokensItem = styled.button`
+ display: inline-flex;
+ flex-direction: row;
+ align-items: center;
+ gap: 6px;
+ justify-content: center;
+ min-width: 140px;
+ margin: 5px 5px 5px 0;
+ background: none;
+ outline: none;
+ padding: 6px 0;
+ border-radius: 10px;
+ color: var(${UI.COLOR_TEXT1});
+ border: 1px solid var(${UI.COLOR_GREY});
+ font-weight: 500;
+ font-size: 16px;
+ cursor: ${({ disabled }) => (disabled ? '' : 'pointer')};
+ background-color: ${({ theme, disabled }) => disabled && theme.bg3};
+ opacity: ${({ disabled }) => (disabled ? 0.5 : 1)};
+
+ :hover {
+ background-color: ${({ theme, disabled }) => !disabled && theme.bg4};
+ }
+
+ > img {
+ --size: 24px;
+ width: var(--size);
+ height: var(--size);
+ border-radius: 50%;
+ background: var(${UI.COLOR_LIGHT_BLUE});
+ }
+`
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/index.cosmos.tsx
new file mode 100644
index 0000000000..c12de15cad
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/index.cosmos.tsx
@@ -0,0 +1,24 @@
+import styled from 'styled-components/macro'
+
+import { importListsMock } from '../../mocks'
+
+import { ImportListModal } from './index'
+
+const Wrapper = styled.div`
+ width: 450px;
+`
+
+const Fixtures = {
+ default: (
+
+ console.log('onBack')}
+ onClose={() => console.log('onClose')}
+ onImport={() => console.log('onImport')}
+ />
+
+ ),
+}
+
+export default Fixtures
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/index.tsx
new file mode 100644
index 0000000000..7be3afa732
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/index.tsx
@@ -0,0 +1,65 @@
+import { useState } from 'react'
+
+import { ButtonPrimary } from '@cowprotocol/ui'
+
+import { AlertTriangle } from 'react-feather'
+
+import * as styledEl from './styled'
+
+import { TokenList } from '../../types'
+import { ModalHeader } from '../ModalHeader'
+import { TokenLogo } from '../TokenLogo'
+
+export interface ImportListModalProps {
+ list: TokenList
+ onImport(): void
+ onBack(): void
+ onClose(): void
+}
+
+export function ImportListModal(props: ImportListModalProps) {
+ const { list, onBack, onClose, onImport } = props
+
+ const [isAccepted, setIsAccepted] = useState(false)
+
+ return (
+
+
+ Import List
+
+
+
+
+
+ {list.name} · {list.tokensCount} tokens
+
+
+ {list.url}
+
+
+
+
+
+ Import at your own risk
+
+ By adding this list you are implicitly trusting that the data is correct. Anyone can create a list, including
+ creating fake versions of existing lists and lists that claim to represent projects that do not have one.
+
+
+ If you purchase a token from this list, you may not be able to sell it back.
+
+
+
+ setIsAccepted((state) => !state)} />
+ I understand
+
+
+
+
+
+ Import
+
+
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/styled.ts
new file mode 100644
index 0000000000..d5d4221900
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/styled.ts
@@ -0,0 +1,50 @@
+import styled from 'styled-components/macro'
+
+import { UI } from 'common/constants/theme'
+
+export const Wrapper = styled.div`
+ display: block;
+ width: 100%;
+ background: var(${UI.COLOR_CONTAINER_BG_01});
+ border-radius: 20px;
+`
+
+export const Contents = styled.div`
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ text-align: center;
+ gap: 5px;
+ padding: 20px;
+ margin: 20px;
+ border-radius: 20px;
+ color: var(${UI.COLOR_RED});
+ background: var(${UI.COLOR_DANGER_BG});
+`
+
+export const ActionButtonWrapper = styled.div`
+ padding: 0 20px 20px 20px;
+`
+
+export const AcceptanceBox = styled.label`
+ display: flex;
+ gap: 6px;
+ cursor: pointer;
+`
+
+export const ListInfo = styled.div`
+ display: flex;
+ flex-direction: row;
+ margin: 20px;
+ gap: 20px;
+ padding: 0 10px;
+`
+
+export const ListTitle = styled.div`
+ font-weight: 600;
+ font-size: 18px;
+`
+
+export const ListLink = styled.a`
+ font-size: 14px;
+`
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenItem/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenItem/index.tsx
new file mode 100644
index 0000000000..c9a158eaa5
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenItem/index.tsx
@@ -0,0 +1,25 @@
+import * as styledEl from './styled'
+
+import { TokenWithLogo } from '../../types'
+import { ImportButton } from '../commonElements'
+import { TokenInfo } from '../TokenInfo'
+
+export interface ImportTokenItemProps {
+ token: TokenWithLogo
+ importToken(token: TokenWithLogo): void
+ shadowed?: boolean
+}
+
+export function ImportTokenItem(props: ImportTokenItemProps) {
+ const { token, importToken, shadowed } = props
+ return (
+
+
+
+
+
+ importToken(token)}>Import
+
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenItem/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenItem/styled.ts
new file mode 100644
index 0000000000..446ba08db5
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenItem/styled.ts
@@ -0,0 +1,13 @@
+import styled from 'styled-components/macro'
+
+export const Wrapper = styled.div`
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ padding: 0 20px;
+ margin-bottom: 20px;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+`
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/index.tsx
new file mode 100644
index 0000000000..efd6d6b44a
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/index.tsx
@@ -0,0 +1,23 @@
+import * as styledEl from './styled'
+
+import { TokenList } from '../../types'
+import { ImportButton } from '../commonElements'
+import { TokenListInfo } from '../TokenListInfo'
+
+export interface ImportTokenListItemProps {
+ list: TokenList
+ importList(list: TokenList): void
+}
+
+export function ImportTokenListItem(props: ImportTokenListItemProps) {
+ const { list } = props
+
+ return (
+
+
+
+ Import
+
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/styled.ts
new file mode 100644
index 0000000000..524b879730
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/styled.ts
@@ -0,0 +1,9 @@
+import styled from 'styled-components/macro'
+
+export const Wrapper = styled.div`
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ margin: 20px;
+ padding: 0 10px;
+`
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/index.cosmos.tsx
new file mode 100644
index 0000000000..75bff5e775
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/index.cosmos.tsx
@@ -0,0 +1,23 @@
+import styled from 'styled-components/macro'
+
+import { customTokensMock } from '../../mocks'
+
+import { ImportTokenModal } from './index'
+
+const Wrapper = styled.div`
+ width: 450px;
+`
+
+const Fixtures = {
+ default: (
+
+ console.log('onBack')}
+ onClose={() => console.log('onClose')}
+ />
+
+ ),
+}
+
+export default Fixtures
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/index.tsx
new file mode 100644
index 0000000000..579ac595be
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/index.tsx
@@ -0,0 +1,51 @@
+import { ExplorerDataType, getExplorerLink } from '@cowprotocol/common-utils'
+import { ButtonPrimary } from '@cowprotocol/ui'
+
+import { AlertCircle } from 'react-feather'
+
+import * as styledEl from './styled'
+
+import { TokenWithLogo } from '../../types'
+import { ModalHeader } from '../ModalHeader'
+import { TokenLogo } from '../TokenLogo'
+
+export interface ImportTokenModalProps {
+ token: TokenWithLogo
+ onBack(): void
+ onClose(): void
+}
+
+export function ImportTokenModal(props: ImportTokenModalProps) {
+ const { token, onBack, onClose } = props
+
+ return (
+
+
+ Import token
+
+
+
+
+ This token doesn't appear on the active token list(s). Make sure this is the token that you want to trade.
+
+
+
+
+ {token.name}
+
+ {token.address}
+
+
+
+ Unknown Source
+
+
+ Import token
+
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/styled.ts
new file mode 100644
index 0000000000..4f99b6d7f4
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/styled.ts
@@ -0,0 +1,56 @@
+import { TokenSymbol } from '@cowprotocol/ui'
+
+import { AlertCircle } from 'react-feather'
+import styled from 'styled-components/macro'
+
+import { UI } from 'common/constants/theme'
+
+export const Wrapper = styled.div`
+ display: block;
+ width: 100%;
+ background: var(${UI.COLOR_CONTAINER_BG_01});
+ border-radius: 20px;
+`
+
+export const Contents = styled.div`
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ text-align: center;
+ gap: 20px;
+ padding: 20px;
+`
+
+export const AlertIcon = styled(AlertCircle)`
+ color: var(${UI.COLOR_RED});
+ margin-top: 20px;
+`
+
+export const TokenInfo = styled.div`
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ text-align: center;
+ gap: 10px;
+ font-size: 14px;
+`
+
+export const StyledTokenSymbol = styled(TokenSymbol)`
+ font-weight: 600;
+ font-size: 20px;
+`
+
+export const TokenName = styled.div`
+ color: var(${UI.COLOR_LINK});
+`
+
+export const UnknownSourceWarning = styled.div`
+ display: flex;
+ gap: 8px;
+ align-items: center;
+ background: var(${UI.COLOR_DANGER_BG});
+ color: var(${UI.COLOR_DANGER_TEXT});
+ border-radius: 10px;
+ font-size: 13px;
+ padding: 6px 12px;
+`
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/LoadedTokenListItem/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/LoadedTokenListItem/index.tsx
new file mode 100644
index 0000000000..714a00b983
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/LoadedTokenListItem/index.tsx
@@ -0,0 +1,26 @@
+import { CheckCircle } from 'react-feather'
+
+import * as styledEl from './styled'
+
+import { TokenList } from '../../types'
+import { TokenListInfo } from '../TokenListInfo'
+
+export interface LoadedTokenListItemProps {
+ list: TokenList
+}
+
+export function LoadedTokenListItem(props: LoadedTokenListItemProps) {
+ const { list } = props
+
+ return (
+
+
+
+
+
+ Loaded
+
+
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/LoadedTokenListItem/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/LoadedTokenListItem/styled.ts
new file mode 100644
index 0000000000..5125a5e65b
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/LoadedTokenListItem/styled.ts
@@ -0,0 +1,17 @@
+import styled from 'styled-components/macro'
+
+export const Wrapper = styled.div`
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ margin: 20px;
+ padding: 0 10px;
+`
+
+export const LoadedInfo = styled.div`
+ display: flex;
+ flex-direction: row;
+ gap: 10px;
+ align-items: center;
+`
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ModalHeader/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/ModalHeader/index.tsx
new file mode 100644
index 0000000000..10ef4f5d85
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ModalHeader/index.tsx
@@ -0,0 +1,41 @@
+import { ArrowLeft, X } from 'react-feather'
+import styled from 'styled-components/macro'
+
+import { UI } from 'common/constants/theme'
+
+import { IconButton } from '../commonElements'
+
+const Header = styled.div`
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ font-weight: 500;
+ font-size: 20px;
+ padding: 20px;
+ border-bottom: 1px solid var(${UI.COLOR_BORDER});
+`
+
+export interface ModalHeaderProps {
+ children: string
+ onBack(): void
+ onClose(): void
+ className?: string
+}
+
+export function ModalHeader({ children, className, onBack, onClose }: ModalHeaderProps) {
+ return (
+
+
+ {children}
+
+
+
+
+
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/TokenInfo/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenInfo/index.tsx
new file mode 100644
index 0000000000..52c40d4936
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenInfo/index.tsx
@@ -0,0 +1,25 @@
+import { TokenSymbol } from '@cowprotocol/ui'
+
+import * as styledEl from './styled'
+
+import { TokenWithLogo } from '../../types'
+import { TokenLogo } from '../TokenLogo'
+
+export interface TokenInfoProps {
+ token: TokenWithLogo
+ className?: string
+}
+
+export function TokenInfo(props: TokenInfoProps) {
+ const { token, className } = props
+
+ return (
+
+
+
+
+ {token.name}
+
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/TokenInfo/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenInfo/styled.ts
new file mode 100644
index 0000000000..0c0f1dabe9
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenInfo/styled.ts
@@ -0,0 +1,17 @@
+import styled from 'styled-components/macro'
+
+import { UI } from 'common/constants/theme'
+
+export const Wrapper = styled.div`
+ display: flex;
+ flex-direction: row;
+ text-align: left;
+ gap: 16px;
+ font-weight: 500;
+`
+
+export const TokenName = styled.div`
+ font-size: 12px;
+ font-weight: 400;
+ color: var(${UI.COLOR_TEXT2});
+`
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListInfo/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListInfo/index.tsx
new file mode 100644
index 0000000000..53ade782b0
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListInfo/index.tsx
@@ -0,0 +1,30 @@
+import { ReactNode } from 'react'
+
+import * as styledEl from './styled'
+
+import { TokenList } from '../../types'
+import { TokenLogo } from '../TokenLogo'
+
+export interface TokenListItemProps {
+ list: TokenList
+ className?: string
+ children?: ReactNode
+}
+
+export function TokenListInfo(props: TokenListItemProps) {
+ const { list, children, className } = props
+
+ return (
+
+
+
+
+
+ {list.name}
+
+ {list.tokensCount} tokens {children}
+
+
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListInfo/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListInfo/styled.ts
new file mode 100644
index 0000000000..c97f74be3e
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListInfo/styled.ts
@@ -0,0 +1,21 @@
+import styled from 'styled-components/macro'
+
+export const ListInfo = styled.div`
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ gap: 10px;
+ font-size: 12px;
+`
+
+export const ListName = styled.div`
+ font-size: 16px;
+ font-weight: 600;
+ margin-bottom: 5px;
+`
+
+export const TokensInfo = styled.div`
+ display: flex;
+ gap: 5px;
+`
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/index.tsx
new file mode 100644
index 0000000000..b7bc926eb4
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/index.tsx
@@ -0,0 +1,53 @@
+import { useState } from 'react'
+
+import { Menu, MenuItem } from '@reach/menu-button'
+import { Settings } from 'react-feather'
+
+import { Toggle } from 'legacy/components/Toggle'
+
+import * as styledEl from './styled'
+
+import { TokenList } from '../../types'
+import { IconButton } from '../commonElements'
+import { TokenListInfo } from '../TokenListInfo'
+
+export interface TokenListItemProps {
+ list: TokenList
+ removeList(id: string): void
+ viewList(id: string): void
+}
+
+export function TokenListItem(props: TokenListItemProps) {
+ const { list, removeList, viewList } = props
+
+ // TODO: bind logic
+ const [isActive, setIsActive] = useState(list.enabled)
+
+ return (
+
+
+
+
+
+
+
+
+
+ void 0}>
+ {list.version}
+
+ viewList(list.id)}>
+ View List
+
+ removeList(list.id)}>
+ Remove list
+
+
+
+
+
+ setIsActive((state) => !state)} />
+
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/styled.ts
new file mode 100644
index 0000000000..f48bdcec19
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/styled.ts
@@ -0,0 +1,46 @@
+import { MenuButton, MenuList } from '@reach/menu-button'
+import { transparentize } from 'polished'
+import styled from 'styled-components/macro'
+
+import { UI } from 'common/constants/theme'
+
+import { blankButtonMixin } from '../commonElements'
+
+export const Wrapper = styled.div<{ $enabled: boolean }>`
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ margin: 20px;
+ padding: 20px;
+ border-radius: 20px;
+ border: 1px solid var(${UI.COLOR_GREY});
+ background-color: ${({ $enabled, theme }) => ($enabled ? transparentize(0.8, theme.bg2) : 'transparent')};
+`
+
+export const SettingsButton = styled(MenuButton)`
+ ${blankButtonMixin}
+`
+
+export const SettingsContainer = styled(MenuList)`
+ background: var(${UI.COLOR_CONTAINER_BG_01});
+ padding: 10px;
+ border-radius: 10px;
+ border: 1px solid var(${UI.COLOR_GREY});
+`
+
+export const SettingsAction = styled.div`
+ color: var(${UI.COLOR_LINK});
+ cursor: pointer;
+ padding: 5px;
+ box-sizing: content-box;
+
+ &:hover {
+ text-decoration: underline;
+ }
+`
+
+export const ListVersion = styled.div`
+ color: var(${UI.COLOR_TEXT1_INACTIVE});
+ border-bottom: 1px solid var(${UI.COLOR_GREY});
+ padding: 0 5px 10px 5px;
+`
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/TokenLogo/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenLogo/index.tsx
new file mode 100644
index 0000000000..4ffc0aed23
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenLogo/index.tsx
@@ -0,0 +1,38 @@
+import { atom, useAtom } from 'jotai'
+
+import { Slash } from 'react-feather'
+import styled from 'styled-components/macro'
+
+import { UI } from 'common/constants/theme'
+
+const invalidUrlsAtom = atom<{ [url: string]: boolean }>({})
+
+const TokenLogoWrapper = styled.div`
+ display: inline-block;
+ background: var(${UI.COLOR_CONTAINER_BG_01});
+ border-radius: 50%;
+`
+
+export interface TokenLogoProps {
+ logoURI: string | undefined
+ className?: string
+ size?: number
+}
+
+export function TokenLogo({ logoURI, className, size = 36 }: TokenLogoProps) {
+ const [invalidUrls, setInvalidUrls] = useAtom(invalidUrlsAtom)
+
+ const hasError = invalidUrls[logoURI!]
+
+ const onError = () => setInvalidUrls({ ...invalidUrls, [logoURI!]: true })
+
+ return (
+
+ {hasError || !logoURI ? (
+
+ ) : (
+
+ )}
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/TokenSourceTitle/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenSourceTitle/index.tsx
new file mode 100644
index 0000000000..36d55445ba
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenSourceTitle/index.tsx
@@ -0,0 +1,45 @@
+import TokenListLogo from '@cowprotocol/assets/svg/tokenlist.svg'
+
+import styled from 'styled-components/macro'
+
+import { InfoIcon } from 'legacy/components/InfoIcon'
+
+const Wrapper = styled.div`
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 10px;
+ padding: 0 20px;
+`
+
+const Title = styled.h4`
+ font-size: 13px;
+ font-weight: 500;
+
+ > img {
+ width: 18px;
+ vertical-align: middle;
+ margin-right: 6px;
+ }
+`
+
+export interface TokenSourceTitleProps {
+ children: string
+ tooltip: string
+}
+
+export function TokenSourceTitle(props: TokenSourceTitleProps) {
+ const { children, tooltip } = props
+
+ return (
+
+
+
+ {children}
+
+
+
+
+
+ )
+}
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/commonElements.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/commonElements.ts
new file mode 100644
index 0000000000..b8edf20eec
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/commonElements.ts
@@ -0,0 +1,73 @@
+import { transparentize } from 'polished'
+import styled, { css } from 'styled-components/macro'
+
+import { UI } from 'common/constants/theme'
+
+export const blankButtonMixin = css`
+ background: none;
+ padding: 0;
+ margin: 0;
+ outline: none;
+ border: 0;
+ cursor: pointer;
+
+ &:disabled {
+ cursor: default;
+ }
+`
+
+export const PrimaryInputBox = styled.div`
+ margin: 20px 0 10px 0;
+ padding: 0 20px 20px 20px;
+ border-bottom: 1px solid var(${UI.COLOR_GREY});
+`
+
+export const PrimaryInput = styled.input`
+ width: 100%;
+ border: none;
+ background: var(${UI.COLOR_GREY});
+ font-size: 18px;
+ border-radius: 20px;
+ padding: 16px;
+ color: var(${UI.COLOR_TEXT1});
+ outline: none;
+
+ ::placeholder {
+ color: var(${UI.COLOR_TEXT1});
+ }
+
+ &:focus {
+ ::placeholder {
+ color: ${({ theme }) => transparentize(0.7, theme.text1)};
+ }
+ }
+`
+
+export const IconButton = styled.button`
+ ${blankButtonMixin}
+
+ > svg {
+ color: var(${UI.COLOR_TEXT1});
+
+ &:hover {
+ color: var(${UI.COLOR_TEXT2});
+ }
+ }
+`
+
+export const ImportButton = styled.button`
+ ${blankButtonMixin};
+
+ background-color: var(${UI.COLOR_CONTAINER_BG_02});
+ color: var(${UI.COLOR_WHITE});
+ font-size: 16px;
+ font-weight: 600;
+ padding: 6px 15px;
+ border-radius: 24px;
+ cursor: pointer;
+ transition: background-color 0.2s ease-in-out;
+
+ &:hover {
+ background-color: var(${UI.COLOR_LINK});
+ }
+`
diff --git a/apps/cowswap-frontend/src/modules/tokensList/state/tokensListAtom.ts b/apps/cowswap-frontend/src/modules/tokensList/state/tokensListAtom.ts
index 0abca1bf79..39d2add888 100644
--- a/apps/cowswap-frontend/src/modules/tokensList/state/tokensListAtom.ts
+++ b/apps/cowswap-frontend/src/modules/tokensList/state/tokensListAtom.ts
@@ -1,21 +1,6 @@
import { atom } from 'jotai'
-import { Token } from '@uniswap/sdk-core'
-
-// It's a hack for useCurrencyLogoURIs(), must be refactored
-export class TokenWithLogo extends Token {
- constructor(
- public logoURI: string | undefined,
- chainId: number,
- address: string,
- decimals: number,
- symbol?: string,
- name?: string,
- bypassChecksum?: boolean
- ) {
- super(chainId, address, decimals, symbol, name, bypassChecksum)
- }
-}
+import { TokenWithLogo } from '../types'
export type TokensByAddress = { [address: string]: TokenWithLogo }
diff --git a/apps/cowswap-frontend/src/modules/tokensList/types.ts b/apps/cowswap-frontend/src/modules/tokensList/types.ts
new file mode 100644
index 0000000000..77a7608e7a
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/tokensList/types.ts
@@ -0,0 +1,25 @@
+import { Token } from '@uniswap/sdk-core'
+
+export class TokenWithLogo extends Token {
+ constructor(
+ public logoURI: string | undefined,
+ chainId: number,
+ address: string,
+ decimals: number,
+ symbol?: string,
+ name?: string,
+ bypassChecksum?: boolean
+ ) {
+ super(chainId, address, decimals, symbol, name, bypassChecksum)
+ }
+}
+
+export interface TokenList {
+ id: string
+ name: string
+ logoUrl: string
+ url: string
+ enabled: boolean
+ tokensCount: number
+ version: string
+}
diff --git a/apps/cowswap-frontend/src/modules/tokensList/updaters/TokensListUpdater.ts b/apps/cowswap-frontend/src/modules/tokensList/updaters/TokensListUpdater.ts
index d9708e316e..2f6aa18f98 100644
--- a/apps/cowswap-frontend/src/modules/tokensList/updaters/TokensListUpdater.ts
+++ b/apps/cowswap-frontend/src/modules/tokensList/updaters/TokensListUpdater.ts
@@ -3,7 +3,9 @@ import { useEffect, useMemo } from 'react'
import { useTokensListWithDefaults } from 'legacy/state/lists/hooks'
-import { tokensByAddressAtom, tokensBySymbolAtom, TokenWithLogo } from 'modules/tokensList/state/tokensListAtom'
+import { tokensByAddressAtom, tokensBySymbolAtom } from 'modules/tokensList/state/tokensListAtom'
+
+import { TokenWithLogo } from '../types'
/**
* This updater protects from redundant recalculations
diff --git a/apps/cowswap-frontend/src/modules/tokensList/utils/getTokensByAddress.ts b/apps/cowswap-frontend/src/modules/tokensList/utils/getTokensByAddress.ts
index 1cde518e0a..3895274499 100644
--- a/apps/cowswap-frontend/src/modules/tokensList/utils/getTokensByAddress.ts
+++ b/apps/cowswap-frontend/src/modules/tokensList/utils/getTokensByAddress.ts
@@ -1,10 +1,8 @@
+import { NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const'
+import { doesTokenMatchSymbolOrAddress } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { Token } from '@uniswap/sdk-core'
-import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants'
-
-import { doesTokenMatchSymbolOrAddress } from 'utils/doesTokenMatchSymbolOrAddress'
-
import { TokensByAddress } from '../state/tokensListAtom'
export function getTokensByAddress(
diff --git a/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/TradeConfirmPendingContent.tsx b/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/TradeConfirmPendingContent.tsx
index ee8bacce8b..82521c3d65 100644
--- a/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/TradeConfirmPendingContent.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/TradeConfirmPendingContent.tsx
@@ -1,10 +1,10 @@
import React from 'react'
-import { useWalletDisplayedAddress } from 'modules/wallet'
+import { TokenAmount } from '@cowprotocol/ui'
+import { useWalletDisplayedAddress } from '@cowprotocol/wallet'
import { useWalletStatusIcon } from 'common/hooks/useWalletStatusIcon'
import { ConfirmationPendingContent } from 'common/pure/ConfirmationPendingContent'
-import { TokenAmount } from 'common/pure/TokenAmount'
import { TradeAmounts } from 'common/types'
const description = `Almost there! \n Follow these steps:`
diff --git a/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/index.cosmos.tsx
index 1729f198aa..6266f269f2 100644
--- a/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/index.cosmos.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/index.cosmos.tsx
@@ -2,11 +2,10 @@ import { useSetAtom } from 'jotai'
import React, { useEffect } from 'react'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { walletInfoAtom } from '@cowprotocol/wallet'
import { inputCurrencyInfoMock, outputCurrencyInfoMock, priceImpactMock } from 'mocks/tradeStateMock'
-import { walletInfoAtom } from 'modules/wallet/api/state'
-
import { TradeAmounts } from 'common/types'
import { useTradeConfirmActions } from '../../hooks/useTradeConfirmActions'
diff --git a/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/index.tsx b/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/index.tsx
index 76cad91c7c..4d6e9c4fd3 100644
--- a/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/index.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/index.tsx
@@ -1,10 +1,13 @@
import { useAtomValue } from 'jotai'
-import { useIsSafeWallet, useWalletInfo } from 'modules/wallet'
+import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { useIsSafeWallet, useWalletInfo } from '@cowprotocol/wallet'
-import { CowModal } from 'common/pure/Modal'
+import { PermitModal } from 'common/containers/PermitModal'
+import { CowModal, NewCowModal } from 'common/pure/Modal'
import { OrderSubmittedContent } from 'common/pure/OrderSubmittedContent'
import { TransactionErrorContent } from 'common/pure/TransactionErrorContent'
+import { TradeAmounts } from 'common/types'
import { TradeConfirmPendingContent } from './TradeConfirmPendingContent'
@@ -20,37 +23,90 @@ export function TradeConfirmModal(props: TradeConfirmModalProps) {
const { chainId, account } = useWalletInfo()
const isSafeWallet = useIsSafeWallet()
- const { isOpen, pendingTrade, transactionHash, error } = useAtomValue(tradeConfirmStateAtom)
+ const { isOpen, permitSignatureState, pendingTrade, transactionHash, error } = useAtomValue(tradeConfirmStateAtom)
const { onDismiss } = useTradeConfirmActions()
if (!account) return null
+ const Modal = permitSignatureState ? NewCowModal : CowModal
+
return (
-
- {(() => {
- if (error) {
- return
- }
-
- if (pendingTrade) {
- return
- }
-
- // TODO: use for Swap
- if (transactionHash) {
- return (
-
- )
- }
-
- return children
- })()}
-
+
+
+ {children}
+
+
)
}
+
+type InnerComponentProps = {
+ children: JSX.Element
+ chainId: SupportedChainId
+ account: string
+ error: string | null
+ pendingTrade: TradeAmounts | null
+ transactionHash: string | null
+ onDismiss: () => void
+ permitSignatureState: string | undefined
+ isSafeWallet: boolean
+}
+
+function InnerComponent(props: InnerComponentProps) {
+ const {
+ account,
+ chainId,
+ children,
+ error,
+ isSafeWallet,
+ onDismiss,
+ pendingTrade,
+ permitSignatureState,
+ transactionHash,
+ } = props
+
+ if (error) {
+ return
+ }
+
+ if (pendingTrade && permitSignatureState) {
+ // TODO: potentially replace TradeConfirmPendingContent completely with PermitModal
+ // We could use this not just for permit, but for any token, even already approved
+ const step = permitSignatureState === 'signed' ? 'submit' : 'approve'
+ return (
+
+ )
+ }
+
+ if (pendingTrade) {
+ return
+ }
+
+ if (transactionHash) {
+ return (
+
+ )
+ }
+
+ return children
+}
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 1bd42bf439..930b93fc6b 100644
--- a/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/TradeWidgetModals.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/TradeWidgetModals.tsx
@@ -1,6 +1,6 @@
import React from 'react'
-import { useWalletInfo } from 'modules/wallet'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { ImportTokenModal } from 'common/containers/ImportTokenModal'
import { TradeApproveModal } from 'common/containers/TradeApprove'
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 2eb4d26b48..bb5f1d3dcc 100644
--- a/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/index.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/index.tsx
@@ -1,9 +1,11 @@
import { ReactNode, useEffect } from 'react'
+import { maxAmountSpend } from '@cowprotocol/common-utils'
+import { useIsSafeWallet, useWalletDetails, useWalletInfo } from '@cowprotocol/wallet'
+
import { t } from '@lingui/macro'
import { PriceImpact } from 'legacy/hooks/usePriceImpact'
-import { maxAmountSpend } from 'legacy/utils/maxAmountSpend'
import { TradeWidgetLinks } from 'modules/application/containers/TradeWidgetLinks'
import { SetRecipientProps } from 'modules/swap/containers/SetRecipient'
@@ -11,7 +13,6 @@ import { useIsWrapOrUnwrap } from 'modules/trade/hooks/useIsWrapOrUnwrap'
import { RecipientAddressUpdater } from 'modules/trade/updaters/RecipientAddressUpdater'
import { TradeFormValidationUpdater } from 'modules/tradeFormValidation'
import { TradeQuoteUpdater } from 'modules/tradeQuote'
-import { useIsSafeWallet, useWalletDetails, useWalletInfo } from 'modules/wallet'
import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported'
import { useThrottleFn } from 'common/hooks/useThrottleFn'
diff --git a/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/styled.tsx b/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/styled.tsx
index 49c68e8dda..e8643f3388 100644
--- a/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/styled.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/styled.tsx
@@ -2,6 +2,8 @@ import styled from 'styled-components/macro'
import { SetRecipient } from 'modules/swap/containers/SetRecipient'
+import { UI } from 'common/constants/theme'
+
export const Container = styled.div`
width: 100%;
max-width: ${({ theme }) => theme.appBody.maxWidth.swap};
@@ -12,7 +14,7 @@ export const ContainerBox = styled.div`
display: flex;
flex-flow: column wrap;
gap: 10px;
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
border: none;
border-radius: 16px;
box-shadow: ${({ theme }) => theme.boxShadow1};
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 402668a682..cdafbb4479 100644
--- a/apps/cowswap-frontend/src/modules/trade/containers/WrapNativeModal/index.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/containers/WrapNativeModal/index.tsx
@@ -1,13 +1,12 @@
import { useAtom } from 'jotai'
import { useCallback } from 'react'
-import { useWalletDisplayedAddress } from 'modules/wallet'
+import { TokenAmount, TokenSymbol } from '@cowprotocol/ui'
+import { useWalletDisplayedAddress } from '@cowprotocol/wallet'
import { useWalletStatusIcon } from 'common/hooks/useWalletStatusIcon'
import { ConfirmationPendingContent } from 'common/pure/ConfirmationPendingContent'
import { CowModal } from 'common/pure/Modal'
-import { TokenAmount } from 'common/pure/TokenAmount'
-import { TokenSymbol } from 'common/pure/TokenSymbol'
import { useDerivedTradeState } from '../../hooks/useDerivedTradeState'
import { wrapNativeStateAtom } from '../../state/wrapNativeStateAtom'
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 b2267c9076..db2c485178 100644
--- a/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useResetStateWithSymbolDuplication.ts
+++ b/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useResetStateWithSymbolDuplication.ts
@@ -1,8 +1,8 @@
import { useEffect } from 'react'
-import { t } from '@lingui/macro'
+import { useWalletInfo } from '@cowprotocol/wallet'
-import { useWalletInfo } from 'modules/wallet'
+import { t } from '@lingui/macro'
import { useAreThereTokensWithSameSymbol } from 'common/hooks/useAreThereTokensWithSameSymbol'
diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeState.ts b/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeState.ts
index 8f16f85ad7..7ada7d4922 100644
--- a/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeState.ts
+++ b/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeState.ts
@@ -1,14 +1,12 @@
import { useEffect, useState } from 'react'
+import { usePrevious } from '@cowprotocol/common-hooks'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { useWalletInfo, switchChain } from '@cowprotocol/wallet'
import { useWeb3React } from '@web3-react/core'
-import usePrevious from 'legacy/hooks/usePrevious'
-
import { useTradeNavigate } from 'modules/trade/hooks/useTradeNavigate'
import { getDefaultTradeRawState, TradeRawState } from 'modules/trade/types/TradeRawState'
-import { useWalletInfo } from 'modules/wallet'
-import { switchChain } from 'modules/wallet/web3-react/hooks/switchChain'
import { useResetStateWithSymbolDuplication } from './useResetStateWithSymbolDuplication'
import { useTradeStateFromUrl } from './useTradeStateFromUrl'
diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useBuildTradeDerivedState.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useBuildTradeDerivedState.ts
index 286bc6e12b..27140cdd8d 100644
--- a/apps/cowswap-frontend/src/modules/trade/hooks/useBuildTradeDerivedState.ts
+++ b/apps/cowswap-frontend/src/modules/trade/hooks/useBuildTradeDerivedState.ts
@@ -1,13 +1,14 @@
import { Atom, useAtomValue } from 'jotai'
+import { tryParseFractionalAmount } from '@cowprotocol/common-utils'
+import { useWalletInfo } from '@cowprotocol/wallet'
+
import useCurrencyBalance from 'modules/tokens/hooks/useCurrencyBalance'
import { ExtendedTradeRawState } from 'modules/trade/types/TradeRawState'
import { useTradeUsdAmounts } from 'modules/usdAmount'
-import { useWalletInfo } from 'modules/wallet'
import { useSafeMemoObject } from 'common/hooks/useSafeMemo'
import { useTokenBySymbolOrAddress } from 'common/hooks/useTokenBySymbolOrAddress'
-import { tryParseFractionalAmount } from 'utils/tryParseFractionalAmount'
export function useBuildTradeDerivedState(stateAtom: Atom) {
const { account } = useWalletInfo()
diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useDerivedTradeState.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useDerivedTradeState.ts
index 22e48f7710..5781562082 100644
--- a/apps/cowswap-frontend/src/modules/trade/hooks/useDerivedTradeState.ts
+++ b/apps/cowswap-frontend/src/modules/trade/hooks/useDerivedTradeState.ts
@@ -18,19 +18,13 @@ export function useDerivedTradeState(): { state?: TradeDerivedState } {
if (!tradeTypeInfo) return {}
if (tradeTypeInfo.tradeType === TradeType.SWAP) {
- return {
- state: swapDerivedState,
- }
+ return { state: swapDerivedState }
}
if (tradeTypeInfo.tradeType === TradeType.ADVANCED_ORDERS) {
- return {
- state: advancedOrdersDerivedState,
- }
+ return { state: advancedOrdersDerivedState }
}
- return {
- state: limitOrdersDerivedState,
- }
+ return { state: limitOrdersDerivedState }
}, [tradeTypeInfo, swapDerivedState, limitOrdersDerivedState, advancedOrdersDerivedState])
}
diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useDisableNativeTokenSelling.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useDisableNativeTokenSelling.ts
index 3c7e8417d6..610faa95ac 100644
--- a/apps/cowswap-frontend/src/modules/trade/hooks/useDisableNativeTokenSelling.ts
+++ b/apps/cowswap-frontend/src/modules/trade/hooks/useDisableNativeTokenSelling.ts
@@ -1,9 +1,8 @@
import { useEffect } from 'react'
-import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants'
-import { WRAPPED_NATIVE_CURRENCY } from 'legacy/constants/tokens'
-
-import { useWalletInfo } from 'modules/wallet'
+import { WRAPPED_NATIVE_CURRENCY } from '@cowprotocol/common-const'
+import { NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { useTradeNavigate } from './useTradeNavigate'
import { useTradeState } from './useTradeState'
diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useIsNativeInOrOut.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useIsNativeInOrOut.ts
index 57bf3b6efe..1deb924e48 100644
--- a/apps/cowswap-frontend/src/modules/trade/hooks/useIsNativeInOrOut.ts
+++ b/apps/cowswap-frontend/src/modules/trade/hooks/useIsNativeInOrOut.ts
@@ -1,8 +1,7 @@
import { useMemo } from 'react'
-import { useWalletInfo } from 'modules/wallet'
-
-import { getIsNativeToken } from 'utils/getIsNativeToken'
+import { getIsNativeToken } from '@cowprotocol/common-utils'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { useTradeState } from './useTradeState'
diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useIsWrapOrUnwrap.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useIsWrapOrUnwrap.ts
index 1949f6db02..ede54d04b3 100644
--- a/apps/cowswap-frontend/src/modules/trade/hooks/useIsWrapOrUnwrap.ts
+++ b/apps/cowswap-frontend/src/modules/trade/hooks/useIsWrapOrUnwrap.ts
@@ -1,9 +1,9 @@
import { useMemo } from 'react'
-import { useTradeState } from 'modules/trade/hooks/useTradeState'
-import { useWalletInfo } from 'modules/wallet'
+import { getIsWrapOrUnwrap } from '@cowprotocol/common-utils'
+import { useWalletInfo } from '@cowprotocol/wallet'
-import { getIsWrapOrUnwrap } from 'utils/getIsWrapOrUnwrap'
+import { useTradeState } from 'modules/trade/hooks/useTradeState'
export function useIsWrapOrUnwrap(): boolean {
const { chainId } = useWalletInfo()
diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useIsWrappedInOrOut.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useIsWrappedInOrOut.ts
index ce62913a0c..ef4a07e9eb 100644
--- a/apps/cowswap-frontend/src/modules/trade/hooks/useIsWrappedInOrOut.ts
+++ b/apps/cowswap-frontend/src/modules/trade/hooks/useIsWrappedInOrOut.ts
@@ -1,12 +1,9 @@
import { useMemo } from 'react'
+import { WRAPPED_NATIVE_CURRENCY } from '@cowprotocol/common-const'
+import { doesTokenMatchSymbolOrAddress } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
-
-import { WRAPPED_NATIVE_CURRENCY } from 'legacy/constants/tokens'
-
-import { useWalletInfo } from 'modules/wallet'
-
-import { doesTokenMatchSymbolOrAddress } from 'utils/doesTokenMatchSymbolOrAddress'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { useTradeState } from './useTradeState'
diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useNavigateOnCurrencySelection.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useNavigateOnCurrencySelection.ts
index 2616b476ad..1df5d47bd7 100644
--- a/apps/cowswap-frontend/src/modules/trade/hooks/useNavigateOnCurrencySelection.ts
+++ b/apps/cowswap-frontend/src/modules/trade/hooks/useNavigateOnCurrencySelection.ts
@@ -1,12 +1,12 @@
import { useCallback } from 'react'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Currency, Token } from '@uniswap/sdk-core'
-import { Field } from 'legacy/state/swap/actions'
+import { Field } from 'legacy/state/types'
import { useTradeNavigate } from 'modules/trade/hooks/useTradeNavigate'
import { useTradeState } from 'modules/trade/hooks/useTradeState'
-import { useWalletInfo } from 'modules/wallet'
import { useAreThereTokensWithSameSymbol } from 'common/hooks/useAreThereTokensWithSameSymbol'
diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useOnCurrencySelection.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useOnCurrencySelection.ts
index 4d80ea1d35..872793f7a4 100644
--- a/apps/cowswap-frontend/src/modules/trade/hooks/useOnCurrencySelection.ts
+++ b/apps/cowswap-frontend/src/modules/trade/hooks/useOnCurrencySelection.ts
@@ -1,15 +1,15 @@
import { useSetAtom } from 'jotai'
import { useCallback } from 'react'
+import { FractionUtils } from '@cowprotocol/common-utils'
import { Currency } from '@uniswap/sdk-core'
-import { Field } from 'legacy/state/swap/actions'
+import { Field } from 'legacy/state/types'
import { updateLimitOrdersRawStateAtom } from 'modules/limitOrders'
import { useLimitOrdersDerivedState } from 'modules/limitOrders/hooks/useLimitOrdersDerivedState'
import { useNavigateOnCurrencySelection } from 'modules/trade/hooks/useNavigateOnCurrencySelection'
-import { FractionUtils } from 'utils/fractionUtils'
import { convertAmountToCurrency } from 'utils/orderUtils/calculateExecutionPrice'
export function useOnCurrencySelection(): (field: Field, currency: Currency | null) => void {
diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useSwitchTokensPlaces.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useSwitchTokensPlaces.ts
index a303893490..c46a42d864 100644
--- a/apps/cowswap-frontend/src/modules/trade/hooks/useSwitchTokensPlaces.ts
+++ b/apps/cowswap-frontend/src/modules/trade/hooks/useSwitchTokensPlaces.ts
@@ -1,10 +1,8 @@
import { useCallback } from 'react'
-import { switchTokensAnalytics } from 'legacy/components/analytics'
-
-import { useWalletInfo } from 'modules/wallet'
-
-import { FractionUtils } from 'utils/fractionUtils'
+import { switchTokensAnalytics } from '@cowprotocol/analytics'
+import { FractionUtils } from '@cowprotocol/common-utils'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { useDerivedTradeState } from './useDerivedTradeState'
import { useIsWrapOrUnwrap } from './useIsWrapOrUnwrap'
diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useTradeConfirmActions.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useTradeConfirmActions.ts
index 1fa198cf14..867269f267 100644
--- a/apps/cowswap-frontend/src/modules/trade/hooks/useTradeConfirmActions.ts
+++ b/apps/cowswap-frontend/src/modules/trade/hooks/useTradeConfirmActions.ts
@@ -7,6 +7,7 @@ import {
setErrorTradeConfirmAtom,
setOpenTradeConfirmAtom,
setPendingTradeConfirmAtom,
+ setPermitSignatureRequestedTradeConfirmAtom,
setTxHashTradeConfirmAtom,
} from '../state/tradeConfirmStateAtom'
@@ -15,15 +16,17 @@ export interface TradeConfirmActions {
onError(error: string): void
onSuccess(transactionHash: string): void
onOpen(): void
+ requestPermitSignature(pendingTrade: TradeAmounts): void
onDismiss(): void
}
export function useTradeConfirmActions(): TradeConfirmActions {
- const setOpenTradeConfim = useSetAtom(setOpenTradeConfirmAtom)
+ const setOpenTradeConfirm = useSetAtom(setOpenTradeConfirmAtom)
const setCloseTradeConfirm = useSetAtom(setCloseTradeConfirmAtom)
const setErrorTradeConfirm = useSetAtom(setErrorTradeConfirmAtom)
const setPendingTradeConfirm = useSetAtom(setPendingTradeConfirmAtom)
const setTxHashTradeConfirm = useSetAtom(setTxHashTradeConfirmAtom)
+ const setPermitSignatureRequested = useSetAtom(setPermitSignatureRequestedTradeConfirmAtom)
return {
onSign(pendingTrade: TradeAmounts) {
@@ -36,7 +39,10 @@ export function useTradeConfirmActions(): TradeConfirmActions {
setTxHashTradeConfirm(transactionHash)
},
onOpen() {
- setOpenTradeConfim()
+ setOpenTradeConfirm()
+ },
+ requestPermitSignature(pendingTrade: TradeAmounts) {
+ setPermitSignatureRequested(pendingTrade)
},
onDismiss() {
setCloseTradeConfirm()
diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useTradeTypeInfo.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useTradeTypeInfo.ts
index 57a971ba4d..46de0eac16 100644
--- a/apps/cowswap-frontend/src/modules/trade/hooks/useTradeTypeInfo.ts
+++ b/apps/cowswap-frontend/src/modules/trade/hooks/useTradeTypeInfo.ts
@@ -6,9 +6,9 @@ import { useMatch } from 'react-router-dom'
import { Routes, RoutesValues, TRADE_WIDGET_PREFIX } from 'common/constants/routes'
export enum TradeType {
- SWAP,
- LIMIT_ORDER,
- ADVANCED_ORDERS,
+ SWAP = 'SWAP',
+ LIMIT_ORDER = 'LIMIT_ORDER',
+ ADVANCED_ORDERS = 'ADVANCED_ORDERS',
}
export interface TradeTypeInfo {
diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useUpdateCurrencyAmount.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useUpdateCurrencyAmount.ts
index eda576ba17..c8b6d98cd6 100644
--- a/apps/cowswap-frontend/src/modules/trade/hooks/useUpdateCurrencyAmount.ts
+++ b/apps/cowswap-frontend/src/modules/trade/hooks/useUpdateCurrencyAmount.ts
@@ -1,14 +1,12 @@
import { useCallback } from 'react'
+import { FractionUtils, tryParseCurrencyAmount } from '@cowprotocol/common-utils'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
-import { Field } from 'legacy/state/swap/actions'
+import { Field } from 'legacy/state/types'
import { useTradeState } from 'modules/trade/hooks/useTradeState'
-import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount'
-import { FractionUtils } from 'utils/fractionUtils'
-
type AmountType = {
value: string
isTyped: boolean
diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useWrapNativeFlow.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useWrapNativeFlow.ts
index 09a15df475..620af0c833 100644
--- a/apps/cowswap-frontend/src/modules/trade/hooks/useWrapNativeFlow.ts
+++ b/apps/cowswap-frontend/src/modules/trade/hooks/useWrapNativeFlow.ts
@@ -1,11 +1,12 @@
import { useSetAtom } from 'jotai'
import { useCallback } from 'react'
+import { useWETHContract } from '@cowprotocol/common-hooks'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import { Nullish } from 'types'
-import { useWETHContract } from 'legacy/hooks/useContract'
import {
wrapUnwrapCallback,
WrapUnwrapCallback,
@@ -14,8 +15,6 @@ import {
} from 'legacy/hooks/useWrapCallback'
import { useTransactionAdder } from 'legacy/state/enhancedTransactions/hooks'
-import { useWalletInfo } from 'modules/wallet'
-
import { useDerivedTradeState } from './useDerivedTradeState'
import { useTradeState } from './useTradeState'
diff --git a/apps/cowswap-frontend/src/modules/trade/index.ts b/apps/cowswap-frontend/src/modules/trade/index.ts
index cadc5d77d0..ce49753c7b 100644
--- a/apps/cowswap-frontend/src/modules/trade/index.ts
+++ b/apps/cowswap-frontend/src/modules/trade/index.ts
@@ -6,4 +6,5 @@ export * from './hooks/useTradeTypeInfo'
export * from './hooks/useTradePriceImpact'
export * from './hooks/setupTradeState/useSetupTradeState'
export * from './hooks/useWrapNativeFlow'
+export * from './hooks/useDerivedTradeState'
export * from './types/TradeDerivedState'
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/CompatibilityIssuesWarning/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/CompatibilityIssuesWarning/index.tsx
index ed91bf1955..c9e417f562 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/CompatibilityIssuesWarning/index.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/pure/CompatibilityIssuesWarning/index.tsx
@@ -1,13 +1,12 @@
import React from 'react'
+import { genericPropsChecker } from '@cowprotocol/common-utils'
import { Currency } from '@uniswap/sdk-core'
import { HashLink } from 'react-router-hash-link'
import UnsupportedCurrencyFooter from 'legacy/components/swap/UnsupportedCurrencyFooter'
-import { genericPropsChecker } from 'utils/genericPropsChecker'
-
export interface CompatibilityIssuesWarningProps {
currencyIn: Currency
currencyOut: Currency
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/ConfirmDetailsItem/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/ConfirmDetailsItem/index.tsx
index 7b408b6ff8..e54f111a7e 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/ConfirmDetailsItem/index.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/pure/ConfirmDetailsItem/index.tsx
@@ -1,9 +1,10 @@
import { ReactNode } from 'react'
+import { RowFixed } from '@cowprotocol/ui'
+
import { CornerDownRight } from 'react-feather'
import { InfoIcon } from 'legacy/components/InfoIcon'
-import { RowFixed } from 'legacy/components/Row'
import { TextWrapper } from 'modules/swap/pure/Row/styled'
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/ConfirmDetailsItem/styled.ts b/apps/cowswap-frontend/src/modules/trade/pure/ConfirmDetailsItem/styled.ts
index caa261faef..aef244cb79 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/ConfirmDetailsItem/styled.ts
+++ b/apps/cowswap-frontend/src/modules/trade/pure/ConfirmDetailsItem/styled.ts
@@ -2,6 +2,8 @@ import styled from 'styled-components/macro'
import { StyledRowBetween } from 'modules/swap/pure/Row/styled'
+import { UI } from 'common/constants/theme'
+
export const Wrapper = styled.div`
display: flex;
align-items: center;
@@ -15,7 +17,7 @@ export const Wrapper = styled.div`
> svg:first-child {
margin: 0 4px 0 0;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
opacity: 0.5;
}
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/ReviewOrderModalAmountRow/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/ReviewOrderModalAmountRow/index.tsx
index b5abb13d58..14fe26e8bf 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/ReviewOrderModalAmountRow/index.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/pure/ReviewOrderModalAmountRow/index.tsx
@@ -1,12 +1,10 @@
import { ReactNode } from 'react'
+import { FiatAmount, TokenAmount } from '@cowprotocol/ui'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import { Nullish } from 'types'
-import { FiatAmount } from 'common/pure/FiatAmount'
-import { TokenAmount } from 'common/pure/TokenAmount'
-
import { ConfirmDetailsItem } from '../ConfirmDetailsItem'
export type ReviewOrderAmountRowProps = {
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/Settings/SettingsBox.tsx b/apps/cowswap-frontend/src/modules/trade/pure/Settings/SettingsBox.tsx
index 13bd2385d2..18b1d6d72f 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/Settings/SettingsBox.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/pure/Settings/SettingsBox.tsx
@@ -4,7 +4,7 @@ import { Trans } from '@lingui/macro'
import { ThemeContext } from 'styled-components/macro'
import QuestionHelper from 'legacy/components/QuestionHelper'
-import Toggle from 'legacy/components/Toggle'
+import { Toggle } from 'legacy/components/Toggle'
import { SettingsBoxTitle, SettingsBoxWrapper } from './styled'
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/Settings/styled.ts b/apps/cowswap-frontend/src/modules/trade/pure/Settings/styled.ts
index 77fdee8b7f..7c299250e6 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/Settings/styled.ts
+++ b/apps/cowswap-frontend/src/modules/trade/pure/Settings/styled.ts
@@ -3,10 +3,12 @@ import { transparentize } from 'polished'
import { Settings as SettingsIconRaw } from 'react-feather'
import styled from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
export const SettingsTitle = styled.h3`
font-weight: 600;
font-size: 14px;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
margin: 0 0 12px 0;
`
@@ -16,8 +18,8 @@ export const SettingsContainer = styled.div`
border-radius: 12px;
box-shadow: ${({ theme }) => theme.boxShadow2};
border: 1px solid ${({ theme }) => transparentize(0.95, theme.white)};
- background: ${({ theme }) => theme.bg1};
- color: ${({ theme }) => theme.text1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
+ color: var(${UI.COLOR_TEXT1});
`
export const SettingsBoxWrapper = styled.div<{ disabled: boolean }>`
@@ -37,7 +39,7 @@ export const SettingsBoxTitle = styled.div`
display: flex;
align-items: center;
font-weight: 400;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
font-size: 14px;
opacity: 0.85;
margin-right: 2rem;
@@ -116,6 +118,6 @@ export const SettingsIcon = styled(SettingsIconRaw)`
&:hover > path,
&:hover > circle {
- stroke: ${({ theme }) => theme.text1};
+ stroke: var(${UI.COLOR_TEXT1});
}
`
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/TradeConfirmation/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/TradeConfirmation/index.tsx
index 8458312344..9e315575bb 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/TradeConfirmation/index.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/pure/TradeConfirmation/index.tsx
@@ -1,11 +1,11 @@
import React, { useCallback, useEffect, useRef, useState } from 'react'
+import { ButtonSize, ButtonPrimary } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
-import { ButtonPrimary } from 'legacy/components/Button'
import { PriceImpact } from 'legacy/hooks/usePriceImpact'
import { CloseIcon } from 'legacy/theme'
-import { ButtonSize } from 'legacy/theme/enum'
import { CurrencyArrowSeparator } from 'common/pure/CurrencyArrowSeparator'
import { CurrencyAmountPreview, CurrencyPreviewInfo } from 'common/pure/CurrencyInputPanel'
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/TradeConfirmation/styled.tsx b/apps/cowswap-frontend/src/modules/trade/pure/TradeConfirmation/styled.tsx
index d79c30c070..b72a62e11d 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/TradeConfirmation/styled.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/pure/TradeConfirmation/styled.tsx
@@ -1,5 +1,7 @@
import styled from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
export const WidgetWrapper = styled.div`
width: 100%;
padding: 0;
@@ -32,7 +34,7 @@ export const Header = styled.div`
justify-content: space-between;
align-items: center;
position: sticky;
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
top: 0;
left: 0;
width: 100%;
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/TradeNumberInput/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/TradeNumberInput/index.tsx
index cacd356cc6..ac9a5f722b 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/TradeNumberInput/index.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/pure/TradeNumberInput/index.tsx
@@ -1,10 +1,10 @@
import { useCallback, useEffect, useState } from 'react'
+import carretDown from '@cowprotocol/assets/cow-swap/carret-down.svg'
+
import BigNumberJs from 'bignumber.js'
import SVG from 'react-inlinesvg'
-import carretDown from 'legacy/assets/cow-swap/carret-down.svg'
-
import { TradeWidgetField, TradeWidgetFieldProps } from 'modules/trade/pure/TradeWidgetField'
import { ArrowsWrapper, InputWrapper, NumericalInput, Suffix } from './styled'
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/TradeNumberInput/styled.tsx b/apps/cowswap-frontend/src/modules/trade/pure/TradeNumberInput/styled.tsx
index 7dadb4c6d2..82414cb371 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/TradeNumberInput/styled.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/pure/TradeNumberInput/styled.tsx
@@ -3,6 +3,8 @@ import styled from 'styled-components/macro'
import Input from 'legacy/components/NumericalInput'
+import { UI } from 'common/constants/theme'
+
export const Suffix = styled.span`
margin: 0 0 0 3px;
opacity: 0.7;
@@ -47,7 +49,7 @@ export const ArrowsWrapper = styled.div`
&:hover {
> span > svg > path {
- fill: ${({ theme }) => theme.text1};
+ fill: var(${UI.COLOR_TEXT1});
}
}
}
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/TradeSelect/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/TradeSelect/index.tsx
index ae2eb60d7c..ba783dd588 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/TradeSelect/index.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/pure/TradeSelect/index.tsx
@@ -3,6 +3,8 @@ import { transparentize } from 'polished'
import { ChevronDown } from 'react-feather'
import styled from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
import { TradeWidgetField, TradeWidgetFieldProps } from '../TradeWidgetField'
export type TradeSelectItem = { label: string; value: unknown }
@@ -15,7 +17,7 @@ export interface TradeSelectProps extends TradeWidgetFieldProps {
}
const StyledMenuList = styled(MenuList)`
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
box-shadow: ${({ theme }) => theme.boxShadow2};
margin: 15px 0 0 0;
padding: 16px;
@@ -44,7 +46,7 @@ const StyledMenuButton = styled(MenuButton)`
cursor: pointer;
width: 100%;
justify-content: space-between;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
`
const StyledMenuItem = styled(MenuItem)`
@@ -53,7 +55,7 @@ const StyledMenuItem = styled(MenuItem)`
color: ${({ theme }) => transparentize(0.2, theme.text1)};
&:hover {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
&:not(:last-child) {
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/TradeTextBox/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/TradeTextBox/index.tsx
index 7713ddf16c..346624ecbd 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/TradeTextBox/index.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/pure/TradeTextBox/index.tsx
@@ -1,9 +1,11 @@
import styled from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
import { TradeWidgetField, TradeWidgetFieldProps } from '../TradeWidgetField'
const StyledTradeWidgetField = styled(TradeWidgetField)`
- background-color: ${({ theme }) => theme.bg1};
+ background-color: var(${UI.COLOR_CONTAINER_BG_01});
border: 1px solid ${({ theme }) => theme.grey1};
display: flex;
flex-flow: column wrap;
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/TradeWidgetField/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/TradeWidgetField/index.tsx
index 4705d10da8..26e4a3788e 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/TradeWidgetField/index.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/pure/TradeWidgetField/index.tsx
@@ -1,9 +1,10 @@
import React from 'react'
+import { renderTooltip } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import QuestionHelper from 'legacy/components/QuestionHelper'
-import { renderTooltip } from 'legacy/components/Tooltip'
import { Content, ErrorText, TradeWidgetFieldBox, TradeWidgetFieldLabel } from './styled'
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/UnlockWidgetScreen/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/UnlockWidgetScreen/index.tsx
index 0cdc3c2799..9fe3f30b3c 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/UnlockWidgetScreen/index.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/pure/UnlockWidgetScreen/index.tsx
@@ -1,8 +1,8 @@
-import SVG from 'react-inlinesvg'
+import iconCompleted from '@cowprotocol/assets/cow-swap/check.svg'
+import { ButtonPrimary } from '@cowprotocol/ui'
+import { ExternalLink } from '@cowprotocol/ui'
-import iconCompleted from 'legacy/assets/cow-swap/check.svg'
-import { ButtonPrimary } from 'legacy/components/Button'
-import { ExternalLink } from 'legacy/theme'
+import SVG from 'react-inlinesvg'
import * as styledEl from './styled'
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/UnlockWidgetScreen/styled.ts b/apps/cowswap-frontend/src/modules/trade/pure/UnlockWidgetScreen/styled.ts
index 8572ebdf9b..c2dfd5fc45 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/UnlockWidgetScreen/styled.ts
+++ b/apps/cowswap-frontend/src/modules/trade/pure/UnlockWidgetScreen/styled.ts
@@ -1,6 +1,8 @@
import { transparentize, darken } from 'polished'
import styled from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
export const Container = styled.div`
padding: 16px;
border-radius: 16px;
@@ -10,7 +12,7 @@ export const Container = styled.div`
export const TitleSection = styled.div`
text-align: center;
font-size: 20px;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
margin: 24px auto 42px;
> h3 {
diff --git a/apps/cowswap-frontend/src/modules/trade/state/tradeConfirmStateAtom.ts b/apps/cowswap-frontend/src/modules/trade/state/tradeConfirmStateAtom.ts
index f2a06240e5..9e34917f6b 100644
--- a/apps/cowswap-frontend/src/modules/trade/state/tradeConfirmStateAtom.ts
+++ b/apps/cowswap-frontend/src/modules/trade/state/tradeConfirmStateAtom.ts
@@ -7,6 +7,7 @@ interface TradeConfirmModalState {
pendingTrade: TradeAmounts | null
transactionHash: string | null
error: string | null
+ permitSignatureState: undefined | 'requested' | 'signed'
}
export const tradeConfirmStateAtom = atom({
@@ -14,63 +15,66 @@ export const tradeConfirmStateAtom = atom({
pendingTrade: null,
transactionHash: null,
error: null,
+ permitSignatureState: undefined,
})
export const setOpenTradeConfirmAtom = atom(null, (get, set) => {
- set(tradeConfirmStateAtom, () => {
- return {
- isOpen: true,
- error: null,
- pendingTrade: null,
- transactionHash: null,
- }
- })
+ set(tradeConfirmStateAtom, () => ({
+ isOpen: true,
+ error: null,
+ pendingTrade: null,
+ transactionHash: null,
+ permitSignatureState: undefined,
+ }))
})
export const setCloseTradeConfirmAtom = atom(null, (get, set) => {
- set(tradeConfirmStateAtom, () => {
- return {
- ...get(tradeConfirmStateAtom),
- isOpen: false,
- }
- })
+ set(tradeConfirmStateAtom, () => ({
+ ...get(tradeConfirmStateAtom),
+ isOpen: false,
+ permitSignatureState: undefined,
+ }))
})
export const setErrorTradeConfirmAtom = atom(null, (get, set, error: string) => {
- set(tradeConfirmStateAtom, () => {
- const currentState = get(tradeConfirmStateAtom)
+ set(tradeConfirmStateAtom, () => ({
+ ...get(tradeConfirmStateAtom),
+ error,
+ pendingTrade: null,
+ transactionHash: null,
+ permitSignatureState: undefined,
+ }))
+})
- return {
- isOpen: currentState.isOpen,
- error,
- pendingTrade: null,
- transactionHash: null,
- }
- })
+export const setPermitSignatureRequestedTradeConfirmAtom = atom(null, (get, set, pendingTrade: TradeAmounts) => {
+ set(tradeConfirmStateAtom, () => ({
+ ...get(tradeConfirmStateAtom),
+ pendingTrade,
+ permitSignatureState: 'requested',
+ }))
})
export const setPendingTradeConfirmAtom = atom(null, (get, set, pendingTrade: TradeAmounts) => {
- set(tradeConfirmStateAtom, () => {
- const currentState = get(tradeConfirmStateAtom)
+ const currentState = get(tradeConfirmStateAtom)
+ set(tradeConfirmStateAtom, () => {
return {
- isOpen: currentState.isOpen,
+ ...currentState,
error: null,
pendingTrade,
transactionHash: null,
+ // Only move to the next state if coming in the right sequence.
+ // Otherwise, reset it
+ permitSignatureState: currentState.permitSignatureState === 'requested' ? 'signed' : undefined,
}
})
})
export const setTxHashTradeConfirmAtom = atom(null, (get, set, transactionHash: string) => {
- set(tradeConfirmStateAtom, () => {
- const currentState = get(tradeConfirmStateAtom)
-
- return {
- isOpen: currentState.isOpen,
- error: null,
- pendingTrade: null,
- transactionHash,
- }
- })
+ set(tradeConfirmStateAtom, () => ({
+ ...get(tradeConfirmStateAtom),
+ error: null,
+ pendingTrade: null,
+ transactionHash,
+ }))
})
diff --git a/apps/cowswap-frontend/src/modules/trade/types/TradeDerivedState.ts b/apps/cowswap-frontend/src/modules/trade/types/TradeDerivedState.ts
index abf2be3627..aa80b975e7 100644
--- a/apps/cowswap-frontend/src/modules/trade/types/TradeDerivedState.ts
+++ b/apps/cowswap-frontend/src/modules/trade/types/TradeDerivedState.ts
@@ -1,6 +1,8 @@
import { OrderKind } from '@cowprotocol/cow-sdk'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
+import { TradeType } from '../hooks/useTradeTypeInfo'
+
export interface TradeDerivedState {
readonly inputCurrency: Currency | null
readonly outputCurrency: Currency | null
@@ -25,6 +27,7 @@ export interface TradeDerivedState {
readonly recipient: string | null
readonly recipientAddress: string | null
readonly orderKind: OrderKind
+ readonly tradeType: TradeType | null
}
export const DEFAULT_TRADE_DERIVED_STATE: TradeDerivedState = {
@@ -40,4 +43,5 @@ export const DEFAULT_TRADE_DERIVED_STATE: TradeDerivedState = {
recipient: null,
recipientAddress: null,
orderKind: OrderKind.SELL,
+ tradeType: null,
}
diff --git a/apps/cowswap-frontend/src/modules/trade/types/TradeRawState.ts b/apps/cowswap-frontend/src/modules/trade/types/TradeRawState.ts
index bfbd00e7d8..8403f3b0dc 100644
--- a/apps/cowswap-frontend/src/modules/trade/types/TradeRawState.ts
+++ b/apps/cowswap-frontend/src/modules/trade/types/TradeRawState.ts
@@ -1,7 +1,6 @@
+import { WRAPPED_NATIVE_CURRENCY as WETH } from '@cowprotocol/common-const'
import { OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk'
-import { WRAPPED_NATIVE_CURRENCY as WETH } from 'legacy/constants/tokens'
-
export interface TradeUrlParams {
readonly chainId: string | undefined
readonly inputCurrencyId: string | undefined
diff --git a/apps/cowswap-frontend/src/modules/trade/updaters/RecipientAddressUpdater.tsx b/apps/cowswap-frontend/src/modules/trade/updaters/RecipientAddressUpdater.tsx
index 9322be5251..7e46c45981 100644
--- a/apps/cowswap-frontend/src/modules/trade/updaters/RecipientAddressUpdater.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/updaters/RecipientAddressUpdater.tsx
@@ -1,6 +1,6 @@
import { useEffect } from 'react'
-import useENSAddress from 'legacy/hooks/useENSAddress'
+import { useENSAddress } from '@cowprotocol/ens'
import { useTradeState } from '../hooks/useTradeState'
diff --git a/apps/cowswap-frontend/src/modules/trade/utils/analytics.ts b/apps/cowswap-frontend/src/modules/trade/utils/analytics.ts
index 7ebf50ffe0..f84ebaa76f 100644
--- a/apps/cowswap-frontend/src/modules/trade/utils/analytics.ts
+++ b/apps/cowswap-frontend/src/modules/trade/utils/analytics.ts
@@ -1,5 +1,5 @@
-import { signTradeAnalytics, tradeAnalytics } from 'legacy/components/analytics'
-import { AnalyticsOrderType } from 'legacy/components/analytics/types'
+import { signTradeAnalytics, tradeAnalytics } from '@cowprotocol/analytics'
+import { AnalyticsOrderType } from '@cowprotocol/analytics'
import { USER_SWAP_REJECTED_ERROR } from 'modules/trade/utils/swapErrorHelper'
diff --git a/apps/cowswap-frontend/src/modules/trade/utils/swapErrorHelper.ts b/apps/cowswap-frontend/src/modules/trade/utils/swapErrorHelper.ts
index aeae1e97ae..14d0416ed8 100644
--- a/apps/cowswap-frontend/src/modules/trade/utils/swapErrorHelper.ts
+++ b/apps/cowswap-frontend/src/modules/trade/utils/swapErrorHelper.ts
@@ -1,4 +1,6 @@
-import { getProviderErrorMessage, isRejectRequestProviderError } from 'legacy/utils/misc'
+import { capitalizeFirstLetter, getProviderErrorMessage, isRejectRequestProviderError } from '@cowprotocol/common-utils'
+
+import { getIsOrderBookTypedError } from 'api/gnosisProtocol'
export const USER_SWAP_REJECTED_ERROR = 'User rejected signing the order'
@@ -6,6 +8,12 @@ export function getSwapErrorMessage(error: Error): string {
if (isRejectRequestProviderError(error)) {
return USER_SWAP_REJECTED_ERROR
} else {
- return getProviderErrorMessage(error)
+ const defaultErrorMessage = getProviderErrorMessage(error)
+
+ if (getIsOrderBookTypedError(error)) {
+ return capitalizeFirstLetter(error.body?.description) || defaultErrorMessage
+ }
+
+ return defaultErrorMessage
}
}
diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useGetTradeFormValidation.ts b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useGetTradeFormValidation.ts
index 04c2cb7275..43a1fa6dc3 100644
--- a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useGetTradeFormValidation.ts
+++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useGetTradeFormValidation.ts
@@ -1,6 +1,6 @@
import { useAtomValue } from 'jotai'
-import useDebounce from 'legacy/hooks/useDebounce'
+import { useDebounce } from '@cowprotocol/common-hooks'
import { tradeFormValidationAtom } from '../state/tradeFormValidationAtom'
import { TradeFormValidation } from '../types'
diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormButtonContext.ts b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormButtonContext.ts
index f39622e706..c69bfe49d0 100644
--- a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormButtonContext.ts
+++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormButtonContext.ts
@@ -1,11 +1,12 @@
import { useMemo } from 'react'
+import { useWalletDetails } from '@cowprotocol/wallet'
+
import { useToggleWalletModal } from 'legacy/state/application/hooks'
import { useWrapNativeFlow } from 'modules/trade'
import { useDerivedTradeState } from 'modules/trade/hooks/useDerivedTradeState'
import { useTradeQuote } from 'modules/tradeQuote'
-import { useWalletDetails } from 'modules/wallet'
import { TradeFormButtonContext } from '../types'
diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts
index 0074bcfdf4..1c1d9ce845 100644
--- a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts
+++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts
@@ -1,16 +1,17 @@
import { useMemo } from 'react'
-import useENSAddress from 'legacy/hooks/useENSAddress'
+import { useENSAddress } from '@cowprotocol/ens'
+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'
import { useIsWrapOrUnwrap } from 'modules/trade/hooks/useIsWrapOrUnwrap'
import { useTradeQuote } from 'modules/tradeQuote'
-import { useGnosisSafeInfo, useWalletDetails, useWalletInfo } from 'modules/wallet'
import { useTradeApproveState } from 'common/containers/TradeApprove'
-import { useIsTxBundlingEnabled } from 'common/hooks/featureFlags/useIsTxBundlingEnabled'
import { TradeFormValidationCommonContext } from '../types'
@@ -19,29 +20,32 @@ export function useTradeFormValidationContext(): TradeFormValidationCommonContex
const { state: derivedTradeState } = useDerivedTradeState()
const tradeQuote = useTradeQuote()
- const { inputCurrency, outputCurrency, slippageAdjustedSellAmount, recipient } = derivedTradeState || {}
+ const { inputCurrency, outputCurrency, slippageAdjustedSellAmount, recipient, tradeType } = derivedTradeState || {}
const approvalState = useTradeApproveState(slippageAdjustedSellAmount)
const { address: recipientEnsAddress } = useENSAddress(recipient)
const isSwapUnsupported =
useIsTradeUnsupported(inputCurrency, outputCurrency) || isUnsupportedTokenInQuote(tradeQuote)
- const isTxBundlingEnabled = useIsTxBundlingEnabled()
+ const isBundlingSupported = useIsBundlingSupported()
const isWrapUnwrap = useIsWrapOrUnwrap()
const { isSupportedWallet } = useWalletDetails()
const gnosisSafeInfo = useGnosisSafeInfo()
const isSafeReadonlyUser = gnosisSafeInfo?.isReadOnly || false
+ const isPermitSupported = !!useIsTokenPermittable(inputCurrency, tradeType)
+
const commonContext = {
account,
isWrapUnwrap,
- isTxBundlingEnabled,
+ isBundlingSupported,
isSupportedWallet,
isSwapUnsupported,
isSafeReadonlyUser,
recipientEnsAddress,
approvalState,
tradeQuote,
+ isPermitSupported,
}
return useMemo(() => {
diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/pure/TradeFormBlankButton/index.tsx b/apps/cowswap-frontend/src/modules/tradeFormValidation/pure/TradeFormBlankButton/index.tsx
index efda5ba520..2a17cc57c0 100644
--- a/apps/cowswap-frontend/src/modules/tradeFormValidation/pure/TradeFormBlankButton/index.tsx
+++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/pure/TradeFormBlankButton/index.tsx
@@ -4,6 +4,8 @@ import { Trans } from '@lingui/macro'
import { lighten, transparentize } from 'polished'
import styled from 'styled-components/macro'
+import { UI } from 'common/constants/theme'
+
const LONG_TEXT_LENGTH = 20
const ActionButton = styled.button<{ hasLongText$: boolean }>`
@@ -27,7 +29,7 @@ const ActionButton = styled.button<{ hasLongText$: boolean }>`
}
&:disabled {
- background-color: ${({ theme }) => theme.grey1};
+ background-color: var(${UI.COLOR_GREY});
color: ${({ theme }) => transparentize(0.4, theme.text1)};
background-image: none;
border: 0;
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 fac973ae41..af472af4f5 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,7 @@
import React from 'react'
+import { TokenSymbol } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import styled from 'styled-components/macro'
@@ -7,7 +9,6 @@ import { CompatibilityIssuesWarning } from 'modules/trade/pure/CompatibilityIssu
import { GpQuoteErrorCodes } from 'api/gnosisProtocol/errors/QuoteError'
import { TradeApproveButton } from 'common/containers/TradeApprove'
-import { TokenSymbol } from 'common/pure/TokenSymbol'
import { TradeLoadingButton } from 'common/pure/TradeLoadingButton'
import { TradeFormButtonContext, TradeFormValidation } from '../../types'
diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/services/validateTradeForm.ts b/apps/cowswap-frontend/src/modules/tradeFormValidation/services/validateTradeForm.ts
index ecd88eda97..c128750939 100644
--- a/apps/cowswap-frontend/src/modules/tradeFormValidation/services/validateTradeForm.ts
+++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/services/validateTradeForm.ts
@@ -1,7 +1,6 @@
-import { ApprovalState } from 'legacy/hooks/useApproveCallback/useApproveCallbackMod'
-import { isAddress } from 'legacy/utils'
+import { isAddress, isFractionFalsy } from '@cowprotocol/common-utils'
-import { isFractionFalsy } from 'utils/isFractionFalsy'
+import { ApprovalState } from 'legacy/hooks/useApproveCallback/useApproveCallbackMod'
import { TradeFormValidation, TradeFormValidationContext } from '../types'
@@ -9,7 +8,7 @@ export function validateTradeForm(context: TradeFormValidationContext): TradeFor
const {
derivedTradeState,
approvalState,
- isTxBundlingEnabled,
+ isBundlingSupported,
isWrapUnwrap,
isExpertMode,
isSupportedWallet,
@@ -18,11 +17,13 @@ export function validateTradeForm(context: TradeFormValidationContext): TradeFor
recipientEnsAddress,
tradeQuote,
account,
+ isPermitSupported,
} = context
const { inputCurrency, outputCurrency, inputCurrencyAmount, inputCurrencyBalance, recipient } = derivedTradeState
- const approvalRequired = approvalState === ApprovalState.NOT_APPROVED || approvalState === ApprovalState.PENDING
+ const approvalRequired =
+ !isPermitSupported && (approvalState === ApprovalState.NOT_APPROVED || approvalState === ApprovalState.PENDING)
const inputAmountIsNotSet = !inputCurrencyAmount || isFractionFalsy(inputCurrencyAmount)
@@ -77,11 +78,8 @@ export function validateTradeForm(context: TradeFormValidationContext): TradeFor
}
if (approvalRequired) {
- if (isTxBundlingEnabled) {
- if (isExpertMode) {
- return TradeFormValidation.ExpertApproveAndSwap
- }
- return TradeFormValidation.ApproveAndSwap
+ if (isBundlingSupported) {
+ return isExpertMode ? TradeFormValidation.ExpertApproveAndSwap : TradeFormValidation.ApproveAndSwap
}
return TradeFormValidation.ApproveRequired
}
diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/types.ts b/apps/cowswap-frontend/src/modules/tradeFormValidation/types.ts
index f90018345b..5f14fa9cb9 100644
--- a/apps/cowswap-frontend/src/modules/tradeFormValidation/types.ts
+++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/types.ts
@@ -45,10 +45,11 @@ export interface TradeFormValidationCommonContext {
tradeQuote: TradeQuoteState
recipientEnsAddress: string | null
isWrapUnwrap: boolean
- isTxBundlingEnabled: boolean
+ isBundlingSupported: boolean
isSupportedWallet: boolean
isSwapUnsupported: boolean
isSafeReadonlyUser: boolean
+ isPermitSupported: boolean
}
export interface TradeFormValidationContext extends TradeFormValidationLocalContext, TradeFormValidationCommonContext {}
diff --git a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/__snapshots__/useTradeQuotePolling.test.tsx.snap b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/__snapshots__/useTradeQuotePolling.test.tsx.snap
index 126e1be152..078816dcfa 100644
--- a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/__snapshots__/useTradeQuotePolling.test.tsx.snap
+++ b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/__snapshots__/useTradeQuotePolling.test.tsx.snap
@@ -1,33 +1,33 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`useTradeQuotePolling() When wallet is NOT connected Then the "useAddress" field in the quote request should be 0x000...0000 1`] = `
+exports[`useTradeQuotePolling() When wallet is NOT connected Then the "useAddress" field in the quote request should be 0x000...0000 1`] = `
{
- "amount": "10000000",
+ "appData": "0xbace6e636671f2df6e59ef1eb4e63dce6b646a70c51b004ae5a07a9fbe4356fc",
+ "appDataHash": undefined,
"buyToken": "0x91056D4A53E1faa1A84306D4deAEc71085394bC8",
- "chainId": 1,
- "fromDecimals": 18,
- "isEthFlow": false,
+ "from": "0x0000000000000000000000000000000000000000",
"kind": "sell",
+ "partiallyFillable": false,
"priceQuality": "optimal",
- "receiver": undefined,
+ "receiver": "0x0000000000000000000000000000000000000000",
+ "sellAmountBeforeFee": "10000000",
"sellToken": "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6",
- "toDecimals": 18,
- "userAddress": undefined,
+ "validTo": undefined,
}
`;
exports[`useTradeQuotePolling() When wallet is connected Then should put account address into "useAddress" field in the quote request 1`] = `
{
- "amount": "10000000",
+ "appData": "0xbace6e636671f2df6e59ef1eb4e63dce6b646a70c51b004ae5a07a9fbe4356fc",
+ "appDataHash": undefined,
"buyToken": "0x91056D4A53E1faa1A84306D4deAEc71085394bC8",
- "chainId": 1,
- "fromDecimals": 18,
- "isEthFlow": false,
+ "from": "0x333333f332a06ecb5d20d35da44ba07986d6e203",
"kind": "sell",
+ "partiallyFillable": false,
"priceQuality": "optimal",
"receiver": "0x333333f332a06ecb5d20d35da44ba07986d6e203",
+ "sellAmountBeforeFee": "10000000",
"sellToken": "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6",
- "toDecimals": 18,
- "userAddress": "0x333333f332a06ecb5d20d35da44ba07986d6e203",
+ "validTo": undefined,
}
`;
diff --git a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useProcessUnsupportedTokenError.ts b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useProcessUnsupportedTokenError.ts
index 9d297e3d6d..6bd3d9a61e 100644
--- a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useProcessUnsupportedTokenError.ts
+++ b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useProcessUnsupportedTokenError.ts
@@ -1,11 +1,11 @@
import { useCallback } from 'react'
-import { useAddGpUnsupportedToken } from 'legacy/state/lists/hooks'
+import { getQuoteUnsupportedToken } from '@cowprotocol/common-utils'
+import { useWalletInfo } from '@cowprotocol/wallet'
-import { useWalletInfo } from 'modules/wallet'
+import { useAddGpUnsupportedToken } from 'legacy/state/lists/hooks'
import GpQuoteError from 'api/gnosisProtocol/errors/QuoteError'
-import { getQuoteUnsupportedToken } from 'utils/getQuoteUnsupportedToken'
export function useProcessUnsupportedTokenError() {
const { chainId } = useWalletInfo()
diff --git a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useQuoteParams.ts b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useQuoteParams.ts
index d0d48b150e..bec2b7f889 100644
--- a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useQuoteParams.ts
+++ b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useQuoteParams.ts
@@ -1,21 +1,23 @@
import { useMemo } from 'react'
+import { NATIVE_CURRENCY_BUY_ADDRESS } from '@cowprotocol/common-const'
+import { getAddress } from '@cowprotocol/common-utils'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { CurrencyAmount } from '@uniswap/sdk-core'
-import { NATIVE_CURRENCY_BUY_ADDRESS } from 'legacy/constants'
+import { LegacyFeeQuoteParams } from 'legacy/state/price/types'
+import { useAppData } from 'modules/appData'
import { useEnoughBalanceAndAllowance } from 'modules/tokens'
import { useDerivedTradeState } from 'modules/trade/hooks/useDerivedTradeState'
-import { useWalletInfo } from 'modules/wallet'
import { getPriceQuality } from 'api/gnosisProtocol/api'
-import { LegacyFeeQuoteParams } from 'api/gnosisProtocol/legacy/types'
import { useVerifiedQuotesEnabled } from 'common/hooks/featureFlags/useVerifiedQuotesEnabled'
-import { getAddress } from 'utils/getAddress'
export function useQuoteParams(amount: string | null): LegacyFeeQuoteParams | undefined {
const { chainId, account } = useWalletInfo()
const verifiedQuotesEnabled = useVerifiedQuotesEnabled(chainId)
+ const appData = useAppData()
const { state } = useDerivedTradeState()
@@ -26,7 +28,7 @@ export function useQuoteParams(amount: string | null): LegacyFeeQuoteParams | un
const fromDecimals = inputCurrency?.decimals
const toDecimals = outputCurrency?.decimals
- const enoughBalance = useEnoughBalanceAndAllowance({
+ const { enoughBalance } = useEnoughBalanceAndAllowance({
account,
amount: (inputCurrency && amount && CurrencyAmount.fromRawAmount(inputCurrency, amount)) || undefined,
})
@@ -46,19 +48,23 @@ export function useQuoteParams(amount: string | null): LegacyFeeQuoteParams | un
fromDecimals,
isEthFlow: false,
priceQuality: getPriceQuality({ verifyQuote: verifiedQuotesEnabled && enoughBalance }),
+ appData: appData?.fullAppData,
+ appDataHash: appData?.appDataKeccak256,
}
return params
}, [
+ sellToken,
+ buyToken,
amount,
- account,
- chainId,
orderKind,
- enoughBalance,
- buyToken,
- fromDecimals,
- sellToken,
+ chainId,
+ account,
toDecimals,
+ fromDecimals,
+ enoughBalance,
verifiedQuotesEnabled,
+ appData?.fullAppData,
+ appData?.appDataKeccak256,
])
}
diff --git a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.test.tsx b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.test.tsx
index b1282614ec..4961fa1015 100644
--- a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.test.tsx
+++ b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.test.tsx
@@ -1,40 +1,27 @@
import { ReactNode } from 'react'
+import { COW, ZERO_ADDRESS } from '@cowprotocol/common-const'
+import { WETH_GOERLI } from '@cowprotocol/common-const'
+import { WalletInfo, walletInfoAtom } from '@cowprotocol/wallet'
import { CurrencyAmount } from '@uniswap/sdk-core'
import { renderHook } from '@testing-library/react-hooks'
+import { orderBookApi } from 'cowSdk'
import { JotaiTestProvider, WithMockedWeb3 } from 'test-utils'
-import { COW } from 'legacy/constants/tokens'
-import { WETH_GOERLI } from 'legacy/utils/goerli/constants'
-
import { LimitOrdersDerivedState, limitOrdersDerivedStateAtom } from 'modules/limitOrders/state/limitOrdersRawStateAtom'
-import { useEnoughBalanceAndAllowance } from 'modules/tokens'
+import * as tokensModule from 'modules/tokens'
import { DEFAULT_TRADE_DERIVED_STATE } from 'modules/trade'
-import { WalletInfo } from 'modules/wallet'
-
-import { getQuote } from 'api/gnosisProtocol/api'
import { useTradeQuotePolling } from './useTradeQuotePolling'
-import { walletInfoAtom } from '../../wallet/api/state'
import { tradeQuoteParamsAtom } from '../state/tradeQuoteParamsAtom'
jest.mock('common/hooks/useShouldZeroApprove/useShouldZeroApprove')
-jest.mock('legacy/components/analytics/hooks/useGetMarketDimension')
-
-jest.mock('api/gnosisProtocol/api', () => ({
- ...jest.requireActual('api/gnosisProtocol/api'),
- getQuote: jest.fn(),
-}))
+jest.mock('common/hooks/useGetMarketDimension')
-jest.mock('modules/tokens', () => ({
- ...jest.requireActual('modules/tokens'),
- useEnoughBalanceAndAllowance: jest.fn(),
-}))
-
-const getQuoteMock = jest.mocked(getQuote)
-const useEnoughBalanceAndAllowanceMock = jest.mocked(useEnoughBalanceAndAllowance)
+const getQuoteMock = jest.spyOn(orderBookApi, 'getQuote')
+const useEnoughBalanceAndAllowanceMock = jest.spyOn(tokensModule, 'useEnoughBalanceAndAllowance')
const inputCurrencyAmount = CurrencyAmount.fromRawAmount(WETH_GOERLI, 10_000_000)
const outputCurrencyAmount = CurrencyAmount.fromRawAmount(COW[5], 2_000_000)
@@ -44,6 +31,7 @@ const walletInfoMock: WalletInfo = {
account: '0x333333f332a06ecb5d20d35da44ba07986d6e203',
active: true,
}
+
const limitOrdersDerivedStateMock: LimitOrdersDerivedState = {
...DEFAULT_TRADE_DERIVED_STATE,
inputCurrency: inputCurrencyAmount.currency,
@@ -71,7 +59,7 @@ describe('useTradeQuotePolling()', () => {
beforeEach(() => {
jest.clearAllMocks()
- getQuoteMock.mockReturnValue(new Promise(() => void 0))
+ getQuoteMock.mockImplementation(() => new Promise(() => void 0))
useEnoughBalanceAndAllowanceMock.mockReturnValue(true)
})
@@ -86,14 +74,14 @@ describe('useTradeQuotePolling()', () => {
// Assert
const callParams = getQuoteMock.mock.calls[0][0]
- expect(callParams.userAddress).toBe(walletInfoMock.account) // useAddress field value
+ expect(callParams.from).toBe(walletInfoMock.account) // useAddress field value
expect(getQuoteMock).toHaveBeenCalledTimes(1)
expect(callParams).toMatchSnapshot()
})
})
describe('When wallet is NOT connected', () => {
- it('Then the "useAddress" field in the quote request should be 0x000...0000', () => {
+ it('Then the "useAddress" field in the quote request should be 0x000...0000', () => {
// Arrange
const mocks = [...jotaiMock, [walletInfoAtom, { ...walletInfoMock, account: undefined }]]
@@ -103,7 +91,7 @@ describe('useTradeQuotePolling()', () => {
// Assert
const callParams = getQuoteMock.mock.calls[0][0]
- expect(callParams.userAddress).toBe(undefined) // useAddress field value
+ expect(callParams.from).toBe(ZERO_ADDRESS) // useAddress field value
expect(getQuoteMock).toHaveBeenCalledTimes(1)
expect(callParams).toMatchSnapshot()
})
diff --git a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.ts b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.ts
index 93bceec339..baf4ce96e2 100644
--- a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.ts
+++ b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.ts
@@ -1,13 +1,13 @@
import { useAtomValue, useSetAtom } from 'jotai'
import { useLayoutEffect, useMemo } from 'react'
+import { useDebounce } from '@cowprotocol/common-hooks'
+import { onlyResolvesLast } from '@cowprotocol/common-utils'
import { OrderQuoteResponse } from '@cowprotocol/cow-sdk'
import ms from 'ms.macro'
-import useDebounce from 'legacy/hooks/useDebounce'
import { useIsUnsupportedTokens } from 'legacy/state/lists/hooks'
-import { onlyResolvesLast } from 'legacy/utils/async'
import { useUpdateCurrencyAmount } from 'modules/trade/hooks/useUpdateCurrencyAmount'
import { updateTradeQuoteAtom } from 'modules/tradeQuote/state/tradeQuoteAtom'
diff --git a/apps/cowswap-frontend/src/modules/twap/const.ts b/apps/cowswap-frontend/src/modules/twap/const.ts
index 0acd222869..6689eba082 100644
--- a/apps/cowswap-frontend/src/modules/twap/const.ts
+++ b/apps/cowswap-frontend/src/modules/twap/const.ts
@@ -1,10 +1,9 @@
+import { USDC } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import ms from 'ms.macro'
-import { USDC } from 'legacy/constants/tokens'
-
import { TwapOrderExecutionInfo, TwapOrderStatus } from './types'
export const DEFAULT_TWAP_SLIPPAGE = new Percent(10, 100) // 10%
diff --git a/apps/cowswap-frontend/src/modules/twap/containers/ActionButtons/index.tsx b/apps/cowswap-frontend/src/modules/twap/containers/ActionButtons/index.tsx
index ee126bb1cc..7dce3c832c 100644
--- a/apps/cowswap-frontend/src/modules/twap/containers/ActionButtons/index.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/containers/ActionButtons/index.tsx
@@ -1,6 +1,6 @@
import React from 'react'
-import { twapConversionAnalytics } from 'legacy/components/analytics/events/twapEvents'
+import { twapConversionAnalytics } from '@cowprotocol/analytics'
import { useTradeConfirmActions } from 'modules/trade'
import { TradeFormButtons, TradeFormValidation } from 'modules/tradeFormValidation'
diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapConfirmModal/TwapConfirmDetails.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapConfirmModal/TwapConfirmDetails.tsx
index bb8c04f232..85d0bc2f78 100644
--- a/apps/cowswap-frontend/src/modules/twap/containers/TwapConfirmModal/TwapConfirmDetails.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapConfirmModal/TwapConfirmDetails.tsx
@@ -1,14 +1,14 @@
import React from 'react'
+import { shortenAddress } from '@cowprotocol/common-utils'
+import { useWalletInfo } from '@cowprotocol/wallet'
+
import { isAddress } from 'ethers/lib/utils'
import styled from 'styled-components/macro'
-import { shortenAddress } from 'legacy/utils'
-
import { useAdvancedOrdersDerivedState } from 'modules/advancedOrders'
import { ConfirmDetailsItem } from 'modules/trade/pure/ConfirmDetailsItem'
import { ReviewOrderModalAmountRow } from 'modules/trade/pure/ReviewOrderModalAmountRow'
-import { useWalletInfo } from 'modules/wallet'
import { PartsState } from '../../state/partsStateAtom'
import { deadlinePartsDisplay } from '../../utils/deadlinePartsDisplay'
diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/index.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/index.tsx
index ac50ad1191..a9b4df69c7 100644
--- a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/index.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/index.tsx
@@ -1,16 +1,19 @@
-import { useAtomValue } from 'jotai'
-import { useSetAtom } from 'jotai'
+import { useAtomValue, useSetAtom } from 'jotai'
import { useCallback } from 'react'
-import { modifySafeHandlerAnalytics } from 'legacy/components/analytics/events/twapEvents'
+import { modifySafeHandlerAnalytics } from '@cowprotocol/analytics'
+import { useIsSafeViaWc, useWalletInfo } from '@cowprotocol/wallet'
import { useTradeRouteContext } from 'modules/trade/hooks/useTradeRouteContext'
import { NoImpactWarning } from 'modules/trade/pure/NoImpactWarning'
import { useTradeQuoteFeeFiatAmount } from 'modules/tradeQuote'
-import { useIsSafeViaWc, useWalletInfo } from 'modules/wallet'
import { useShouldZeroApprove } from 'common/hooks/useShouldZeroApprove'
-import { BundleTxApprovalBanner } from 'common/pure/InlineBanner/banners'
+import {
+ BannerOrientation,
+ BundleTxApprovalBanner,
+ CustomRecipientWarningBanner,
+} from 'common/pure/InlineBanner/banners'
import { ZeroApprovalWarning } from 'common/pure/ZeroApprovalWarning'
import {
@@ -79,6 +82,10 @@ export function TwapFormWarnings({ localFormValidation, isConfirmationModal }: T
updateTwapOrdersSettings({ isPriceImpactAccepted: !isPriceImpactAccepted })
}, [updateTwapOrdersSettings, isPriceImpactAccepted])
+ const { account } = useWalletInfo()
+
+ const showRecipientWarning = isConfirmationModal && twapOrder?.receiver && twapOrder.receiver !== account
+
// Don't display any warnings while a wallet is not connected
if (walletIsNotConnected) return null
@@ -103,6 +110,8 @@ export function TwapFormWarnings({ localFormValidation, isConfirmationModal }: T
/>
)}
+ {showRecipientWarning && }
+
{(() => {
if (localFormValidation === TwapFormState.NOT_SAFE) {
return
diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/FallbackHandlerWarning.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/FallbackHandlerWarning.tsx
index 3c1f277f4e..76be392d47 100644
--- a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/FallbackHandlerWarning.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/FallbackHandlerWarning.tsx
@@ -1,6 +1,6 @@
-import styled from 'styled-components/macro'
+import { ExternalLink } from '@cowprotocol/ui'
-import { ExternalLink } from 'legacy/theme'
+import styled from 'styled-components/macro'
import { UNSUPPORTED_SAFE_LINK } from 'modules/twap/const'
@@ -74,7 +74,7 @@ export function FallbackHandlerWarning({
if (isFallbackHandlerSetupAccepted) {
return (
-
+
{fallbackHandlerCheckbox}
@@ -82,7 +82,7 @@ export function FallbackHandlerWarning({
} else {
return (
-
+
Unsupported Safe detected
Connected Safe lacks required fallback handler. Switch to a compatible Safe or modify fallback handler for
diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/SmallPartVolumeWarning.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/SmallPartVolumeWarning.tsx
index 1d6483ef9f..a72afcfb3b 100644
--- a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/SmallPartVolumeWarning.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/SmallPartVolumeWarning.tsx
@@ -1,7 +1,7 @@
import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { TokenAmount } from '@cowprotocol/ui'
import { InlineBanner } from 'common/pure/InlineBanner'
-import { TokenAmount } from 'common/pure/TokenAmount'
import { MINIMUM_PART_SELL_AMOUNT_FIAT } from '../../../const'
diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/SwapPriceDifferenceWarning.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/SwapPriceDifferenceWarning.tsx
index 22887727a2..5500199b33 100644
--- a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/SwapPriceDifferenceWarning.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/SwapPriceDifferenceWarning.tsx
@@ -1,3 +1,4 @@
+import { FiatAmount, TokenAmount } from '@cowprotocol/ui'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { NavLink } from 'react-router-dom'
@@ -7,9 +8,7 @@ import { TradeUrlParams } from 'modules/trade/types/TradeRawState'
import { parameterizeTradeRoute } from 'modules/trade/utils/parameterizeTradeRoute'
import { Routes } from 'common/constants/routes'
-import { FiatAmount } from 'common/pure/FiatAmount'
import { InlineBanner } from 'common/pure/InlineBanner'
-import { TokenAmount } from 'common/pure/TokenAmount'
import { SwapAmountDifference } from '../../../state/swapAmountDifferenceAtom'
@@ -48,7 +47,7 @@ export function SwapPriceDifferenceWarning({
const swapOrderLink = SWAP order
return (
-
+
{isTwapBetter ? (
<>
Maximizing Your Gains! {/* */}
diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/UnsupportedWalletWarning.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/UnsupportedWalletWarning.tsx
index 98bcc29203..8f3198794c 100644
--- a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/UnsupportedWalletWarning.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/UnsupportedWalletWarning.tsx
@@ -1,4 +1,4 @@
-import { ExternalLink } from 'legacy/theme'
+import { ExternalLink } from '@cowprotocol/ui'
import { UNSUPPORTED_WALLET_LINK } from 'modules/twap/const'
@@ -8,7 +8,7 @@ import { InlineBanner } from 'common/pure/InlineBanner'
export function UnsupportedWalletWarning({ isSafeViaWc }: { isSafeViaWc: boolean }) {
if (isSafeViaWc) {
return (
-
+
Use Safe web app
Use the Safe web app for advanced trading.
@@ -19,7 +19,7 @@ export function UnsupportedWalletWarning({ isSafeViaWc }: { isSafeViaWc: boolean
}
return (
-
+
Unsupported wallet detected
TWAP orders currently require a Safe with a special fallback handler. Have one? Switch to it! Need setup?{' '}
diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/index.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/index.tsx
index 7dbd251409..bfbca0f4ea 100644
--- a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/index.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/index.tsx
@@ -1,11 +1,9 @@
import { useAtomValue, useSetAtom } from 'jotai'
import { useEffect, useState } from 'react'
-import {
- openAdvancedOrdersTabAnalytics,
- twapWalletCompatibilityAnalytics,
-} from 'legacy/components/analytics/events/twapEvents'
-import { renderTooltip } from 'legacy/components/Tooltip'
+import { openAdvancedOrdersTabAnalytics, twapWalletCompatibilityAnalytics } from '@cowprotocol/analytics'
+import { renderTooltip } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { useAdvancedOrdersDerivedState, useAdvancedOrdersRawState } from 'modules/advancedOrders'
import { useIsWrapOrUnwrap } from 'modules/trade/hooks/useIsWrapOrUnwrap'
@@ -14,7 +12,6 @@ import { TradeNumberInput } from 'modules/trade/pure/TradeNumberInput'
import { TradeTextBox } from 'modules/trade/pure/TradeTextBox'
import { useGetTradeFormValidation } from 'modules/tradeFormValidation'
import { TwapFormState } from 'modules/twap/pure/PrimaryActionButton/getTwapFormState'
-import { useWalletInfo } from 'modules/wallet'
import { usePrice } from 'common/hooks/usePrice'
import { useRateInfoParams } from 'common/hooks/useRateInfoParams'
diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/tooltips.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/tooltips.tsx
index 6b5aa4f0a5..2568b2652f 100644
--- a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/tooltips.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/tooltips.tsx
@@ -1,10 +1,12 @@
+import ShieldImage from '@cowprotocol/assets/cow-swap/protection.svg'
+
import SVG from 'react-inlinesvg'
import styled from 'styled-components/macro'
-import ShieldImage from 'legacy/assets/cow-swap/protection.svg'
-
import { deadlinePartsDisplay } from 'modules/twap/utils/deadlinePartsDisplay'
+import { UI } from 'common/constants/theme'
+
const IconImage = styled.div`
display: flex;
align-items: center;
@@ -12,7 +14,7 @@ const IconImage = styled.div`
> svg {
opacity: 0.5;
- fill: ${({ theme }) => theme.text1};
+ fill: var(${UI.COLOR_TEXT1});
margin: 0 3px 0 0;
}
`
diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useAllEmulatedOrders.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useAllEmulatedOrders.ts
index f8401d28e8..b02315f559 100644
--- a/apps/cowswap-frontend/src/modules/twap/hooks/useAllEmulatedOrders.ts
+++ b/apps/cowswap-frontend/src/modules/twap/hooks/useAllEmulatedOrders.ts
@@ -1,12 +1,11 @@
import { useMemo } from 'react'
import { OrderClass } from '@cowprotocol/cow-sdk'
+import { useIsSafeApp, useWalletInfo } from '@cowprotocol/wallet'
import { Order } from 'legacy/state/orders/actions'
import { useOrders } from 'legacy/state/orders/hooks'
-import { useIsSafeApp, useWalletInfo } from 'modules/wallet'
-
import { useEmulatedPartOrders } from './useEmulatedPartOrders'
import { useEmulatedTwapOrders } from './useEmulatedTwapOrders'
import { useTwapOrdersTokens } from './useTwapOrdersTokens'
diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useCancelTwapOrder.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useCancelTwapOrder.ts
index a9ff3801e8..155f6288b0 100644
--- a/apps/cowswap-frontend/src/modules/twap/hooks/useCancelTwapOrder.ts
+++ b/apps/cowswap-frontend/src/modules/twap/hooks/useCancelTwapOrder.ts
@@ -1,11 +1,12 @@
import { useAtomValue, useSetAtom } from 'jotai'
import { useCallback } from 'react'
-import { useGP2SettlementContract } from 'legacy/hooks/useContract'
+import { useGP2SettlementContract } from '@cowprotocol/common-hooks'
+import { useSafeAppsSdk } from '@cowprotocol/wallet'
+
import { Order } from 'legacy/state/orders/actions'
import { useComposableCowContract } from 'modules/advancedOrders/hooks/useComposableCowContract'
-import { useSafeAppsSdk } from 'modules/wallet/web3-react/hooks/useSafeAppsSdk'
import type { OnChainCancellation } from 'common/hooks/useCancelOrder/onChainCancellation'
diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.ts
index 28ee879221..72eb4716fb 100644
--- a/apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.ts
+++ b/apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.ts
@@ -2,23 +2,22 @@ import { useAtomValue } from 'jotai'
import { useSetAtom } from 'jotai'
import { useCallback } from 'react'
+import { twapConversionAnalytics } from '@cowprotocol/analytics'
+import { getCowSoundSend } from '@cowprotocol/common-utils'
import { OrderClass, OrderKind } from '@cowprotocol/cow-sdk'
+import { useWalletInfo, useSafeAppsSdk } from '@cowprotocol/wallet'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { Nullish } from 'types'
-import { twapConversionAnalytics } from 'legacy/components/analytics/events/twapEvents'
-import store from 'legacy/state'
+import { cowSwapStore } from 'legacy/state'
import { dispatchPresignedOrderPosted } from 'legacy/state/orders/middleware/updateOrderPopup'
-import { getCowSoundSend } from 'legacy/utils/sound'
import { getOrderSubmitSummary } from 'legacy/utils/trade'
import { updateAdvancedOrdersAtom, useAdvancedOrdersDerivedState } from 'modules/advancedOrders'
import { useAppData, useUploadAppData } from 'modules/appData'
import { useTradeConfirmActions, useTradePriceImpact } from 'modules/trade'
import { SwapFlowAnalyticsContext, tradeFlowAnalytics } from 'modules/trade/utils/analytics'
-import { useWalletInfo } from 'modules/wallet'
-import { useSafeAppsSdk } from 'modules/wallet/web3-react/hooks/useSafeAppsSdk'
import { useConfirmPriceImpactWithoutFee } from 'common/hooks/useConfirmPriceImpactWithoutFee'
@@ -125,7 +124,7 @@ export function useCreateTwapOrder() {
feeAmount: undefined,
})
getCowSoundSend().play()
- dispatchPresignedOrderPosted(store, safeTxHash, summary, OrderClass.LIMIT, 'composable-order')
+ dispatchPresignedOrderPosted(cowSwapStore, safeTxHash, summary, OrderClass.LIMIT, 'composable-order')
uploadAppData({ chainId, orderId, appData: appDataInfo })
updateAdvancedOrdersState({ recipient: null, recipientAddress: null })
diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedPartOrders.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedPartOrders.ts
index 9b905e89bb..a8736ee5f8 100644
--- a/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedPartOrders.ts
+++ b/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedPartOrders.ts
@@ -1,9 +1,10 @@
import { useAtomValue } from 'jotai'
import { useMemo } from 'react'
+import { useMachineTimeMs } from '@cowprotocol/common-hooks'
+
import ms from 'ms.macro'
-import useMachineTimeMs from 'legacy/hooks/useMachineTime'
import { Order } from 'legacy/state/orders/actions'
import { TokensByAddress } from 'modules/tokensList/state/tokensListAtom'
diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedTwapOrders.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedTwapOrders.ts
index 5227eb682d..17dc8e82f9 100644
--- a/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedTwapOrders.ts
+++ b/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedTwapOrders.ts
@@ -1,13 +1,14 @@
import { useAtomValue } from 'jotai'
import { useMemo } from 'react'
+import { useMachineTimeMs } from '@cowprotocol/common-hooks'
+import { useWalletInfo } from '@cowprotocol/wallet'
+
import ms from 'ms.macro'
-import useMachineTimeMs from 'legacy/hooks/useMachineTime'
import { Order } from 'legacy/state/orders/actions'
import { TokensByAddress } from 'modules/tokensList/state/tokensListAtom'
-import { useWalletInfo } from 'modules/wallet'
import { twapOrdersListAtom } from '../state/twapOrdersListAtom'
import { mapTwapOrderToStoreOrder } from '../utils/mapTwapOrderToStoreOrder'
@@ -27,10 +28,13 @@ export function useEmulatedTwapOrders(tokensByAddress: TokensByAddress | undefin
if (!refresher) return []
if (!tokensByAddress) return []
- return allTwapOrders
- .filter((order) => order.chainId === chainId && order.safeAddress.toLowerCase() === accountLowerCase)
- .map((order) => {
- return mapTwapOrderToStoreOrder(order, tokensByAddress)
- })
+ return allTwapOrders.reduce((acc, order) => {
+ if (order.chainId !== chainId || order.safeAddress.toLowerCase() !== accountLowerCase) {
+ return acc
+ }
+
+ acc.push(mapTwapOrderToStoreOrder(order, tokensByAddress))
+ return acc
+ }, [])
}, [allTwapOrders, accountLowerCase, chainId, tokensByAddress, refresher])
}
diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useExtensibleFallbackContext.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useExtensibleFallbackContext.ts
index e4891ad27b..1d5fccb200 100644
--- a/apps/cowswap-frontend/src/modules/twap/hooks/useExtensibleFallbackContext.ts
+++ b/apps/cowswap-frontend/src/modules/twap/hooks/useExtensibleFallbackContext.ts
@@ -1,12 +1,10 @@
+import { GPv2Settlement } from '@cowprotocol/abis'
+import { useGP2SettlementContract } from '@cowprotocol/common-hooks'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
-import { GPv2Settlement } from '@cowswap/abis'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Web3Provider } from '@ethersproject/providers'
import { useWeb3React } from '@web3-react/core'
-import { useGP2SettlementContract } from 'legacy/hooks/useContract'
-
-import { useWalletInfo } from 'modules/wallet'
-
export interface ExtensibleFallbackContext {
safeAddress: string
chainId: SupportedChainId
diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useFallbackHandlerVerification.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useFallbackHandlerVerification.ts
index 6c4ab260e4..a849e84a1c 100644
--- a/apps/cowswap-frontend/src/modules/twap/hooks/useFallbackHandlerVerification.ts
+++ b/apps/cowswap-frontend/src/modules/twap/hooks/useFallbackHandlerVerification.ts
@@ -1,6 +1,6 @@
import { useAtomValue } from 'jotai'
-import { useWalletInfo } from 'modules/wallet'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { ExtensibleFallbackVerification } from '../services/verifyExtensibleFallback'
import { fallbackHandlerVerificationAtom } from '../state/fallbackHandlerVerificationAtom'
diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useFetchTwapOrdersFromSafe.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useFetchTwapOrdersFromSafe.ts
index 7903898d73..e003d79c2b 100644
--- a/apps/cowswap-frontend/src/modules/twap/hooks/useFetchTwapOrdersFromSafe.ts
+++ b/apps/cowswap-frontend/src/modules/twap/hooks/useFetchTwapOrdersFromSafe.ts
@@ -1,10 +1,10 @@
import { useEffect, useState } from 'react'
-import { ComposableCoW } from '@cowswap/abis'
+import { ComposableCoW } from '@cowprotocol/abis'
import ms from 'ms.macro'
-import { useSafeApiKit } from 'api/gnosisSafe/hooks/useSafeApiKit'
+import { useSafeApiKit } from 'common/hooks/useSafeApiKit'
import { fetchTwapOrdersFromSafe } from '../services/fetchTwapOrdersFromSafe'
import { TwapOrdersSafeData } from '../types'
diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useSetupTwapAmountsFromUrls.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useSetupTwapAmountsFromUrls.ts
index 5b4d408c4a..613568ffc4 100644
--- a/apps/cowswap-frontend/src/modules/twap/hooks/useSetupTwapAmountsFromUrls.ts
+++ b/apps/cowswap-frontend/src/modules/twap/hooks/useSetupTwapAmountsFromUrls.ts
@@ -1,13 +1,13 @@
import { useCallback, useLayoutEffect, useMemo } from 'react'
+import { getIntOrFloat } from '@cowprotocol/common-utils'
+
import { useLocation, useNavigate } from 'react-router-dom'
-import { Field } from 'legacy/state/swap/actions'
+import { Field } from 'legacy/state/types'
import { TRADE_URL_BUY_AMOUNT_KEY, TRADE_URL_SELL_AMOUNT_KEY } from 'modules/trade/const/tradeUrl'
-import { getIntOrFloat } from 'utils/getIntOrFloat'
-
import { useAdvancedOrdersActions } from '../../advancedOrders/hooks/useAdvancedOrdersActions'
// TODO: unify into a single thing for all forms
diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapFormState.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapFormState.ts
index 360378d170..f6a693c42c 100644
--- a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapFormState.ts
+++ b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapFormState.ts
@@ -1,7 +1,7 @@
import { useAtomValue } from 'jotai'
import { useMemo } from 'react'
-import { useIsSafeApp, useWalletInfo } from 'modules/wallet'
+import { useIsSafeApp, useWalletInfo } from '@cowprotocol/wallet'
import { useFallbackHandlerVerification } from './useFallbackHandlerVerification'
diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrderCreationContext.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrderCreationContext.ts
index d23df78b79..377502dac3 100644
--- a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrderCreationContext.ts
+++ b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrderCreationContext.ts
@@ -1,13 +1,12 @@
-import { ComposableCoW, Erc20 } from '@cowswap/abis'
+import { ComposableCoW, Erc20 } from '@cowprotocol/abis'
+import { useTokenContract } from '@cowprotocol/common-hooks'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { Nullish } from 'types'
-import { useTokenContract } from 'legacy/hooks/useContract'
-
import { CURRENT_BLOCK_FACTORY_ADDRESS } from 'modules/advancedOrders'
import { useComposableCowContract } from 'modules/advancedOrders/hooks/useComposableCowContract'
-import { useWalletInfo } from 'modules/wallet'
import { useNeedsApproval } from 'common/hooks/useNeedsApproval'
import { useNeedsZeroApproval } from 'common/hooks/useNeedsZeroApproval'
diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersAuthMulticall.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersAuthMulticall.ts
index 508d091c98..4f39c7570a 100644
--- a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersAuthMulticall.ts
+++ b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersAuthMulticall.ts
@@ -1,6 +1,6 @@
import { useMemo } from 'react'
-import { ComposableCoW } from '@cowswap/abis'
+import { ComposableCoW } from '@cowprotocol/abis'
import { ListenerOptionsWithGas } from '@uniswap/redux-multicall'
import { useSingleContractMultipleData } from 'lib/hooks/multicall'
diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersExecutions.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersExecutions.ts
index 5792ce6dd6..f258eb030f 100644
--- a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersExecutions.ts
+++ b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersExecutions.ts
@@ -1,11 +1,11 @@
import { useAtomValue } from 'jotai'
import { useMemo } from 'react'
+import { useWalletInfo } from '@cowprotocol/wallet'
+
import { Order, OrderInfoApi } from 'legacy/state/orders/actions'
import { useOrdersById } from 'legacy/state/orders/hooks'
-import { useWalletInfo } from 'modules/wallet'
-
import { getIsFinalizedOrder } from 'utils/orderUtils/getIsFinalizedOrder'
import { DEFAULT_TWAP_EXECUTION_INFO } from '../const'
diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersTradeableMulticall.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersTradeableMulticall.ts
index 0b759dc5fa..458b109c44 100644
--- a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersTradeableMulticall.ts
+++ b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersTradeableMulticall.ts
@@ -1,6 +1,6 @@
import { useMemo } from 'react'
-import { ComposableCoW, GPv2Order } from '@cowswap/abis'
+import { ComposableCoW, GPv2Order } from '@cowprotocol/abis'
import { ListenerOptionsWithGas } from '@uniswap/redux-multicall'
import { useSingleContractMultipleData } from 'lib/hooks/multicall'
diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapWarningsContext.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapWarningsContext.ts
index 6b1d38ac00..b02275864d 100644
--- a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapWarningsContext.ts
+++ b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapWarningsContext.ts
@@ -1,8 +1,9 @@
import { useMemo } from 'react'
+import { useWalletInfo } from '@cowprotocol/wallet'
+
import { useTradePriceImpact } from 'modules/trade'
import { TradeFormValidation, useGetTradeFormValidation } from 'modules/tradeFormValidation'
-import { useWalletInfo } from 'modules/wallet'
const NOT_BLOCKING_VALIDATIONS = [
TradeFormValidation.ExpertApproveAndSwap,
diff --git a/apps/cowswap-frontend/src/modules/twap/pure/AmountParts/index.tsx b/apps/cowswap-frontend/src/modules/twap/pure/AmountParts/index.tsx
index 0a779625b8..282d52ed9c 100644
--- a/apps/cowswap-frontend/src/modules/twap/pure/AmountParts/index.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/pure/AmountParts/index.tsx
@@ -1,12 +1,12 @@
import React, { ReactNode } from 'react'
+import { renderTooltip } from '@cowprotocol/ui'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import { Trans } from '@lingui/macro'
import { Nullish } from 'types'
import QuestionHelper from 'legacy/components/QuestionHelper'
-import { renderTooltip } from 'legacy/components/Tooltip'
import { LabelTooltipItems } from 'modules/twap'
diff --git a/apps/cowswap-frontend/src/modules/twap/pure/AmountParts/styled.tsx b/apps/cowswap-frontend/src/modules/twap/pure/AmountParts/styled.tsx
index e753097f32..f27a19a309 100644
--- a/apps/cowswap-frontend/src/modules/twap/pure/AmountParts/styled.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/pure/AmountParts/styled.tsx
@@ -1,3 +1,5 @@
+import { FiatAmount, TokenAmount } from '@cowprotocol/ui'
+
import { transparentize } from 'polished'
import styled from 'styled-components/macro'
@@ -5,9 +7,6 @@ import { QuestionWrapper } from 'legacy/components/QuestionHelper'
import { TradeWidgetFieldBox, TradeWidgetFieldLabel } from 'modules/trade/pure/TradeWidgetField/styled'
-import { FiatAmount } from 'common/pure/FiatAmount'
-import { TokenAmount } from 'common/pure/TokenAmount'
-
export const Wrapper = styled.div`
display: flex;
grid-gap: 8px;
diff --git a/apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/index.tsx b/apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/index.tsx
index dac48a0d12..244e0441c4 100644
--- a/apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/index.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/index.tsx
@@ -1,10 +1,10 @@
import { useCallback, useEffect, useState } from 'react'
+import { ButtonPrimary } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import ms from 'ms'
-import { ButtonPrimary } from 'legacy/components/Button'
-
import { TradeNumberInput } from 'modules/trade/pure/TradeNumberInput'
import { CowModal as Modal } from 'common/pure/Modal'
diff --git a/apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/styled.tsx b/apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/styled.tsx
index 7257c673ac..7579d35386 100644
--- a/apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/styled.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/styled.tsx
@@ -1,11 +1,13 @@
+import { ButtonSecondary } from '@cowprotocol/ui'
+
import { X } from 'react-feather'
import styled from 'styled-components/macro'
-import { ButtonSecondary } from 'legacy/components/Button'
-
import { NumericalInput } from 'modules/trade/pure/TradeNumberInput/styled'
import { TradeWidgetFieldBox } from 'modules/trade/pure/TradeWidgetField/styled'
+import { UI } from 'common/constants/theme'
+
export const ModalWrapper = styled.div`
display: flex;
flex-flow: column wrap;
@@ -70,18 +72,18 @@ export const CloseIcon = styled(X)`
}
> line {
- stroke: ${({ theme }) => theme.text1};
+ stroke: var(${UI.COLOR_TEXT1});
}
`
export const CancelButton = styled(ButtonSecondary)`
background: transparent;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
border: 1px solid ${({ theme }) => theme.text1};
:hover {
background: transparent;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
border: 1px solid ${({ theme }) => theme.text1};
}
`
diff --git a/apps/cowswap-frontend/src/modules/twap/pure/DeadlineSelector/index.tsx b/apps/cowswap-frontend/src/modules/twap/pure/DeadlineSelector/index.tsx
index 36260920b4..7ae76f2cf3 100644
--- a/apps/cowswap-frontend/src/modules/twap/pure/DeadlineSelector/index.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/pure/DeadlineSelector/index.tsx
@@ -1,8 +1,8 @@
import React, { useCallback, useMemo, useState } from 'react'
-import styled from 'styled-components/macro'
+import { renderTooltip } from '@cowprotocol/ui'
-import { renderTooltip } from 'legacy/components/Tooltip'
+import styled from 'styled-components/macro'
import { TradeSelect, TradeSelectItem } from 'modules/trade/pure/TradeSelect'
import { Content } from 'modules/trade/pure/TradeWidgetField/styled'
diff --git a/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/getTwapFormState.test.ts b/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/getTwapFormState.test.ts
index 64747a4f5e..18a51eb043 100644
--- a/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/getTwapFormState.test.ts
+++ b/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/getTwapFormState.test.ts
@@ -1,8 +1,7 @@
+import { COW } from '@cowprotocol/common-const'
+import { WETH_GOERLI } from '@cowprotocol/common-const'
import { CurrencyAmount } from '@uniswap/sdk-core'
-import { COW } from 'legacy/constants/tokens'
-import { WETH_GOERLI } from 'legacy/utils/goerli/constants'
-
import { getTwapFormState, TwapFormState } from './getTwapFormState'
import { ExtensibleFallbackVerification } from '../../services/verifyExtensibleFallback'
diff --git a/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/getTwapFormState.tsx b/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/getTwapFormState.tsx
index 99e058b2ab..0d3e73c5b7 100644
--- a/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/getTwapFormState.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/getTwapFormState.tsx
@@ -1,10 +1,9 @@
+import { isFractionFalsy } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import { Nullish } from 'types'
-import { isFractionFalsy } from 'utils/isFractionFalsy'
-
import { ExtensibleFallbackVerification } from '../../services/verifyExtensibleFallback'
import { TWAPOrder } from '../../types'
import { isPartTimeIntervalTooShort } from '../../utils/isPartTimeIntervalTooShort'
diff --git a/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/index.tsx b/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/index.tsx
index f7072b0064..1be765d11e 100644
--- a/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/index.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/index.tsx
@@ -1,7 +1,6 @@
import React from 'react'
-import { ButtonPrimary } from 'legacy/components/Button'
-import { ButtonSize } from 'legacy/theme/enum'
+import { ButtonSize, ButtonPrimary } from '@cowprotocol/ui'
import { TwapFormState } from './getTwapFormState'
diff --git a/apps/cowswap-frontend/src/modules/twap/services/cancelTwapOrderTxs.ts b/apps/cowswap-frontend/src/modules/twap/services/cancelTwapOrderTxs.ts
index a0ce440609..b7ae0ca152 100644
--- a/apps/cowswap-frontend/src/modules/twap/services/cancelTwapOrderTxs.ts
+++ b/apps/cowswap-frontend/src/modules/twap/services/cancelTwapOrderTxs.ts
@@ -1,4 +1,4 @@
-import { ComposableCoW, GPv2Settlement } from '@cowswap/abis'
+import { ComposableCoW, GPv2Settlement } from '@cowprotocol/abis'
import { BigNumber } from '@ethersproject/bignumber'
import { MetaTransactionData } from '@safe-global/safe-core-sdk-types'
diff --git a/apps/cowswap-frontend/src/modules/twap/services/createTwapOrderTxs.test.ts b/apps/cowswap-frontend/src/modules/twap/services/createTwapOrderTxs.test.ts
index 24c24db14b..950ee1da98 100644
--- a/apps/cowswap-frontend/src/modules/twap/services/createTwapOrderTxs.test.ts
+++ b/apps/cowswap-frontend/src/modules/twap/services/createTwapOrderTxs.test.ts
@@ -1,9 +1,7 @@
+import { COW, WETH_GOERLI } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { CurrencyAmount } from '@uniswap/sdk-core'
-import { COW } from 'legacy/constants/tokens'
-import { WETH_GOERLI } from 'legacy/utils/goerli/constants'
-
import { COMPOSABLE_COW_ADDRESS, CURRENT_BLOCK_FACTORY_ADDRESS } from 'modules/advancedOrders'
import { getAppData } from 'modules/appData'
@@ -13,6 +11,8 @@ import { TwapOrderCreationContext } from '../hooks/useTwapOrderCreationContext'
import { TWAPOrder } from '../types'
import { buildTwapOrderParamsStruct } from '../utils/buildTwapOrderParamsStruct'
+jest.mock('modules/permit')
+
const APP_DATA_HASH = getAppData().appDataKeccak256
const chainId = SupportedChainId.GOERLI
diff --git a/apps/cowswap-frontend/src/modules/twap/services/fetchTwapOrdersFromSafe.ts b/apps/cowswap-frontend/src/modules/twap/services/fetchTwapOrdersFromSafe.ts
index b4e2b04805..17c721c6ba 100644
--- a/apps/cowswap-frontend/src/modules/twap/services/fetchTwapOrdersFromSafe.ts
+++ b/apps/cowswap-frontend/src/modules/twap/services/fetchTwapOrdersFromSafe.ts
@@ -1,12 +1,11 @@
-import { ComposableCoW } from '@cowswap/abis'
+import { ComposableCoW } from '@cowprotocol/abis'
+import { delay, isTruthy } from '@cowprotocol/common-utils'
import type SafeApiKit from '@safe-global/api-kit'
import type { AllTransactionsListResponse } from '@safe-global/api-kit'
import type { SafeMultisigTransactionResponse } from '@safe-global/safe-core-sdk-types'
import ms from 'ms.macro'
-import { delay, isTruthy } from 'legacy/utils/misc'
-
import { SafeTransactionParams } from 'common/types'
import { ConditionalOrderParams, TwapOrdersSafeData } from '../types'
diff --git a/apps/cowswap-frontend/src/modules/twap/services/getSignatureVerifierContract.ts b/apps/cowswap-frontend/src/modules/twap/services/getSignatureVerifierContract.ts
index a67d80ff0a..d75e61d9f9 100644
--- a/apps/cowswap-frontend/src/modules/twap/services/getSignatureVerifierContract.ts
+++ b/apps/cowswap-frontend/src/modules/twap/services/getSignatureVerifierContract.ts
@@ -1,4 +1,4 @@
-import { SignatureVerifierMuxerAbi, SignatureVerifierMuxer } from '@cowswap/abis'
+import { SignatureVerifierMuxerAbi, SignatureVerifierMuxer } from '@cowprotocol/abis'
import { Contract } from '@ethersproject/contracts'
import { ExtensibleFallbackContext } from '../hooks/useExtensibleFallbackContext'
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/composableOrdersPopupMiddleware.ts b/apps/cowswap-frontend/src/modules/twap/state/composableOrdersPopupMiddleware.ts
similarity index 64%
rename from apps/cowswap-frontend/src/legacy/state/orders/middleware/composableOrdersPopupMiddleware.ts
rename to apps/cowswap-frontend/src/modules/twap/state/composableOrdersPopupMiddleware.ts
index 80e9f25e42..eb9c3673ea 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/composableOrdersPopupMiddleware.ts
+++ b/apps/cowswap-frontend/src/modules/twap/state/composableOrdersPopupMiddleware.ts
@@ -1,18 +1,18 @@
+import { isTruthy } from '@cowprotocol/common-utils'
+import { jotaiStore } from '@cowprotocol/core'
+
import { isAnyOf } from '@reduxjs/toolkit'
-import { jotaiStore } from 'jotaiStore'
import { Middleware } from 'redux'
-import { isTruthy } from 'legacy/utils/misc'
-
-import { tokensByAddressAtom } from 'modules/tokensList/state/tokensListAtom'
-import { setTwapOrderStatusAtom, twapOrdersAtom } from 'modules/twap/state/twapOrdersListAtom'
-import { TwapOrderStatus } from 'modules/twap/types'
-import { mapTwapOrderToStoreOrder } from 'modules/twap/utils/mapTwapOrderToStoreOrder'
+import { AppState } from 'legacy/state'
+import { cancelOrdersBatch } from 'legacy/state/orders/actions'
+import { batchCancelOrdersPopup } from 'legacy/state/orders/middleware/batchCancelOrdersPopup'
-import { batchCancelOrdersPopup } from './batchCancelOrdersPopup'
+import { setTwapOrderStatusAtom, twapOrdersAtom } from './twapOrdersListAtom'
-import { AppState } from '../../index'
-import { cancelOrdersBatch } from '../actions'
+import { tokensByAddressAtom } from '../../tokensList/state/tokensListAtom'
+import { TwapOrderStatus } from '../types'
+import { mapTwapOrderToStoreOrder } from '../utils/mapTwapOrderToStoreOrder'
const isCancelOrdersBatch = isAnyOf(cancelOrdersBatch)
diff --git a/apps/cowswap-frontend/src/modules/twap/state/fallbackHandlerVerificationAtom.ts b/apps/cowswap-frontend/src/modules/twap/state/fallbackHandlerVerificationAtom.ts
index eee1e16545..50733c8c1a 100644
--- a/apps/cowswap-frontend/src/modules/twap/state/fallbackHandlerVerificationAtom.ts
+++ b/apps/cowswap-frontend/src/modules/twap/state/fallbackHandlerVerificationAtom.ts
@@ -1,6 +1,6 @@
import { atomWithStorage } from 'jotai/utils'
-import { atomWithPartialUpdate } from 'utils/jotai/atomWithPartialUpdate'
+import { atomWithPartialUpdate } from '@cowprotocol/common-utils'
import { ExtensibleFallbackVerification } from '../services/verifyExtensibleFallback'
diff --git a/apps/cowswap-frontend/src/modules/twap/state/swapAmountDifferenceAtom.ts b/apps/cowswap-frontend/src/modules/twap/state/swapAmountDifferenceAtom.ts
index ea71c92d27..29ef390c9a 100644
--- a/apps/cowswap-frontend/src/modules/twap/state/swapAmountDifferenceAtom.ts
+++ b/apps/cowswap-frontend/src/modules/twap/state/swapAmountDifferenceAtom.ts
@@ -1,9 +1,8 @@
import { atom } from 'jotai'
+import { isFractionFalsy } from '@cowprotocol/common-utils'
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
-import { isFractionFalsy } from 'utils/isFractionFalsy'
-
import { fullAmountQuoteAtom } from './fullAmountQuoteAtom'
import { partsStateAtom } from './partsStateAtom'
diff --git a/apps/cowswap-frontend/src/modules/twap/state/twapOrderAtom.ts b/apps/cowswap-frontend/src/modules/twap/state/twapOrderAtom.ts
index 490c60da70..5c8a389f26 100644
--- a/apps/cowswap-frontend/src/modules/twap/state/twapOrderAtom.ts
+++ b/apps/cowswap-frontend/src/modules/twap/state/twapOrderAtom.ts
@@ -1,11 +1,11 @@
import { atom } from 'jotai'
+import { walletInfoAtom } from '@cowprotocol/wallet'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { advancedOrdersDerivedStateAtom } from 'modules/advancedOrders'
import { getAppData } from 'modules/appData'
import { appDataInfoAtom } from 'modules/appData/state/atoms'
-import { walletInfoAtom } from 'modules/wallet/api/state'
import { twapOrderSlippageAtom, twapOrdersSettingsAtom } from './twapOrdersSettingsAtom'
diff --git a/apps/cowswap-frontend/src/modules/twap/state/twapOrdersListAtom.ts b/apps/cowswap-frontend/src/modules/twap/state/twapOrdersListAtom.ts
index 76d7ae9e15..3899fa26bd 100644
--- a/apps/cowswap-frontend/src/modules/twap/state/twapOrdersListAtom.ts
+++ b/apps/cowswap-frontend/src/modules/twap/state/twapOrdersListAtom.ts
@@ -1,15 +1,13 @@
import { atom } from 'jotai'
import { atomWithStorage } from 'jotai/utils'
-import { getJotaiIsolatedStorage } from 'jotaiStore'
+import { deepEqual } from '@cowprotocol/common-utils'
+import { getJotaiIsolatedStorage } from '@cowprotocol/core'
+import { walletInfoAtom } from '@cowprotocol/wallet'
-import store from 'legacy/state'
+import { cowSwapStore } from 'legacy/state'
import { deleteOrders } from 'legacy/state/orders/actions'
-import { walletInfoAtom } from 'modules/wallet/api/state'
-
-import { deepEqual } from 'utils/deepEqual'
-
import { TWAP_FINAL_STATUSES } from '../const'
import { TwapOrderItem, TwapOrderStatus } from '../types'
import { updateTwapOrdersList } from '../utils/updateTwapOrdersList'
@@ -55,7 +53,7 @@ export const deleteTwapOrdersFromListAtom = atom(null, (get, set, ids: string[])
delete currentState[id]
})
- store.dispatch(deleteOrders({ chainId, ids }))
+ cowSwapStore.dispatch(deleteOrders({ chainId, ids }))
set(twapOrdersAtom, currentState)
})
diff --git a/apps/cowswap-frontend/src/modules/twap/state/twapOrdersSettingsAtom.ts b/apps/cowswap-frontend/src/modules/twap/state/twapOrdersSettingsAtom.ts
index 694c0e4042..faaecd4b8d 100644
--- a/apps/cowswap-frontend/src/modules/twap/state/twapOrdersSettingsAtom.ts
+++ b/apps/cowswap-frontend/src/modules/twap/state/twapOrdersSettingsAtom.ts
@@ -1,9 +1,9 @@
import { atom } from 'jotai'
import { atomWithStorage } from 'jotai/utils'
+import { getJotaiIsolatedStorage } from '@cowprotocol/core'
import { Percent } from '@uniswap/sdk-core'
-import { getJotaiIsolatedStorage } from 'jotaiStore'
import { Milliseconds } from 'types'
import { DEFAULT_NUM_OF_PARTS, DEFAULT_ORDER_DEADLINE, DEFAULT_TWAP_SLIPPAGE } from '../const'
diff --git a/apps/cowswap-frontend/src/modules/twap/state/twapPartOrdersAtom.ts b/apps/cowswap-frontend/src/modules/twap/state/twapPartOrdersAtom.ts
index 0e345fd116..d7423130c7 100644
--- a/apps/cowswap-frontend/src/modules/twap/state/twapPartOrdersAtom.ts
+++ b/apps/cowswap-frontend/src/modules/twap/state/twapPartOrdersAtom.ts
@@ -1,13 +1,10 @@
import { atom } from 'jotai'
import { atomWithStorage } from 'jotai/utils'
+import { deepEqual } from '@cowprotocol/common-utils'
+import { getJotaiIsolatedStorage } from '@cowprotocol/core'
import { OrderParameters, SupportedChainId } from '@cowprotocol/cow-sdk'
-
-import { getJotaiIsolatedStorage } from 'jotaiStore'
-
-import { walletInfoAtom } from 'modules/wallet/api/state'
-
-import { deepEqual } from 'utils/deepEqual'
+import { walletInfoAtom } from '@cowprotocol/wallet'
export interface TwapPartOrderItem {
uid: string
diff --git a/apps/cowswap-frontend/src/modules/twap/updaters/CreatedInOrderBookOrdersUpdater.tsx b/apps/cowswap-frontend/src/modules/twap/updaters/CreatedInOrderBookOrdersUpdater.tsx
index b721894cbf..2317c59b22 100644
--- a/apps/cowswap-frontend/src/modules/twap/updaters/CreatedInOrderBookOrdersUpdater.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/updaters/CreatedInOrderBookOrdersUpdater.tsx
@@ -3,13 +3,13 @@ import { useSetAtom } from 'jotai'
import { useEffect, useMemo } from 'react'
import { EnrichedOrder } from '@cowprotocol/cow-sdk'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { useAsyncMemo } from 'use-async-memo'
import { useAddOrUpdateOrders } from 'legacy/state/orders/hooks'
import { useTokensForOrdersList, getTokensListFromOrders, useSWRProdOrders } from 'modules/orders'
-import { useWalletInfo } from 'modules/wallet'
import { twapOrdersAtom } from '../state/twapOrdersListAtom'
import { TwapPartOrderItem, twapPartOrdersListAtom, updatePartOrdersAtom } from '../state/twapPartOrdersAtom'
diff --git a/apps/cowswap-frontend/src/modules/twap/updaters/FallbackHandlerVerificationUpdater.tsx b/apps/cowswap-frontend/src/modules/twap/updaters/FallbackHandlerVerificationUpdater.tsx
index a6fe2a9f09..8ec9e6244d 100644
--- a/apps/cowswap-frontend/src/modules/twap/updaters/FallbackHandlerVerificationUpdater.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/updaters/FallbackHandlerVerificationUpdater.tsx
@@ -1,9 +1,9 @@
import { useSetAtom } from 'jotai'
import { useEffect } from 'react'
-import { useAsyncMemo } from 'use-async-memo'
+import { useWalletInfo } from '@cowprotocol/wallet'
-import { useWalletInfo } from 'modules/wallet'
+import { useAsyncMemo } from 'use-async-memo'
import { useExtensibleFallbackContext } from '../hooks/useExtensibleFallbackContext'
import { useFallbackHandlerVerification } from '../hooks/useFallbackHandlerVerification'
diff --git a/apps/cowswap-frontend/src/modules/twap/updaters/FullAmountQuoteUpdater.tsx b/apps/cowswap-frontend/src/modules/twap/updaters/FullAmountQuoteUpdater.tsx
index 20f81b6f1c..361826f498 100644
--- a/apps/cowswap-frontend/src/modules/twap/updaters/FullAmountQuoteUpdater.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/updaters/FullAmountQuoteUpdater.tsx
@@ -1,10 +1,9 @@
import { useSetAtom } from 'jotai'
import { useEffect } from 'react'
+import { onlyResolvesLast } from '@cowprotocol/common-utils'
import { OrderQuoteResponse } from '@cowprotocol/cow-sdk'
-import { onlyResolvesLast } from 'legacy/utils/async'
-
import { useAdvancedOrdersDerivedState } from 'modules/advancedOrders'
import { useTradeQuote, useQuoteParams } from 'modules/tradeQuote'
diff --git a/apps/cowswap-frontend/src/modules/twap/updaters/PartOrdersUpdater.tsx b/apps/cowswap-frontend/src/modules/twap/updaters/PartOrdersUpdater.tsx
index 0e3ddbb3df..bf0baa2519 100644
--- a/apps/cowswap-frontend/src/modules/twap/updaters/PartOrdersUpdater.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/updaters/PartOrdersUpdater.tsx
@@ -1,12 +1,10 @@
import { useAtomValue, useSetAtom } from 'jotai'
import { useEffect } from 'react'
+import { isTruthy } from '@cowprotocol/common-utils'
import { Order } from '@cowprotocol/contracts'
import { OrderParameters, SupportedChainId } from '@cowprotocol/cow-sdk'
-
-import { isTruthy } from 'legacy/utils/misc'
-
-import { useWalletInfo } from 'modules/wallet'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { computeOrderUid } from 'utils/orderUtils/computeOrderUid'
diff --git a/apps/cowswap-frontend/src/modules/twap/updaters/QuoteObserverUpdater.tsx b/apps/cowswap-frontend/src/modules/twap/updaters/QuoteObserverUpdater.tsx
index 203c37c703..e7b395f051 100644
--- a/apps/cowswap-frontend/src/modules/twap/updaters/QuoteObserverUpdater.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/updaters/QuoteObserverUpdater.tsx
@@ -1,10 +1,10 @@
import { useAtomValue } from 'jotai'
import { useMemo } from 'react'
+import { usePrevious } from '@cowprotocol/common-hooks'
import { CurrencyAmount } from '@uniswap/sdk-core'
-import usePrevious from 'legacy/hooks/usePrevious'
-import { Field } from 'legacy/state/swap/actions'
+import { Field } from 'legacy/state/types'
import { useDerivedTradeState } from 'modules/trade/hooks/useDerivedTradeState'
import { useUpdateCurrencyAmount } from 'modules/trade/hooks/useUpdateCurrencyAmount'
diff --git a/apps/cowswap-frontend/src/modules/twap/updaters/TwapOrdersUpdater.tsx b/apps/cowswap-frontend/src/modules/twap/updaters/TwapOrdersUpdater.tsx
index 8c1e6c9bd0..8e54615510 100644
--- a/apps/cowswap-frontend/src/modules/twap/updaters/TwapOrdersUpdater.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/updaters/TwapOrdersUpdater.tsx
@@ -1,13 +1,12 @@
import { useAtomValue, useSetAtom } from 'jotai'
import { useEffect, useMemo, useRef } from 'react'
+import { ComposableCoW } from '@cowprotocol/abis'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
-import { ComposableCoW } from '@cowswap/abis'
+import { useGnosisSafeInfo } from '@cowprotocol/wallet'
import ms from 'ms.macro'
-import { useGnosisSafeInfo } from 'modules/wallet'
-
import { TWAP_PENDING_STATUSES } from '../const'
import { useFetchTwapOrdersFromSafe } from '../hooks/useFetchTwapOrdersFromSafe'
import { useTwapOrdersAuthMulticall } from '../hooks/useTwapOrdersAuthMulticall'
diff --git a/apps/cowswap-frontend/src/modules/twap/updaters/index.tsx b/apps/cowswap-frontend/src/modules/twap/updaters/index.tsx
index e9220f64e4..671048db15 100644
--- a/apps/cowswap-frontend/src/modules/twap/updaters/index.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/updaters/index.tsx
@@ -1,8 +1,9 @@
import { useAtomValue } from 'jotai'
+import { useIsSafeApp, useWalletInfo } from '@cowprotocol/wallet'
+
import { useComposableCowContract } from 'modules/advancedOrders/hooks/useComposableCowContract'
import { AppDataUpdater } from 'modules/appData'
-import { useIsSafeApp, useWalletInfo } from 'modules/wallet'
import { CreatedInOrderBookOrdersUpdater } from './CreatedInOrderBookOrdersUpdater'
import { FallbackHandlerVerificationUpdater } from './FallbackHandlerVerificationUpdater'
diff --git a/apps/cowswap-frontend/src/modules/twap/utils/emulateTwapAsOrder.ts b/apps/cowswap-frontend/src/modules/twap/utils/emulateTwapAsOrder.ts
index 73dffa195f..76a6de409d 100644
--- a/apps/cowswap-frontend/src/modules/twap/utils/emulateTwapAsOrder.ts
+++ b/apps/cowswap-frontend/src/modules/twap/utils/emulateTwapAsOrder.ts
@@ -22,7 +22,7 @@ export function emulateTwapAsOrder(item: TwapOrderItem): EnrichedOrder {
const creationTime = new Date(item.executedDate || item.submissionDate)
const expirationTime = new Date(creationTime.getTime() + t * n * 1000)
- const { executedSellAmount, executedBuyAmount, executedFeeAmount } = executionInfo.info
+ const { executedSellAmount = '0', executedBuyAmount = '0', executedFeeAmount = '0' } = executionInfo?.info || {}
return {
signingScheme: SigningScheme.EIP1271,
diff --git a/apps/cowswap-frontend/src/modules/twap/utils/mapPartOrderToStoreOrder.ts b/apps/cowswap-frontend/src/modules/twap/utils/mapPartOrderToStoreOrder.ts
index 6c5902970e..3cfbea976b 100644
--- a/apps/cowswap-frontend/src/modules/twap/utils/mapPartOrderToStoreOrder.ts
+++ b/apps/cowswap-frontend/src/modules/twap/utils/mapPartOrderToStoreOrder.ts
@@ -1,11 +1,12 @@
import { EnrichedOrder } from '@cowprotocol/cow-sdk'
import { Order } from 'legacy/state/orders/actions'
-import { computeOrderSummary } from 'legacy/state/orders/updaters/utils'
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'
import { getPartOrderStatus } from './getPartOrderStatus'
diff --git a/apps/cowswap-frontend/src/modules/twap/utils/mapTwapOrderToStoreOrder.ts b/apps/cowswap-frontend/src/modules/twap/utils/mapTwapOrderToStoreOrder.ts
index 8336dc2c94..76f943c32e 100644
--- a/apps/cowswap-frontend/src/modules/twap/utils/mapTwapOrderToStoreOrder.ts
+++ b/apps/cowswap-frontend/src/modules/twap/utils/mapTwapOrderToStoreOrder.ts
@@ -1,9 +1,10 @@
import { Order, OrderStatus } from 'legacy/state/orders/actions'
-import { computeOrderSummary } from 'legacy/state/orders/updaters/utils'
import { TokensByAddress } from 'modules/tokensList/state/tokensListAtom'
import { getTokensByAddress } from 'modules/tokensList/utils/getTokensByAddress'
+import { computeOrderSummary } from 'common/updaters/orders/utils'
+
import { emulateTwapAsOrder } from './emulateTwapAsOrder'
import { TwapOrderItem, TwapOrderStatus } from '../types'
diff --git a/apps/cowswap-frontend/src/modules/twap/utils/twapOrderToStruct.ts b/apps/cowswap-frontend/src/modules/twap/utils/twapOrderToStruct.ts
index b9bf124d15..8e33c2ed95 100644
--- a/apps/cowswap-frontend/src/modules/twap/utils/twapOrderToStruct.ts
+++ b/apps/cowswap-frontend/src/modules/twap/utils/twapOrderToStruct.ts
@@ -1,4 +1,4 @@
-import { NATIVE_CURRENCY_BUY_ADDRESS } from 'legacy/constants'
+import { NATIVE_CURRENCY_BUY_ADDRESS } from '@cowprotocol/common-const'
import { TWAPOrder, TWAPOrderStruct } from '../types'
diff --git a/apps/cowswap-frontend/src/modules/twap/utils/updateTwapOrdersList.ts b/apps/cowswap-frontend/src/modules/twap/utils/updateTwapOrdersList.ts
index 825cffd8f7..6cd69a281c 100644
--- a/apps/cowswap-frontend/src/modules/twap/utils/updateTwapOrdersList.ts
+++ b/apps/cowswap-frontend/src/modules/twap/utils/updateTwapOrdersList.ts
@@ -1,4 +1,4 @@
-import { deepEqual } from 'utils/deepEqual'
+import { deepEqual } from '@cowprotocol/common-utils'
import { TWAP_FINAL_STATUSES } from '../const'
import { TwapOrdersList } from '../state/twapOrdersListAtom'
diff --git a/apps/cowswap-frontend/src/modules/usdAmount/apis/getCoingeckoUsdPrice.ts b/apps/cowswap-frontend/src/modules/usdAmount/apis/getCoingeckoUsdPrice.ts
index bb9b98eae9..cb792c9aa1 100644
--- a/apps/cowswap-frontend/src/modules/usdAmount/apis/getCoingeckoUsdPrice.ts
+++ b/apps/cowswap-frontend/src/modules/usdAmount/apis/getCoingeckoUsdPrice.ts
@@ -1,10 +1,10 @@
+import { FractionUtils } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { Fraction, Token } from '@uniswap/sdk-core'
import ms from 'ms.macro'
import { fetchWithRateLimit } from 'common/utils/fetch'
-import { FractionUtils } from 'utils/fractionUtils'
export interface CoinGeckoUsdQuote {
[address: string]: {
diff --git a/apps/cowswap-frontend/src/modules/usdAmount/apis/getCowProtocolUsdPrice.ts b/apps/cowswap-frontend/src/modules/usdAmount/apis/getCowProtocolUsdPrice.ts
index 881ecf61f2..f28c2ab114 100644
--- a/apps/cowswap-frontend/src/modules/usdAmount/apis/getCowProtocolUsdPrice.ts
+++ b/apps/cowswap-frontend/src/modules/usdAmount/apis/getCowProtocolUsdPrice.ts
@@ -1,10 +1,8 @@
+import { USDC } from '@cowprotocol/common-const'
+import { FractionUtils } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { Fraction, Token } from '@uniswap/sdk-core'
-import { USDC } from 'legacy/constants/tokens'
-
-import { FractionUtils } from 'utils/fractionUtils'
-
import { getCowProtocolNativePrice } from './getCowProtocolNativePrice'
export async function getCowProtocolUsdPrice(
diff --git a/apps/cowswap-frontend/src/modules/usdAmount/hooks/useTradeUsdAmounts.ts b/apps/cowswap-frontend/src/modules/usdAmount/hooks/useTradeUsdAmounts.ts
index 14e20c7384..00e56dbf84 100644
--- a/apps/cowswap-frontend/src/modules/usdAmount/hooks/useTradeUsdAmounts.ts
+++ b/apps/cowswap-frontend/src/modules/usdAmount/hooks/useTradeUsdAmounts.ts
@@ -1,11 +1,10 @@
+import { isFractionFalsy } from '@cowprotocol/common-utils'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import { Nullish } from 'types'
import { useIsWrapOrUnwrap } from 'modules/trade/hooks/useIsWrapOrUnwrap'
-import { isFractionFalsy } from 'utils/isFractionFalsy'
-
import { UsdAmountInfo, useUsdAmount } from './useUsdAmount'
export interface TradeUSDAmounts {
diff --git a/apps/cowswap-frontend/src/modules/usdAmount/hooks/useUsdAmount.test.tsx b/apps/cowswap-frontend/src/modules/usdAmount/hooks/useUsdAmount.test.tsx
index 1b72d18fbf..c8f6aaa188 100644
--- a/apps/cowswap-frontend/src/modules/usdAmount/hooks/useUsdAmount.test.tsx
+++ b/apps/cowswap-frontend/src/modules/usdAmount/hooks/useUsdAmount.test.tsx
@@ -1,13 +1,12 @@
import { createStore } from 'jotai/vanilla'
import { ReactNode } from 'react'
+import { WETH_GNOSIS_CHAIN } from '@cowprotocol/common-const'
import { CurrencyAmount, Fraction } from '@uniswap/sdk-core'
import { renderHook } from '@testing-library/react-hooks'
import { JotaiTestProvider } from 'test-utils'
-import { WETH_GNOSIS_CHAIN } from 'legacy/utils/gnosis_chain/constants'
-
import { useUsdAmount } from './useUsdAmount'
import { usdRawPricesAtom, UsdRawPriceState } from '../state/usdRawPricesAtom'
diff --git a/apps/cowswap-frontend/src/modules/usdAmount/hooks/useUsdAmount.ts b/apps/cowswap-frontend/src/modules/usdAmount/hooks/useUsdAmount.ts
index b6a227bdd5..13a29fee0f 100644
--- a/apps/cowswap-frontend/src/modules/usdAmount/hooks/useUsdAmount.ts
+++ b/apps/cowswap-frontend/src/modules/usdAmount/hooks/useUsdAmount.ts
@@ -1,9 +1,9 @@
+import { currencyAmountToTokenAmount } from '@cowprotocol/common-utils'
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
import { Nullish } from 'types'
import { useSafeMemo } from 'common/hooks/useSafeMemo'
-import { currencyAmountToTokenAmount } from 'utils/currencyAmountToTokenAmount'
import { useUsdPrice } from './useUsdPrice'
diff --git a/apps/cowswap-frontend/src/modules/usdAmount/state/usdRawPricesAtom.ts b/apps/cowswap-frontend/src/modules/usdAmount/state/usdRawPricesAtom.ts
index 4c40b0dd76..af2afd8f02 100644
--- a/apps/cowswap-frontend/src/modules/usdAmount/state/usdRawPricesAtom.ts
+++ b/apps/cowswap-frontend/src/modules/usdAmount/state/usdRawPricesAtom.ts
@@ -1,9 +1,8 @@
import { atom } from 'jotai'
+import { deepEqual } from '@cowprotocol/common-utils'
import { Fraction, Token } from '@uniswap/sdk-core'
-import { deepEqual } from 'utils/deepEqual'
-
export interface UsdRawPriceState {
updatedAt?: number
price: Fraction | null
diff --git a/apps/cowswap-frontend/src/modules/usdAmount/state/usdTokenPricesAtom.ts b/apps/cowswap-frontend/src/modules/usdAmount/state/usdTokenPricesAtom.ts
index bf63574d40..543eace08a 100644
--- a/apps/cowswap-frontend/src/modules/usdAmount/state/usdTokenPricesAtom.ts
+++ b/apps/cowswap-frontend/src/modules/usdAmount/state/usdTokenPricesAtom.ts
@@ -1,12 +1,10 @@
import { atom } from 'jotai'
+import { USDC } from '@cowprotocol/common-const'
+import { tryParseCurrencyAmount } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { Fraction, Price, Token } from '@uniswap/sdk-core'
-import { USDC } from 'legacy/constants/tokens'
-
-import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount'
-
import { usdRawPricesAtom, UsdRawPriceState } from './usdRawPricesAtom'
export interface UsdPriceState extends Omit {
diff --git a/apps/cowswap-frontend/src/modules/usdAmount/updaters/UsdPricesUpdater.test.tsx b/apps/cowswap-frontend/src/modules/usdAmount/updaters/UsdPricesUpdater.test.tsx
index e299ec6e94..e1a2f188d4 100644
--- a/apps/cowswap-frontend/src/modules/usdAmount/updaters/UsdPricesUpdater.test.tsx
+++ b/apps/cowswap-frontend/src/modules/usdAmount/updaters/UsdPricesUpdater.test.tsx
@@ -1,6 +1,7 @@
import { createStore } from 'jotai/vanilla'
import { ReactNode } from 'react'
+import { COW as COWS, USDC_MAINNET } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { Token } from '@uniswap/sdk-core'
@@ -8,8 +9,6 @@ import { act, render, waitFor } from '@testing-library/react'
import { SWRConfig } from 'swr'
import { JotaiTestProvider } from 'test-utils'
-import { COW as COWS, USDC_MAINNET } from 'legacy/constants/tokens'
-
import { UsdPricesUpdater } from './UsdPricesUpdater'
import * as coingeckoApi from '../apis/getCoingeckoUsdPrice'
diff --git a/apps/cowswap-frontend/src/modules/usdAmount/updaters/UsdPricesUpdater.ts b/apps/cowswap-frontend/src/modules/usdAmount/updaters/UsdPricesUpdater.ts
index 8c0c04f046..52e4d2a657 100644
--- a/apps/cowswap-frontend/src/modules/usdAmount/updaters/UsdPricesUpdater.ts
+++ b/apps/cowswap-frontend/src/modules/usdAmount/updaters/UsdPricesUpdater.ts
@@ -1,19 +1,16 @@
import { useAtomValue, useSetAtom } from 'jotai'
import { useEffect, useMemo } from 'react'
+import { USDC } from '@cowprotocol/common-const'
+import { useDebounce } from '@cowprotocol/common-hooks'
+import { FractionUtils } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Fraction, Token } from '@uniswap/sdk-core'
import ms from 'ms.macro'
import useSWR, { SWRConfiguration } from 'swr'
-import { USDC } from 'legacy/constants/tokens'
-import useDebounce from 'legacy/hooks/useDebounce'
-
-import { useWalletInfo } from 'modules/wallet'
-
-import { FractionUtils } from 'utils/fractionUtils'
-
import { getCowProtocolNativePrice } from '../apis/getCowProtocolNativePrice'
import { fetchCurrencyUsdPrice } from '../services/fetchCurrencyUsdPrice'
import {
diff --git a/apps/cowswap-frontend/src/modules/wallet/api/assets/formatic.png b/apps/cowswap-frontend/src/modules/wallet/api/assets/formatic.png
deleted file mode 100644
index 414bab299b..0000000000
Binary files a/apps/cowswap-frontend/src/modules/wallet/api/assets/formatic.png and /dev/null differ
diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/ZengoBanner/index.tsx b/apps/cowswap-frontend/src/modules/wallet/api/pure/ZengoBanner/index.tsx
deleted file mode 100644
index 2bf8e37418..0000000000
--- a/apps/cowswap-frontend/src/modules/wallet/api/pure/ZengoBanner/index.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-import { Trans } from '@lingui/macro'
-
-import { ExternalLink } from 'legacy/theme'
-
-import { default as ZengoImage } from 'modules/wallet/api/assets/zengo.svg'
-
-import * as styled from './styled'
-
-const GET_ZENGO_LINK = 'https://zengo.com/'
-const HOW_TO_USE_ZENGO = 'https://help.zengo.com/en/collections/1646183-how-to-guides'
-
-export function ZengoBanner() {
- return (
-
-
-
-
-
-
-
- Need a crypto wallet?
-
-
- Download ZenGo: The most secure crypto wallet.
-
-
-
-
-
-
- Get ZenGo
-
-
-
-
- How to use ZenGo
-
-
-
- )
-}
diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/ZengoBanner/styled.ts b/apps/cowswap-frontend/src/modules/wallet/api/pure/ZengoBanner/styled.ts
deleted file mode 100644
index a77555abf1..0000000000
--- a/apps/cowswap-frontend/src/modules/wallet/api/pure/ZengoBanner/styled.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import styled from 'styled-components/macro'
-
-import { ButtonPrimary } from 'legacy/components/Button'
-import { ExternalLink } from 'legacy/theme/components'
-
-export const Wrapper = styled.div`
- display: flex;
- align-items: center;
- justify-content: space-between;
- flex-wrap: wrap;
- width: 100%;
- ${({ theme }) => theme.mediaWidth.upToExtraSmall`
- flex-direction: column;
- justify-content: center;
- `};
-`
-
-export const Icon = styled.div`
- max-width: 50px;
- img {
- max-width: 100%;
- }
-`
-
-export const Content = styled.div`
- flex: 1;
- padding: 0 1rem;
- color: ${({ theme }) => theme.text1};
- h4 {
- margin-bottom: 5px;
- font-size: 1.1rem;
- }
- p {
- margin: 0;
- font-size: 0.8rem;
- }
- ${({ theme }) => theme.mediaWidth.upToExtraSmall`
- margin-top: 5px;
- text-align: center;
- `};
-`
-
-export const Actions = styled.div`
- ${({ theme }) => theme.mediaWidth.upToExtraSmall`
- margin-top: 10px;
- display: flex;
- justify-content: center;
- flex-direction: column;
- `};
-`
-
-export const GetZengoButton = styled(ButtonPrimary)`
- font-size: 12px;
- border-radius: 8px;
- padding: 8px;
- min-height: auto;
- a {
- color: ${({ theme }) => theme.white};
- &:hover {
- text-decoration: none;
- }
- }
-`
-
-export const HowToUse = styled(ExternalLink)`
- font-size: 0.8rem;
- margin-top: 5px;
- color: ${({ theme }) => theme.text1};
- cursor: pointer;
-`
diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/index.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/index.tsx
similarity index 87%
rename from apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/index.tsx
rename to apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/index.tsx
index 8ac22e48b3..f344109ca0 100644
--- a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/index.tsx
+++ b/apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/index.tsx
@@ -1,7 +1,16 @@
import { useAtom, useAtomValue, useSetAtom } from 'jotai'
import React, { useCallback, useEffect, useMemo, useState } from 'react'
-import { useAddSnackbar } from '@cowswap/snackbars'
+import { useAddSnackbar } from '@cowprotocol/snackbars'
+import {
+ accountsLoaders,
+ hwAccountIndexAtom,
+ getConnectionIcon,
+ getConnectionName,
+ AccountIndexSelect,
+ HardWareWallet,
+ getWeb3ReactConnection,
+} from '@cowprotocol/wallet'
import { useWeb3React } from '@web3-react/core'
import { Trans } from '@lingui/macro'
@@ -10,15 +19,9 @@ import { useNativeCurrencyBalances } from 'modules/tokens/hooks/useCurrencyBalan
import { CowModal } from 'common/pure/Modal'
-import { accountsLoaders } from './accountsLoaders'
import { accountSelectorModalAtom, toggleAccountSelectorModalAtom } from './state'
import * as styledEl from './styled'
-import { hwAccountIndexAtom } from '../../../api/state'
-import { getConnectionIcon, getConnectionName } from '../../../api/utils/connection'
-import { getWeb3ReactConnection, HardWareWallet } from '../../connection'
-import { AccountIndexSelect } from '../../pure/AccountIndexSelect'
-
export function AccountSelectorModal() {
const { isOpen } = useAtomValue(accountSelectorModalAtom)
const closeModal = useSetAtom(toggleAccountSelectorModalAtom)
diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/state.ts b/apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/state.ts
similarity index 100%
rename from apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/state.ts
rename to apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/state.ts
diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/styled.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/styled.tsx
similarity index 77%
rename from apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/styled.tsx
rename to apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/styled.tsx
index d5502835d2..14af67bb69 100644
--- a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/styled.tsx
+++ b/apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/styled.tsx
@@ -1,11 +1,13 @@
+import { ReactComponent as Close } from '@cowprotocol/assets/images/x.svg'
+
import styled from 'styled-components/macro'
-import { ReactComponent as Close } from 'legacy/assets/images/x.svg'
+import { UI } from 'common/constants/theme'
export const CloseIcon = styled(Close)`
opacity: 0.6;
transition: opacity 0.3s ease-in-out;
- stroke: ${({ theme }) => theme.text1};
+ stroke: var(${UI.COLOR_TEXT1});
width: 24px;
height: 24px;
cursor: pointer;
diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AddToMetamask/index.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/AddToMetamask/index.tsx
similarity index 66%
rename from apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AddToMetamask/index.tsx
rename to apps/cowswap-frontend/src/modules/wallet/containers/AddToMetamask/index.tsx
index 0c543789d0..fc8aa550e9 100644
--- a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AddToMetamask/index.tsx
+++ b/apps/cowswap-frontend/src/modules/wallet/containers/AddToMetamask/index.tsx
@@ -1,24 +1,22 @@
import React, { useCallback, useState } from 'react'
+import { addTokenToMetamaskAnalytics } from '@cowprotocol/analytics'
+import { getIsMetaMask } from '@cowprotocol/wallet'
import { Currency } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
-import { Nullish } from 'types'
-
-import { addTokenToMetamaskAnalytics } from 'legacy/components/analytics'
-
-import { AddToMetamask as AddToMetamaskPure } from 'modules/wallet/api/pure/AddToMetamask'
-import { getIsMetaMask } from 'modules/wallet/api/utils/connection'
-
import useCurrencyLogoURIs from 'common/pure/CurrencyLogo/hooks/useCurrencyLogoURIs'
+import { AddToMetamask as AddToMetamaskPure } from '../../pure/AddToMetamask'
+
export type AddToMetamaskProps = {
- currency: Nullish
+ currency: Currency | null | undefined
shortLabel?: boolean
+ className?: string
}
-export default function AddToMetamask(props: AddToMetamaskProps) {
- const { currency, shortLabel } = props
+export function AddToMetamask(props: AddToMetamaskProps) {
+ const { currency, shortLabel, className } = props
const { connector } = useWeb3React()
const isMetamask = getIsMetaMask()
@@ -50,5 +48,13 @@ export default function AddToMetamask(props: AddToMetamaskProps) {
return null
}
- return
+ return (
+
+ )
}
diff --git a/apps/cowswap-frontend/src/modules/wallet/containers/ConnectWalletOptions.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/ConnectWalletOptions.tsx
new file mode 100644
index 0000000000..72218b1556
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/wallet/containers/ConnectWalletOptions.tsx
@@ -0,0 +1,94 @@
+import { useTheme } from '@cowprotocol/common-hooks'
+import { isMobile } from '@cowprotocol/common-utils'
+import {
+ AlphaOption,
+ AmbireOption,
+ CoinbaseWalletOption,
+ InjectedOption,
+ InstallMetaMaskOption,
+ MetaMaskOption,
+ OpenMetaMaskMobileOption,
+ InstallKeystoneOption,
+ KeystoneOption,
+ LedgerOption,
+ TrezorOption,
+ TrustWalletOption,
+ WalletConnectV2Option,
+ getIsCoinbaseWallet,
+ getIsInjected,
+ getIsMetaMask,
+} from '@cowprotocol/wallet'
+import { Connector } from '@web3-react/types'
+
+import { useSelectedWallet } from 'legacy/state/user/hooks'
+
+import { FeatureGuard } from 'common/containers/FeatureGuard'
+
+export type TryActivation = (connector: Connector) => void
+
+export function ConnectWalletOptions({ tryActivation }: { tryActivation: TryActivation }) {
+ const isInjected = getIsInjected()
+ const isMetaMask = getIsMetaMask()
+ const isCoinbaseWallet = getIsCoinbaseWallet()
+ const selectedWallet = useSelectedWallet()
+ const { darkMode } = useTheme()
+
+ const isCoinbaseWalletBrowser = isMobile && isCoinbaseWallet
+ const isMetaMaskBrowser = isMobile && isMetaMask
+ const isInjectedMobileBrowser = isCoinbaseWalletBrowser || isMetaMaskBrowser
+ // const isChromeMobile = isMobile && isChrome
+ const showKeystone = !isInjectedMobileBrowser && !isMobile && window.ethereum?.isMetaMask
+
+ const connectionProps = { darkMode, selectedWallet, tryActivation }
+
+ // Show Tally option only in Chrome (includes Brave too), but not on mobile or as an injected browser
+ // const showTally = !isInjectedMobileBrowser && isChrome && !isChromeMobile
+
+ let injectedOption
+ if (!isInjected) {
+ if (!isMobile) {
+ injectedOption =
+ } else {
+ injectedOption =
+ }
+ } else {
+ if (isMetaMask) {
+ injectedOption =
+ } else {
+ injectedOption =
+ }
+ }
+
+ const coinbaseWalletOption =
+
+ const walletConnectionV2Option = (!isInjectedMobileBrowser && ) ?? null
+
+ // Wallet-connect based
+ // const zengoOption = (!isInjectedMobileBrowser && ) ?? null
+ const ambireOption = (!isInjectedMobileBrowser && ) ?? null
+ const alphaOption = (!isInjectedMobileBrowser && ) ?? null
+ const ledgerOption = (!isInjectedMobileBrowser && !isMobile && ) ?? null
+ const trezorOption = (!isInjectedMobileBrowser && !isMobile && ) ?? null
+ const keystoneOption =
+ (showKeystone && ) || (!isMobile && )
+
+ // Injected
+ // const tallyOption = (showTally && ) ?? null
+ const trustOption = (!isInjectedMobileBrowser && ) ?? null
+
+ return (
+ <>
+ {injectedOption}
+ {walletConnectionV2Option}
+ {coinbaseWalletOption}
+ {ledgerOption}
+ {trezorOption}
+ {/*{zengoOption}*/}
+ {ambireOption}
+ {alphaOption}
+ {/* {tallyOption} */}
+ {trustOption}
+ {keystoneOption}
+ >
+ )
+}
diff --git a/apps/cowswap-frontend/src/legacy/components/Popups/FollowPendingTxPopup/FollowPendingTxPopupUI.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/FollowPendingTxPopup/FollowPendingTxPopupUI.tsx
similarity index 97%
rename from apps/cowswap-frontend/src/legacy/components/Popups/FollowPendingTxPopup/FollowPendingTxPopupUI.tsx
rename to apps/cowswap-frontend/src/modules/wallet/containers/FollowPendingTxPopup/FollowPendingTxPopupUI.tsx
index 8f5d1c36f6..54b6852023 100644
--- a/apps/cowswap-frontend/src/legacy/components/Popups/FollowPendingTxPopup/FollowPendingTxPopupUI.tsx
+++ b/apps/cowswap-frontend/src/modules/wallet/containers/FollowPendingTxPopup/FollowPendingTxPopupUI.tsx
@@ -1,11 +1,12 @@
import React from 'react'
+import { Tooltip, TooltipProps } from '@cowprotocol/ui'
+
import { Text } from 'rebass'
import styled from 'styled-components/macro'
import { AutoColumn } from 'legacy/components/Column'
import { StyledClose as IconClose } from 'legacy/components/Popups/styled'
-import Tooltip, { TooltipProps } from 'legacy/components/Tooltip'
interface PopupContentProps {
onCheck: () => void
diff --git a/apps/cowswap-frontend/src/legacy/components/Popups/FollowPendingTxPopup/index.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/FollowPendingTxPopup/index.tsx
similarity index 91%
rename from apps/cowswap-frontend/src/legacy/components/Popups/FollowPendingTxPopup/index.tsx
rename to apps/cowswap-frontend/src/modules/wallet/containers/FollowPendingTxPopup/index.tsx
index 42666204ab..5f2270a7d9 100644
--- a/apps/cowswap-frontend/src/legacy/components/Popups/FollowPendingTxPopup/index.tsx
+++ b/apps/cowswap-frontend/src/modules/wallet/containers/FollowPendingTxPopup/index.tsx
@@ -3,19 +3,18 @@ import { selectAtom } from 'jotai/utils'
import React, { useEffect, useMemo, useCallback, useRef, PropsWithChildren } from 'react'
import { useRecentActivityLastPendingOrder } from 'legacy/hooks/useRecentActivity'
+import { Order } from 'legacy/state/orders/actions'
+import { useIsExpertMode } from 'legacy/state/user/hooks'
+
+import { FollowPendingTxPopupUI } from './FollowPendingTxPopupUI'
+
import {
handleFollowPendingTxPopupAtom,
handleHidePopupPermanentlyAtom,
showFollowTxPopupAtom,
followPendingTxPopupAtom,
handleCloseOrderPopupAtom,
-} from 'legacy/state/application/atoms'
-import { Order } from 'legacy/state/orders/actions'
-import { useIsExpertMode } from 'legacy/state/user/hooks'
-
-import { OrderID } from 'api/gnosisProtocol'
-
-import { FollowPendingTxPopupUI } from './FollowPendingTxPopupUI'
+} from '../../state/followPendingTxPopupAtom'
export function useLastPendingOrder(): { lastPendingOrder: Order | null; onClose: () => void } {
const setShowFollowPendingTxPopup = useSetAtom(handleFollowPendingTxPopupAtom)
@@ -45,7 +44,7 @@ export function useCloseFollowTxPopupIfNotPendingOrder() {
}, [lastPendingOrder, onClose, showingPopup])
}
-const useShowingPopupFirstTime = (orderId: OrderID | undefined) => {
+const useShowingPopupFirstTime = (orderId: string | undefined) => {
const showingPopup = useAtomValue(showFollowTxPopupAtom)
const _firstTimePopupOrderAppears = useMemo(
() =>
@@ -62,7 +61,7 @@ const useShowingPopupFirstTime = (orderId: OrderID | undefined) => {
return { showPopup: firstTimePopupOrderAppears && showingPopup, firstTimePopupOrderAppears }
}
-const FollowPendingTxPopup: React.FC = ({ children }): JSX.Element => {
+export const FollowPendingTxPopup: React.FC = ({ children }): JSX.Element => {
const setShowFollowPendingTxPopup = useSetAtom(handleFollowPendingTxPopupAtom)
const setHidePendingTxPopupPermanently = useSetAtom(handleHidePopupPermanentlyAtom)
const isExpertMode = useIsExpertMode()
@@ -87,5 +86,3 @@ const FollowPendingTxPopup: React.FC = ({ children }): JSX.El
)
}
-
-export default FollowPendingTxPopup
diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/WalletModal/index.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/WalletModal/index.tsx
similarity index 73%
rename from apps/cowswap-frontend/src/modules/wallet/web3-react/containers/WalletModal/index.tsx
rename to apps/cowswap-frontend/src/modules/wallet/containers/WalletModal/index.tsx
index b70e80dfbf..daef27f9be 100644
--- a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/WalletModal/index.tsx
+++ b/apps/cowswap-frontend/src/modules/wallet/containers/WalletModal/index.tsx
@@ -1,22 +1,21 @@
import { useSetAtom } from 'jotai'
import { useCallback, useEffect, useState } from 'react'
+import { changeWalletAnalytics } from '@cowprotocol/analytics'
+import { usePrevious } from '@cowprotocol/common-hooks'
+import { getCurrentChainIdFromUrl } from '@cowprotocol/common-utils'
+import { useWalletInfo, getIsHardWareWallet, getWeb3ReactConnection } from '@cowprotocol/wallet'
import { useWeb3React } from '@web3-react/core'
import { Connector } from '@web3-react/types'
-import { changeWalletAnalytics } from 'legacy/components/analytics'
-import usePrevious from 'legacy/hooks/usePrevious'
import { useModalIsOpen, useToggleWalletModal } from 'legacy/state/application/hooks'
import { ApplicationModal } from 'legacy/state/application/reducer'
import { updateConnectionError } from 'legacy/state/connection/reducer'
import { useAppDispatch, useAppSelector } from 'legacy/state/hooks'
import { updateSelectedWallet } from 'legacy/state/user/reducer'
-import { ConnectionType, toggleAccountSelectorModalAtom, useWalletInfo } from 'modules/wallet'
-import { WalletModal as WalletModalPure, WalletModalView } from 'modules/wallet/api/pure/WalletModal'
-import { getIsHardWareWallet, getWeb3ReactConnection } from 'modules/wallet/web3-react/connection'
-
-import { getCurrentChainIdFromUrl } from 'utils/getCurrentChainIdFromUrl'
+import { WalletModal as WalletModalPure, WalletModalView } from '../../pure/WalletModal'
+import { toggleAccountSelectorModalAtom } from '../AccountSelectorModal/state'
export function WalletModal() {
const dispatch = useAppDispatch()
@@ -85,33 +84,12 @@ export function WalletModal() {
changeWalletAnalytics('Todo: wallet name')
try {
- // Fortmatic opens it's own modal on activation to log in. This modal has a tabIndex
- // collision into the WalletModal, so we special case by closing the modal.
- if (connectionType === ConnectionType.FORTMATIC) {
- toggleWalletModal()
- }
-
setPendingConnector(connector)
setWalletView('pending')
dispatch(updateConnectionError({ connectionType, error: undefined }))
await connector.activate(getCurrentChainIdFromUrl())
- const connection = getWeb3ReactConnection(connector)
-
- // Important for balances to load when connected to Gnosis-chain via WalletConnect
- if (connection.type === ConnectionType.WALLET_CONNECT) {
- const provider: any = connector.provider
-
- if (provider && provider.isWalletConnect) {
- const { http, rpc, signer } = (connector as any).provider
- const chainId = signer.connection.chainId
- // don't default to SupportedChainId.Mainnet - throw instead
- if (!chainId) throw new Error('[WalletModal::activation error: No chainId')
- http.connection.url = rpc.custom[chainId]
- }
- }
-
dispatch(updateSelectedWallet({ wallet: connectionType }))
if (isHardWareWallet) {
@@ -131,7 +109,7 @@ export function WalletModal() {
)
}
},
- [chainId, dispatch, toggleWalletModal, toggleAccountSelectorModal]
+ [chainId, dispatch, toggleAccountSelectorModal]
)
return (
diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/Web3Status/index.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/Web3Status/index.tsx
similarity index 59%
rename from apps/cowswap-frontend/src/modules/wallet/web3-react/containers/Web3Status/index.tsx
rename to apps/cowswap-frontend/src/modules/wallet/containers/Web3Status/index.tsx
index 29915da1e3..98d9318854 100644
--- a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/Web3Status/index.tsx
+++ b/apps/cowswap-frontend/src/modules/wallet/containers/Web3Status/index.tsx
@@ -1,18 +1,17 @@
+import { STORAGE_KEY_LAST_PROVIDER } from '@cowprotocol/common-const'
+import { useWalletDetails, useWalletInfo, getWeb3ReactConnection } from '@cowprotocol/wallet'
import { useWeb3React } from '@web3-react/core'
-import { useCloseFollowTxPopupIfNotPendingOrder } from 'legacy/components/Popups/FollowPendingTxPopup'
-import { STORAGE_KEY_LAST_PROVIDER } from 'legacy/constants'
import { useToggleWalletModal } from 'legacy/state/application/hooks'
import { useAppSelector } from 'legacy/state/hooks'
-import { useWalletDetails, useWalletInfo, WalletModal, AccountSelectorModal } from 'modules/wallet'
-import { Web3StatusInner } from 'modules/wallet/api/pure/Web3StatusInner'
-import { Wrapper } from 'modules/wallet/api/pure/Web3StatusInner/styled'
-import { getWeb3ReactConnection } from 'modules/wallet/web3-react/connection'
+import { Web3StatusInner } from '../../pure/Web3StatusInner'
+import { Wrapper } from '../../pure/Web3StatusInner/styled'
+import { AccountSelectorModal } from '../AccountSelectorModal'
+import { useCloseFollowTxPopupIfNotPendingOrder } from '../FollowPendingTxPopup'
+import { WalletModal } from '../WalletModal'
-import { useCategorizeRecentActivity } from 'common/hooks/useCategorizeRecentActivity'
-
-export function Web3Status() {
+export function Web3Status({ pendingActivities }: { pendingActivities: string[] }) {
const { connector } = useWeb3React()
const { account, active, chainId } = useWalletInfo()
const { ensName } = useWalletDetails()
@@ -27,8 +26,6 @@ export function Web3Status() {
const latestProvider = localStorage.getItem(STORAGE_KEY_LAST_PROVIDER)
- const { pendingActivity } = useCategorizeRecentActivity()
-
if (!active && !latestProvider) {
return null
}
@@ -36,7 +33,7 @@ export function Web3Status() {
return (
theme.border2};
- color: ${({ theme }) => theme.text1};
+ color: var(--cow-color-text1);
background: transparent;
outline: 0;
padding: 8px 16px;
@@ -62,14 +58,15 @@ export type AddToMetamaskProps = {
shortLabel?: boolean
addToken: () => void
success?: boolean
+ className?: string
}
export function AddToMetamask(props: AddToMetamaskProps) {
- const { currency, shortLabel, addToken, success } = props
+ const { className, currency, shortLabel, addToken, success } = props
const theme = useContext(ThemeContext)
return (
-
+
{!success ? (
{' '}
diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/PendingView/index.tsx b/apps/cowswap-frontend/src/modules/wallet/pure/PendingView/index.tsx
similarity index 96%
rename from apps/cowswap-frontend/src/modules/wallet/api/pure/PendingView/index.tsx
rename to apps/cowswap-frontend/src/modules/wallet/pure/PendingView/index.tsx
index 17bd20276a..bcf5a9ec59 100644
--- a/apps/cowswap-frontend/src/modules/wallet/api/pure/PendingView/index.tsx
+++ b/apps/cowswap-frontend/src/modules/wallet/pure/PendingView/index.tsx
@@ -1,9 +1,9 @@
+import { ButtonEmpty, ButtonPrimary, Loader } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import { transparentize } from 'polished'
import styled from 'styled-components/macro'
-import { ButtonEmpty, ButtonPrimary } from 'legacy/components/Button'
-import Loader from 'legacy/components/Loader'
import { ThemedText } from 'legacy/theme'
const PendingSection = styled.div`
diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/StatusIcon/index.tsx b/apps/cowswap-frontend/src/modules/wallet/pure/StatusIcon/index.tsx
similarity index 61%
rename from apps/cowswap-frontend/src/modules/wallet/api/pure/StatusIcon/index.tsx
rename to apps/cowswap-frontend/src/modules/wallet/pure/StatusIcon/index.tsx
index e4976c9f50..8c9a9910ae 100644
--- a/apps/cowswap-frontend/src/modules/wallet/api/pure/StatusIcon/index.tsx
+++ b/apps/cowswap-frontend/src/modules/wallet/pure/StatusIcon/index.tsx
@@ -1,10 +1,7 @@
-import styled from 'styled-components/macro'
+import { Identicon, ConnectionType } from '@cowprotocol/wallet'
+import { CoinbaseWalletIcon, WalletConnectIcon } from '@cowprotocol/wallet'
-import { ConnectionType } from 'modules/wallet'
-import CoinbaseWalletIcon from 'modules/wallet/api/assets/coinbase.svg'
-import FortmaticIcon from 'modules/wallet/api/assets/formatic.png'
-import WalletConnectIcon from 'modules/wallet/api/assets/walletConnectIcon.svg'
-import { Identicon } from 'modules/wallet/api/container/Identicon'
+import styled from 'styled-components/macro'
const IconWrapper = styled.div<{ size?: number }>`
${({ theme }) => theme.flexColumnNoWrap};
@@ -25,21 +22,18 @@ export interface StatusIconProps {
connectionType: ConnectionType
}
-export default function StatusIcon({ connectionType }: StatusIconProps) {
+export function StatusIcon({ connectionType }: StatusIconProps) {
let image
switch (connectionType) {
case ConnectionType.INJECTED:
image =
break
- case ConnectionType.WALLET_CONNECT:
+ case ConnectionType.WALLET_CONNECT_V2:
image =
break
case ConnectionType.COINBASE_WALLET:
image =
break
- case ConnectionType.FORTMATIC:
- image =
- break
}
return {image}
diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/WalletModal/index.tsx b/apps/cowswap-frontend/src/modules/wallet/pure/WalletModal/index.tsx
similarity index 93%
rename from apps/cowswap-frontend/src/modules/wallet/api/pure/WalletModal/index.tsx
rename to apps/cowswap-frontend/src/modules/wallet/pure/WalletModal/index.tsx
index 98493699f0..ad4be408f5 100644
--- a/apps/cowswap-frontend/src/modules/wallet/api/pure/WalletModal/index.tsx
+++ b/apps/cowswap-frontend/src/modules/wallet/pure/WalletModal/index.tsx
@@ -1,21 +1,21 @@
+import { AutoRow } from '@cowprotocol/ui'
import { Connector } from '@web3-react/types'
import { Trans } from '@lingui/macro'
import { LightCard } from 'legacy/components/Card'
import { AutoColumn } from 'legacy/components/Column'
-import { AutoRow } from 'legacy/components/Row'
import { ThemedText } from 'legacy/theme'
import { StyledInternalLink } from 'legacy/theme/components'
-import { PendingView } from 'modules/wallet/api/pure/PendingView'
-import { ConnectWalletOptions, TryActivation } from 'modules/wallet/web3-react/connection'
-
import { Routes } from 'common/constants/routes'
import { CloseIcon, ContentWrapper, CowModal, HeaderRow, HoverText } from 'common/pure/Modal'
import { CloseColor, OptionGrid, TermsWrapper, UpperSection, Wrapper } from './styled'
+import { ConnectWalletOptions, TryActivation } from '../../containers/ConnectWalletOptions'
+import { PendingView } from '../PendingView'
+
export type WalletModalView = 'options' | 'account' | 'pending'
interface WalletModalProps {
diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/WalletModal/styled.tsx b/apps/cowswap-frontend/src/modules/wallet/pure/WalletModal/styled.tsx
similarity index 85%
rename from apps/cowswap-frontend/src/modules/wallet/api/pure/WalletModal/styled.tsx
rename to apps/cowswap-frontend/src/modules/wallet/pure/WalletModal/styled.tsx
index 81eff40a82..2c2de9c91e 100644
--- a/apps/cowswap-frontend/src/modules/wallet/api/pure/WalletModal/styled.tsx
+++ b/apps/cowswap-frontend/src/modules/wallet/pure/WalletModal/styled.tsx
@@ -1,10 +1,12 @@
+import { ReactComponent as Close } from '@cowprotocol/assets/images/x.svg'
+import { ExternalLink } from '@cowprotocol/ui'
+
import styled from 'styled-components/macro'
-import { ReactComponent as Close } from 'legacy/assets/images/x.svg'
-import { ExternalLink } from 'legacy/theme'
+import { UI } from 'common/constants/theme'
export const TermsWrapper = styled.div`
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
`
export const Blurb = styled.div`
@@ -76,7 +78,7 @@ export const IconWrapper = styled.div`
align-items: center;
justify-content: center;
background: transparent;
- border: 1px solid var(--cow-color-border);
+ border: 1px solid var(${UI.COLOR_BORDER});
padding: 8px;
margin: 0 12px 0 0;
@@ -86,7 +88,7 @@ export const IconWrapper = styled.div`
}
> svg > path {
- --color: var(--cow-color-text1);
+ --color: var(${UI.COLOR_TEXT1});
fill: var(--color);
stroke: var(--color);
}
diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/Web3StatusInner/index.tsx b/apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/index.tsx
similarity index 82%
rename from apps/cowswap-frontend/src/modules/wallet/api/pure/Web3StatusInner/index.tsx
rename to apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/index.tsx
index ba324b17c1..0a8a9affdc 100644
--- a/apps/cowswap-frontend/src/modules/wallet/api/pure/Web3StatusInner/index.tsx
+++ b/apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/index.tsx
@@ -1,15 +1,14 @@
-import { Trans } from '@lingui/macro'
-
-import Loader from 'legacy/components/Loader'
-import FollowPendingTxPopup from 'legacy/components/Popups/FollowPendingTxPopup'
-import { RowBetween } from 'legacy/components/Row'
-import { shortenAddress } from 'legacy/utils'
+import { shortenAddress } from '@cowprotocol/common-utils'
+import { Loader, RowBetween } from '@cowprotocol/ui'
+import { ConnectionType } from '@cowprotocol/wallet'
-import StatusIcon from 'modules/wallet/api/pure/StatusIcon'
-import { ConnectionType } from 'modules/wallet/api/types'
+import { Trans } from '@lingui/macro'
import { NetworkIcon, Text, Web3StatusConnect, Web3StatusConnected, Web3StatusError } from './styled'
+import { FollowPendingTxPopup } from '../../containers/FollowPendingTxPopup'
+import { StatusIcon } from '../StatusIcon'
+
export interface Web3StatusInnerProps {
account?: string | null
chainId?: number
diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/Web3StatusInner/styled.ts b/apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/styled.ts
similarity index 88%
rename from apps/cowswap-frontend/src/modules/wallet/api/pure/Web3StatusInner/styled.ts
rename to apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/styled.ts
index d82660de22..35738b87d3 100644
--- a/apps/cowswap-frontend/src/modules/wallet/api/pure/Web3StatusInner/styled.ts
+++ b/apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/styled.ts
@@ -1,8 +1,10 @@
+import { ButtonSecondary } from '@cowprotocol/ui'
+
import { darken } from 'polished'
import { Activity } from 'react-feather'
import styled, { css } from 'styled-components/macro'
-import { ButtonSecondary } from 'legacy/components/Button'
+import { UI } from 'common/constants/theme'
export const Web3StatusGeneric = styled(ButtonSecondary)``
@@ -44,14 +46,14 @@ export const Web3StatusConnect = styled(Web3StatusGeneric)<{ faded?: boolean }>`
`
export const Web3StatusConnected = styled(Web3StatusGeneric)<{ pending?: boolean; clickDisabled?: boolean }>`
- background-color: ${({ theme }) => theme.grey1};
+ background-color: var(${UI.COLOR_GREY});
border: 1px solid transparent;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
font-weight: 500;
&:hover {
- background-color: ${({ theme }) => theme.grey1};
- color: ${({ theme }) => theme.text1};
+ background-color: var(${UI.COLOR_GREY});
+ color: var(${UI.COLOR_TEXT1});
}
${({ clickDisabled }) =>
@@ -81,7 +83,7 @@ export const NetworkIcon = styled(Activity)`
`
export const Wrapper = styled.div`
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
height: 40px;
width: 100%;
display: flex;
@@ -92,7 +94,7 @@ export const Wrapper = styled.div`
${({ theme }) => theme.mediaWidth.upToMedium`
width: auto;
height: 100%;
- margin: 0 0 0 auto;
+ margin: 0 auto;
`};
button {
diff --git a/apps/cowswap-frontend/src/legacy/state/application/atoms.ts b/apps/cowswap-frontend/src/modules/wallet/state/followPendingTxPopupAtom.ts
similarity index 96%
rename from apps/cowswap-frontend/src/legacy/state/application/atoms.ts
rename to apps/cowswap-frontend/src/modules/wallet/state/followPendingTxPopupAtom.ts
index e64a6f5469..58be234eb6 100644
--- a/apps/cowswap-frontend/src/legacy/state/application/atoms.ts
+++ b/apps/cowswap-frontend/src/modules/wallet/state/followPendingTxPopupAtom.ts
@@ -5,7 +5,7 @@ import { OrderID } from 'api/gnosisProtocol'
type FollowPendingTxPopup = {
showPopup: boolean
- lastOrderPopupClosed: OrderID | undefined
+ lastOrderPopupClosed: string | undefined
hidePopupPermanently: boolean
}
diff --git a/apps/cowswap-frontend/src/modules/wallet/utils/PermitProviderConnector.ts b/apps/cowswap-frontend/src/modules/wallet/utils/PermitProviderConnector.ts
new file mode 100644
index 0000000000..8a8f6c47c0
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/wallet/utils/PermitProviderConnector.ts
@@ -0,0 +1,73 @@
+import { getContract } from '@cowprotocol/common-utils'
+import { defaultAbiCoder, ParamType } from '@ethersproject/abi'
+import { TypedDataField } from '@ethersproject/abstract-signer'
+import { BigNumber } from '@ethersproject/bignumber'
+import type { Web3Provider } from '@ethersproject/providers'
+import { Wallet } from '@ethersproject/wallet'
+
+import { AbiItem, EIP712TypedData, ProviderConnector } from '@1inch/permit-signed-approvals-utils'
+import { AbiInput } from 'web3-utils'
+
+export class PermitProviderConnector implements ProviderConnector {
+ constructor(private provider: Web3Provider, private walletSigner?: Wallet | undefined) {}
+
+ contractEncodeABI(abi: AbiItem[], address: string | null, methodName: string, methodParams: unknown[]): string {
+ const contract = getContract(address || '', abi, this.provider)
+
+ return contract.interface.encodeFunctionData(methodName, methodParams)
+ }
+
+ signTypedData(_walletAddress: string, typedData: EIP712TypedData, _typedDataHash: string): Promise {
+ // Removes `EIP712Domain` as it's already part of EIP712 (see https://ethereum.stackexchange.com/a/151930/55204)
+ // and EthersJS complains when a type is not needed (see https://github.com/ethers-io/ethers.js/discussions/4000)
+ const types = Object.keys(typedData.types).reduce>((acc, type) => {
+ if (type !== 'EIP712Domain') {
+ acc[type] = typedData.types[type]
+ }
+ return acc
+ }, {})
+
+ const signer = this.walletSigner || this.provider.getSigner()
+
+ return signer._signTypedData(typedData.domain, types, typedData.message)
+ }
+
+ ethCall(contractAddress: string, callData: string): Promise {
+ return this.provider.call({
+ to: contractAddress,
+ data: callData,
+ })
+ }
+
+ decodeABIParameter(type: string, hex: string): T {
+ return defaultAbiCoder.decode([type], hex)[0]
+ }
+ decodeABIParameters(types: AbiInput[], hex: string): T {
+ const decodedValues = defaultAbiCoder.decode(types as unknown as (ParamType | string)[], hex) as T
+
+ // Ethersjs decodes numbers as BigNumber instances
+ // However, 1inch utils do not deal with BigNumber instances,
+ // so we need this mess to convert them to hex strings, which 1inch understands
+ // TODO: Any way to make this typing mess any cleaner?
+ if (decodedValues && typeof decodedValues === 'object') {
+ const copy: Record = {}
+
+ Object.keys(decodedValues).forEach((key) => {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ const value = decodedValues[key]
+ if (BigNumber.isBigNumber(value)) {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ copy[key] = value.toHexString()
+ } else {
+ copy[key] = value
+ }
+ })
+
+ return copy as T
+ }
+
+ return decodedValues
+ }
+}
diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/asyncConnector.ts b/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/asyncConnector.ts
deleted file mode 100644
index dc2e46961e..0000000000
--- a/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/asyncConnector.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { Actions, Connector } from '@web3-react/types'
-
-/**
- * To avoid including external libs for wallet connection in the bundle
- * We load them in runtime by demand
- */
-export class AsyncConnector extends Connector {
- constructor(private loader: () => Promise, actions: Actions, onError?: (error: Error) => void) {
- super(actions, onError)
- }
-
- activate(...args: unknown[]): Promise | void {
- return this.loader().then((connector) => {
- // There is a magic - we change async-connector prototype to the loaded connector
- ;(this as any).__proto__ = connector
- return connector.activate(...args)
- })
- }
-
- async connectEagerly(...args: unknown[]) {
- return this.loader().then((connector) => {
- // There is a magic - we change async-connector prototype to the loaded connector
- ;(this as any).__proto__ = connector
- return connector.connectEagerly?.(...args)
- })
- }
-}
diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/formatic.tsx b/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/formatic.tsx
deleted file mode 100644
index 704082274d..0000000000
--- a/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/formatic.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-import { initializeConnector } from '@web3-react/core'
-
-import { useIsActiveWallet } from 'legacy/hooks/useIsActiveWallet'
-
-import { ConnectionType } from 'modules/wallet'
-import { default as FormaticImage } from 'modules/wallet/api/assets/formatic.png'
-import { ConnectWalletOption } from 'modules/wallet/api/pure/ConnectWalletOption'
-import { getConnectionName } from 'modules/wallet/api/utils/connection'
-
-import { AsyncConnector } from './asyncConnector'
-
-import { Web3ReactConnection } from '../types'
-
-import { TryActivation } from '.'
-
-const [web3Fortmatic, web3FortmaticHooks] = initializeConnector(
- (actions) =>
- new AsyncConnector(
- () =>
- Promise.all([import('@web3-react/eip1193'), import('fortmatic')]).then(([{ EIP1193 }, m]) => {
- const Fortmatic = m.default
- return new EIP1193({ actions, provider: new Fortmatic(process.env.REACT_APP_FORTMATIC_KEY).getProvider() })
- }),
- actions
- )
-)
-export const fortmaticConnection: Web3ReactConnection = {
- connector: web3Fortmatic,
- hooks: web3FortmaticHooks,
- type: ConnectionType.FORTMATIC,
-}
-
-export const formaticOption = {
- color: '#6748FF',
- icon: FormaticImage,
- id: 'fortmatic',
-}
-
-export function FortmaticOption({ tryActivation }: { tryActivation: TryActivation }) {
- const isActive = useIsActiveWallet(fortmaticConnection)
-
- return (
- tryActivation(fortmaticConnection.connector)}
- header={getConnectionName(ConnectionType.FORTMATIC)}
- />
- )
-}
diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/index.tsx b/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/index.tsx
deleted file mode 100644
index ddd5c5c003..0000000000
--- a/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/index.tsx
+++ /dev/null
@@ -1,174 +0,0 @@
-import { SupportedChainId } from '@cowprotocol/cow-sdk'
-import { Connector } from '@web3-react/types'
-
-import { ALL_SUPPORTED_CHAIN_IDS } from 'legacy/constants/chains'
-import { isMobile } from 'legacy/utils/userAgent'
-
-import { getIsCoinbaseWallet, getIsInjected, getIsMetaMask } from 'modules/wallet/api/utils/connection'
-
-import { FeatureGuard } from 'common/containers/FeatureGuard'
-
-import { AlphaOption } from './alpha'
-import { AmbireOption } from './ambire'
-import { coinbaseWalletConnection, CoinbaseWalletOption } from './coinbase'
-import { fortmaticConnection } from './formatic'
-import {
- injectedConnection,
- InjectedOption,
- InstallMetaMaskOption,
- MetaMaskOption,
- OpenMetaMaskMobileOption,
-} from './injected'
-import { injectedWidgetConnection } from './injectedWidget'
-import { InstallKeystoneOption, keystoneConnection, KeystoneOption } from './keystone'
-import { ledgerConnection, LedgerOption } from './ledger'
-import { networkConnection } from './network'
-import { gnosisSafeConnection } from './safe'
-import { tallyWalletConnection } from './tally'
-import { trezorConnection, TrezorOption } from './trezor'
-import { trustWalletConnection, TrustWalletOption } from './trust'
-import { walletConnectConnection, WalletConnectOption } from './walletConnect'
-import { walletConnectConnectionV2, WalletConnectV2Option } from './walletConnectV2'
-
-import { ConnectionType } from '../../api/types'
-import { Web3ReactConnection } from '../types'
-
-const allowedChainsByWallet: Record = {
- [ConnectionType.FORTMATIC]: [SupportedChainId.MAINNET],
- [ConnectionType.INJECTED]: ALL_SUPPORTED_CHAIN_IDS,
- [ConnectionType.INJECTED_WIDGET]: ALL_SUPPORTED_CHAIN_IDS,
- [ConnectionType.COINBASE_WALLET]: ALL_SUPPORTED_CHAIN_IDS,
- [ConnectionType.WALLET_CONNECT]: ALL_SUPPORTED_CHAIN_IDS,
- [ConnectionType.WALLET_CONNECT_V2]: ALL_SUPPORTED_CHAIN_IDS,
- [ConnectionType.NETWORK]: ALL_SUPPORTED_CHAIN_IDS,
- [ConnectionType.GNOSIS_SAFE]: ALL_SUPPORTED_CHAIN_IDS,
- [ConnectionType.TALLY]: ALL_SUPPORTED_CHAIN_IDS,
- [ConnectionType.TRUST]: ALL_SUPPORTED_CHAIN_IDS,
- [ConnectionType.LEDGER]: ALL_SUPPORTED_CHAIN_IDS,
- [ConnectionType.TREZOR]: ALL_SUPPORTED_CHAIN_IDS,
- [ConnectionType.KEYSTONE]: ALL_SUPPORTED_CHAIN_IDS,
- [ConnectionType.ALPHA]: [],
- [ConnectionType.AMBIRE]: [],
- [ConnectionType.ZENGO]: [],
-}
-
-export function isChainAllowed(connector: Connector, chainId: number): boolean {
- const connection = getWeb3ReactConnection(connector)
-
- return allowedChainsByWallet[connection.type].includes(chainId)
-}
-
-const connectionTypeToConnection: Record = {
- [ConnectionType.INJECTED]: injectedConnection,
- [ConnectionType.COINBASE_WALLET]: coinbaseWalletConnection,
- [ConnectionType.WALLET_CONNECT]: walletConnectConnection,
- [ConnectionType.WALLET_CONNECT_V2]: walletConnectConnectionV2,
- [ConnectionType.ZENGO]: walletConnectConnection,
- [ConnectionType.FORTMATIC]: fortmaticConnection,
- [ConnectionType.NETWORK]: networkConnection,
- [ConnectionType.GNOSIS_SAFE]: gnosisSafeConnection,
- [ConnectionType.AMBIRE]: walletConnectConnection,
- [ConnectionType.ALPHA]: walletConnectConnection,
- [ConnectionType.TALLY]: tallyWalletConnection,
- [ConnectionType.TRUST]: trustWalletConnection,
- [ConnectionType.LEDGER]: ledgerConnection,
- [ConnectionType.KEYSTONE]: keystoneConnection,
- [ConnectionType.INJECTED_WIDGET]: injectedWidgetConnection,
- [ConnectionType.TREZOR]: trezorConnection,
-}
-
-const CONNECTIONS: Web3ReactConnection[] = Object.values(connectionTypeToConnection)
-
-// TODO: add others
-export const HARDWARE_WALLETS = [ConnectionType.TREZOR] as const
-
-export type HardWareWallet = (typeof HARDWARE_WALLETS)[number]
-
-export const getIsHardWareWallet = (connectionType: ConnectionType) =>
- HARDWARE_WALLETS.includes(connectionType as HardWareWallet)
-
-export function getWeb3ReactConnection(c: Connector | ConnectionType): Web3ReactConnection {
- if (c instanceof Connector) {
- const connection = CONNECTIONS.find((connection) => connection.connector === c)
- if (!connection) {
- throw Error('unsupported connector')
- }
- return connection
- }
-
- return connectionTypeToConnection[c]
-}
-
-export type TryActivation = (connector: Connector) => void
-
-export function ConnectWalletOptions({ tryActivation }: { tryActivation: TryActivation }) {
- const isInjected = getIsInjected()
- const isMetaMask = getIsMetaMask()
- const isCoinbaseWallet = getIsCoinbaseWallet()
-
- const isCoinbaseWalletBrowser = isMobile && isCoinbaseWallet
- const isMetaMaskBrowser = isMobile && isMetaMask
- const isInjectedMobileBrowser = isCoinbaseWalletBrowser || isMetaMaskBrowser
- // const isChromeMobile = isMobile && isChrome
- const showKeystone = !isInjectedMobileBrowser && !isMobile && window.ethereum?.isMetaMask
-
- // Show Tally option only in Chrome (includes Brave too), but not on mobile or as an injected browser
- // const showTally = !isInjectedMobileBrowser && isChrome && !isChromeMobile
-
- let injectedOption
- if (!isInjected) {
- if (!isMobile) {
- injectedOption =
- } else {
- injectedOption =
- }
- } else {
- if (isMetaMask) {
- injectedOption =
- } else {
- injectedOption =
- }
- }
-
- const coinbaseWalletOption =
-
- const walletConnectionOption =
- (!isInjectedMobileBrowser && ) ?? null
-
- const walletConnectionV2Option =
- (!isInjectedMobileBrowser && ) ?? null
-
- // Wallet-connect based
- // const zengoOption = (!isInjectedMobileBrowser && ) ?? null
- const ambireOption = (!isInjectedMobileBrowser && ) ?? null
- const alphaOption = (!isInjectedMobileBrowser && ) ?? null
- const ledgerOption = (!isInjectedMobileBrowser && !isMobile && ) ?? null
- const trezorOption = (!isInjectedMobileBrowser && !isMobile && ) ?? null
- const keystoneOption =
- (showKeystone && ) || (!isMobile && )
-
- // Injected
- // const tallyOption = (showTally && ) ?? null
- const trustOption = (!isInjectedMobileBrowser && ) ?? null
-
- return (
- <>
- {injectedOption}
- {walletConnectionOption}
- {walletConnectionV2Option}
- {coinbaseWalletOption}
- {ledgerOption}
- {trezorOption}
- {/*{zengoOption}*/}
- {ambireOption}
- {alphaOption}
- {/* {tallyOption} */}
- {trustOption}
- {keystoneOption}
- >
- )
-}
-
-export function onError(error: Error) {
- console.debug(`[web3-react] Error: ${error}`)
-}
diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/walletConnect.tsx b/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/walletConnect.tsx
deleted file mode 100644
index d6bc8bd9d0..0000000000
--- a/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/walletConnect.tsx
+++ /dev/null
@@ -1,90 +0,0 @@
-import { useMemo } from 'react'
-
-import { initializeConnector } from '@web3-react/core'
-import { WalletConnect } from '@web3-react/walletconnect'
-
-import { RPC_URLS } from 'legacy/constants/networks'
-import { useIsActiveWallet } from 'legacy/hooks/useIsActiveWallet'
-
-import { ConnectionType, useWalletMetaData } from 'modules/wallet'
-import { default as WalletConnectImage } from 'modules/wallet/api/assets/walletConnectIcon.svg'
-import { ConnectWalletOption } from 'modules/wallet/api/pure/ConnectWalletOption'
-import {
- getConnectionName,
- getIsAlphaWallet,
- getIsAmbireWallet,
- getIsTrustWallet,
- getIsZengoWallet,
-} from 'modules/wallet/api/utils/connection'
-import { WC_DISABLED_TEXT } from 'modules/wallet/constants'
-
-import { useFeatureFlags } from 'common/hooks/featureFlags/useFeatureFlags'
-
-import { Web3ReactConnection } from '../types'
-
-import { onError, TryActivation } from '.'
-
-const WC_SUNSET_LINK =
- 'https://medium.com/walletconnect/weve-reset-the-clock-on-the-walletconnect-v1-0-shutdown-now-scheduled-for-june-28-2023-ead2d953b595'
-const WC_SUNSET_TEXT =
- 'The WalletConnect v1.0 protocol has been shut down on June 28, 2023 at 2pm (UTC). Click to read more.'
-
-export const walletConnectOption = {
- color: '#4196FC',
- icon: WalletConnectImage,
- id: 'wallet-connect',
-}
-
-const [web3WalletConnect, web3WalletConnectHooks] = initializeConnector(
- (actions) =>
- new WalletConnect({
- actions,
- options: {
- rpc: RPC_URLS,
- qrcode: true,
- bridge: process.env.REACT_APP_WALLET_CONNECT_V1_BRIDGE || 'https://safe-walletconnect.safe.global',
- },
- onError,
- })
-)
-export const walletConnectConnection: Web3ReactConnection = {
- connector: web3WalletConnect,
- hooks: web3WalletConnectHooks,
- type: ConnectionType.WALLET_CONNECT,
-}
-
-export function WalletConnectOption({ tryActivation }: { tryActivation: TryActivation }) {
- const { walletName } = useWalletMetaData()
- const { walletConnectV1Deprecated: isDeprecated } = useFeatureFlags()
-
- const isWalletConnect = useIsActiveWallet(walletConnectConnection)
- const isActive =
- isWalletConnect &&
- !getIsZengoWallet(walletName) &&
- !getIsAmbireWallet(walletName) &&
- !getIsAlphaWallet(walletName) &&
- !getIsTrustWallet(walletName)
-
- const tooltipText = useMemo(() => {
- if (isDeprecated) {
- return WC_SUNSET_TEXT
- }
-
- return !isActive && isWalletConnect ? WC_DISABLED_TEXT : null
- }, [isActive, isWalletConnect, isDeprecated])
-
- const link = isDeprecated ? WC_SUNSET_LINK : null
-
- return (
- (!isDeprecated ? tryActivation(walletConnectConnection.connector) : null)}
- header={getConnectionName(ConnectionType.WALLET_CONNECT)}
- />
- )
-}
diff --git a/apps/cowswap-frontend/src/pages/About/index.tsx b/apps/cowswap-frontend/src/pages/About/index.tsx
index 0cca13a89f..91712a3f34 100644
--- a/apps/cowswap-frontend/src/pages/About/index.tsx
+++ b/apps/cowswap-frontend/src/pages/About/index.tsx
@@ -1,15 +1,12 @@
-// Assets
+import diagramIMG from '@cowprotocol/assets/cow-swap/cowswap-diagram.png'
+import gaslessIMG from '@cowprotocol/assets/cow-swap/gasless.png'
+import mevIMG from '@cowprotocol/assets/cow-swap/mev.png'
+import { MEV_TOTAL, FLASHBOTS_LINK } from '@cowprotocol/common-const'
+import { ExternalLink as ExternalLinkTheme } from '@cowprotocol/ui'
+
import { Link } from 'react-router-dom'
import styled from 'styled-components/macro'
-import diagramIMG from 'legacy/assets/cow-swap/cowswap-diagram.png'
-import gaslessIMG from 'legacy/assets/cow-swap/gasless.png'
-import mevIMG from 'legacy/assets/cow-swap/mev.png'
-import { PageName } from 'legacy/components/AmplitudeAnalytics/constants'
-import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace'
-import { MEV_TOTAL, FLASHBOTS_LINK } from 'legacy/constants'
-import { ExternalLink as ExternalLinkTheme } from 'legacy/theme'
-
import { PageTitle } from 'modules/application/containers/PageTitle'
import { Page, Title, Content, GdocsListStyle } from 'modules/application/pure/Page'
@@ -32,7 +29,7 @@ const Wrapper = styled(Page)`
export default function About() {
return (
-
+ <>
About
@@ -115,6 +112,6 @@ export default function About() {
-
+ >
)
}
diff --git a/apps/cowswap-frontend/src/pages/Account/Balances.tsx b/apps/cowswap-frontend/src/pages/Account/Balances.tsx
index d889b18846..63b4991a21 100644
--- a/apps/cowswap-frontend/src/pages/Account/Balances.tsx
+++ b/apps/cowswap-frontend/src/pages/Account/Balances.tsx
@@ -1,5 +1,15 @@
import { useCallback, useEffect, useMemo, useState } from 'react'
+import ArrowIcon from '@cowprotocol/assets/cow-swap/arrow.svg'
+import CowImage from '@cowprotocol/assets/cow-swap/cow_v2.svg'
+import vCOWImage from '@cowprotocol/assets/cow-swap/vCOW.png'
+import { COW, COW_CONTRACT_ADDRESS, V_COW, V_COW_CONTRACT_ADDRESS } from '@cowprotocol/common-const'
+import { usePrevious } from '@cowprotocol/common-hooks'
+import { useBlockNumber } from '@cowprotocol/common-hooks'
+import { getBlockExplorerUrl, getProviderErrorMessage } from '@cowprotocol/common-utils'
+import { TokenAmount, ButtonPrimary } from '@cowprotocol/ui'
+import { MouseoverTooltipContent } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { CurrencyAmount } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { MetaMask } from '@web3-react/metamask'
@@ -8,31 +18,17 @@ import { Trans } from '@lingui/macro'
import SVG from 'react-inlinesvg'
import { Link } from 'react-router-dom'
-import ArrowIcon from 'legacy/assets/cow-swap/arrow.svg'
-import CowImage from 'legacy/assets/cow-swap/cow_v2.svg'
-import vCOWImage from 'legacy/assets/cow-swap/vCOW.png'
-import { ButtonPrimary } from 'legacy/components/Button'
import CopyHelper from 'legacy/components/Copy'
-import { MouseoverTooltipContent } from 'legacy/components/Tooltip'
-import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal'
-import { V_COW_CONTRACT_ADDRESS, COW_CONTRACT_ADDRESS } from 'legacy/constants'
-import { COW, V_COW } from 'legacy/constants/tokens'
import { useErrorModal } from 'legacy/hooks/useErrorMessageAndModal'
-import usePrevious from 'legacy/hooks/usePrevious'
import useTransactionConfirmationModal from 'legacy/hooks/useTransactionConfirmationModal'
import { SwapVCowStatus } from 'legacy/state/cowToken/actions'
import { useVCowData, useSwapVCowCallback, useSetSwapVCowStatus, useSwapVCowStatus } from 'legacy/state/cowToken/hooks'
-import { getBlockExplorerUrl } from 'legacy/utils'
-import { getProviderErrorMessage } from 'legacy/utils/misc'
+import { ConfirmOperationType } from 'legacy/state/types'
import { useTokenBalance } from 'modules/tokens/hooks/useCurrencyBalance'
-import { useWalletInfo } from 'modules/wallet'
-import AddToMetamask from 'modules/wallet/web3-react/containers/AddToMetamask'
import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported'
import { HelpCircle } from 'common/pure/HelpCircle'
-import { TokenAmount } from 'common/pure/TokenAmount'
-import useBlockNumber from 'lib/hooks/useBlockNumber'
import { useCowFromLockedGnoBalances } from 'pages/Account/LockedGnoVesting/hooks'
import {
ExtLink,
@@ -43,6 +39,7 @@ import {
VestingBreakdown,
CardsLoader,
CardsSpinner,
+ StyledAddToMetamask,
} from 'pages/Account/styled'
import LockedGnoVesting from './LockedGnoVesting'
@@ -285,7 +282,7 @@ export default function Profile() {
View contract ↗
- {isMetaMask && !isProviderNetworkUnsupported && }
+ {isMetaMask && !isProviderNetworkUnsupported && }
{!isMetaMask && (
diff --git a/apps/cowswap-frontend/src/pages/Account/Governance.tsx b/apps/cowswap-frontend/src/pages/Account/Governance.tsx
index 5ea6b8832f..5d20432fe4 100644
--- a/apps/cowswap-frontend/src/pages/Account/Governance.tsx
+++ b/apps/cowswap-frontend/src/pages/Account/Governance.tsx
@@ -1,4 +1,4 @@
-import CowProtocolImage from 'legacy/assets/cow-swap/cowprotocol.svg'
+import CowProtocolImage from '@cowprotocol/assets/cow-swap/cowprotocol.svg'
import { ExtLink, BannerCard, BannerCardContent, BannerCardSvg, CardActions } from './styled'
diff --git a/apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/hooks.ts b/apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/hooks.ts
index 84438a7dae..c0810359fb 100644
--- a/apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/hooks.ts
+++ b/apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/hooks.ts
@@ -1,32 +1,35 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
+import { MerkleDrop, TokenDistro, MerkleDropAbi, TokenDistroAbi } from '@cowprotocol/abis'
+import {
+ COW,
+ LOCKED_GNO_VESTING_DURATION,
+ LOCKED_GNO_VESTING_START_TIME,
+ MERKLE_DROP_CONTRACT_ADDRESSES,
+ TOKEN_DISTRO_CONTRACT_ADDRESSES,
+} from '@cowprotocol/common-const'
+import { useContract } from '@cowprotocol/common-hooks'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
-import { MerkleDrop, TokenDistro, MerkleDropAbi, TokenDistroAbi } from '@cowswap/abis'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { ContractTransaction } from '@ethersproject/contracts'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
-import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal'
-import { LOCKED_GNO_VESTING_START_TIME, LOCKED_GNO_VESTING_DURATION } from 'legacy/constants'
-import { COW as COW_TOKENS } from 'legacy/constants/tokens'
-import { MERKLE_DROP_CONTRACT_ADDRESSES, TOKEN_DISTRO_CONTRACT_ADDRESSES } from 'legacy/constants/tokens'
-import { useContract } from 'legacy/hooks/useContract'
import { useTransactionAdder } from 'legacy/state/enhancedTransactions/hooks'
-
-import { useWalletInfo } from 'modules/wallet'
+import { ConfirmOperationType } from 'legacy/state/types'
import { useSingleCallResult } from 'lib/hooks/multicall'
import { fetchClaim } from './claimData'
// We just generally use the mainnet version. We don't read from the contract anyways so the address doesn't matter
-const COW = COW_TOKENS[SupportedChainId.MAINNET]
+const _COW = COW[SupportedChainId.MAINNET]
const useMerkleDropContract = () => useContract(MERKLE_DROP_CONTRACT_ADDRESSES, MerkleDropAbi, true)
const useTokenDistroContract = () => useContract(TOKEN_DISTRO_CONTRACT_ADDRESSES, TokenDistroAbi, true)
export const useAllocation = (): CurrencyAmount => {
const { chainId, account } = useWalletInfo()
- const initialAllocation = useRef(CurrencyAmount.fromRawAmount(COW, 0))
+ const initialAllocation = useRef(CurrencyAmount.fromRawAmount(_COW, 0))
const [allocation, setAllocation] = useState(initialAllocation.current)
useEffect(() => {
@@ -34,7 +37,7 @@ export const useAllocation = (): CurrencyAmount => {
if (account && chainId) {
fetchClaim(account, chainId).then((claim) => {
if (!canceled) {
- setAllocation(CurrencyAmount.fromRawAmount(COW, claim?.amount ?? 0))
+ setAllocation(CurrencyAmount.fromRawAmount(_COW, claim?.amount ?? 0))
}
})
} else {
@@ -59,7 +62,7 @@ export const useCowFromLockedGnoBalances = () => {
const { result, loading } = useSingleCallResult(allocated.greaterThan(0) ? tokenDistro : null, 'balances', [
account ?? undefined,
])
- const claimed = useMemo(() => CurrencyAmount.fromRawAmount(COW, result ? result.claimed.toString() : 0), [result])
+ const claimed = useMemo(() => CurrencyAmount.fromRawAmount(_COW, result ? result.claimed.toString() : 0), [result])
return {
allocated,
diff --git a/apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/index.tsx b/apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/index.tsx
index bcd3ad354f..372e71f18f 100644
--- a/apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/index.tsx
+++ b/apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/index.tsx
@@ -1,32 +1,35 @@
import { useCallback, useState, useEffect } from 'react'
+import { claimAnalytics } from '@cowprotocol/analytics'
+import ArrowIcon from '@cowprotocol/assets/cow-swap/arrow.svg'
+import cowImage from '@cowprotocol/assets/cow-swap/cow_v2.svg'
+import {
+ LOCKED_GNO_VESTING_START_DATE,
+ MERKLE_DROP_CONTRACT_ADDRESSES,
+ TOKEN_DISTRO_CONTRACT_ADDRESSES,
+} from '@cowprotocol/common-const'
+import { usePrevious } from '@cowprotocol/common-hooks'
+import {
+ formatDateWithTimezone,
+ getBlockExplorerUrl,
+ getProviderErrorMessage,
+ isRejectRequestProviderError,
+} from '@cowprotocol/common-utils'
import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
+import { ButtonSize, TokenAmount, ButtonPrimary } from '@cowprotocol/ui'
+import { MouseoverTooltipContent } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { CurrencyAmount, Currency } from '@uniswap/sdk-core'
import { Trans } from '@lingui/macro'
import SVG from 'react-inlinesvg'
-import ArrowIcon from 'legacy/assets/cow-swap/arrow.svg'
-import cowImage from 'legacy/assets/cow-swap/cow_v2.svg'
-import { claimAnalytics } from 'legacy/components/analytics'
-import { ButtonPrimary } from 'legacy/components/Button'
import CopyHelper from 'legacy/components/Copy'
-import { MouseoverTooltipContent } from 'legacy/components/Tooltip'
-import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal'
-import { LOCKED_GNO_VESTING_START_DATE } from 'legacy/constants'
-import { MERKLE_DROP_CONTRACT_ADDRESSES, TOKEN_DISTRO_CONTRACT_ADDRESSES } from 'legacy/constants/tokens'
import { useErrorModal } from 'legacy/hooks/useErrorMessageAndModal'
-import usePrevious from 'legacy/hooks/usePrevious'
-import { ButtonSize } from 'legacy/theme/enum'
-import { getBlockExplorerUrl } from 'legacy/utils'
-import { getProviderErrorMessage, isRejectRequestProviderError } from 'legacy/utils/misc'
-
-import { useWalletInfo } from 'modules/wallet'
+import { ConfirmOperationType } from 'legacy/state/types'
import { HelpCircle } from 'common/pure/HelpCircle'
-import { TokenAmount } from 'common/pure/TokenAmount'
import { Card, BalanceDisplay, ConvertWrapper, VestingBreakdown, CardActions, ExtLink } from 'pages/Account/styled'
-import { formatDateWithTimezone } from 'utils/time'
import { useClaimCowFromLockedGnoCallback } from './hooks'
diff --git a/apps/cowswap-frontend/src/pages/Account/Menu.tsx b/apps/cowswap-frontend/src/pages/Account/Menu.tsx
index c38569b496..c358e6f6f4 100644
--- a/apps/cowswap-frontend/src/pages/Account/Menu.tsx
+++ b/apps/cowswap-frontend/src/pages/Account/Menu.tsx
@@ -1,7 +1,8 @@
+import { ACCOUNT_MENU_LINKS } from '@cowprotocol/common-const'
+
import { NavLink } from 'react-router-dom'
import { SideMenu } from 'legacy/components/SideMenu'
-import { ACCOUNT_MENU_LINKS } from 'legacy/constants'
export function AccountMenu() {
return (
diff --git a/apps/cowswap-frontend/src/pages/Account/Tokens/TokensOverview.tsx b/apps/cowswap-frontend/src/pages/Account/Tokens/TokensOverview.tsx
index e68d39aa4e..cdcfa8efb1 100644
--- a/apps/cowswap-frontend/src/pages/Account/Tokens/TokensOverview.tsx
+++ b/apps/cowswap-frontend/src/pages/Account/Tokens/TokensOverview.tsx
@@ -1,29 +1,22 @@
import { useEffect, useMemo, useState, useCallback, useRef, ChangeEventHandler } from 'react'
+import { useDebounce, useOnClickOutside, usePrevious, useTheme } from '@cowprotocol/common-hooks'
+import { isAddress, isTruthy } from '@cowprotocol/common-utils'
+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 { PageName } from 'legacy/components/AmplitudeAnalytics/constants'
-import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace'
import { ContentWrapper as SearchInputFormatter } from 'legacy/components/SearchModal/CurrencySearch'
import { TokenSearchInput } from 'legacy/components/Tokens/styled'
import TokensTable from 'legacy/components/Tokens/TokensTable'
-import { useAllTokens } from 'legacy/hooks/Tokens'
-import useDebounce from 'legacy/hooks/useDebounce'
-import { useOnClickOutside } from 'legacy/hooks/useOnClickOutside'
-import usePrevious from 'legacy/hooks/usePrevious'
-import useTheme from 'legacy/hooks/useTheme'
-import { useAllTokenBalances } from 'legacy/state/connection/hooks'
+import { useAllTokenBalances, useAllTokens } from 'legacy/hooks/Tokens'
import { useFavouriteTokens, useRemoveAllFavouriteTokens, useInitFavouriteTokens } from 'legacy/state/user/hooks'
import { CloseIcon } from 'legacy/theme'
-import { isAddress } from 'legacy/utils'
-import { isTruthy } from 'legacy/utils/misc'
import { PageTitle } from 'modules/application/containers/PageTitle'
-import { useWalletInfo } from 'modules/wallet'
import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported'
@@ -156,7 +149,7 @@ export default function TokensOverview() {
}, [account, chainId, prevAccount, prevChainId, prevSelectedView, selectedView])
return (
-
+ <>
{!isProviderNetworkUnsupported && (
@@ -214,6 +207,6 @@ export default function TokensOverview() {
{isProviderNetworkUnsupported ? 'Unsupported network' : renderTableContent()}
-
+ >
)
}
diff --git a/apps/cowswap-frontend/src/pages/Account/Tokens/styled.ts b/apps/cowswap-frontend/src/pages/Account/Tokens/styled.ts
index dfd53aa438..d4f614d7b0 100644
--- a/apps/cowswap-frontend/src/pages/Account/Tokens/styled.ts
+++ b/apps/cowswap-frontend/src/pages/Account/Tokens/styled.ts
@@ -4,6 +4,7 @@ import styled from 'styled-components/macro'
import { ThemedText } from 'legacy/theme'
+import { UI } from 'common/constants/theme'
import { Card } from 'pages/Account/styled'
export const MenuWrapper = styled.div`
@@ -15,8 +16,8 @@ export const MenuButton = styled.button`
outline: none;
border: none;
cursor: pointer;
- color: ${({ theme }) => theme.text1};
- background: ${({ theme }) => theme.bg1};
+ color: var(${UI.COLOR_TEXT1});
+ background: var(${UI.COLOR_CONTAINER_BG_01});
height: 44px;
border-radius: 21px;
padding: 0 16px;
@@ -86,7 +87,7 @@ export const AccountPageWrapper = styled.div`
`
export const MainText = styled(ThemedText.Main)`
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
font-size: 14px;
`
@@ -130,7 +131,7 @@ export const ClearSearchInput = styled.div`
`
export const Overview = styled.div`
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
border-radius: 16px;
gap: 16px;
margin: 0;
diff --git a/apps/cowswap-frontend/src/pages/Account/index.tsx b/apps/cowswap-frontend/src/pages/Account/index.tsx
index 645d6d2c90..9a80bfb7f1 100644
--- a/apps/cowswap-frontend/src/pages/Account/index.tsx
+++ b/apps/cowswap-frontend/src/pages/Account/index.tsx
@@ -2,8 +2,6 @@ import { lazy, Suspense } from 'react'
import { useLocation, Outlet } from 'react-router-dom'
-import { PageName } from 'legacy/components/AmplitudeAnalytics/constants'
-import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace'
import { Loading } from 'legacy/components/FlashingLoading'
import { PageTitle } from 'modules/application/containers/PageTitle'
@@ -35,7 +33,7 @@ function _getPropsFromRoute(route: string) {
// Note: As we build these single pages, we will remove this component in the future
export const AccountOverview = () => {
return (
-
+ <>
@@ -43,7 +41,7 @@ export const AccountOverview = () => {
-
+ >
)
}
diff --git a/apps/cowswap-frontend/src/pages/Account/styled.tsx b/apps/cowswap-frontend/src/pages/Account/styled.tsx
index 590b6e245a..ab2e53a4d2 100644
--- a/apps/cowswap-frontend/src/pages/Account/styled.tsx
+++ b/apps/cowswap-frontend/src/pages/Account/styled.tsx
@@ -1,15 +1,14 @@
-import * as CSS from 'csstype'
+import { Loader as SpinnerLoader, ButtonPrimary } from '@cowprotocol/ui'
+import { ExternalLink } from '@cowprotocol/ui'
+
import { transparentize } from 'polished'
import SVG from 'react-inlinesvg'
import styled, { css } from 'styled-components/macro'
-import { ButtonPrimary } from 'legacy/components/Button'
import { CopyIcon as ClickToCopy } from 'legacy/components/Copy'
-import SpinnerLoader from 'legacy/components/Loader'
-import { ExternalLink } from 'legacy/theme'
import { Page, GdocsListStyle } from 'modules/application/pure/Page'
-import { ButtonCustom as AddToMetaMask } from 'modules/wallet/api/pure/AddToMetamask'
+import { AddToMetamask } from 'modules/wallet/containers/AddToMetamask'
import { BannerExplainer } from 'pages/Claim/styled'
@@ -55,138 +54,59 @@ export const ExtLink = styled(ExternalLink)`
}
`
-export const ChildWrapper = styled.div`
+const linkMixin = css`
+ font-size: 13px;
+ height: 100%;
+ font-weight: 500;
+ border-radius: 0;
+ min-height: initial;
+ margin: 0;
+ padding: 0;
+ line-height: 1;
+ color: ${({ theme }) => transparentize(0.3, theme.text1)};
display: flex;
- flex-direction: column;
align-items: center;
- flex-grow: 1;
- justify-content: center;
- border-radius: 21px;
- padding: 20px;
- background-color: ${({ theme }) => theme.grey1};
+ text-decoration: underline;
+ text-decoration-color: transparent;
+ transition: text-decoration-color 0.2s ease-in-out, color 0.2s ease-in-out;
- ${({ theme }) => theme.mediaWidth.upToSmall`
- grid-column-start: 1;
- grid-column-end: 2;
- width: 100%;
- padding: 14px;
- `}
+ ${({ theme }) => theme.mediaWidth.upToMedium`
+ font-size: 15px;
+ margin: 0 auto;
+ `};
- > .item {
- width: 100%;
+ &:hover {
+ text-decoration-color: ${({ theme }) => theme.text1};
+ color: ${({ theme }) => theme.text1};
}
`
-export const GridWrap = styled.div>`
- display: grid;
- grid-column-gap: 22px;
- grid-row-gap: 22px;
- grid-template-columns: ${(props) => (props.horizontal ? '1fr 1fr' : '1fr')};
+export const StyledAddToMetamask = styled(AddToMetamask)`
+ border: 0;
+ min-height: initial;
+ border-radius: initial;
- ${({ theme }) => theme.mediaWidth.upToSmall`
- grid-template-columns: 1fr;
- grid-column-gap: 0;
- > :first-child,
- > :nth-child(2) {
- grid-column-start: 1;
- grid-column-end: 2;
- }
- `}
+ &:hover {
+ background: transparent;
- @supports (-webkit-touch-callout: none) {
- /* CSS specific to iOS devices */
- display: flex;
- flex-direction: column;
+ > div {
+ text-decoration: underline;
+ }
}
-`
-
-export const CardHead = styled.div`
- display: flex;
- flex-grow: 1;
- flex-direction: column;
-`
-export const StyledTime = styled.p`
- margin: 0;
-`
-
-export const ItemTitle = styled.h3`
- display: flex;
- align-items: center;
- margin: 0 0 16px 0;
- font-size: 18px;
- line-height: 1.21;
- color: ${({ theme }) => theme.text1};
- gap: 4px;
-
- ${({ theme }) => theme.mediaWidth.upToSmall`
- margin: 0 0 10px 0;
- font-size: 16px;
- `}
-`
-
-export const FlexWrap = styled.div`
- display: flex;
- flex-grow: 1;
- align-items: center;
- flex-direction: row;
- justify-content: center;
-
- > div {
+ > div > img,
+ > div > svg {
+ height: 13px;
width: auto;
+ object-fit: contain;
+ margin: 0 6px 0 0;
}
- button {
- max-width: 180px;
- }
-
- ${({ theme }) => theme.mediaWidth.upToSmall`
- flex-wrap: wrap;
- > div {
- width: 50%;
- }
- button {
- max-width: 100%;
- }
- `}
+ ${linkMixin}
`
-export const StyledContainer = styled.div`
- display: flex;
- flex: 1;
- align-items: center;
- justify-content: space-between;
-
- ${({ theme }) => theme.mediaWidth.upToSmall`
- flex-wrap: wrap;
- flex-direction: column;
- `}
-`
-
-export const FlexCol = styled.div`
- display: flex;
- flex-grow: 1;
- align-items: center;
- flex-direction: column;
- justify-content: center;
-
- strong {
- font-size: 21px;
- margin-top: 6px;
-
- ${({ theme }) => theme.mediaWidth.upToSmall`
- font-size: 14px;
- `}
- }
-
- span:not([role='img']) {
- font-size: 14px;
- color: ${({ theme }) => transparentize(0.3, theme.text1)};
- text-align: center;
- display: flex;
- align-items: center;
- padding: 8px 0 0 0;
- }
+export const StyledTime = styled.p`
+ margin: 0;
`
export const Loader = styled.div<{ isLoading: boolean }>`
@@ -212,29 +132,6 @@ export const Loader = styled.div<{ isLoading: boolean }>`
`}
`
-export const ProfileGridWrap = styled(GridWrap)`
- grid-template-columns: 1fr auto;
- justify-content: space-between;
- align-items: center;
-
- ${({ theme }) => theme.mediaWidth.upToSmall`
- > :first-child,
- > :nth-child(2) {
- grid-column-start: auto;
- grid-column-end: auto;
- }
- `};
-
- ${({ theme }) => theme.mediaWidth.upToVerySmall`
- > :first-child,
- > :nth-child(2) {
- grid-column-start: 1;
- grid-column-end: 1;
- }
- grid-row-gap: 0px;
- `};
-`
-
export const CardsWrapper = styled.div`
display: flex;
flex-flow: row wrap;
@@ -455,53 +352,8 @@ export const CardActions = styled.div<{ justify?: string; content?: string }>`
`};
> a,
- ${AddToMetaMask}, > ${ClickToCopy} {
- font-size: 13px;
- height: 100%;
- font-weight: 500;
- border-radius: 0;
- min-height: initial;
- margin: 0;
- padding: 0;
- line-height: 1;
- color: ${({ theme }) => transparentize(0.3, theme.text1)};
- display: flex;
- align-items: center;
- text-decoration: underline;
- text-decoration-color: transparent;
- transition: text-decoration-color 0.2s ease-in-out, color 0.2s ease-in-out;
-
- ${({ theme }) => theme.mediaWidth.upToMedium`
- font-size: 15px;
- margin: 0 auto;
- `};
-
- &:hover {
- text-decoration-color: ${({ theme }) => theme.text1};
- color: ${({ theme }) => theme.text1};
- }
- }
-
- ${AddToMetaMask} {
- border: 0;
- min-height: initial;
- border-radius: initial;
-
- &:hover {
- background: transparent;
-
- > div {
- text-decoration: underline;
- }
- }
-
- > div > img,
- > div > svg {
- height: 13px;
- width: auto;
- object-fit: contain;
- margin: 0 6px 0 0;
- }
+ > ${ClickToCopy} {
+ ${linkMixin}
}
> ${ClickToCopy} svg {
@@ -669,31 +521,3 @@ export const CardsSpinner = styled(SpinnerLoader)`
stroke: ${({ theme }) => theme.text1};
}
`
-
-interface TimeProps {
- date: string | undefined
-}
-
-export const TimeFormatted = ({ date }: TimeProps) => {
- if (!date) return null
-
- const months = [
- 'January',
- 'February',
- 'March',
- 'April',
- 'May',
- 'June',
- 'July',
- 'August',
- 'September',
- 'October',
- 'November',
- 'December',
- ]
- const _date = new Date(date)
- const monthName = months[_date.getMonth()]
- const hours = _date.toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', hour12: true })
-
- return {`${_date.getDate()} ${monthName} ${_date.getFullYear()} - ${hours}`}
-}
diff --git a/apps/cowswap-frontend/src/pages/AdvancedOrders/index.tsx b/apps/cowswap-frontend/src/pages/AdvancedOrders/index.tsx
index 876cbf5187..f41b65eb5b 100644
--- a/apps/cowswap-frontend/src/pages/AdvancedOrders/index.tsx
+++ b/apps/cowswap-frontend/src/pages/AdvancedOrders/index.tsx
@@ -1,24 +1,15 @@
import { useAtomValue } from 'jotai'
-import { Navigate } from 'react-router-dom'
-
import { advancedOrdersAtom, AdvancedOrdersWidget, FillAdvancedOrdersDerivedStateUpdater } from 'modules/advancedOrders'
import { OrdersTableWidget } from 'modules/ordersTable'
import { TabOrderTypes } from 'modules/ordersTable/pure/OrdersTableContainer'
-import { useTradeRouteContext } from 'modules/trade/hooks/useTradeRouteContext'
import * as styledEl from 'modules/trade/pure/TradePageLayout'
-import { parameterizeTradeRoute } from 'modules/trade/utils/parameterizeTradeRoute'
import { TradeFormValidation, useGetTradeFormValidation } from 'modules/tradeFormValidation'
import { TwapFormWidget, TwapUpdaters, useAllEmulatedOrders } from 'modules/twap'
import { useTwapFormState } from 'modules/twap/hooks/useTwapFormState'
import { TwapFormState } from 'modules/twap/pure/PrimaryActionButton/getTwapFormState'
-import { Routes as RoutesEnum } from 'common/constants/routes'
-import { useIsAdvancedOrdersEnabled } from 'common/hooks/useIsAdvancedOrdersEnabled'
-
export default function AdvancedOrdersPage() {
- const isAdvancedOrdersEnabled = useIsAdvancedOrdersEnabled()
- const tradeContext = useTradeRouteContext()
const { isUnlocked } = useAtomValue(advancedOrdersAtom)
const allEmulatedOrders = useAllEmulatedOrders()
@@ -26,15 +17,6 @@ export default function AdvancedOrdersPage() {
const primaryFormValidation = useGetTradeFormValidation()
const twapFormValidation = useTwapFormState()
- if (isAdvancedOrdersEnabled === undefined) {
- return null
- }
-
- if (!isAdvancedOrdersEnabled) {
- // To prevent direct access when the flag is off
- return
- }
-
const disablePriceImpact =
primaryFormValidation === TradeFormValidation.QuoteErrors ||
primaryFormValidation === TradeFormValidation.CurrencyNotSupported ||
diff --git a/apps/cowswap-frontend/src/pages/Claim/CanUserClaimMessage.tsx b/apps/cowswap-frontend/src/pages/Claim/CanUserClaimMessage.tsx
index 09a1c14838..7605a44820 100644
--- a/apps/cowswap-frontend/src/pages/Claim/CanUserClaimMessage.tsx
+++ b/apps/cowswap-frontend/src/pages/Claim/CanUserClaimMessage.tsx
@@ -1,17 +1,17 @@
+import CowProtocolImage from '@cowprotocol/assets/cow-swap/cowprotocol.svg'
+import { useNetworkName } from '@cowprotocol/common-hooks'
+import { formatDateWithTimezone } from '@cowprotocol/common-utils'
+import { ButtonSecondary } from '@cowprotocol/ui'
+import { ExternalLink } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
import SVG from 'react-inlinesvg'
-import CowProtocolImage from 'legacy/assets/cow-swap/cowprotocol.svg'
-import { ButtonSecondary } from 'legacy/components/Button'
-import useNetworkName from 'legacy/hooks/useNetworkName'
import { ClaimStatus } from 'legacy/state/claim/actions'
import { useClaimState, useClaimTimeInfo, useClaimLinks } from 'legacy/state/claim/hooks'
-import { ExternalLink } from 'legacy/theme'
-
-import { formatDateWithTimezone } from 'utils/time'
+import { ClaimCommonTypes } from 'legacy/state/claim/types'
import { IntroDescription, BannerExplainer } from './styled'
-import { ClaimCommonTypes } from './types'
type ClaimIntroductionProps = Pick<
ClaimCommonTypes,
diff --git a/apps/cowswap-frontend/src/pages/Claim/ClaimAddress.tsx b/apps/cowswap-frontend/src/pages/Claim/ClaimAddress.tsx
index cf029380e2..54401255a2 100644
--- a/apps/cowswap-frontend/src/pages/Claim/ClaimAddress.tsx
+++ b/apps/cowswap-frontend/src/pages/Claim/ClaimAddress.tsx
@@ -1,16 +1,17 @@
import { useMemo } from 'react'
+import Circle from '@cowprotocol/assets/images/blue-loader.svg'
+import { useENS } from '@cowprotocol/ens'
+import { ButtonSecondary } from '@cowprotocol/ui'
+
import { Trans } from '@lingui/macro'
-import Circle from 'legacy/assets/images/blue-loader.svg'
-import { ButtonSecondary } from 'legacy/components/Button'
-import useENS from 'legacy/hooks/useENS'
import { ClaimStatus } from 'legacy/state/claim/actions'
import { useClaimDispatchers, useClaimState } from 'legacy/state/claim/hooks'
+import { ClaimCommonTypes } from 'legacy/state/claim/types'
import { CustomLightSpinner, ThemedText } from 'legacy/theme'
import { CheckAddress, InputField, InputFieldTitle, InputErrorText } from './styled'
-import { ClaimCommonTypes } from './types'
export type ClaimAddressProps = Pick & {
toggleWalletModal: () => void
diff --git a/apps/cowswap-frontend/src/pages/Claim/ClaimBanner.tsx b/apps/cowswap-frontend/src/pages/Claim/ClaimBanner.tsx
index 5de79e8536..15aa79456e 100644
--- a/apps/cowswap-frontend/src/pages/Claim/ClaimBanner.tsx
+++ b/apps/cowswap-frontend/src/pages/Claim/ClaimBanner.tsx
@@ -1,12 +1,12 @@
+import CheckCircle from '@cowprotocol/assets/cow-swap/check.svg'
+import { useNetworkName } from '@cowprotocol/common-hooks'
+
import { Trans } from '@lingui/macro'
import SVG from 'react-inlinesvg'
-import CheckCircle from 'legacy/assets/cow-swap/check.svg'
-import useNetworkName from 'legacy/hooks/useNetworkName'
import { ClaimStatus } from 'legacy/state/claim/actions'
import { useClaimState } from 'legacy/state/claim/hooks'
-
-import { ClaimCommonTypes } from 'pages/Claim/types'
+import { ClaimCommonTypes } from 'legacy/state/claim/types'
import { ClaimBanner as ClaimBannerWrapper } from './styled'
diff --git a/apps/cowswap-frontend/src/pages/Claim/ClaimNav.tsx b/apps/cowswap-frontend/src/pages/Claim/ClaimNav.tsx
index 8079e2bdbc..356e317e2f 100644
--- a/apps/cowswap-frontend/src/pages/Claim/ClaimNav.tsx
+++ b/apps/cowswap-frontend/src/pages/Claim/ClaimNav.tsx
@@ -1,13 +1,13 @@
-import { ButtonSecondary } from 'legacy/components/Button'
+import { shortenAddress } from '@cowprotocol/common-utils'
+import { ButtonSecondary } from '@cowprotocol/ui'
+import { Identicon } from '@cowprotocol/wallet'
+
import CopyHelper from 'legacy/components/Copy'
import { ClaimStatus } from 'legacy/state/claim/actions'
import { useClaimDispatchers, useClaimState } from 'legacy/state/claim/hooks'
-import { shortenAddress } from 'legacy/utils'
-
-import { Identicon } from 'modules/wallet/api/container/Identicon'
+import { ClaimCommonTypes } from 'legacy/state/claim/types'
import { TopNav, ClaimAccount, ClaimAccountButtons } from './styled'
-import { ClaimCommonTypes } from './types'
type ClaimNavProps = Pick
diff --git a/apps/cowswap-frontend/src/pages/Claim/ClaimSummary.tsx b/apps/cowswap-frontend/src/pages/Claim/ClaimSummary.tsx
index b29f27c32b..e0590b6155 100644
--- a/apps/cowswap-frontend/src/pages/Claim/ClaimSummary.tsx
+++ b/apps/cowswap-frontend/src/pages/Claim/ClaimSummary.tsx
@@ -1,20 +1,19 @@
+import { V_COW } from '@cowprotocol/common-const'
+import { TokenAmount } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { CurrencyAmount, Currency, Token } from '@uniswap/sdk-core'
import { Trans } from '@lingui/macro'
import JSBI from 'jsbi'
import CowProtocolLogo from 'legacy/components/CowProtocolLogo'
-import { V_COW } from 'legacy/constants/tokens'
import { ClaimStatus } from 'legacy/state/claim/actions'
import { useClaimState } from 'legacy/state/claim/hooks'
+import { ClaimCommonTypes } from 'legacy/state/claim/types'
import { useTokenBalance } from 'modules/tokens/hooks/useCurrencyBalance'
-import { useWalletInfo } from 'modules/wallet'
-
-import { TokenAmount } from 'common/pure/TokenAmount'
import { ClaimSummary as ClaimSummaryWrapper, ClaimSummaryTitle, ClaimTotal } from './styled'
-import { ClaimCommonTypes } from './types'
type ClaimSummaryProps = Pick & {
unclaimedAmount: ClaimCommonTypes['tokenCurrencyAmount'] | undefined
diff --git a/apps/cowswap-frontend/src/pages/Claim/ClaimingStatus.tsx b/apps/cowswap-frontend/src/pages/Claim/ClaimingStatus.tsx
index 984f7dfcb3..35b1c9692a 100644
--- a/apps/cowswap-frontend/src/pages/Claim/ClaimingStatus.tsx
+++ b/apps/cowswap-frontend/src/pages/Claim/ClaimingStatus.tsx
@@ -1,31 +1,31 @@
import { useMemo } from 'react'
+import CowProtocolIcon from '@cowprotocol/assets/cow-swap/cowprotocol.svg'
+import discordImage from '@cowprotocol/assets/cow-swap/discord.svg'
+import twitterImage from '@cowprotocol/assets/cow-swap/twitter.svg'
+import { V_COW } from '@cowprotocol/common-const'
+import { shortenAddress } from '@cowprotocol/common-utils'
+import { TokenAmount, ButtonSecondary } from '@cowprotocol/ui'
+import { ExternalLink } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { CurrencyAmount } from '@uniswap/sdk-core'
import { Trans } from '@lingui/macro'
import SVG from 'react-inlinesvg'
import { Link } from 'react-router-dom'
-import CowProtocolIcon from 'legacy/assets/cow-swap/cowprotocol.svg'
-import discordImage from 'legacy/assets/cow-swap/discord.svg'
-import twitterImage from 'legacy/assets/cow-swap/twitter.svg'
-import { ButtonSecondary } from 'legacy/components/Button'
import CopyHelper from 'legacy/components/Copy'
import CowProtocolLogo from 'legacy/components/CowProtocolLogo'
import { EnhancedTransactionLink } from 'legacy/components/EnhancedTransactionLink'
import { ExplorerLink } from 'legacy/components/ExplorerLink'
-import { V_COW } from 'legacy/constants/tokens'
import { ClaimStatus } from 'legacy/state/claim/actions'
import { useClaimDispatchers, useClaimState } from 'legacy/state/claim/hooks'
+import { ClaimCommonTypes } from 'legacy/state/claim/types'
import { useAllClaimingTransactions } from 'legacy/state/enhancedTransactions/hooks'
-import { ExternalLink } from 'legacy/theme'
-import { shortenAddress } from 'legacy/utils'
-import { useWalletInfo } from 'modules/wallet'
-import AddToMetamask from 'modules/wallet/web3-react/containers/AddToMetamask'
+import { AddToMetamask } from 'modules/wallet/containers/AddToMetamask'
import { Routes } from 'common/constants/routes'
-import { TokenAmount } from 'common/pure/TokenAmount'
import {
ConfirmOrLoadingWrapper,
ConfirmedIcon,
@@ -35,8 +35,6 @@ import {
SuccessBanner,
} from 'pages/Claim/styled'
-import { ClaimCommonTypes } from './types'
-
const COW_TWEET_TEMPLATE =
'I just joined the 🐮 CoWmunity @CoWSwap and claimed my first vCOW tokens! Join me at https://swap.cow.fi/'
diff --git a/apps/cowswap-frontend/src/pages/Claim/ClaimsOnOtherChainsBanner.tsx b/apps/cowswap-frontend/src/pages/Claim/ClaimsOnOtherChainsBanner.tsx
index a2dde0130d..db278cd3ae 100644
--- a/apps/cowswap-frontend/src/pages/Claim/ClaimsOnOtherChainsBanner.tsx
+++ b/apps/cowswap-frontend/src/pages/Claim/ClaimsOnOtherChainsBanner.tsx
@@ -1,6 +1,7 @@
import { useMemo } from 'react'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { AlertTriangle } from 'react-feather'
import styled from 'styled-components/macro'
@@ -9,8 +10,6 @@ import NotificationBanner from 'legacy/components/NotificationBanner'
import { useClaimState } from 'legacy/state/claim/hooks'
import { ClaimInfo } from 'legacy/state/claim/reducer'
-import { useWalletInfo } from 'modules/wallet'
-
// const ChainSpan = styled.span``
const Wrapper = styled.div`
display: flex;
diff --git a/apps/cowswap-frontend/src/pages/Claim/ClaimsTable.tsx b/apps/cowswap-frontend/src/pages/Claim/ClaimsTable.tsx
index 789dd7d340..3f0eba9c31 100644
--- a/apps/cowswap-frontend/src/pages/Claim/ClaimsTable.tsx
+++ b/apps/cowswap-frontend/src/pages/Claim/ClaimsTable.tsx
@@ -1,30 +1,25 @@
import { useEffect } from 'react'
+import CowProtocolImage from '@cowprotocol/assets/cow-swap/cowprotocol.svg'
+import Circle from '@cowprotocol/assets/images/blue-loader.svg'
+import { TokenAmount } from '@cowprotocol/ui'
+import { ExternalLink } from '@cowprotocol/ui'
+
import SVG from 'react-inlinesvg'
import styled from 'styled-components/macro'
-import CowProtocolImage from 'legacy/assets/cow-swap/cowprotocol.svg'
-import Circle from 'legacy/assets/images/blue-loader.svg'
import CowProtocolLogo from 'legacy/components/CowProtocolLogo'
import { ClaimStatus } from 'legacy/state/claim/actions'
-import {
- ClaimType,
- useClaimDispatchers,
- useClaimState,
- useClaimTimeInfo,
- useClaimLinks,
-} from 'legacy/state/claim/hooks'
+import { useClaimDispatchers, useClaimState, useClaimTimeInfo, useClaimLinks } from 'legacy/state/claim/hooks'
+import { ClaimType } from 'legacy/state/claim/hooks/types'
import { getPaidClaims, getIndexes } from 'legacy/state/claim/hooks/utils'
+import { ClaimCommonTypes, EnhancedUserClaimData } from 'legacy/state/claim/types'
import { useAllClaimingTransactionIndices } from 'legacy/state/enhancedTransactions/hooks'
import { CustomLightSpinner } from 'legacy/theme'
-import { ExternalLink } from 'legacy/theme'
-import { TokenAmount } from 'common/pure/TokenAmount'
import { Countdown } from 'pages/Claim/Countdown'
import { ClaimTable, ClaimBreakdown, TokenLogo, BannerExplainer } from 'pages/Claim/styled'
-import { ClaimCommonTypes, EnhancedUserClaimData } from './types'
-
export type ClaimsTableProps = Pick
// TODO: fix in other pr
diff --git a/apps/cowswap-frontend/src/pages/Claim/FooterNavButtons.tsx b/apps/cowswap-frontend/src/pages/Claim/FooterNavButtons.tsx
index 6cb6feb30a..2f679a05c7 100644
--- a/apps/cowswap-frontend/src/pages/Claim/FooterNavButtons.tsx
+++ b/apps/cowswap-frontend/src/pages/Claim/FooterNavButtons.tsx
@@ -1,10 +1,11 @@
import { ReactNode, useEffect, useRef } from 'react'
+import { ButtonPrimary, ButtonSecondary } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { isAddress } from '@ethersproject/address'
import { Trans } from '@lingui/macro'
-import { ButtonPrimary, ButtonSecondary } from 'legacy/components/Button'
import { ClaimStatus } from 'legacy/state/claim/actions'
import {
useClaimDispatchers,
@@ -12,10 +13,7 @@ import {
useHasClaimInvestmentFlowError,
useHasZeroInvested,
} from 'legacy/state/claim/hooks'
-
-import { useWalletInfo } from 'modules/wallet'
-
-import { ClaimCommonTypes } from 'pages/Claim/types'
+import { ClaimCommonTypes } from 'legacy/state/claim/types'
import { ClaimAddressProps } from './ClaimAddress'
import { FooterNavButtons as FooterNavButtonsWrapper } from './styled'
diff --git a/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/InvestOption.tsx b/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/InvestOption.tsx
index 15ce851919..aba0b53bd0 100644
--- a/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/InvestOption.tsx
+++ b/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/InvestOption.tsx
@@ -1,40 +1,36 @@
import { useCallback, useEffect, useMemo, useState } from 'react'
+import CheckCircle from '@cowprotocol/assets/cow-swap/check.svg'
+import ImportantIcon from '@cowprotocol/assets/cow-swap/important.svg'
+import { AVG_APPROVE_COST_GWEI, ONE_HUNDRED_PERCENT } from '@cowprotocol/common-const'
+import {
+ calculateGasMargin,
+ getProviderErrorMessage,
+ tryParseCurrencyAmount,
+ formatTokenAmount,
+ formatSymbol,
+} from '@cowprotocol/common-utils'
+import { Loader, loadingOpacityMixin, ButtonSize, TokenAmount, ButtonConfirmed, Row } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { BigNumber } from '@ethersproject/bignumber'
import { CurrencyAmount } from '@uniswap/sdk-core'
import SVG from 'react-inlinesvg'
import styled from 'styled-components/macro'
-import CheckCircle from 'legacy/assets/cow-swap/check.svg'
-import ImportantIcon from 'legacy/assets/cow-swap/important.svg'
-import { ButtonConfirmed } from 'legacy/components/Button'
import CowProtocolLogo from 'legacy/components/CowProtocolLogo'
-import Loader from 'legacy/components/Loader'
-import { loadingOpacityMixin } from 'legacy/components/Loader/styled'
import { Input as NumericalInput } from 'legacy/components/NumericalInput'
-import Row from 'legacy/components/Row'
-import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal'
-import { AVG_APPROVE_COST_GWEI } from 'legacy/constants'
-import { ONE_HUNDRED_PERCENT } from 'legacy/constants/misc'
import { useApproveCallbackFromClaim } from 'legacy/hooks/useApproveCallback'
+import { ApprovalState } from 'legacy/hooks/useApproveCallback/useApproveCallbackMod'
import { useErrorModal } from 'legacy/hooks/useErrorMessageAndModal'
import { useClaimDispatchers, useClaimState } from 'legacy/state/claim/hooks'
import { calculateInvestmentAmounts, calculatePercentage } from 'legacy/state/claim/hooks/utils'
+import { EnhancedUserClaimData } from 'legacy/state/claim/types'
import { useGasPrices } from 'legacy/state/gas/hooks'
-import { ButtonSize } from 'legacy/theme/enum'
-import { calculateGasMargin } from 'legacy/utils/calculateGasMargin'
-import { getProviderErrorMessage } from 'legacy/utils/misc'
+import { ConfirmOperationType } from 'legacy/state/types'
import useCurrencyBalance from 'modules/tokens/hooks/useCurrencyBalance'
-import { useWalletInfo } from 'modules/wallet'
-import { TokenAmount } from 'common/pure/TokenAmount'
-import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount'
-import { formatTokenAmount } from 'utils/amountFormat'
-import { formatSymbol } from 'utils/format'
-
-import { ApprovalState } from 'legacy/hooks/useApproveCallback/useApproveCallbackMod'
import { IS_TESTING_ENV } from '../const'
import {
InvestAvailableBar,
@@ -46,7 +42,6 @@ import {
UserMessage,
WarningWrapper,
} from '../styled'
-import { EnhancedUserClaimData } from '../types'
import { InvestmentFlowProps } from '.'
diff --git a/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/InvestSummaryRow.tsx b/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/InvestSummaryRow.tsx
index 05f7a6dadb..1cc4743f68 100644
--- a/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/InvestSummaryRow.tsx
+++ b/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/InvestSummaryRow.tsx
@@ -1,14 +1,15 @@
+import ImportantIcon from '@cowprotocol/assets/cow-swap/important.svg'
+import { ONE_HUNDRED_PERCENT } from '@cowprotocol/common-const'
+import { TokenAmount } from '@cowprotocol/ui'
+
import SVG from 'react-inlinesvg'
-import ImportantIcon from 'legacy/assets/cow-swap/important.svg'
import CowProtocolLogo from 'legacy/components/CowProtocolLogo'
-import { ONE_HUNDRED_PERCENT } from 'legacy/constants/misc'
-import { ClaimType } from 'legacy/state/claim/hooks'
+import { ClaimType } from 'legacy/state/claim/hooks/types'
import { calculatePercentage } from 'legacy/state/claim/hooks/utils'
+import { ClaimWithInvestmentData } from 'legacy/state/claim/types'
-import { TokenAmount } from 'common/pure/TokenAmount'
import { TokenLogo, InvestAvailableBar, UserMessage } from 'pages/Claim/styled'
-import { ClaimWithInvestmentData } from 'pages/Claim/types'
export type Props = { claim: ClaimWithInvestmentData }
diff --git a/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/index.tsx b/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/index.tsx
index ab5a2758f9..0b48baa463 100644
--- a/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/index.tsx
+++ b/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/index.tsx
@@ -1,18 +1,19 @@
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 { SupportedChainId } from '@cowprotocol/cow-sdk'
+import { ExternalLink } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { CurrencyAmount } from '@uniswap/sdk-core'
import SVG from 'react-inlinesvg'
-import CowProtocolImage from 'legacy/assets/cow-swap/cowprotocol.svg'
-import ImportantIcon from 'legacy/assets/cow-swap/important.svg'
-import RoundArrow from 'legacy/assets/cow-swap/round-arrow.svg'
import { BadgeVariant } from 'legacy/components/Badge'
import { ExplorerLink } from 'legacy/components/ExplorerLink'
import { FaqDrawer } from 'legacy/components/FaqDrawer'
import { Stepper } from 'legacy/components/Stepper'
-import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal'
import { ClaimStatus } from 'legacy/state/claim/actions'
import {
useClaimState,
@@ -23,9 +24,8 @@ import {
} from 'legacy/state/claim/hooks'
import { calculateInvestmentAmounts } from 'legacy/state/claim/hooks/utils'
import { InvestClaim } from 'legacy/state/claim/reducer'
-import { ExternalLink } from 'legacy/theme'
-
-import { useWalletInfo } from 'modules/wallet'
+import { ClaimCommonTypes, ClaimWithInvestmentData, EnhancedUserClaimData } from 'legacy/state/claim/types'
+import { ConfirmOperationType } from 'legacy/state/types'
import { ClaimSummaryView } from 'pages/Claim/ClaimSummary'
import { InvestSummaryRow } from 'pages/Claim/InvestmentFlow/InvestSummaryRow'
@@ -43,8 +43,6 @@ import {
import InvestOption from './InvestOption'
-import { ClaimCommonTypes, ClaimWithInvestmentData, EnhancedUserClaimData } from '../types'
-
const STEPS_DATA = [
{
title: 'Start',
diff --git a/apps/cowswap-frontend/src/pages/Claim/const.ts b/apps/cowswap-frontend/src/pages/Claim/const.ts
index 071a062a96..d377de27ce 100644
--- a/apps/cowswap-frontend/src/pages/Claim/const.ts
+++ b/apps/cowswap-frontend/src/pages/Claim/const.ts
@@ -1,3 +1,3 @@
-import { isProd, isEns, isBarn } from 'legacy/utils/environments'
+import { isProd, isEns, isBarn } from '@cowprotocol/common-utils'
export const IS_TESTING_ENV = !isProd && !isEns && !isBarn
diff --git a/apps/cowswap-frontend/src/pages/Claim/index.tsx b/apps/cowswap-frontend/src/pages/Claim/index.tsx
index b2e71d4d4a..15d1b068fb 100644
--- a/apps/cowswap-frontend/src/pages/Claim/index.tsx
+++ b/apps/cowswap-frontend/src/pages/Claim/index.tsx
@@ -1,26 +1,22 @@
import { useCallback, useEffect, useMemo } from 'react'
+import { usePrevious } from '@cowprotocol/common-hooks'
+import { getProviderErrorMessage } from '@cowprotocol/common-utils'
+import { useENS } from '@cowprotocol/ens'
+import { Loader } from '@cowprotocol/ui'
+import { useWalletInfo } from '@cowprotocol/wallet'
+
import Confetti from 'legacy/components/Confetti'
-import Loader from 'legacy/components/Loader'
-import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal'
-import useENS from 'legacy/hooks/useENS'
import { useErrorModal } from 'legacy/hooks/useErrorMessageAndModal'
-import usePrevious from 'legacy/hooks/usePrevious'
import useTransactionConfirmationModal from 'legacy/hooks/useTransactionConfirmationModal'
import { useToggleWalletModal } from 'legacy/state/application/hooks'
import { ClaimStatus } from 'legacy/state/claim/actions'
-import {
- useUserEnhancedClaimData,
- useUserUnclaimedAmount,
- useClaimCallback,
- ClaimInput,
-} from 'legacy/state/claim/hooks'
+import { useUserEnhancedClaimData, useUserUnclaimedAmount, useClaimCallback } from 'legacy/state/claim/hooks'
import { useClaimDispatchers, useClaimState } from 'legacy/state/claim/hooks'
+import { ClaimInput } from 'legacy/state/claim/hooks/types'
import { getFreeClaims, hasPaidClaim, hasFreeClaim, prepareInvestClaims } from 'legacy/state/claim/hooks/utils'
import ClaimsOnOtherChainsUpdater from 'legacy/state/claim/updater'
-import { getProviderErrorMessage } from 'legacy/utils/misc'
-
-import { useWalletInfo } from 'modules/wallet'
+import { ConfirmOperationType } from 'legacy/state/types'
import { PageWrapper, InnerPageWrapper } from 'pages/Claim/styled'
diff --git a/apps/cowswap-frontend/src/pages/Claim/styled.ts b/apps/cowswap-frontend/src/pages/Claim/styled.ts
index 353417bf2b..78e2615587 100644
--- a/apps/cowswap-frontend/src/pages/Claim/styled.ts
+++ b/apps/cowswap-frontend/src/pages/Claim/styled.ts
@@ -1,17 +1,20 @@
+import LogoGNO from '@cowprotocol/assets/cow-swap/gno.png'
+import LogoETH from '@cowprotocol/assets/cow-swap/network-mainnet-logo.svg'
+import LogoUSDC from '@cowprotocol/assets/cow-swap/usdc.png'
+import LogoXDAI from '@cowprotocol/assets/cow-swap/xdai.png'
+import { ButtonPrimary, ButtonSecondary } from '@cowprotocol/ui'
+
import { transparentize, darken, lighten } from 'polished'
import { CheckCircle, Frown } from 'react-feather'
import styled from 'styled-components/macro'
-import LogoGNO from 'legacy/assets/cow-swap/gno.png'
-import LogoETH from 'legacy/assets/cow-swap/network-mainnet-logo.svg'
-import LogoUSDC from 'legacy/assets/cow-swap/usdc.png'
-import LogoXDAI from 'legacy/assets/cow-swap/xdai.png'
import BadgeOriginal from 'legacy/components/Badge'
-import { ButtonPrimary, ButtonSecondary } from 'legacy/components/Button'
import { CopyIcon } from 'legacy/components/Copy'
import { Icon } from 'legacy/components/CowProtocolLogo'
import { Step } from 'legacy/components/Stepper'
+import { UI } from 'common/constants/theme'
+
import ClaimsOnOtherChainsBanner from './ClaimsOnOtherChainsBanner'
export const InnerPageWrapper = styled.div`
@@ -19,11 +22,11 @@ export const InnerPageWrapper = styled.div`
--border-radius-small: 16px;
display: flex;
flex-flow: column wrap;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
padding: 30px;
border: none;
box-shadow: ${({ theme }) => theme.boxShadow1};
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
min-height: 450px;
justify-content: center;
align-items: center;
@@ -161,7 +164,7 @@ export const ClaimSummary = styled.div`
align-items: center;
justify-content: flex-start;
padding: 8px;
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
border: 0;
border-radius: var(--border-radius);
margin: 0 auto 24px;
@@ -201,7 +204,7 @@ export const IntroDescription = styled.div<{ center?: boolean }>`
}
> p > i {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
font-weight: 600;
font-style: normal;
}
@@ -431,7 +434,7 @@ export const ClaimTable = styled.div`
text-align: left;
font-weight: normal;
font-size: 15px;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
position: relative;
}
@@ -442,7 +445,7 @@ export const ClaimTable = styled.div`
td {
display: flex;
align-items: center;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
word-break: break-word;
background: ${({ theme }) => theme.blueShade3};
}
@@ -505,7 +508,7 @@ export const ClaimTable = styled.div`
> span > b {
font-weight: 500;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
}
@@ -548,7 +551,7 @@ export const UserMessage = styled.div<{ variant?: string }>`
? transparentize(0.9, theme.blue2)
: transparentize(0.9, theme.attention)};
color: ${({ variant, theme }) =>
- variant === 'danger' ? theme.danger : variant === 'info' ? theme.blue2 : darken(0.1, theme.attention)};
+ variant === 'danger' ? `var(${UI.COLOR_DANGER})` : variant === 'info' ? theme.blue2 : darken(0.1, theme.attention)};
margin: 0 auto;
align-items: center;
font-size: 15px;
@@ -571,7 +574,11 @@ export const UserMessage = styled.div<{ variant?: string }>`
> svg > path {
fill: ${({ variant, theme }) =>
- variant === 'danger' ? theme.danger : variant === 'info' ? theme.blue2 : darken(0.1, theme.attention)};
+ variant === 'danger'
+ ? `var(${UI.COLOR_DANGER})`
+ : variant === 'info'
+ ? theme.blue2
+ : darken(0.1, theme.attention)};
}
> span {
@@ -652,7 +659,7 @@ export const ClaimTotal = styled.div`
export const ConfirmOrLoadingWrapper = styled.div<{ activeBG: boolean }>`
width: 100%;
padding: 24px 24px 0;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
position: relative;
display: flex;
flex-direction: column;
@@ -670,7 +677,7 @@ export const ConfirmOrLoadingWrapper = styled.div<{ activeBG: boolean }>`
line-height: 1.2;
text-align: center;
margin: 0 0 12px;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
${({ theme }) => theme.mediaWidth.upToSmall`
font-size: 26px;
@@ -751,8 +758,8 @@ export const ClaimBanner = styled.div<{ isClaimed: boolean }>`
display: flex;
justify-content: center;
align-items: center;
- background: ${({ theme, isClaimed }) => transparentize(0.9, !isClaimed ? theme.success : theme.blue2)};
- color: ${({ theme, isClaimed }) => (!isClaimed ? theme.success : theme.blue2)};
+ background: ${({ theme, isClaimed }) => transparentize(0.9, !isClaimed ? `var(${UI.COLOR_SUCCESS})` : theme.blue2)};
+ color: ${({ theme, isClaimed }) => (!isClaimed ? `var(${UI.COLOR_SUCCESS})` : theme.blue2)};
margin: 0 auto 16px;
font-weight: 600;
@@ -767,7 +774,7 @@ export const ClaimBanner = styled.div<{ isClaimed: boolean }>`
height: 21px;
> path {
- fill: ${({ theme, isClaimed }) => (!isClaimed ? theme.success : theme.blue2)};
+ fill: ${({ theme, isClaimed }) => (!isClaimed ? `var(${UI.COLOR_SUCCESS})` : theme.blue2)};
}
${({ theme }) => theme.mediaWidth.upToSmall`
@@ -780,7 +787,7 @@ export const InputField = styled.div`
padding: 18px 18px 18px 36px;
border-radius: var(--border-radius);
border: ${({ theme }) => theme.currencyInput?.border};
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
display: flex;
flex-flow: row wrap;
background: ${({ theme }) => theme.currencyInput?.background};
@@ -792,7 +799,7 @@ export const InputField = styled.div`
border: 0;
font-size: 24px;
outline: 0;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
width: 100%;
}
@@ -839,7 +846,7 @@ export const InputField = styled.div`
padding: 0;
font-size: 22px;
font-weight: 600;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
> span {
@@ -961,7 +968,7 @@ export const TopNav = styled.div`
${ButtonSecondary} {
margin: 0;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
font-size: 15px;
width: auto;
}
@@ -1198,7 +1205,7 @@ export const UnderlineButton = styled.button`
}
&:hover {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
&:disabled {
@@ -1258,7 +1265,7 @@ export const InvestInput = styled.span<{ disabled: boolean }>`
bottom: 0;
margin: auto;
font-weight: normal;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
background: ${({ theme }) => theme.bg5};
border-radius: 12px;
padding: 0 12px;
@@ -1271,7 +1278,7 @@ export const InvestInput = styled.span<{ disabled: boolean }>`
}
> div > label > input {
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
border: none;
padding: 12px 70px 0 0;
font-size: 26px;
@@ -1353,7 +1360,7 @@ export const InvestAvailableBar = styled.div<{ percentage?: number }>`
justify-content: flex-start;
overflow: hidden;
border-radius: 24px;
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
margin: 6px 0;
padding: 0;
@@ -1376,7 +1383,7 @@ export const InvestAvailableBar = styled.div<{ percentage?: number }>`
content: ${({ percentage }) => (percentage ? `'${percentage}%'` : '0%')};
display: block;
font-size: 12px;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
z-index: 1;
height: 100%;
width: ${({ percentage }) => (percentage ? `${percentage}%` : '0%')};
@@ -1425,7 +1432,7 @@ export const InvestSummary = styled.div`
> span > b {
font-weight: 600;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
}
`
@@ -1519,7 +1526,7 @@ export const AccountClaimSummary = styled.div`
border-radius: var(--iconSize);
width: var(--iconSize);
height: var(--iconSize);
- background: ${({ theme }) => theme.bg1};
+ background: var(${UI.COLOR_CONTAINER_BG_01});
${({ theme }) => theme.mediaWidth.upToSmall`
transform: rotate(90deg);
@@ -1532,7 +1539,7 @@ export const AccountClaimSummary = styled.div`
}
> svg > path {
- fill: ${({ theme }) => theme.text1};
+ fill: var(${UI.COLOR_TEXT1});
}
}
`
@@ -1589,7 +1596,7 @@ export const CowSpinner = styled.div`
height: 94%;
width: 94%;
padding: 0;
- stroke: ${({ theme }) => theme.text1};
+ stroke: var(${UI.COLOR_TEXT1});
border-radius: var(--circle-size);
z-index: 1;
}
diff --git a/apps/cowswap-frontend/src/pages/CookiePolicy/index.tsx b/apps/cowswap-frontend/src/pages/CookiePolicy/index.tsx
index 5df2fc89c1..d8f788d682 100644
--- a/apps/cowswap-frontend/src/pages/CookiePolicy/index.tsx
+++ b/apps/cowswap-frontend/src/pages/CookiePolicy/index.tsx
@@ -5,6 +5,8 @@ import { MarkdownPage } from 'legacy/components/Markdown'
import { PageTitle } from 'modules/application/containers/PageTitle'
import { GdocsListStyle } from 'modules/application/pure/Page'
+import { UI } from 'common/constants/theme'
+
import contentFile from './CookiePolicy.md'
const Wrapper = styled(MarkdownPage)`
@@ -20,14 +22,14 @@ const Wrapper = styled(MarkdownPage)`
width: 100%;
min-width: 800px;
border-spacing: 1px;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
> thead {
background: ${({ theme }) => theme.bg3};
}
> tbody > tr {
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
}
> tbody > tr > td > span[role='img'] {
diff --git a/apps/cowswap-frontend/src/pages/Faq/AffiliateFaq.tsx b/apps/cowswap-frontend/src/pages/Faq/AffiliateFaq.tsx
index 0c16e79461..50e68d9a92 100644
--- a/apps/cowswap-frontend/src/pages/Faq/AffiliateFaq.tsx
+++ b/apps/cowswap-frontend/src/pages/Faq/AffiliateFaq.tsx
@@ -1,9 +1,8 @@
+import { BARN_URL, PRODUCTION_URL } from '@cowprotocol/common-const'
+
import { Link } from 'react-router-dom'
-import { PageName } from 'legacy/components/AmplitudeAnalytics/constants'
-import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace'
import { LinkScrollable } from 'legacy/components/Link'
-import { BARN_URL, PRODUCTION_URL } from 'legacy/constants'
import { PageTitle } from 'modules/application/containers/PageTitle'
import { Page, Content } from 'modules/application/pure/Page'
@@ -17,8 +16,6 @@ import ToC from './ToC'
import { Footer } from '.'
-// AmplitudeAnalytics
-
const PROD = `https://${PRODUCTION_URL}`
const BARN = `https://${BARN_URL}`
@@ -26,7 +23,7 @@ export default function AffiliateFaq() {
const { toc, faqRef } = useToC()
return (
-
+ <>
@@ -203,6 +200,6 @@ export default function AffiliateFaq() {
-
+ >
)
}
diff --git a/apps/cowswap-frontend/src/pages/Faq/EthFlowFaq.tsx b/apps/cowswap-frontend/src/pages/Faq/EthFlowFaq.tsx
index 8def34fb02..b839996389 100644
--- a/apps/cowswap-frontend/src/pages/Faq/EthFlowFaq.tsx
+++ b/apps/cowswap-frontend/src/pages/Faq/EthFlowFaq.tsx
@@ -1,6 +1,3 @@
-import { PageName } from 'legacy/components/AmplitudeAnalytics/constants'
-import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace'
-
import { PageTitle } from 'modules/application/containers/PageTitle'
import { Page, Content } from 'modules/application/pure/Page'
@@ -11,13 +8,11 @@ import ToC from './ToC'
import { Footer } from '.'
-// AmplitudeAnalytics
-
export default function EthFlowFAQ() {
const { toc, faqRef } = useToC()
return (
-
+ <>
@@ -347,6 +342,6 @@ export default function EthFlowFAQ() {
-
+ >
)
}
diff --git a/apps/cowswap-frontend/src/pages/Faq/LimitOrdersFaq.tsx b/apps/cowswap-frontend/src/pages/Faq/LimitOrdersFaq.tsx
index e1295bec70..6a76ce33c0 100644
--- a/apps/cowswap-frontend/src/pages/Faq/LimitOrdersFaq.tsx
+++ b/apps/cowswap-frontend/src/pages/Faq/LimitOrdersFaq.tsx
@@ -1,6 +1,3 @@
-import { PageName } from 'legacy/components/AmplitudeAnalytics/constants'
-import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace'
-
import { PageTitle } from 'modules/application/containers/PageTitle'
import { Content, Page } from 'modules/application/pure/Page'
@@ -15,7 +12,7 @@ export default function LimitOrderFAQ() {
const { toc, faqRef } = useToC()
return (
-
+ <>
@@ -228,6 +225,6 @@ export default function LimitOrderFAQ() {
-
+ >
)
}
diff --git a/apps/cowswap-frontend/src/pages/Faq/Menu.tsx b/apps/cowswap-frontend/src/pages/Faq/Menu.tsx
index c1bf435cc1..fdb72cff07 100644
--- a/apps/cowswap-frontend/src/pages/Faq/Menu.tsx
+++ b/apps/cowswap-frontend/src/pages/Faq/Menu.tsx
@@ -1,7 +1,8 @@
+import { FAQ_MENU_LINKS } from '@cowprotocol/common-const'
+
import { NavLink } from 'react-router-dom'
import { SideMenu } from 'legacy/components/SideMenu'
-import { FAQ_MENU_LINKS } from 'legacy/constants'
export function FaqMenu() {
return (
diff --git a/apps/cowswap-frontend/src/pages/Faq/ProtocolFaq.tsx b/apps/cowswap-frontend/src/pages/Faq/ProtocolFaq.tsx
index cf17adf769..182a9731e3 100644
--- a/apps/cowswap-frontend/src/pages/Faq/ProtocolFaq.tsx
+++ b/apps/cowswap-frontend/src/pages/Faq/ProtocolFaq.tsx
@@ -1,5 +1,3 @@
-import { PageName } from 'legacy/components/AmplitudeAnalytics/constants'
-import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace'
import { LinkScrollable } from 'legacy/components/Link'
import { PageTitle } from 'modules/application/containers/PageTitle'
@@ -12,13 +10,11 @@ import ToC from './ToC'
import { Footer } from '.'
-// AmplitudeAnalytics
-
export default function ProtocolFaq() {
const { toc, faqRef } = useToC()
return (
-
+ <>
@@ -271,6 +267,6 @@ export default function ProtocolFaq() {
-
+ >
)
}
diff --git a/apps/cowswap-frontend/src/pages/Faq/TokenFaq.tsx b/apps/cowswap-frontend/src/pages/Faq/TokenFaq.tsx
index 37158f0814..9119e8a239 100644
--- a/apps/cowswap-frontend/src/pages/Faq/TokenFaq.tsx
+++ b/apps/cowswap-frontend/src/pages/Faq/TokenFaq.tsx
@@ -1,8 +1,5 @@
import { Link } from 'react-router-dom'
-import { PageName } from 'legacy/components/AmplitudeAnalytics/constants'
-import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace'
-
import { PageTitle } from 'modules/application/containers/PageTitle'
import { Page, Content } from 'modules/application/pure/Page'
@@ -19,7 +16,7 @@ export default function TokenFaq() {
const { toc, faqRef } = useToC()
return (
-
+ <>
@@ -134,6 +131,6 @@ export default function TokenFaq() {
-
+ >
)
}
diff --git a/apps/cowswap-frontend/src/pages/Faq/TradingFaq.tsx b/apps/cowswap-frontend/src/pages/Faq/TradingFaq.tsx
index f99625aa34..1a5b9c0ffa 100644
--- a/apps/cowswap-frontend/src/pages/Faq/TradingFaq.tsx
+++ b/apps/cowswap-frontend/src/pages/Faq/TradingFaq.tsx
@@ -1,5 +1,3 @@
-import { PageName } from 'legacy/components/AmplitudeAnalytics/constants'
-import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace'
import { LinkScrollable } from 'legacy/components/Link'
import { PageTitle } from 'modules/application/containers/PageTitle'
@@ -12,13 +10,11 @@ import ToC from './ToC'
import { Footer } from '.'
-// AmplitudeAnalytics
-
export default function TokenFaq() {
const { toc, faqRef } = useToC()
return (
-
+ <>
@@ -238,6 +234,6 @@ export default function TokenFaq() {
-
+ >
)
}
diff --git a/apps/cowswap-frontend/src/pages/Faq/index.tsx b/apps/cowswap-frontend/src/pages/Faq/index.tsx
index 28636aeda1..378ba11468 100644
--- a/apps/cowswap-frontend/src/pages/Faq/index.tsx
+++ b/apps/cowswap-frontend/src/pages/Faq/index.tsx
@@ -1,7 +1,3 @@
-import { Link } from 'react-router-dom'
-
-import { PageName } from 'legacy/components/AmplitudeAnalytics/constants'
-import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace'
import {
GPAUDIT_LINK,
COWWIKI_LINK,
@@ -10,7 +6,10 @@ import {
DISCORD_LINK,
MEV_TOTAL,
FLASHBOTS_LINK,
-} from 'legacy/constants'
+} from '@cowprotocol/common-const'
+
+import { Link } from 'react-router-dom'
+
import { StyledInternalLink } from 'legacy/theme'
import { PageTitle } from 'modules/application/containers/PageTitle'
@@ -58,7 +57,7 @@ export function Footer() {
export default function Faq() {
const { toc, faqRef } = useToC()
return (
-
+ <>
@@ -201,6 +200,6 @@ export default function Faq() {
-
+ >
)
}
diff --git a/apps/cowswap-frontend/src/pages/Faq/styled.tsx b/apps/cowswap-frontend/src/pages/Faq/styled.tsx
index dc510880c2..33c972294e 100644
--- a/apps/cowswap-frontend/src/pages/Faq/styled.tsx
+++ b/apps/cowswap-frontend/src/pages/Faq/styled.tsx
@@ -1,11 +1,15 @@
+import { ButtonPrimary } from '@cowprotocol/ui'
+import { ExternalLink as ExternalLinkTheme } from '@cowprotocol/ui'
+
import { transparentize } from 'polished'
import styled from 'styled-components/macro'
-import { ButtonPrimary } from 'legacy/components/Button'
-import { ExternalLink as ExternalLinkTheme, StyledInternalLink } from 'legacy/theme'
+import { StyledInternalLink } from 'legacy/theme'
import { Content } from 'modules/application/pure/Page'
+import { UI } from 'common/constants/theme'
+
export const ExternalLinkFaq = styled(ExternalLinkTheme)`
text-decoration: underline;
font-weight: normal;
@@ -34,14 +38,14 @@ export const Wrapper = styled.div`
> table {
width: 100%;
border-spacing: 1px;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
> thead {
background: ${({ theme }) => theme.bg3};
}
> tbody > tr {
- background: ${({ theme }) => theme.grey1};
+ background: var(${UI.COLOR_GREY});
}
> tbody > tr > td > span[role='img'] {
@@ -119,7 +123,7 @@ export const Menu = styled.div`
font-weight: bold;
line-height: 1;
margin: 0 24px 0 0;
- color: ${({ theme }) => theme.text1};
+ color: var(${UI.COLOR_TEXT1});
height: max-content;
position: sticky;
top: 0;
diff --git a/apps/cowswap-frontend/src/pages/KitchenSink/index.tsx b/apps/cowswap-frontend/src/pages/KitchenSink/index.tsx
deleted file mode 100644
index c6a78abe46..0000000000
--- a/apps/cowswap-frontend/src/pages/KitchenSink/index.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-import { PinkTitle } from '@cowswap/ui'
-import { CowSwapWidgetSettings } from '@cowswap/widget-lib'
-import { CowSwapWidget, CowSwapWidgetParams } from '@cowswap/widget-react'
-
-import styled from 'styled-components/macro'
-
-import { Page, Title, Content } from 'modules/application/pure/Page'
-
-const Wrapper = styled(Page)``
-
-export default function KitchenSink() {
- const cowSwapWidgetParams: CowSwapWidgetParams = {
- width: 600,
- height: 700,
- metaData: {
- appKey: 'KitchenSink',
- url: '/',
- },
- }
-
- const cowSwapWidgetSettings: CowSwapWidgetSettings = {
- urlParams: {
- chainId: 1,
- tradeType: 'swap',
- env: 'local',
- },
- appParams: {},
- }
-
- return (
-
- Kitchen Sink
-
- pink title
-
-
-
-
- )
-}
diff --git a/apps/cowswap-frontend/src/pages/LimitOrders/index.tsx b/apps/cowswap-frontend/src/pages/LimitOrders/index.tsx
index e0d3a54523..45fecd5aa4 100644
--- a/apps/cowswap-frontend/src/pages/LimitOrders/index.tsx
+++ b/apps/cowswap-frontend/src/pages/LimitOrders/index.tsx
@@ -2,6 +2,7 @@ import { useAtomValue } from 'jotai'
import { useMemo } from 'react'
import { OrderClass } from '@cowprotocol/cow-sdk'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { useOrders } from 'legacy/state/orders/hooks'
@@ -19,7 +20,6 @@ import {
import { OrdersTableWidget } from 'modules/ordersTable'
import { TabOrderTypes } from 'modules/ordersTable/pure/OrdersTableContainer'
import * as styledEl from 'modules/trade/pure/TradePageLayout'
-import { useWalletInfo } from 'modules/wallet'
import { getIsNotComposableCowOrder } from 'utils/orderUtils/getIsNotComposableCowOrder'
diff --git a/apps/cowswap-frontend/src/pages/Swap/index.tsx b/apps/cowswap-frontend/src/pages/Swap/index.tsx
index f1a2a56abd..02bcef39c6 100644
--- a/apps/cowswap-frontend/src/pages/Swap/index.tsx
+++ b/apps/cowswap-frontend/src/pages/Swap/index.tsx
@@ -1,15 +1,15 @@
import React from 'react'
-import { Navigate, useLocation, useParams } from 'react-router-dom'
+import { WRAPPED_NATIVE_CURRENCY as WETH } from '@cowprotocol/common-const'
+import { useWalletInfo } from '@cowprotocol/wallet'
-import { WRAPPED_NATIVE_CURRENCY as WETH } from 'legacy/constants/tokens'
+import { Navigate, useLocation, useParams } from 'react-router-dom'
import { AppDataUpdater } from 'modules/appData'
import { SwapWidget, SwapDerivedStateUpdater, SwapAmountsFromUrlUpdater } from 'modules/swap'
import { useSwapSlippage } from 'modules/swap/hooks/useSwapSlippage'
import { getDefaultTradeRawState } from 'modules/trade/types/TradeRawState'
import { parameterizeTradeRoute } from 'modules/trade/utils/parameterizeTradeRoute'
-import { useWalletInfo } from 'modules/wallet'
import { Routes } from 'common/constants/routes'
diff --git a/apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/index.tsx b/apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/index.tsx
index 8c490424fb..d6c3ebc51d 100644
--- a/apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/index.tsx
+++ b/apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/index.tsx
@@ -1,8 +1,8 @@
-import styled from 'styled-components/macro'
+import cow404IMG from '@cowprotocol/assets/cow-swap/cow-404.png'
+import { ButtonPrimary } from '@cowprotocol/ui'
+import { ExternalLink as ExternalLinkTheme } from '@cowprotocol/ui'
-import cow404IMG from 'legacy/assets/cow-swap/cow-404.png'
-import { ButtonPrimary } from 'legacy/components/Button'
-import { ExternalLink as ExternalLinkTheme } from 'legacy/theme'
+import styled from 'styled-components/macro'
import { Page, Title, Content, GdocsListStyle } from 'modules/application/pure/Page'
diff --git a/apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/useIsAnySwapAffectedUser.ts b/apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/useIsAnySwapAffectedUser.ts
index 78e4192481..62a2618fc0 100644
--- a/apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/useIsAnySwapAffectedUser.ts
+++ b/apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/useIsAnySwapAffectedUser.ts
@@ -1,15 +1,13 @@
import { useMemo } from 'react'
+import { Erc20Abi, Erc20Interface } from '@cowprotocol/abis'
+import { ZERO_ADDRESS } from '@cowprotocol/common-const'
+import { WRAPPED_NATIVE_CURRENCY as WETH } from '@cowprotocol/common-const'
import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
-import { Erc20Abi, Erc20Interface } from '@cowswap/abis'
+import { useWalletInfo } from '@cowprotocol/wallet'
import { Interface } from '@ethersproject/abi'
import { BigNumber } from '@ethersproject/bignumber'
-import { ZERO_ADDRESS } from 'legacy/constants/misc'
-import { WRAPPED_NATIVE_CURRENCY as WETH } from 'legacy/constants/tokens'
-
-import { useWalletInfo } from 'modules/wallet'
-
import { useMultipleContractSingleData } from 'lib/hooks/multicall'
const WETH_ADDRESS = WETH[ChainId.MAINNET].address
diff --git a/apps/cowswap-frontend/src/pages/error/NotFound/index.tsx b/apps/cowswap-frontend/src/pages/error/NotFound/index.tsx
index 401bd97461..b876efb624 100644
--- a/apps/cowswap-frontend/src/pages/error/NotFound/index.tsx
+++ b/apps/cowswap-frontend/src/pages/error/NotFound/index.tsx
@@ -1,9 +1,9 @@
+import cow404IMG from '@cowprotocol/assets/cow-swap/cow-404.png'
+import { ButtonPrimary } from '@cowprotocol/ui'
+
import { Link } from 'react-router-dom'
import styled from 'styled-components/macro'
-import cow404IMG from 'legacy/assets/cow-swap/cow-404.png'
-import { ButtonPrimary } from 'legacy/components/Button'
-
import { Page, Title, Content, GdocsListStyle } from 'modules/application/pure/Page'
const Wrapper = styled(Page)`
diff --git a/apps/cowswap-frontend/src/pages/games/CowRunner/index.tsx b/apps/cowswap-frontend/src/pages/games/CowRunner/index.tsx
index 2e5eb2c843..ee7e5c0465 100644
--- a/apps/cowswap-frontend/src/pages/games/CowRunner/index.tsx
+++ b/apps/cowswap-frontend/src/pages/games/CowRunner/index.tsx
@@ -1,11 +1,10 @@
import { useEffect } from 'react'
+import { gameAnalytics } from '@cowprotocol/analytics'
import { CowGame } from '@cowprotocol/cow-runner-game'
import styled from 'styled-components/macro'
-import { gameAnalytics } from 'legacy/components/analytics'
-
import { PageTitle } from 'modules/application/containers/PageTitle'
import { Page, Content } from 'modules/application/pure/Page'
diff --git a/apps/cowswap-frontend/src/pages/games/MevSlicer/index.tsx b/apps/cowswap-frontend/src/pages/games/MevSlicer/index.tsx
index e181fe114e..0cd932be19 100644
--- a/apps/cowswap-frontend/src/pages/games/MevSlicer/index.tsx
+++ b/apps/cowswap-frontend/src/pages/games/MevSlicer/index.tsx
@@ -1,8 +1,8 @@
-import styled from 'styled-components/macro'
+import { gameAnalytics } from '@cowprotocol/analytics'
+import ninjaCowImg from '@cowprotocol/assets/cow-swap/ninja-cow.png'
+import { ButtonPrimary } from '@cowprotocol/ui'
-import ninjaCowImg from 'legacy/assets/cow-swap/ninja-cow.png'
-import { gameAnalytics } from 'legacy/components/analytics'
-import { ButtonPrimary } from 'legacy/components/Button'
+import styled from 'styled-components/macro'
import { PageTitle } from 'modules/application/containers/PageTitle'
import { Page, Content } from 'modules/application/pure/Page'
diff --git a/apps/cowswap-frontend/src/react-app-env.d.ts b/apps/cowswap-frontend/src/react-app-env.d.ts
index 8ffbf1ae56..b44e322480 100644
--- a/apps/cowswap-frontend/src/react-app-env.d.ts
+++ b/apps/cowswap-frontend/src/react-app-env.d.ts
@@ -6,8 +6,6 @@ declare module '@metamask/jazzicon' {
export default function (diameter: number, seed: number): HTMLElement
}
-declare module 'fortmatic'
-
interface Window {
console: Console & { force: Console }
// walletLinkExtension is injected by the Coinbase Wallet extension
diff --git a/apps/cowswap-frontend/src/test-utils.tsx b/apps/cowswap-frontend/src/test-utils.tsx
index 38595a99bd..5ae90fdf46 100644
--- a/apps/cowswap-frontend/src/test-utils.tsx
+++ b/apps/cowswap-frontend/src/test-utils.tsx
@@ -15,7 +15,7 @@ import { MemoryRouter } from 'react-router-dom'
import { ThemeProvider as StyledComponentsThemeProvider } from 'styled-components/macro'
import Web3Provider from 'legacy/components/Web3Provider'
-import store from 'legacy/state'
+import { cowSwapStore } from 'legacy/state'
import { useIsDarkMode } from 'legacy/state/user/hooks'
import { theme } from 'legacy/theme'
@@ -37,7 +37,7 @@ const WithProviders = ({ children }: { children?: ReactNode }) => {
return (
-
+
{children}
@@ -71,7 +71,7 @@ export function WithMockedWeb3({ children, location }: { children?: ReactNode; l
return (
-
+
{children}
diff --git a/apps/cowswap-frontend/src/types/index.ts b/apps/cowswap-frontend/src/types/index.ts
index d5c2713020..dc466c7a62 100644
--- a/apps/cowswap-frontend/src/types/index.ts
+++ b/apps/cowswap-frontend/src/types/index.ts
@@ -23,7 +23,7 @@ declare global {
}
export type FractionLike = Fraction | Price | CurrencyAmount
-// TODO: it's legacy from the old SDK version
+// TODO: it'legacy from the old SDK version
export interface PriceInformation {
token: string
amount: string | null
diff --git a/apps/cowswap-frontend/src/utils/orderUtils/calculateAmountForRate.ts b/apps/cowswap-frontend/src/utils/orderUtils/calculateAmountForRate.ts
index 3a7b9d94f2..f15c72799f 100644
--- a/apps/cowswap-frontend/src/utils/orderUtils/calculateAmountForRate.ts
+++ b/apps/cowswap-frontend/src/utils/orderUtils/calculateAmountForRate.ts
@@ -1,8 +1,7 @@
+import { FractionUtils } from '@cowprotocol/common-utils'
import { Currency, Fraction } from '@uniswap/sdk-core'
-import JSBI from 'jsbi'
-
-import { Field } from 'legacy/state/swap/actions'
+import { Field } from 'legacy/state/types'
export type RateCalculationParams = {
amount: Fraction | null
@@ -12,21 +11,6 @@ export type RateCalculationParams = {
outputCurrency: Currency | null
}
-/**
- * Adjust a fraction defined in units for both token to consider the decimals.
- * For example, a fraction like 1.1/1 representing the price of USDC, DAI in units, will be turned into
- * 1.1/1000000000000 in atoms
- */
-export function adjustDecimalsAtoms(value: Fraction, decimalsA: number, decimalsB: number): Fraction {
- if (decimalsA === decimalsB) {
- return value
- }
-
- const decimalsShift = JSBI.BigInt(JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(Math.abs(decimalsA - decimalsB))))
-
- return decimalsA < decimalsB ? value.multiply(decimalsShift) : value.divide(decimalsShift)
-}
-
export function calculateAmountForRate({
activeRate,
amount,
@@ -41,7 +25,7 @@ export function calculateAmountForRate({
const { decimals: inputDecimals } = inputCurrency
const { decimals: outputDecimals } = outputCurrency
- const parsedValue = adjustDecimalsAtoms(
+ const parsedValue = FractionUtils.adjustDecimalsAtoms(
amount,
field === Field.INPUT ? inputDecimals : outputDecimals,
field === Field.INPUT ? outputDecimals : inputDecimals
diff --git a/apps/cowswap-frontend/src/utils/orderUtils/calculateExecutionPrice.test.ts b/apps/cowswap-frontend/src/utils/orderUtils/calculateExecutionPrice.test.ts
index 01474a1c8a..a65c715101 100644
--- a/apps/cowswap-frontend/src/utils/orderUtils/calculateExecutionPrice.test.ts
+++ b/apps/cowswap-frontend/src/utils/orderUtils/calculateExecutionPrice.test.ts
@@ -1,12 +1,10 @@
+import { USDC_GOERLI, WETH_GOERLI } from '@cowprotocol/common-const'
+import { rawToTokenAmount } from '@cowprotocol/common-utils'
import { OrderKind } from '@cowprotocol/contracts'
import { CurrencyAmount, Fraction } from '@uniswap/sdk-core'
-import { USDC_GOERLI, WETH_GOERLI } from 'legacy/utils/goerli/constants'
-
import { calculateExecutionPrice, convertAmountToCurrency } from './calculateExecutionPrice'
-import { rawToTokenAmount } from '../rawToTokenAmount'
-
describe('calculateExecutionPrice', () => {
describe('When market price is less than execution price', () => {
const marketPrice = new Fraction(3, 7000) // 0
diff --git a/apps/cowswap-frontend/src/utils/orderUtils/calculateExecutionPrice.ts b/apps/cowswap-frontend/src/utils/orderUtils/calculateExecutionPrice.ts
index 04762b4e94..77fa94c15c 100644
--- a/apps/cowswap-frontend/src/utils/orderUtils/calculateExecutionPrice.ts
+++ b/apps/cowswap-frontend/src/utils/orderUtils/calculateExecutionPrice.ts
@@ -1,10 +1,9 @@
+import { rawToTokenAmount } from '@cowprotocol/common-utils'
import { OrderKind } from '@cowprotocol/contracts'
import { Currency, CurrencyAmount, Fraction, Price } from '@uniswap/sdk-core'
import JSBI from 'jsbi'
-import { rawToTokenAmount } from 'utils/rawToTokenAmount'
-
export interface ExecutionPriceParams {
inputCurrencyAmount: CurrencyAmount | null
outputCurrencyAmount: CurrencyAmount | null
diff --git a/apps/cowswap-frontend/src/utils/orderUtils/calculatePercentageInRelationToReference.ts b/apps/cowswap-frontend/src/utils/orderUtils/calculatePercentageInRelationToReference.ts
index 6d72f305cd..0817b73a82 100644
--- a/apps/cowswap-frontend/src/utils/orderUtils/calculatePercentageInRelationToReference.ts
+++ b/apps/cowswap-frontend/src/utils/orderUtils/calculatePercentageInRelationToReference.ts
@@ -1,9 +1,8 @@
+import { ZERO_FRACTION } from '@cowprotocol/common-const'
import { Percent } from '@uniswap/sdk-core'
import { FractionLike, Nullish } from 'types'
-import { ZERO_FRACTION } from 'legacy/constants'
-
export type CalculateAmountPercentDifferenceProps = {
reference: Nullish
value: Nullish
diff --git a/apps/cowswap-frontend/src/utils/orderUtils/calculatePriceDifference.test.ts b/apps/cowswap-frontend/src/utils/orderUtils/calculatePriceDifference.test.ts
index 52e1a9e985..271ba0b29f 100644
--- a/apps/cowswap-frontend/src/utils/orderUtils/calculatePriceDifference.test.ts
+++ b/apps/cowswap-frontend/src/utils/orderUtils/calculatePriceDifference.test.ts
@@ -1,13 +1,9 @@
+import { ZERO_FRACTION } from '@cowprotocol/common-const'
+import { DAI_GOERLI, USDC_GOERLI } from '@cowprotocol/common-const'
+import { buildPriceFromCurrencyAmounts, tryParseCurrencyAmount } from '@cowprotocol/common-utils'
+import { FractionUtils } from '@cowprotocol/common-utils'
import { Currency, Price } from '@uniswap/sdk-core'
-import { ZERO_FRACTION } from 'legacy/constants'
-import { DAI_GOERLI, USDC_GOERLI } from 'legacy/utils/goerli/constants'
-
-import { buildPriceFromCurrencyAmounts } from 'modules/utils/orderUtils/buildPriceFromCurrencyAmounts'
-
-import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount'
-import { FractionUtils } from 'utils/fractionUtils'
-
import { calculatePriceDifference, CalculatePriceDifferenceParams } from './calculatePriceDifference'
function buildPrice(daiAmount: string, usdcAmount: string): Price {
diff --git a/apps/cowswap-frontend/src/utils/orderUtils/calculatePriceDifference.ts b/apps/cowswap-frontend/src/utils/orderUtils/calculatePriceDifference.ts
index d40019f8cc..0964d6ebec 100644
--- a/apps/cowswap-frontend/src/utils/orderUtils/calculatePriceDifference.ts
+++ b/apps/cowswap-frontend/src/utils/orderUtils/calculatePriceDifference.ts
@@ -1,14 +1,10 @@
+import { ZERO_FRACTION } from '@cowprotocol/common-const'
+import { FractionUtils } from '@cowprotocol/common-utils'
import { Currency, CurrencyAmount, Fraction, Percent, Price } from '@uniswap/sdk-core'
+import invariant from 'tiny-invariant'
import { Nullish } from 'types'
-import { ZERO_FRACTION } from 'legacy/constants'
-
-import { assertSameMarket } from 'common/utils/markets'
-import { FractionUtils } from 'utils/fractionUtils'
-
-import { adjustDecimalsAtoms } from './calculateAmountForRate'
-
const ONE = new Fraction(1)
export type CalculatePriceDifferenceParams = {
@@ -81,7 +77,7 @@ function calculatePriceDifferenceAux({
// Convert difference in token amount
const differenceInUnits = FractionUtils.fromPrice(targetPrice).subtract(FractionUtils.fromPrice(referencePrice))
- const difference = adjustDecimalsAtoms(differenceInUnits, 0, referencePrice.quoteCurrency.decimals)
+ const difference = FractionUtils.adjustDecimalsAtoms(differenceInUnits, 0, referencePrice.quoteCurrency.decimals)
const differenceInQuoteToken = CurrencyAmount.fromFractionalAmount(
referencePrice.quoteCurrency,
difference.numerator,
@@ -98,3 +94,11 @@ function calculatePriceDifferenceAux({
return { percentage, amount: differenceInQuoteToken }
}
+
+function assertSameMarket(price1: Price, price2: Price) {
+ // Assert I'm comparing apples with apples (prices should refer to market)
+ invariant(
+ price1.baseCurrency.equals(price2.baseCurrency) && price1.quoteCurrency.equals(price2.quoteCurrency),
+ 'Prices are not from the same market'
+ )
+}
diff --git a/apps/cowswap-frontend/src/utils/orderUtils/getOrderFilledAmount.ts b/apps/cowswap-frontend/src/utils/orderUtils/getOrderFilledAmount.ts
index 81aeba2aa7..8d1a92bb20 100644
--- a/apps/cowswap-frontend/src/utils/orderUtils/getOrderFilledAmount.ts
+++ b/apps/cowswap-frontend/src/utils/orderUtils/getOrderFilledAmount.ts
@@ -1,6 +1,7 @@
+import { ZERO_BIG_NUMBER } from '@cowprotocol/common-const'
+
import BigNumber from 'bignumber.js'
-import { ZERO_BIG_NUMBER } from 'legacy/constants'
import { Order } from 'legacy/state/orders/actions'
/**
diff --git a/apps/cowswap-frontend/src/utils/orderUtils/getOrderSurplus.ts b/apps/cowswap-frontend/src/utils/orderUtils/getOrderSurplus.ts
index 77f6270ec5..6089b0ab4c 100644
--- a/apps/cowswap-frontend/src/utils/orderUtils/getOrderSurplus.ts
+++ b/apps/cowswap-frontend/src/utils/orderUtils/getOrderSurplus.ts
@@ -1,8 +1,9 @@
// Util functions that only pertain to/deal with operator API related stuff
+import { ZERO_BIG_NUMBER } from '@cowprotocol/common-const'
+
import BigNumber from 'bignumber.js'
import JSBI from 'jsbi'
-import { ZERO_BIG_NUMBER } from 'legacy/constants'
import { Order } from 'legacy/state/orders/actions'
import { getOrderExecutedAmounts } from './getOrderExecutedAmounts'
diff --git a/apps/cowswap-frontend/src/utils/orderUtils/getTokenFromMapping.ts b/apps/cowswap-frontend/src/utils/orderUtils/getTokenFromMapping.ts
index 11fccd9a07..b0e3a4735c 100644
--- a/apps/cowswap-frontend/src/utils/orderUtils/getTokenFromMapping.ts
+++ b/apps/cowswap-frontend/src/utils/orderUtils/getTokenFromMapping.ts
@@ -1,11 +1,9 @@
+import { NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const'
+import { getIsNativeToken } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { getAddress } from '@ethersproject/address'
import { Token } from '@uniswap/sdk-core'
-import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants'
-
-import { getIsNativeToken } from '../getIsNativeToken'
-
export function getTokenFromMapping(
address: string,
chainId: SupportedChainId,
diff --git a/apps/cowswap-frontend/src/utils/orderUtils/parseOrder.ts b/apps/cowswap-frontend/src/utils/orderUtils/parseOrder.ts
index a799edb648..a18121cfe9 100644
--- a/apps/cowswap-frontend/src/utils/orderUtils/parseOrder.ts
+++ b/apps/cowswap-frontend/src/utils/orderUtils/parseOrder.ts
@@ -33,6 +33,7 @@ export interface ParsedOrderExecutionData {
export interface ParsedOrder {
id: string
+ owner: string
isCancelling: boolean | undefined
receiver: string | undefined
inputToken: Token
@@ -47,6 +48,7 @@ export interface ParsedOrder {
creationTime: Date
expirationTime: Date
composableCowInfo?: ComposableCowInfo
+ fullAppData: Order['fullAppData']
executionData: ParsedOrderExecutionData
}
@@ -94,6 +96,7 @@ export const parseOrder = (order: Order): ParsedOrder => {
return {
id: order.id,
+ owner: order.owner,
isCancelling: order.isCancelling,
inputToken: order.inputToken,
outputToken: order.outputToken,
@@ -108,6 +111,7 @@ export const parseOrder = (order: Order): ParsedOrder => {
receiver: order.receiver || undefined,
creationTime,
expirationTime,
+ fullAppData: order.fullAppData,
executionData,
}
}
diff --git a/apps/cowswap-frontend/tsconfig.json b/apps/cowswap-frontend/tsconfig.json
index 65e6c88429..fd5681c653 100644
--- a/apps/cowswap-frontend/tsconfig.json
+++ b/apps/cowswap-frontend/tsconfig.json
@@ -9,12 +9,20 @@
"types": ["node", "vite/client"],
"baseUrl": "src",
"paths": {
- "@cowswap/abis": ["../../../libs/abis/src/index.ts"],
- "@cowswap/ui": ["../../../libs/ui/src/index.ts"],
- "@cowswap/ui-utils": ["../../../libs/ui-utils/src/index.ts"],
- "@cowswap/widget-lib": ["../../../libs/widget-lib/src/index.ts"],
- "@cowswap/widget-react": ["../../../libs/widget-react/src/index.ts"],
- "@cowswap/snackbars": ["../../../libs/snackbars/src/index.ts"]
+ "@cowprotocol/abis": ["../../../libs/abis/src/index.ts"],
+ "@cowprotocol/ui": ["../../../libs/ui/src/index.ts"],
+ "@cowprotocol/ui-utils": ["../../../libs/ui-utils/src/index.ts"],
+ "@cowprotocol/widget-lib": ["../../../libs/widget-lib/src/index.ts"],
+ "@cowprotocol/widget-react": ["../../../libs/widget-react/src/index.ts"],
+ "@cowprotocol/snackbars": ["../../../libs/snackbars/src/index.ts"],
+ "@cowprotocol/wallet": ["../../../libs/wallet/src/index.ts"],
+ "@cowprotocol/assets/*": ["../../../libs/assets/src/*"],
+ "@cowprotocol/common-const": ["../../../libs/common-const/src/index.ts"],
+ "@cowprotocol/common-utils": ["../../../libs/common-utils/src/index.ts"],
+ "@cowprotocol/common-hooks": ["../../../libs/common-hooks/src/index.ts"],
+ "@cowprotocol/ens": ["../../../libs/ens/src/index.ts"],
+ "@cowprotocol/core": ["../../../libs/core/src/index.ts"],
+ "@cowprotocol/analytics": ["../../../libs/analytics/src/index.ts"]
}
},
"files": [],
diff --git a/apps/cowswap-frontend/vite.config.ts b/apps/cowswap-frontend/vite.config.ts
index 2c06ac89b6..ba713e5870 100644
--- a/apps/cowswap-frontend/vite.config.ts
+++ b/apps/cowswap-frontend/vite.config.ts
@@ -3,14 +3,14 @@ import { lingui } from '@lingui/vite-plugin'
import react from '@vitejs/plugin-react-swc'
import stdLibBrowser from 'node-stdlib-browser'
import { visualizer } from 'rollup-plugin-visualizer'
-import { defineConfig, loadEnv, PluginOption, searchForWorkspaceRoot } from 'vite'
+import { defineConfig, PluginOption, searchForWorkspaceRoot } from 'vite'
import macrosPlugin from 'vite-plugin-babel-macros'
import { ModuleNameWithoutNodePrefix, nodePolyfills } from 'vite-plugin-node-polyfills'
import { VitePWA } from 'vite-plugin-pwa'
import svgr from 'vite-plugin-svgr'
import viteTsConfigPaths from 'vite-tsconfig-paths'
-import * as path from 'path'
+import { getReactProcessEnv } from '../../tools/getReactProcessEnv'
// eslint-disable-next-line no-restricted-imports
import type { TemplateType } from 'rollup-plugin-visualizer/dist/plugin/template-types'
@@ -24,16 +24,6 @@ const analyzeBundle = process.env.ANALYZE_BUNDLE === 'true'
const analyzeBundleTemplate: TemplateType = (process.env.ANALYZE_BUNDLE_TEMPLATE as TemplateType) || 'treemap' // "sunburst" | "treemap" | "network" | "raw-data" | "list";
export default defineConfig(({ mode }) => {
- const env = loadEnv(mode, process.cwd(), ['REACT_APP_'])
-
- // expose .env as process.env instead of import.meta since jest does not import meta yet
- const envWithProcessPrefix = Object.entries(env).reduce((prev, [key, val]) => {
- return {
- ...prev,
- ['process.env.' + key]: JSON.stringify(val),
- }
- }, {})
-
const plugins = [
nodePolyfills({
exclude: allNodeDeps.filter((dep) => !nodeDepsToInclude.includes(dep)),
@@ -81,7 +71,7 @@ export default defineConfig(({ mode }) => {
return {
define: {
- ...envWithProcessPrefix,
+ ...getReactProcessEnv(mode),
},
assetsInclude: ['**/*.md'],
@@ -110,18 +100,6 @@ export default defineConfig(({ mode }) => {
resolve: {
alias: {
'node-fetch': 'isomorphic-fetch',
- /**
- * Temporary fix for walletconnect
- * https://github.com/Uniswap/web3-react/issues/861
- */
- '@walletconnect/ethereum-provider': path.resolve(
- __dirname,
- '../../node_modules/@walletconnect/ethereum-provider/dist/umd/index.min.js'
- ),
- '@walletconnect/universal-provider': path.resolve(
- __dirname,
- '../../node_modules/@walletconnect/universal-provider/dist/index.cjs.js'
- ),
},
},
@@ -131,14 +109,9 @@ export default defineConfig(({ mode }) => {
output: {
manualChunks(id) {
if (id.includes('@1inch')) return '@1inch'
- if (id.includes('@amplitude')) return '@amplitude'
- if (id.includes('@cowprotocol')) return '@cowprotocol'
- if (id.includes('@ethersproject')) return '@ethersproject'
- if (id.includes('@metamask') || id.includes('elliptic')) return '@metamask'
if (id.includes('@safe-global') || id.includes('viem')) return '@safe-global'
if (id.includes('@sentry')) return '@sentry'
if (id.includes('@uniswap')) return '@uniswap'
- if (id.includes('@walletconnect')) return '@walletconnect'
if (id.includes('crypto-es/lib')) return 'crypto-es'
if (id.includes('web3/dist')) return 'web3'
},
diff --git a/apps/cowswap-frontend/yarn.lock b/apps/cowswap-frontend/yarn.lock
new file mode 100644
index 0000000000..fb57ccd13a
--- /dev/null
+++ b/apps/cowswap-frontend/yarn.lock
@@ -0,0 +1,4 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
diff --git a/jest.preset.js b/jest.preset.js
index 8cd53f8e9b..9ba35593e5 100644
--- a/jest.preset.js
+++ b/jest.preset.js
@@ -1,3 +1,11 @@
const nxPreset = require('@nx/jest/preset').default
-module.exports = { ...nxPreset }
+module.exports = {
+ ...nxPreset,
+ moduleNameMapper: {
+ '\\.svg': '../../testing/svgrMock.js',
+ '\\.gif': '../../testing/imgMock.js',
+ '\\.webp': '../../testing/imgMock.js',
+ '\\.png': '../../testing/imgMock.js',
+ },
+}
diff --git a/libs/abis/src/abis-legacy/erc20.json b/libs/abis/src/abis-legacy/erc20.json
index dd7bf99d6e..58c0e583be 100644
--- a/libs/abis/src/abis-legacy/erc20.json
+++ b/libs/abis/src/abis-legacy/erc20.json
@@ -3,7 +3,12 @@
"constant": true,
"inputs": [],
"name": "name",
- "outputs": [{ "name": "", "type": "string" }],
+ "outputs": [
+ {
+ "name": "",
+ "type": "string"
+ }
+ ],
"payable": false,
"stateMutability": "view",
"type": "function"
@@ -11,11 +16,22 @@
{
"constant": false,
"inputs": [
- { "name": "_spender", "type": "address" },
- { "name": "_value", "type": "uint256" }
+ {
+ "name": "_spender",
+ "type": "address"
+ },
+ {
+ "name": "_value",
+ "type": "uint256"
+ }
],
"name": "approve",
- "outputs": [{ "name": "", "type": "bool" }],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
@@ -24,7 +40,12 @@
"constant": true,
"inputs": [],
"name": "totalSupply",
- "outputs": [{ "name": "", "type": "uint256" }],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
"payable": false,
"stateMutability": "view",
"type": "function"
@@ -32,12 +53,26 @@
{
"constant": false,
"inputs": [
- { "name": "_from", "type": "address" },
- { "name": "_to", "type": "address" },
- { "name": "_value", "type": "uint256" }
+ {
+ "name": "_from",
+ "type": "address"
+ },
+ {
+ "name": "_to",
+ "type": "address"
+ },
+ {
+ "name": "_value",
+ "type": "uint256"
+ }
],
"name": "transferFrom",
- "outputs": [{ "name": "", "type": "bool" }],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
@@ -46,16 +81,31 @@
"constant": true,
"inputs": [],
"name": "decimals",
- "outputs": [{ "name": "", "type": "uint8" }],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8"
+ }
+ ],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
- "inputs": [{ "name": "_owner", "type": "address" }],
+ "inputs": [
+ {
+ "name": "_owner",
+ "type": "address"
+ }
+ ],
"name": "balanceOf",
- "outputs": [{ "name": "balance", "type": "uint256" }],
+ "outputs": [
+ {
+ "name": "balance",
+ "type": "uint256"
+ }
+ ],
"payable": false,
"stateMutability": "view",
"type": "function"
@@ -64,7 +114,12 @@
"constant": true,
"inputs": [],
"name": "symbol",
- "outputs": [{ "name": "", "type": "string" }],
+ "outputs": [
+ {
+ "name": "",
+ "type": "string"
+ }
+ ],
"payable": false,
"stateMutability": "view",
"type": "function"
@@ -72,11 +127,22 @@
{
"constant": false,
"inputs": [
- { "name": "_to", "type": "address" },
- { "name": "_value", "type": "uint256" }
+ {
+ "name": "_to",
+ "type": "address"
+ },
+ {
+ "name": "_value",
+ "type": "uint256"
+ }
],
"name": "transfer",
- "outputs": [{ "name": "", "type": "bool" }],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
@@ -84,22 +150,49 @@
{
"constant": true,
"inputs": [
- { "name": "_owner", "type": "address" },
- { "name": "_spender", "type": "address" }
+ {
+ "name": "_owner",
+ "type": "address"
+ },
+ {
+ "name": "_spender",
+ "type": "address"
+ }
],
"name": "allowance",
- "outputs": [{ "name": "", "type": "uint256" }],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
"payable": false,
"stateMutability": "view",
"type": "function"
},
- { "payable": true, "stateMutability": "payable", "type": "fallback" },
+ {
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "fallback"
+ },
{
"anonymous": false,
"inputs": [
- { "indexed": true, "name": "owner", "type": "address" },
- { "indexed": true, "name": "spender", "type": "address" },
- { "indexed": false, "name": "value", "type": "uint256" }
+ {
+ "indexed": true,
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "value",
+ "type": "uint256"
+ }
],
"name": "Approval",
"type": "event"
@@ -107,11 +200,85 @@
{
"anonymous": false,
"inputs": [
- { "indexed": true, "name": "from", "type": "address" },
- { "indexed": true, "name": "to", "type": "address" },
- { "indexed": false, "name": "value", "type": "uint256" }
+ {
+ "indexed": true,
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "value",
+ "type": "uint256"
+ }
],
"name": "Transfer",
"type": "event"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "owner",
+ "type": "address"
+ }
+ ],
+ "name": "nonces",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "deadline",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "v",
+ "type": "uint8"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "r",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "s",
+ "type": "bytes32"
+ }
+ ],
+ "name": "permit",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
}
]
diff --git a/libs/abis/src/abis/CoWSwapEthFlow.json b/libs/abis/src/abis/CoWSwapEthFlow.json
new file mode 100644
index 0000000000..2e76a24b83
--- /dev/null
+++ b/libs/abis/src/abis/CoWSwapEthFlow.json
@@ -0,0 +1,152 @@
+[
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "contract IERC20",
+ "name": "buyToken",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "receiver",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "sellAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "buyAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "appData",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "feeAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint32",
+ "name": "validTo",
+ "type": "uint32"
+ },
+ {
+ "internalType": "bool",
+ "name": "partiallyFillable",
+ "type": "bool"
+ },
+ {
+ "internalType": "int64",
+ "name": "quoteId",
+ "type": "int64"
+ }
+ ],
+ "internalType": "struct EthFlowOrder.Data",
+ "name": "order",
+ "type": "tuple"
+ }
+ ],
+ "name": "createOrder",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "orderHash",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "contract IERC20",
+ "name": "buyToken",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "receiver",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "sellAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "buyAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "appData",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "feeAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint32",
+ "name": "validTo",
+ "type": "uint32"
+ },
+ {
+ "internalType": "bool",
+ "name": "partiallyFillable",
+ "type": "bool"
+ },
+ {
+ "internalType": "int64",
+ "name": "quoteId",
+ "type": "int64"
+ }
+ ],
+ "internalType": "struct EthFlowOrder.Data",
+ "name": "order",
+ "type": "tuple"
+ }
+ ],
+ "name": "invalidateOrder",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "name": "orders",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "internalType": "uint32",
+ "name": "validTo",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ }
+]
diff --git a/libs/abis/src/generated/legacy/Erc20.ts b/libs/abis/src/generated/legacy/Erc20.ts
index 54c74b62a9..2de889a712 100644
--- a/libs/abis/src/generated/legacy/Erc20.ts
+++ b/libs/abis/src/generated/legacy/Erc20.ts
@@ -28,6 +28,8 @@ export interface Erc20Interface extends utils.Interface {
'symbol()': FunctionFragment
'transfer(address,uint256)': FunctionFragment
'allowance(address,address)': FunctionFragment
+ 'nonces(address)': FunctionFragment
+ 'permit(address,address,uint256,uint256,uint8,bytes32,bytes32)': FunctionFragment
}
getFunction(
@@ -41,6 +43,8 @@ export interface Erc20Interface extends utils.Interface {
| 'symbol'
| 'transfer'
| 'allowance'
+ | 'nonces'
+ | 'permit'
): FunctionFragment
encodeFunctionData(functionFragment: 'name', values?: undefined): string
@@ -61,6 +65,19 @@ export interface Erc20Interface extends utils.Interface {
values: [PromiseOrValue, PromiseOrValue]
): string
encodeFunctionData(functionFragment: 'allowance', values: [PromiseOrValue, PromiseOrValue]): string
+ encodeFunctionData(functionFragment: 'nonces', values: [PromiseOrValue]): string
+ encodeFunctionData(
+ functionFragment: 'permit',
+ values: [
+ PromiseOrValue,
+ PromiseOrValue,
+ PromiseOrValue,
+ PromiseOrValue,
+ PromiseOrValue,
+ PromiseOrValue,
+ PromiseOrValue
+ ]
+ ): string
decodeFunctionResult(functionFragment: 'name', data: BytesLike): Result
decodeFunctionResult(functionFragment: 'approve', data: BytesLike): Result
@@ -71,6 +88,8 @@ export interface Erc20Interface extends utils.Interface {
decodeFunctionResult(functionFragment: 'symbol', data: BytesLike): Result
decodeFunctionResult(functionFragment: 'transfer', data: BytesLike): Result
decodeFunctionResult(functionFragment: 'allowance', data: BytesLike): Result
+ decodeFunctionResult(functionFragment: 'nonces', data: BytesLike): Result
+ decodeFunctionResult(functionFragment: 'permit', data: BytesLike): Result
events: {
'Approval(address,address,uint256)': EventFragment
@@ -156,6 +175,19 @@ export interface Erc20 extends BaseContract {
_spender: PromiseOrValue,
overrides?: CallOverrides
): Promise<[BigNumber]>
+
+ nonces(owner: PromiseOrValue, overrides?: CallOverrides): Promise<[BigNumber]>
+
+ permit(
+ owner: PromiseOrValue,
+ spender: PromiseOrValue,
+ value: PromiseOrValue,
+ deadline: PromiseOrValue,
+ v: PromiseOrValue,
+ r: PromiseOrValue,
+ s: PromiseOrValue,
+ overrides?: Overrides & { from?: PromiseOrValue }
+ ): Promise
}
name(overrides?: CallOverrides): Promise
@@ -193,6 +225,19 @@ export interface Erc20 extends BaseContract {
overrides?: CallOverrides
): Promise
+ nonces(owner: PromiseOrValue, overrides?: CallOverrides): Promise
+
+ permit(
+ owner: PromiseOrValue,
+ spender: PromiseOrValue,
+ value: PromiseOrValue,
+ deadline: PromiseOrValue,
+ v: PromiseOrValue,
+ r: PromiseOrValue,
+ s: PromiseOrValue,
+ overrides?: Overrides & { from?: PromiseOrValue }
+ ): Promise
+
callStatic: {
name(overrides?: CallOverrides): Promise
@@ -228,6 +273,19 @@ export interface Erc20 extends BaseContract {
_spender: PromiseOrValue,
overrides?: CallOverrides
): Promise
+
+ nonces(owner: PromiseOrValue, overrides?: CallOverrides): Promise
+
+ permit(
+ owner: PromiseOrValue,
+ spender: PromiseOrValue,
+ value: PromiseOrValue,
+ deadline: PromiseOrValue,
+ v: PromiseOrValue,
+ r: PromiseOrValue,
+ s: PromiseOrValue,
+ overrides?: CallOverrides
+ ): Promise
}
filters: {
@@ -289,6 +347,19 @@ export interface Erc20 extends BaseContract {
_spender: PromiseOrValue,
overrides?: CallOverrides
): Promise
+
+ nonces(owner: PromiseOrValue, overrides?: CallOverrides): Promise
+
+ permit(
+ owner: PromiseOrValue,
+ spender: PromiseOrValue,
+ value: PromiseOrValue,
+ deadline: PromiseOrValue,
+ v: PromiseOrValue,
+ r: PromiseOrValue,
+ s: PromiseOrValue,
+ overrides?: Overrides & { from?: PromiseOrValue }
+ ): Promise
}
populateTransaction: {
@@ -326,5 +397,18 @@ export interface Erc20 extends BaseContract {
_spender: PromiseOrValue,
overrides?: CallOverrides
): Promise
+
+ nonces(owner: PromiseOrValue, overrides?: CallOverrides): Promise
+
+ permit(
+ owner: PromiseOrValue,
+ spender: PromiseOrValue,
+ value: PromiseOrValue,
+ deadline: PromiseOrValue,
+ v: PromiseOrValue,
+ r: PromiseOrValue,
+ s: PromiseOrValue,
+ overrides?: Overrides & { from?: PromiseOrValue }
+ ): Promise
}
}
diff --git a/libs/abis/src/generated/legacy/factories/Erc20__factory.ts b/libs/abis/src/generated/legacy/factories/Erc20__factory.ts
index d0ccd7b39f..b344021c45 100644
--- a/libs/abis/src/generated/legacy/factories/Erc20__factory.ts
+++ b/libs/abis/src/generated/legacy/factories/Erc20__factory.ts
@@ -227,6 +227,68 @@ const _abi = [
name: 'Transfer',
type: 'event',
},
+ {
+ constant: true,
+ inputs: [
+ {
+ name: 'owner',
+ type: 'address',
+ },
+ ],
+ name: 'nonces',
+ outputs: [
+ {
+ name: '',
+ type: 'uint256',
+ },
+ ],
+ payable: false,
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'owner',
+ type: 'address',
+ },
+ {
+ internalType: 'address',
+ name: 'spender',
+ type: 'address',
+ },
+ {
+ internalType: 'uint256',
+ name: 'value',
+ type: 'uint256',
+ },
+ {
+ internalType: 'uint256',
+ name: 'deadline',
+ type: 'uint256',
+ },
+ {
+ internalType: 'uint8',
+ name: 'v',
+ type: 'uint8',
+ },
+ {
+ internalType: 'bytes32',
+ name: 'r',
+ type: 'bytes32',
+ },
+ {
+ internalType: 'bytes32',
+ name: 's',
+ type: 'bytes32',
+ },
+ ],
+ name: 'permit',
+ outputs: [],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
] as const
export class Erc20__factory {
diff --git a/libs/abis/src/index.ts b/libs/abis/src/index.ts
index 0c312d27c5..7f3cce77fd 100644
--- a/libs/abis/src/index.ts
+++ b/libs/abis/src/index.ts
@@ -11,6 +11,8 @@ import _MerkleDropAbi from './abis/MerkleDrop.json'
import _TokenDistroAbi from './abis/TokenDistro.json'
+import _CoWSwapEthFlowAbi from './abis/CoWSwapEthFlow.json'
+
import _ethFlowBarnJson from '@cowprotocol/ethflowcontract/networks.barn.json'
import _ethFlowProdJson from '@cowprotocol/ethflowcontract/networks.prod.json'
@@ -20,8 +22,6 @@ import _ArgentWalletContractAbi from './abis-legacy/argent-wallet-contract.json'
import _ArgentWalletDetectorAbi from './abis-legacy/argent-wallet-detector.json'
-import _CoWSwapEthFlowJson from '@cowprotocol/ethflowcontract/artifacts/CoWSwapEthFlow.sol/CoWSwapEthFlow.json'
-
import _Eip2612Abi from './abis-legacy/eip_2612.json'
import _EnsPublicResolverAbi from './abis-legacy/ens-public-resolver.json'
@@ -46,6 +46,7 @@ export const vCowAbi = _vCowAbi
export const SignatureVerifierMuxerAbi = _SignatureVerifierMuxerAbi
export const MerkleDropAbi = _MerkleDropAbi
export const TokenDistroAbi = _TokenDistroAbi
+export const CoWSwapEthFlowAbi = _CoWSwapEthFlowAbi
export * from './generated/custom'
export type { GPv2Order } from './generated/custom/ComposableCoW'
@@ -71,7 +72,6 @@ export const ethFlowBarnJson = _ethFlowBarnJson
export const ethFlowProdJson = _ethFlowProdJson
export const ArgentWalletContractAbi = _ArgentWalletContractAbi
export const ArgentWalletDetectorAbi = _ArgentWalletDetectorAbi
-export const CoWSwapEthFlowJson = _CoWSwapEthFlowJson
export const Eip2612Abi = _Eip2612Abi
export const EnsPublicResolverAbi = _EnsPublicResolverAbi
export const EnsAbi = _EnsAbi
diff --git a/libs/analytics/.babelrc b/libs/analytics/.babelrc
new file mode 100644
index 0000000000..ef4889c1ab
--- /dev/null
+++ b/libs/analytics/.babelrc
@@ -0,0 +1,20 @@
+{
+ "presets": [
+ [
+ "@nx/react/babel",
+ {
+ "runtime": "automatic",
+ "useBuiltIns": "usage"
+ }
+ ]
+ ],
+ "plugins": [
+ [
+ "styled-components",
+ {
+ "pure": true,
+ "ssr": true
+ }
+ ]
+ ]
+}
diff --git a/libs/analytics/.eslintrc.json b/libs/analytics/.eslintrc.json
new file mode 100644
index 0000000000..231aaa5f83
--- /dev/null
+++ b/libs/analytics/.eslintrc.json
@@ -0,0 +1,21 @@
+{
+ "extends": ["plugin:@nx/react", "../../.eslintrc.json"],
+ "ignorePatterns": ["!**/*"],
+ "rules": {
+ "@typescript-eslint/no-explicit-any": "off"
+ },
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.js", "*.jsx"],
+ "rules": {}
+ }
+ ]
+}
diff --git a/libs/analytics/README.md b/libs/analytics/README.md
new file mode 100644
index 0000000000..f097a1dbbf
--- /dev/null
+++ b/libs/analytics/README.md
@@ -0,0 +1 @@
+# Analytics
diff --git a/libs/analytics/jest.config.ts b/libs/analytics/jest.config.ts
new file mode 100644
index 0000000000..2e6915c373
--- /dev/null
+++ b/libs/analytics/jest.config.ts
@@ -0,0 +1,11 @@
+/* eslint-disable */
+export default {
+ displayName: 'analytics',
+ preset: '../../jest.preset.js',
+ transform: {
+ '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nx/react/plugins/jest',
+ '^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nx/react/babel'] }],
+ },
+ moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
+ coverageDirectory: '../../coverage/libs/analytics',
+}
diff --git a/libs/analytics/package.json b/libs/analytics/package.json
new file mode 100644
index 0000000000..31f055efc5
--- /dev/null
+++ b/libs/analytics/package.json
@@ -0,0 +1,12 @@
+{
+ "name": "@cowprotocol/analytics",
+ "version": "0.0.1",
+ "main": "./index.js",
+ "types": "./index.d.ts",
+ "exports": {
+ ".": {
+ "import": "./index.mjs",
+ "require": "./index.js"
+ }
+ }
+}
diff --git a/libs/analytics/project.json b/libs/analytics/project.json
new file mode 100644
index 0000000000..3943c48429
--- /dev/null
+++ b/libs/analytics/project.json
@@ -0,0 +1,46 @@
+{
+ "name": "@cowprotocol/analytics",
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "sourceRoot": "libs/analytics/src",
+ "projectType": "library",
+ "tags": [],
+ "targets": {
+ "lint": {
+ "executor": "@nx/linter:eslint",
+ "outputs": ["{options.outputFile}"],
+ "options": {
+ "lintFilePatterns": ["libs/analytics/**/*.{ts,tsx,js,jsx}"]
+ }
+ },
+ "build": {
+ "executor": "@nx/vite:build",
+ "outputs": ["{options.outputPath}"],
+ "defaultConfiguration": "production",
+ "options": {
+ "outputPath": "dist/libs/analytics"
+ },
+ "configurations": {
+ "development": {
+ "mode": "development"
+ },
+ "production": {
+ "mode": "production"
+ }
+ }
+ },
+ "test": {
+ "executor": "@nx/jest:jest",
+ "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
+ "options": {
+ "jestConfig": "libs/analytics/jest.config.ts",
+ "passWithNoTests": true
+ },
+ "configurations": {
+ "ci": {
+ "ci": true,
+ "codeCoverage": true
+ }
+ }
+ }
+ }
+}
diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/events/cowFortune.ts b/libs/analytics/src/events/cowFortune.ts
similarity index 100%
rename from apps/cowswap-frontend/src/legacy/components/analytics/events/cowFortune.ts
rename to libs/analytics/src/events/cowFortune.ts
diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/events/listEvents.ts b/libs/analytics/src/events/listEvents.ts
similarity index 100%
rename from apps/cowswap-frontend/src/legacy/components/analytics/events/listEvents.ts
rename to libs/analytics/src/events/listEvents.ts
diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/events/otherEvents.ts b/libs/analytics/src/events/otherEvents.ts
similarity index 94%
rename from apps/cowswap-frontend/src/legacy/components/analytics/events/otherEvents.ts
rename to libs/analytics/src/events/otherEvents.ts
index 132edbaae1..eab7c4cb22 100644
--- a/apps/cowswap-frontend/src/legacy/components/analytics/events/otherEvents.ts
+++ b/libs/analytics/src/events/otherEvents.ts
@@ -1,4 +1,4 @@
-import { detectExplorer } from 'legacy/utils/explorer'
+import { detectExplorer } from '@cowprotocol/common-utils'
import { sendEvent } from '../googleAnalytics'
import { Category } from '../types'
diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/events/settingsEvents.ts b/libs/analytics/src/events/settingsEvents.ts
similarity index 95%
rename from apps/cowswap-frontend/src/legacy/components/analytics/events/settingsEvents.ts
rename to libs/analytics/src/events/settingsEvents.ts
index af0c0ffc5e..0718548e96 100644
--- a/apps/cowswap-frontend/src/legacy/components/analytics/events/settingsEvents.ts
+++ b/libs/analytics/src/events/settingsEvents.ts
@@ -1,4 +1,4 @@
-import { debounce } from 'legacy/utils/misc'
+import { debounce } from '@cowprotocol/common-utils'
import { sendEvent } from '../googleAnalytics'
import { Category } from '../types'
diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/events/swapEvents.ts b/libs/analytics/src/events/swapEvents.ts
similarity index 75%
rename from apps/cowswap-frontend/src/legacy/components/analytics/events/swapEvents.ts
rename to libs/analytics/src/events/swapEvents.ts
index 8f0956776f..fdb7bf7798 100644
--- a/apps/cowswap-frontend/src/legacy/components/analytics/events/swapEvents.ts
+++ b/libs/analytics/src/events/swapEvents.ts
@@ -1,10 +1,9 @@
-import { Field } from 'legacy/state/swap/actions'
-import { debounce } from 'legacy/utils/misc'
+import { debounce } from '@cowprotocol/common-utils'
import { sendEvent } from '../googleAnalytics'
import { Category } from '../types'
-export function currencySelectAnalytics(field: Field, label: string | undefined) {
+export function currencySelectAnalytics(field: string, label: string | undefined) {
sendEvent({
category: Category.CURRENCY_SELECT,
action: `Change ${field} token`,
@@ -19,7 +18,7 @@ export function setMaxSellTokensAnalytics() {
})
}
-function _changeSwapAmountAnalytics(field: Field, value: number) {
+function _changeSwapAmountAnalytics(field: string, value: number) {
sendEvent({
category: Category.TRADE,
action: `Change ${field} field amount`,
@@ -27,7 +26,7 @@ function _changeSwapAmountAnalytics(field: Field, value: number) {
})
}
-export const changeSwapAmountAnalytics = debounce(([field, value]: [Field, number]) => {
+export const changeSwapAmountAnalytics = debounce(([field, value]: [string, number]) => {
_changeSwapAmountAnalytics(field, value)
}, 2000)
diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/events/themeEvents.ts b/libs/analytics/src/events/themeEvents.ts
similarity index 100%
rename from apps/cowswap-frontend/src/legacy/components/analytics/events/themeEvents.ts
rename to libs/analytics/src/events/themeEvents.ts
diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/events/transactionEvents.ts b/libs/analytics/src/events/transactionEvents.ts
similarity index 80%
rename from apps/cowswap-frontend/src/legacy/components/analytics/events/transactionEvents.ts
rename to libs/analytics/src/events/transactionEvents.ts
index 7e220b2591..94ad4d9dc7 100644
--- a/apps/cowswap-frontend/src/legacy/components/analytics/events/transactionEvents.ts
+++ b/libs/analytics/src/events/transactionEvents.ts
@@ -1,13 +1,7 @@
import { OrderClass } from '@cowprotocol/cow-sdk'
import { sendEvent } from '../googleAnalytics'
-import { PIXEL_EVENTS } from '../pixel/constants'
-import { sendFacebookEvent } from '../pixel/facebook'
-import { sendLinkedinEvent } from '../pixel/linkedin'
-import { sendMicrosoftEvent } from '../pixel/microsoft'
-import { sendPavedEvent } from '../pixel/paved'
-import { sendRedditEvent } from '../pixel/reddit'
-import { sendTwitterEvent } from '../pixel/twitter'
+import { PixelEvent, sendAllPixels } from '../pixel'
import { AnalyticsOrderType, Category } from '../types'
const LABEL_FROM_CLASS: Record = {
@@ -86,12 +80,7 @@ export function signTradeAnalytics(orderClass: AnalyticsOrderType, label?: strin
export type OrderType = 'Posted' | 'Executed' | 'Canceled' | 'Expired'
export function orderAnalytics(action: OrderType, orderClass: AnalyticsOrderType, label?: string) {
if (action === 'Posted') {
- sendFacebookEvent(PIXEL_EVENTS.POST_TRADE)
- sendLinkedinEvent(PIXEL_EVENTS.POST_TRADE)
- sendTwitterEvent(PIXEL_EVENTS.POST_TRADE)
- sendRedditEvent(PIXEL_EVENTS.POST_TRADE)
- sendPavedEvent(PIXEL_EVENTS.POST_TRADE)
- sendMicrosoftEvent(PIXEL_EVENTS.POST_TRADE)
+ sendAllPixels(PixelEvent.POST_TRADE)
}
sendEvent({
diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/events/twapEvents.ts b/libs/analytics/src/events/twapEvents.ts
similarity index 100%
rename from apps/cowswap-frontend/src/legacy/components/analytics/events/twapEvents.ts
rename to libs/analytics/src/events/twapEvents.ts
diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/events/walletEvents.ts b/libs/analytics/src/events/walletEvents.ts
similarity index 100%
rename from apps/cowswap-frontend/src/legacy/components/analytics/events/walletEvents.ts
rename to libs/analytics/src/events/walletEvents.ts
diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/googleAnalytics.ts b/libs/analytics/src/googleAnalytics.ts
similarity index 100%
rename from apps/cowswap-frontend/src/legacy/components/analytics/googleAnalytics.ts
rename to libs/analytics/src/googleAnalytics.ts
diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/index.ts b/libs/analytics/src/index.ts
similarity index 87%
rename from apps/cowswap-frontend/src/legacy/components/analytics/index.ts
rename to libs/analytics/src/index.ts
index 64a6c8420e..884c06dbc5 100644
--- a/apps/cowswap-frontend/src/legacy/components/analytics/index.ts
+++ b/libs/analytics/src/index.ts
@@ -1,11 +1,9 @@
-import { isMobile } from 'legacy/utils/userAgent'
+import { isMobile } from '@cowprotocol/common-utils'
import { initAnalytics, serviceWorkerAnalytics } from './events/otherEvents'
import { googleAnalytics } from './googleAnalytics'
import { Dimensions } from './types'
-export { useAnalyticsReporter } from './hooks/useAnalyticsReporter'
-
const GOOGLE_ANALYTICS_ID: string | undefined = process.env.REACT_APP_GOOGLE_ANALYTICS_ID
export const GOOGLE_ANALYTICS_CLIENT_ID_STORAGE_KEY = 'ga_client_id'
@@ -42,7 +40,6 @@ if (typeof GOOGLE_ANALYTICS_ID === 'string') {
serviceWorkerAnalytics()
initAnalytics()
-// MOD
export * from './events/listEvents'
export * from './events/settingsEvents'
export * from './events/themeEvents'
@@ -50,3 +47,8 @@ export * from './events/transactionEvents'
export * from './events/walletEvents'
export * from './events/swapEvents'
export * from './events/otherEvents'
+export * from './events/cowFortune'
+export * from './events/twapEvents'
+export * from './googleAnalytics'
+export * from './pixel'
+export * from './types'
diff --git a/libs/analytics/src/pixel/constants.ts b/libs/analytics/src/pixel/constants.ts
new file mode 100644
index 0000000000..6428232da7
--- /dev/null
+++ b/libs/analytics/src/pixel/constants.ts
@@ -0,0 +1,3 @@
+import { isEns, isProd } from '@cowprotocol/common-utils'
+
+export const PIXEL_ENABLED = isProd || isEns
diff --git a/libs/analytics/src/pixel/facebook.ts b/libs/analytics/src/pixel/facebook.ts
new file mode 100644
index 0000000000..250e392cf6
--- /dev/null
+++ b/libs/analytics/src/pixel/facebook.ts
@@ -0,0 +1,17 @@
+import { enablePixel } from './sendAllPixels'
+import { PixelEvent, PixelEventMap } from './types'
+import { sendPixel } from './utils'
+
+const events: PixelEventMap = {
+ [PixelEvent.INIT]: 'InitiateCheckout',
+ [PixelEvent.CONNECT_WALLET]: 'Contact',
+ [PixelEvent.POST_TRADE]: 'Lead',
+}
+
+const sendFacebookEvent = sendPixel((event) => {
+ window.fbq?.('track', events[event])
+})
+
+export function enablePixelFacebook() {
+ enablePixel(events, sendFacebookEvent)
+}
diff --git a/libs/analytics/src/pixel/index.ts b/libs/analytics/src/pixel/index.ts
new file mode 100644
index 0000000000..396dd8d9da
--- /dev/null
+++ b/libs/analytics/src/pixel/index.ts
@@ -0,0 +1,9 @@
+export { sendAllPixels } from './sendAllPixels'
+export * from './types'
+
+// Register
+export { enablePixelFacebook } from './facebook'
+export { enablePixelPaved } from './paved'
+export { enablePixelReddit } from './reddit'
+export { enablePixelTwitter } from './twitter'
+export { enablePixelMicrosoft } from './microsoft'
diff --git a/libs/analytics/src/pixel/linkedin.ts b/libs/analytics/src/pixel/linkedin.ts
new file mode 100644
index 0000000000..102d9f4be3
--- /dev/null
+++ b/libs/analytics/src/pixel/linkedin.ts
@@ -0,0 +1,17 @@
+import { enablePixel } from './sendAllPixels'
+import { PixelEvent, PixelEventMap } from './types'
+import { sendPixel } from './utils'
+
+const events: PixelEventMap = {
+ [PixelEvent.INIT]: 10759506,
+ [PixelEvent.CONNECT_WALLET]: 10759514,
+ [PixelEvent.POST_TRADE]: 10759522,
+}
+
+const sendLinkedinEvent = sendPixel((event) => {
+ window.lintrk?.('track', { conversion_id: events[event] })
+})
+
+export function enablePixelLinkedin() {
+ enablePixel(events, sendLinkedinEvent)
+}
diff --git a/libs/analytics/src/pixel/microsoft.ts b/libs/analytics/src/pixel/microsoft.ts
new file mode 100644
index 0000000000..618f30e3af
--- /dev/null
+++ b/libs/analytics/src/pixel/microsoft.ts
@@ -0,0 +1,18 @@
+import { enablePixel } from './sendAllPixels'
+import { PixelEvent, PixelEventMap } from './types'
+import { sendPixel } from './utils'
+
+const events: PixelEventMap = {
+ [PixelEvent.INIT]: 'page_view',
+ [PixelEvent.CONNECT_WALLET]: 'begin_checkout',
+ [PixelEvent.POST_TRADE]: 'purchase',
+}
+
+const sendMicrosoftEvent = sendPixel((event) => {
+ window.uetq = window.uetq || []
+ window.uetq.push('event', events[event], {})
+})
+
+export function enablePixelMicrosoft() {
+ enablePixel(events, sendMicrosoftEvent)
+}
diff --git a/libs/analytics/src/pixel/paved.ts b/libs/analytics/src/pixel/paved.ts
new file mode 100644
index 0000000000..67b1bccd8b
--- /dev/null
+++ b/libs/analytics/src/pixel/paved.ts
@@ -0,0 +1,17 @@
+import { enablePixel } from './sendAllPixels'
+import { PixelEvent, PixelEventMap } from './types'
+import { sendPixel } from './utils'
+
+const events: PixelEventMap = {
+ [PixelEvent.INIT]: 'search',
+ [PixelEvent.CONNECT_WALLET]: 'sign_up',
+ [PixelEvent.POST_TRADE]: 'purchase',
+}
+
+const sendPavedEvent = sendPixel((event) => {
+ window.pvd?.('event', events[event])
+})
+
+export function enablePixelPaved() {
+ enablePixel(events, sendPavedEvent)
+}
diff --git a/libs/analytics/src/pixel/reddit.ts b/libs/analytics/src/pixel/reddit.ts
new file mode 100644
index 0000000000..eb77a53bd7
--- /dev/null
+++ b/libs/analytics/src/pixel/reddit.ts
@@ -0,0 +1,17 @@
+import { enablePixel } from './sendAllPixels'
+import { PixelEvent, PixelEventMap } from './types'
+import { sendPixel } from './utils'
+
+const events: PixelEventMap = {
+ [PixelEvent.INIT]: 'Lead',
+ [PixelEvent.CONNECT_WALLET]: 'SignUp',
+ [PixelEvent.POST_TRADE]: 'Purchase',
+}
+
+const sendRedditEvent = sendPixel((event) => {
+ window.rdt?.('track', events[event])
+})
+
+export function enablePixelReddit() {
+ enablePixel(events, sendRedditEvent)
+}
diff --git a/libs/analytics/src/pixel/sendAllPixels.ts b/libs/analytics/src/pixel/sendAllPixels.ts
new file mode 100644
index 0000000000..67eb45570d
--- /dev/null
+++ b/libs/analytics/src/pixel/sendAllPixels.ts
@@ -0,0 +1,35 @@
+import { PixelEvent, PixelEventMap, SendPixel } from './types'
+
+const sendPixelCallbacks: Map = new Map()
+
+/**
+ * Sends all the enabled pixels for the given event
+ *
+ * @param event event to send
+ */
+export function sendAllPixels(event: PixelEvent): void {
+ const callbacks = sendPixelCallbacks.get(event)
+ if (!callbacks) return
+
+ callbacks.forEach((callback) => callback(event))
+}
+
+function _enablePixel(event: PixelEvent, sendPixel: SendPixel) {
+ let callbacks = sendPixelCallbacks.get(event)
+ if (!callbacks) {
+ callbacks = []
+ sendPixelCallbacks.set(event, callbacks)
+ }
+
+ callbacks.push(sendPixel)
+}
+
+/**
+ * Register a pixel callback for the given set of events events
+ */
+export function enablePixel(eventMap: PixelEventMap