Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
dd238e8
feat(tokenselector): implement SelectTokenWidget with enhanced chain …
fairlighteth Nov 17, 2025
7739ad4
fix: update fallback logic for unsupported source chains in chain sel…
fairlighteth Nov 18, 2025
43247d6
refactor: remove onSelectChain from SelectTokenModalProps interface
fairlighteth Nov 18, 2025
e0d8edf
Merge branch 'feat/token-selector-9' into feat/token-selector-10
fairlighteth Nov 18, 2025
6e0a8c6
Merge branch 'feat/token-selector-9' into feat/token-selector-10
fairlighteth Nov 18, 2025
7e85dc1
refactor: token pinning logic to ensure recent tokens are displayed c…
fairlighteth Nov 19, 2025
5e58eaf
refactor: remove x close button in manage token list modal
fairlighteth Nov 19, 2025
4f25b7f
Merge branch 'feat/token-selector-9' into feat/token-selector-10
fairlighteth Nov 25, 2025
c5fa3df
Merge branch 'feat/token-selector-9' of github.com:cowprotocol/cowswa…
fairlighteth Nov 28, 2025
ec0d7c2
refactor: make onSelectChain and onOpenMobileChainPanel optional in S…
fairlighteth Nov 28, 2025
1baae32
refactor: simplify JSX structure in SelectTokenModal and TokenColumnC…
fairlighteth Nov 28, 2025
b72b0e0
feat: add onSelectChain prop to defaultModalProps in SelectTokenModal
fairlighteth Nov 28, 2025
2cf36f0
refactor: update chainsToSelect handling in SelectTokenWidget and Sel…
fairlighteth Nov 28, 2025
52dc3a4
Merge remote-tracking branch 'origin/feat/token-selector-9' into feat…
fairlighteth Dec 4, 2025
d77a522
fix: revert token list url
fairlighteth Dec 4, 2025
05327ab
feat: enhance localization support in ChainPanel and SelectTokenModal…
fairlighteth Dec 4, 2025
655226a
fix: update ManageListsAndTokens component to include onDismiss prop
fairlighteth Dec 4, 2025
4e22948
fix: correct Russian plural form for 'View all {totalChains} networks'
fairlighteth Dec 4, 2025
3ac256b
fix: update Spanish and Russian translations for cross-chain swap ter…
fairlighteth Dec 4, 2025
d4f7460
fix: refine Russian translations for cross-chain swap terminology
fairlighteth Dec 4, 2025
50c46c3
fix: add Spanish and Russian translations for 'Recent' in TokensVirtu…
fairlighteth Dec 4, 2025
9a01bf3
fix: add Spanish and Russian translations for 'Clear' in TokensVirtua…
fairlighteth Dec 4, 2025
84f18d8
Merge branch 'feat/token-selector-9' into feat/token-selector-10
fairlighteth Dec 5, 2025
a1a9dcf
fix: update chain selection logic for advanced trade types to prevent…
fairlighteth Dec 5, 2025
24c41b7
test: enhance useChainsToSelect tests for various trade types and cha…
fairlighteth Dec 5, 2025
0c1ce15
feat: integrate feature flag for bridging enablement in BridgingEnabl…
fairlighteth Dec 5, 2025
9eea62d
test: add unit tests for BridgingEnabledUpdater component to validate…
fairlighteth Dec 5, 2025
2925980
Merge remote-tracking branch 'origin/feat/token-selector-9' into feat…
fairlighteth Dec 9, 2025
3befb75
Merge branch 'feat/token-selector-9' into feat/token-selector-10
fairlighteth Dec 10, 2025
54687d1
refactor: remove unused props from SelectTokenModal to simplify compo…
fairlighteth Dec 10, 2025
5452d8e
Merge branch 'feat/token-selector-9' into feat/token-selector-10
fairlighteth Dec 10, 2025
8177cbe
Merge branch 'feat/token-selector-9' into feat/token-selector-10
fairlighteth Dec 11, 2025
de21d1d
Merge branch 'feat/token-selector-9' into feat/token-selector-10
fairlighteth Dec 11, 2025
3884349
Merge branch 'feat/token-selector-9' into feat/token-selector-10
fairlighteth Dec 15, 2025
c3be32a
refactor: remove feature flag dependency from BridgingEnabledUpdater …
fairlighteth Dec 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/cow-fi/data/cow-swap/const.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import IMG_COWSWAP_NOFEES from '@cowprotocol/assets/images/image-cowswap-nofees.
import IMG_COWSWAP_SWAPS from '@cowprotocol/assets/images/image-cowswap-swaps.svg'
import IMG_COWSWAP_TWAP from '@cowprotocol/assets/images/image-cowswap-twap.svg'
import IMG_COWSWAP_UX from '@cowprotocol/assets/images/image-cowswap-ux.svg'
import { Color, UI } from '@cowprotocol/ui'
import { getAvailableChainsText } from '@cowprotocol/common-const'
import { Color, UI } from '@cowprotocol/ui'

import { CowFiCategory } from 'src/common/analytics/types'

import { Link } from '@/components/Link'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { AccountType } from '@cowprotocol/types'

import { render } from '@testing-library/react'

import { BridgingEnabledUpdater } from './BridgingEnabledUpdater'

import { Routes } from '../constants/routes'

jest.mock('@cowprotocol/common-hooks', () => ({
...jest.requireActual('@cowprotocol/common-hooks'),
useSetIsBridgingEnabled: jest.fn(),
}))

jest.mock('@cowprotocol/wallet', () => ({
...jest.requireActual('@cowprotocol/wallet'),
useWalletInfo: jest.fn(),
useAccountType: jest.fn(),
}))

jest.mock('modules/trade', () => ({
...jest.requireActual('modules/trade'),
useTradeTypeInfo: jest.fn(),
}))

const { useSetIsBridgingEnabled } = require('@cowprotocol/common-hooks')
const mockUseSetIsBridgingEnabled = useSetIsBridgingEnabled as jest.MockedFunction<typeof useSetIsBridgingEnabled>
const { useWalletInfo, useAccountType } = require('@cowprotocol/wallet')

const mockUseWalletInfo = useWalletInfo as jest.MockedFunction<typeof useWalletInfo>
const mockUseAccountType = useAccountType as jest.MockedFunction<typeof useAccountType>
const { useTradeTypeInfo } = require('modules/trade')
const mockUseTradeTypeInfo = useTradeTypeInfo as jest.MockedFunction<typeof useTradeTypeInfo>

describe('BridgingEnabledUpdater', () => {
const setIsBridgingEnabled = jest.fn()

beforeEach(() => {
jest.clearAllMocks()
mockUseSetIsBridgingEnabled.mockReturnValue(setIsBridgingEnabled)
mockUseWalletInfo.mockReturnValue({ account: '0x123' })
mockUseAccountType.mockReturnValue(AccountType.EOA)
mockUseTradeTypeInfo.mockReturnValue({ route: Routes.SWAP })
})

it('disables bridging for smart contract wallets', () => {
mockUseAccountType.mockReturnValue(AccountType.SMART_CONTRACT)

render(<BridgingEnabledUpdater />)

expect(setIsBridgingEnabled).toHaveBeenCalledWith(false)
})

it('enables bridging on swap route when the wallet is compatible', () => {
render(<BridgingEnabledUpdater />)

expect(setIsBridgingEnabled).toHaveBeenCalledWith(true)
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export function BridgingEnabledUpdater(): null {
const setIsBridgingEnabled = useSetIsBridgingEnabled()

const isSwapRoute = tradeTypeInfo?.route === Routes.SWAP

const isWalletCompatible = Boolean(account ? accountType !== AccountType.SMART_CONTRACT : true)
const shouldEnableBridging = isWalletCompatible && isSwapRoute

Expand Down
87 changes: 86 additions & 1 deletion apps/cowswap-frontend/src/locales/es-ES.po
Original file line number Diff line number Diff line change
Expand Up @@ -4212,6 +4212,14 @@ msgstr "Habilitar aprobación parcial"
msgid "Version"
msgstr "Versión"

#: apps/cowswap-frontend/src/modules/tokensList/pure/TokensVirtualList/index.tsx
msgid "Recent"
msgstr "Recientes"

#: apps/cowswap-frontend/src/modules/tokensList/pure/TokensVirtualList/index.tsx
msgid "Clear"
msgstr "Borrar"

#: apps/cowswap-frontend/src/pages/Account/Tokens/TokensOverview.tsx
msgid "All tokens"
msgstr "Todos los tokens"
Expand Down Expand Up @@ -5211,7 +5219,7 @@ msgstr "parte"

#: apps/cowswap-frontend/src/modules/swap/pure/CrossChainUnlockScreen/index.tsx
msgid "Cross-chain swaps are here"
msgstr "Los swaps de cadena media están aquí"
msgstr "Los swaps entre cadenas están aquí"

#: apps/cowswap-frontend/src/modules/erc20Approve/containers/ApprovalAmountInput/ApprovalAmountInput.tsx
#~ msgid "Approval amount:"
Expand Down Expand Up @@ -6294,3 +6302,80 @@ msgstr "Aprende más"
msgid "Swap and bridge costs are at least {formattedFeePercentage}% of the swap amount"
msgstr "Los costos de intercambio y puente son por lo menos {formattedFeePercentage}% del monto de intercambio"

# Receive amount labels
msgid "Receive (incl. fees)"
msgstr "Recibir (incl. comisiones)"

msgid "From (incl. fees)"
msgstr "De (incl. comisiones)"

# Notifications / jobs aria labels
msgid "Trade alert settings"
msgstr "Configuración de alertas de trading"

msgid "View jobs (opens in a new tab)"
msgstr "Ver trabajos (se abre en una pestaña nueva)"

#: apps/cowswap-frontend/src/modules/tokensList/pure/ChainPanel/index.tsx
msgid "Search network"
msgstr "Buscar red"

#: apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/controllerState.ts
msgid "Select token"
msgstr "Seleccionar token"

#: apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/controllerState.ts
msgid "From network"
msgstr "Red de origen"

#: apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/controllerState.ts
msgid "To network"
msgstr "Red de destino"

#: apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/controllerState.ts
msgid "Select network"
msgstr "Seleccionar red"

#: apps/cowswap-frontend/src/modules/tokensList/pure/SelectTokenModal/index.tsx
msgid "Cross chain swap"
msgstr "Swap entre cadenas"

#: apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/controllerState.ts
msgid "Swap from"
msgstr "Swap desde"

#: apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/controllerState.ts
msgid "Swap to"
msgstr "Swap a"

#: apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/controllerState.ts
msgid "Sell token"
msgstr "Vender token"

#: apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/controllerState.ts
msgid "Buy token"
msgstr "Comprar token"

#: apps/cowswap-frontend/src/modules/tokensList/pure/SelectTokenModal/helpers.tsx
msgid "Manage token lists"
msgstr "Gestionar listas de tokens"

#: apps/cowswap-frontend/src/modules/tokensList/pure/ChainPanel/index.tsx
msgid "No networks available for this trade."
msgstr "No hay redes disponibles para este intercambio."

#: apps/cowswap-frontend/src/modules/tokensList/pure/ChainPanel/index.tsx
msgid "No networks match {chainQuery}."
msgstr "No hay redes que coincidan con {chainQuery}."

#: apps/cowswap-frontend/src/modules/tokensList/pure/SelectTokenModal/MobileChainSelector.tsx
msgid "View all ({totalChains})"
msgstr "Ver todas ({totalChains})"

#: apps/cowswap-frontend/src/modules/tokensList/pure/SelectTokenModal/MobileChainSelector.tsx
msgid "View all {totalChains} networks"
msgstr "Ver todas las {totalChains} redes"

#: apps/cowswap-frontend/src/modules/tokensList/pure/SelectTokenModal/MobileChainSelector.tsx
msgid "Selected network {activeChainLabel}"
msgstr "Red seleccionada {activeChainLabel}"
87 changes: 86 additions & 1 deletion apps/cowswap-frontend/src/locales/ru-RU.po
Original file line number Diff line number Diff line change
Expand Up @@ -4212,6 +4212,14 @@ msgstr "Включить частичные утверждения"
msgid "Version"
msgstr "Версии"

#: apps/cowswap-frontend/src/modules/tokensList/pure/TokensVirtualList/index.tsx
msgid "Recent"
msgstr "Недавние"

#: apps/cowswap-frontend/src/modules/tokensList/pure/TokensVirtualList/index.tsx
msgid "Clear"
msgstr "Очистить"

#: apps/cowswap-frontend/src/pages/Account/Tokens/TokensOverview.tsx
msgid "All tokens"
msgstr "Все токены"
Expand Down Expand Up @@ -5211,7 +5219,7 @@ msgstr "часть"

#: apps/cowswap-frontend/src/modules/swap/pure/CrossChainUnlockScreen/index.tsx
msgid "Cross-chain swaps are here"
msgstr "Перекрестные цепочки здесь"
msgstr "Межсетевые обмены здесь"

#: apps/cowswap-frontend/src/modules/erc20Approve/containers/ApprovalAmountInput/ApprovalAmountInput.tsx
#~ msgid "Approval amount:"
Expand Down Expand Up @@ -6294,3 +6302,80 @@ msgstr "Узнать больше"
msgid "Swap and bridge costs are at least {formattedFeePercentage}% of the swap amount"
msgstr "Затраты на замену и мост составляют не менее {formattedFeePercentage}% от суммы замены"

# Receive amount labels
msgid "Receive (incl. fees)"
msgstr "К получению (с комиссиями)"

msgid "From (incl. fees)"
msgstr "Отправить (с комиссиями)"

# Notifications / jobs aria labels
msgid "Trade alert settings"
msgstr "Настройки уведомлений о сделках"

msgid "View jobs (opens in a new tab)"
msgstr "Просмотр вакансий (откроется в новой вкладке)"

#: apps/cowswap-frontend/src/modules/tokensList/pure/ChainPanel/index.tsx
msgid "Search network"
msgstr "Поиск сети"

#: apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/controllerState.ts
msgid "Select token"
msgstr "Выбрать токен"

#: apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/controllerState.ts
msgid "From network"
msgstr "Исходная сеть"

#: apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/controllerState.ts
msgid "To network"
msgstr "Целевая сеть"

#: apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/controllerState.ts
msgid "Select network"
msgstr "Выбрать сеть"

#: apps/cowswap-frontend/src/modules/tokensList/pure/SelectTokenModal/index.tsx
msgid "Cross chain swap"
msgstr "Свап между сетями"

#: apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/controllerState.ts
msgid "Swap from"
msgstr "Свап из сети"

#: apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/controllerState.ts
msgid "Swap to"
msgstr "Свап в сеть"

#: apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/controllerState.ts
msgid "Sell token"
msgstr "Продать токен"

#: apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/controllerState.ts
msgid "Buy token"
msgstr "Купить токен"

#: apps/cowswap-frontend/src/modules/tokensList/pure/SelectTokenModal/helpers.tsx
msgid "Manage token lists"
msgstr "Управление списками токенов"

#: apps/cowswap-frontend/src/modules/tokensList/pure/ChainPanel/index.tsx
msgid "No networks available for this trade."
msgstr "Нет доступных сетей для этой сделки."

#: apps/cowswap-frontend/src/modules/tokensList/pure/ChainPanel/index.tsx
msgid "No networks match {chainQuery}."
msgstr "Нет сетей, соответствующих {chainQuery}."

#: apps/cowswap-frontend/src/modules/tokensList/pure/SelectTokenModal/MobileChainSelector.tsx
msgid "View all ({totalChains})"
msgstr "Показать все ({totalChains})"

#: apps/cowswap-frontend/src/modules/tokensList/pure/SelectTokenModal/MobileChainSelector.tsx
msgid "View all {totalChains} networks"
msgstr "Показать все сети ({totalChains})"

#: apps/cowswap-frontend/src/modules/tokensList/pure/SelectTokenModal/MobileChainSelector.tsx
msgid "Selected network {activeChainLabel}"
msgstr "Выбранная сеть {activeChainLabel}"
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export interface ManageListsAndTokensProps {
lists: ListState[]
customTokens: TokenWithLogo[]
onBack(): void
onDismiss(): void
onDismiss?(): void
}

const tokensInputPlaceholder = '0x0000'
Expand Down Expand Up @@ -50,20 +50,15 @@ export function ManageListsAndTokens(props: ManageListsAndTokensProps): ReactNod
const tokenSearchResponse = useSearchToken(isTokenAddressValid ? tokenInput : null)
const listSearchResponse = useSearchList(isListUrlValid ? listInput : null)

// TODO: Add proper return type annotation
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const setListsTab = () => {
const setListsTab = (): void => {
setCurrentTab('lists')
setInputValue('')
}

// TODO: Add proper return type annotation
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const setTokensTab = () => {
const setTokensTab = (): void => {
setCurrentTab('tokens')
setInputValue('')
}

return (
<styledEl.Wrapper>
<ModalHeader onBack={onBack} onClose={onDismiss}>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { MouseEvent, ReactNode } from 'react'

import { createPortal } from 'react-dom'

import { MobileChainPanelCard, MobileChainPanelOverlay } from './styled'

import { ChainPanel } from '../../pure/ChainPanel'

import type { SelectTokenWidgetViewProps } from './controllerProps'

interface MobileChainPanelPortalProps {
chainsPanelTitle: string
chainsToSelect: SelectTokenWidgetViewProps['chainsToSelect']
onSelectChain: SelectTokenWidgetViewProps['onSelectChain']
onClose(): void
}

export function MobileChainPanelPortal({
chainsPanelTitle,
chainsToSelect,
onSelectChain,
onClose,
}: MobileChainPanelPortalProps): ReactNode {
if (typeof document === 'undefined') {
return null
}

return createPortal(
<MobileChainPanelOverlay onClick={onClose}>
<MobileChainPanelCard onClick={(event: MouseEvent<HTMLDivElement>) => event.stopPropagation()}>
<ChainPanel
title={chainsPanelTitle}
chainsState={chainsToSelect}
onSelectChain={(chain) => {
onSelectChain(chain)
onClose()
}}
variant="fullscreen"
onClose={onClose}
/>
</MobileChainPanelCard>
</MobileChainPanelOverlay>,
document.body,
)
}
Loading