From 9de197c7e43377185871ed09c1cef090552fbed3 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 11 Dec 2025 17:41:03 +0100 Subject: [PATCH 1/3] fix: add support for new chain/token --- .../src/common/hooks/useCowShedHooks.ts | 2 +- .../useRecoverFundsFromProxy.ts | 2 +- .../useSetupTradeStateFromUrl.ts | 4 +- .../hooks/useNavigateOnCurrencySelection.ts | 9 +- .../state/slippageValueAndTypeAtom.ts | 2 +- libs/assets/src/images/logo-avalanche.svg | 4 + libs/assets/src/images/logo-bnb.svg | 4 + libs/assets/src/images/logo-linea.svg | 4 + libs/assets/src/images/logo-plasma.svg | 4 + libs/assets/src/index.ts | 12 + libs/common-const/src/chainInfo.ts | 362 +++++++++++++---- libs/common-const/src/common.ts | 55 ++- .../src/nativeAndWrappedTokens.ts | 289 +++++++++----- libs/common-const/src/networks.ts | 72 +++- libs/common-const/src/tokens.ts | 370 +++++++++++++----- libs/common-const/src/types.ts | 19 +- libs/common-utils/src/explorer.ts | 6 + .../state/tokenLists/tokenListsStateAtom.ts | 15 +- .../src/state/tokens/favoriteTokensAtom.ts | 7 +- package.json | 5 +- tsconfig.base.json | 1 + yarn.lock | 187 +++++---- 22 files changed, 1040 insertions(+), 395 deletions(-) create mode 100644 libs/assets/src/images/logo-avalanche.svg create mode 100644 libs/assets/src/images/logo-bnb.svg create mode 100644 libs/assets/src/images/logo-linea.svg create mode 100644 libs/assets/src/images/logo-plasma.svg diff --git a/apps/cowswap-frontend/src/common/hooks/useCowShedHooks.ts b/apps/cowswap-frontend/src/common/hooks/useCowShedHooks.ts index 056d84c0b..02caa2ffe 100644 --- a/apps/cowswap-frontend/src/common/hooks/useCowShedHooks.ts +++ b/apps/cowswap-frontend/src/common/hooks/useCowShedHooks.ts @@ -1,4 +1,4 @@ -import { CowShedHooks } from '@cowprotocol/cow-sdk' +import { CowShedHooks } from '@cowprotocol/sdk-cow-shed' import { useWalletInfo } from '@cowprotocol/wallet' import useSWR from 'swr' diff --git a/apps/cowswap-frontend/src/modules/hooksStore/containers/RecoverFundsFromProxy/useRecoverFundsFromProxy.ts b/apps/cowswap-frontend/src/modules/hooksStore/containers/RecoverFundsFromProxy/useRecoverFundsFromProxy.ts index a5610d5ef..c66360cf5 100644 --- a/apps/cowswap-frontend/src/modules/hooksStore/containers/RecoverFundsFromProxy/useRecoverFundsFromProxy.ts +++ b/apps/cowswap-frontend/src/modules/hooksStore/containers/RecoverFundsFromProxy/useRecoverFundsFromProxy.ts @@ -2,7 +2,7 @@ import { useCallback, useMemo, useState } from 'react' import { CowShedContract, CowShedContractAbi } from '@cowprotocol/abis' import { SigningScheme } from '@cowprotocol/contracts' -import { COW_SHED_FACTORY, ICoWShedCall } from '@cowprotocol/cow-sdk' +import { COW_SHED_FACTORY, ICoWShedCall } from '@cowprotocol/sdk-cow-shed' import { useWalletInfo } from '@cowprotocol/wallet' import { useWalletProvider } from '@cowprotocol/wallet-provider' import { defaultAbiCoder } from '@ethersproject/abi' diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeStateFromUrl.ts b/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeStateFromUrl.ts index a98a909ed..4683ded21 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeStateFromUrl.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeStateFromUrl.ts @@ -1,5 +1,5 @@ import { useSetAtom } from 'jotai' -import { useMemo, useRef } from 'react' +import { useEffect, useRef } from 'react' import { useLocation, useParams } from 'react-router-dom' @@ -28,7 +28,7 @@ export function useSetupTradeStateFromUrl(): null { * In order to update tradeStateFromUrlAtom faster we use useMemo() here. * We need this, because useSetupTradeState() depends on the atom value and needs it to be udpated ASAP. */ - useMemo(() => { + useEffect(() => { const searchParams = new URLSearchParams(location.search) const recipient = searchParams.get('recipient') const recipientAddress = searchParams.get('recipientAddress') diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useNavigateOnCurrencySelection.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useNavigateOnCurrencySelection.ts index 54d8edf29..240a0f84e 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/useNavigateOnCurrencySelection.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/useNavigateOnCurrencySelection.ts @@ -52,13 +52,16 @@ export function useNavigateOnCurrencySelection(): CurrencySelectionCallback { const { inputCurrencyId, outputCurrencyId } = state const tokenSymbolOrAddress = resolveCurrencyAddressOrSymbol(currency) + const currentChainId = state.chainId || chainId + const targetChainId = currency?.chainId || currentChainId + const isDifferentChain = currentChainId && targetChainId && currentChainId !== targetChainId - const targetInputCurrencyId = field === Field.INPUT ? tokenSymbolOrAddress : inputCurrencyId - const targetOutputCurrencyId = field === Field.INPUT ? outputCurrencyId : tokenSymbolOrAddress + const targetInputCurrencyId = field === Field.INPUT ? tokenSymbolOrAddress : isDifferentChain ? null : inputCurrencyId + const targetOutputCurrencyId = field === Field.INPUT ? isDifferentChain ? null : outputCurrencyId : tokenSymbolOrAddress const areCurrenciesTheSame = targetInputCurrencyId === targetOutputCurrencyId navigate( - chainId, + targetChainId, // Just invert tokens when user selected the same token areCurrenciesTheSame ? { inputCurrencyId: outputCurrencyId, outputCurrencyId: inputCurrencyId } diff --git a/apps/cowswap-frontend/src/modules/tradeSlippage/state/slippageValueAndTypeAtom.ts b/apps/cowswap-frontend/src/modules/tradeSlippage/state/slippageValueAndTypeAtom.ts index c0dd34c99..410986582 100644 --- a/apps/cowswap-frontend/src/modules/tradeSlippage/state/slippageValueAndTypeAtom.ts +++ b/apps/cowswap-frontend/src/modules/tradeSlippage/state/slippageValueAndTypeAtom.ts @@ -29,7 +29,7 @@ export const defaultSlippageAtom = atom((get) => { const { chainId } = get(walletInfoAtom) const isEoaEthFlow = get(isEoaEthFlowAtom) - return isEoaEthFlow ? MINIMUM_ETH_FLOW_SLIPPAGE_BPS[chainId] : DEFAULT_SLIPPAGE_BPS + return isEoaEthFlow ? (MINIMUM_ETH_FLOW_SLIPPAGE_BPS[chainId] ?? DEFAULT_SLIPPAGE_BPS) : DEFAULT_SLIPPAGE_BPS }) const currentSlippageAtom = atom((get) => { diff --git a/libs/assets/src/images/logo-avalanche.svg b/libs/assets/src/images/logo-avalanche.svg new file mode 100644 index 000000000..19ac0d3d3 --- /dev/null +++ b/libs/assets/src/images/logo-avalanche.svg @@ -0,0 +1,4 @@ + + + + diff --git a/libs/assets/src/images/logo-bnb.svg b/libs/assets/src/images/logo-bnb.svg new file mode 100644 index 000000000..b24bbd2bd --- /dev/null +++ b/libs/assets/src/images/logo-bnb.svg @@ -0,0 +1,4 @@ + + + + diff --git a/libs/assets/src/images/logo-linea.svg b/libs/assets/src/images/logo-linea.svg new file mode 100644 index 000000000..b24bbd2bd --- /dev/null +++ b/libs/assets/src/images/logo-linea.svg @@ -0,0 +1,4 @@ + + + + diff --git a/libs/assets/src/images/logo-plasma.svg b/libs/assets/src/images/logo-plasma.svg new file mode 100644 index 000000000..b24bbd2bd --- /dev/null +++ b/libs/assets/src/images/logo-plasma.svg @@ -0,0 +1,4 @@ + + + + diff --git a/libs/assets/src/index.ts b/libs/assets/src/index.ts index e69de29bb..2c76caa92 100644 --- a/libs/assets/src/index.ts +++ b/libs/assets/src/index.ts @@ -0,0 +1,12 @@ +export { default as ArbitrumLogo } from './cow-swap/network-arbitrum-one-logo-blue.svg' +export { default as BaseLogo } from './cow-swap/network-base-logo.svg' +export { default as GnosisLogo } from './cow-swap/network-gnosis-chain-logo.svg' +export { default as MainnetLogo } from './cow-swap/network-mainnet-logo.svg' +export { default as SepoliaLogo } from './cow-swap/network-sepolia-logo.svg' +export { default as PolygonLogo } from './images/logo-polygon.svg' +export { default as LensLogo } from './images/icon-cow-lens.svg' +export { default as AvalancheLogo } from './images/logo-avalanche.svg' +export { default as LineaLogo } from './images/logo-linea.svg' +export { default as BnbLogo } from './images/logo-bnb.svg' +export { default as PlasmaLogo } from './images/logo-plasma.svg' + diff --git a/libs/common-const/src/chainInfo.ts b/libs/common-const/src/chainInfo.ts index 5edd3d0ed..508b40c0a 100644 --- a/libs/common-const/src/chainInfo.ts +++ b/libs/common-const/src/chainInfo.ts @@ -1,12 +1,32 @@ -import ArbitrumOneLogoLight from '@cowprotocol/assets/cow-swap/network-arbitrum-one-logo-blue.svg' -import ArbitrumOneLogoDark from '@cowprotocol/assets/cow-swap/network-arbitrum-one-logo-white.svg' -import BaseLogo from '@cowprotocol/assets/cow-swap/network-base-logo.svg' -import GnosisChainLogo from '@cowprotocol/assets/cow-swap/network-gnosis-chain-logo.svg' -import EthereumLogo from '@cowprotocol/assets/cow-swap/network-mainnet-logo.svg' -import SepoliaLogo from '@cowprotocol/assets/cow-swap/network-sepolia-logo.svg' -import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { + arbitrumOne, + avalanche, + base, + bnb, + ChainInfo, + gnosisChain, + lens, + linea, + mainnet, + plasma, + polygon, + sepolia, + SupportedChainId, +} from '@cowprotocol/cow-sdk' +import { + ArbitrumLogo, + AvalancheLogo, + BaseLogo, + BnbLogo, + GnosisLogo, + LensLogo, + LineaLogo, + MainnetLogo, + PlasmaLogo, + PolygonLogo, + SepoliaLogo, +} from '../../assets/src/index' -import { COW_PROTOCOL_LINK } from './common' import { NATIVE_CURRENCIES } from './nativeAndWrappedTokens' import { TokenWithLogo } from './types' @@ -19,6 +39,7 @@ export interface BaseChainInfo { readonly name: string readonly addressPrefix: string readonly label: string + readonly eip155Label: string readonly urlAlias: string readonly helpCenterUrl?: string readonly explorerTitle: string @@ -28,79 +49,284 @@ export interface BaseChainInfo { export type ChainInfoMap = Record -export const CHAIN_INFO: ChainInfoMap = { - [SupportedChainId.MAINNET]: { - docs: 'https://docs.cow.fi', - explorer: 'https://etherscan.io', - infoLink: COW_PROTOCOL_LINK, - label: 'Ethereum', - name: 'mainnet', - addressPrefix: 'eth', - explorerTitle: 'Etherscan', +// Hardcoded chain IDs to avoid SDK import issues in browser bundle +const CHAIN_IDS = { + MAINNET: 1, + BNB: 56, + BASE: 8453, + ARBITRUM_ONE: 42161, + POLYGON: 137, + AVALANCHE: 43114, + GNOSIS_CHAIN: 100, + LENS: 232, + LINEA: 59144, + PLASMA: 9745, + SEPOLIA: 11155111, +} + +function mapChainInfoToBaseChainInfo( + chainInfo: ChainInfo | undefined, + fallbackInfo?: Partial +): Pick< + BaseChainInfo, + | 'docs' + | 'bridge' + | 'explorer' + | 'infoLink' + | 'logo' + | 'addressPrefix' + | 'label' + | 'explorerTitle' + | 'color' + | 'eip155Label' +> { + if (!chainInfo) { + if (fallbackInfo && fallbackInfo.docs && fallbackInfo.explorer && fallbackInfo.logo && fallbackInfo.label && fallbackInfo.color) { + return { + docs: fallbackInfo.docs, + bridge: fallbackInfo.bridge, + explorer: fallbackInfo.explorer, + infoLink: fallbackInfo.infoLink || '', + logo: fallbackInfo.logo, + addressPrefix: fallbackInfo.addressPrefix || '', + label: fallbackInfo.label, + explorerTitle: fallbackInfo.explorerTitle || 'Explorer', + color: fallbackInfo.color, + eip155Label: fallbackInfo.eip155Label || '', + } + } + // Minimal fallback if SDK data is missing and no manual fallback provided + // This prevents crash but data will be incomplete + return { + docs: '', + bridge: undefined, + explorer: '', + infoLink: '', + logo: { light: '', dark: '' }, + addressPrefix: '', + label: 'Unknown Chain', + explorerTitle: '', + color: '#000000', + eip155Label: '', + } + } + + return { + docs: chainInfo.docs.url, + bridge: chainInfo.bridges?.[0]?.url, + explorer: chainInfo.blockExplorer.url ?? '', + infoLink: chainInfo.website.url, + logo: chainInfo.logo, + addressPrefix: chainInfo.addressPrefix, + label: chainInfo.label, + explorerTitle: chainInfo.blockExplorer.name, + color: chainInfo.color, + eip155Label: chainInfo.eip155Label, + } +} + +// Fallback data for when SDK exports are undefined +const FALLBACK_DATA: Record> = { + [CHAIN_IDS.MAINNET]: { + docs: 'https://docs.cow.fi', + explorer: 'https://etherscan.io', + label: 'Ethereum', + color: '#29B6AF', + logo: { light: MainnetLogo, dark: MainnetLogo } + }, + [CHAIN_IDS.GNOSIS_CHAIN]: { + docs: 'https://docs.gnosischain.com', + explorer: 'https://gnosisscan.io', + label: 'Gnosis Chain', + color: '#04795B', + logo: { light: GnosisLogo, dark: GnosisLogo } + }, + [CHAIN_IDS.SEPOLIA]: { + docs: 'https://docs.cow.fi', + explorer: 'https://sepolia.etherscan.io', + label: 'Sepolia', + color: '#48A3FF', + logo: { light: SepoliaLogo, dark: SepoliaLogo } + }, + [CHAIN_IDS.ARBITRUM_ONE]: { + docs: 'https://docs.arbitrum.io', + explorer: 'https://arbiscan.io', + label: 'Arbitrum One', + color: '#28A0F0', + logo: { light: ArbitrumLogo, dark: ArbitrumLogo } + }, + [CHAIN_IDS.BASE]: { + docs: 'https://docs.base.org', + explorer: 'https://basescan.org', + label: 'Base', + color: '#0052FF', + logo: { light: BaseLogo, dark: BaseLogo } + }, + [CHAIN_IDS.BNB]: { + docs: 'https://docs.bnbchain.org', + explorer: 'https://bscscan.com', + label: 'BNB Chain', + color: '#F0B90B', + logo: { light: BnbLogo, dark: BnbLogo } + }, + [CHAIN_IDS.POLYGON]: { + docs: 'https://docs.polygon.technology', + explorer: 'https://polygonscan.com', + label: 'Polygon', + color: '#8247E5', + logo: { light: PolygonLogo, dark: PolygonLogo } + }, + [CHAIN_IDS.AVALANCHE]: { + docs: 'https://docs.avax.network', + explorer: 'https://snowtrace.io', + label: 'Avalanche', + color: '#E84142', + logo: { light: AvalancheLogo, dark: AvalancheLogo } + }, + [CHAIN_IDS.LENS]: { + docs: 'https://docs.lens.xyz', + explorer: 'https://momoka.lens.xyz', + label: 'Lens', + color: '#00501E', + logo: { light: LensLogo, dark: LensLogo } + }, + [CHAIN_IDS.LINEA]: { + docs: 'https://docs.linea.build', + explorer: 'https://lineascan.build', + label: 'Linea', + color: '#000000', + logo: { light: LineaLogo, dark: LineaLogo } + }, + [CHAIN_IDS.PLASMA]: { + docs: 'https://docs.plasma.to', + explorer: 'https://explorer.plasma.to', + label: 'Plasma', + color: '#000000', + logo: { light: PlasmaLogo, dark: PlasmaLogo } + } +} + +/** + * Map with chain information for supported networks. + * Ordered by relevance, first is most relevant. + * Keep in mind when iterating over this map that the order of keys is guaranteed to be numerically sorted. + * So this order is mostly for reference and not for iteration. + */ +export const CHAIN_INFO = { + [CHAIN_IDS.MAINNET]: { + ...mapChainInfoToBaseChainInfo(mainnet, FALLBACK_DATA[CHAIN_IDS.MAINNET as SupportedChainId]), + name: 'ethereum', urlAlias: '', - logo: { light: EthereumLogo, dark: EthereumLogo }, - color: '#62688F', - nativeCurrency: NATIVE_CURRENCIES[SupportedChainId.MAINNET], + nativeCurrency: NATIVE_CURRENCIES[CHAIN_IDS.MAINNET as SupportedChainId], }, - [SupportedChainId.ARBITRUM_ONE]: { - docs: 'https://docs.arbitrum.io', - bridge: 'https://bridge.arbitrum.io', - explorer: 'https://arbiscan.io', - infoLink: 'https://arbitrum.io', - label: 'Arbitrum One', - addressPrefix: 'arb1', - name: 'arbitrum_one', - explorerTitle: 'Arbiscan', - urlAlias: 'arb1', - logo: { light: ArbitrumOneLogoLight, dark: ArbitrumOneLogoDark }, - color: '#1B4ADD', - nativeCurrency: NATIVE_CURRENCIES[SupportedChainId.ARBITRUM_ONE], + [CHAIN_IDS.BNB]: { + ...mapChainInfoToBaseChainInfo(bnb, FALLBACK_DATA[CHAIN_IDS.BNB as SupportedChainId]), + name: 'bnb', + urlAlias: 'bnb', + nativeCurrency: NATIVE_CURRENCIES[CHAIN_IDS.BNB as SupportedChainId], }, - [SupportedChainId.BASE]: { - docs: 'https://docs.base.org/', - bridge: 'https://bridge.base.org/deposit', - explorer: 'https://basescan.org', - infoLink: 'https://www.base.org/', - label: 'Base', - addressPrefix: 'base', + [CHAIN_IDS.BASE]: { + ...mapChainInfoToBaseChainInfo(base, FALLBACK_DATA[CHAIN_IDS.BASE as SupportedChainId]), name: 'base', - explorerTitle: 'Basescan', urlAlias: 'base', - logo: { light: BaseLogo, dark: BaseLogo }, - color: '#0052FF', - nativeCurrency: NATIVE_CURRENCIES[SupportedChainId.BASE], + nativeCurrency: NATIVE_CURRENCIES[CHAIN_IDS.BASE as SupportedChainId], }, - [SupportedChainId.GNOSIS_CHAIN]: { - docs: 'https://docs.gnosischain.com', - bridge: 'https://bridge.gnosischain.com/', - explorer: 'https://gnosisscan.io', - infoLink: 'https://www.gnosischain.com', - label: 'Gnosis Chain', + [CHAIN_IDS.ARBITRUM_ONE]: { + ...mapChainInfoToBaseChainInfo(arbitrumOne, FALLBACK_DATA[CHAIN_IDS.ARBITRUM_ONE as SupportedChainId]), + name: 'arbitrum_one', + urlAlias: 'arb1', + nativeCurrency: NATIVE_CURRENCIES[CHAIN_IDS.ARBITRUM_ONE as SupportedChainId], + }, + [CHAIN_IDS.POLYGON]: { + ...mapChainInfoToBaseChainInfo(polygon, FALLBACK_DATA[CHAIN_IDS.POLYGON as SupportedChainId]), + name: 'polygon', + urlAlias: 'pol', + nativeCurrency: NATIVE_CURRENCIES[CHAIN_IDS.POLYGON as SupportedChainId], + }, + [CHAIN_IDS.AVALANCHE]: { + ...mapChainInfoToBaseChainInfo(avalanche, FALLBACK_DATA[CHAIN_IDS.AVALANCHE as SupportedChainId]), + name: 'avalanche', + urlAlias: 'avax', + nativeCurrency: NATIVE_CURRENCIES[CHAIN_IDS.AVALANCHE as SupportedChainId], + }, + [CHAIN_IDS.GNOSIS_CHAIN]: { + ...mapChainInfoToBaseChainInfo(gnosisChain, FALLBACK_DATA[CHAIN_IDS.GNOSIS_CHAIN as SupportedChainId]), name: 'gnosis_chain', - addressPrefix: 'gno', - explorerTitle: 'Gnosisscan', urlAlias: 'gc', - logo: { light: GnosisChainLogo, dark: GnosisChainLogo }, - color: '#07795B', - nativeCurrency: NATIVE_CURRENCIES[SupportedChainId.GNOSIS_CHAIN], + nativeCurrency: NATIVE_CURRENCIES[CHAIN_IDS.GNOSIS_CHAIN as SupportedChainId], + }, + [CHAIN_IDS.LENS]: { + ...mapChainInfoToBaseChainInfo(lens, FALLBACK_DATA[CHAIN_IDS.LENS as SupportedChainId]), + name: 'lens', + urlAlias: 'lens', + nativeCurrency: NATIVE_CURRENCIES[CHAIN_IDS.LENS as SupportedChainId], }, - [SupportedChainId.SEPOLIA]: { - docs: 'https://docs.cow.fi', - explorer: 'https://sepolia.etherscan.io', - infoLink: COW_PROTOCOL_LINK, - label: 'Sepolia', + [CHAIN_IDS.LINEA]: { + ...mapChainInfoToBaseChainInfo(linea, FALLBACK_DATA[CHAIN_IDS.LINEA as SupportedChainId]), + name: 'linea', + urlAlias: 'linea', + nativeCurrency: NATIVE_CURRENCIES[CHAIN_IDS.LINEA as SupportedChainId], + }, + [CHAIN_IDS.PLASMA]: { + ...mapChainInfoToBaseChainInfo(plasma, FALLBACK_DATA[CHAIN_IDS.PLASMA as SupportedChainId]), + name: 'plasma', + urlAlias: 'plasma', + nativeCurrency: NATIVE_CURRENCIES[CHAIN_IDS.PLASMA as SupportedChainId], + }, + [CHAIN_IDS.SEPOLIA]: { + ...mapChainInfoToBaseChainInfo(sepolia, FALLBACK_DATA[CHAIN_IDS.SEPOLIA as SupportedChainId]), name: 'sepolia', - addressPrefix: 'sep', - explorerTitle: 'Etherscan', urlAlias: 'sepolia', - logo: { light: SepoliaLogo, dark: SepoliaLogo }, - color: '#C12FF2', - nativeCurrency: NATIVE_CURRENCIES[SupportedChainId.SEPOLIA], + nativeCurrency: NATIVE_CURRENCIES[CHAIN_IDS.SEPOLIA as SupportedChainId], }, -} +} as ChainInfoMap + +/** + * Sorted array of chain IDs in order of relevance. + */ +export const SORTED_CHAIN_IDS: SupportedChainId[] = [ + CHAIN_IDS.MAINNET, + CHAIN_IDS.BNB, + CHAIN_IDS.BASE, + CHAIN_IDS.ARBITRUM_ONE, + CHAIN_IDS.POLYGON, + CHAIN_IDS.AVALANCHE, + CHAIN_IDS.LINEA, + CHAIN_IDS.PLASMA, + CHAIN_IDS.GNOSIS_CHAIN, + CHAIN_IDS.LENS, + CHAIN_IDS.SEPOLIA, +] as SupportedChainId[] -export const CHAIN_INFO_ARRAY: BaseChainInfo[] = Object.values(CHAIN_INFO) +export const CHAIN_INFO_ARRAY: BaseChainInfo[] = SORTED_CHAIN_IDS.map((id) => CHAIN_INFO[id]) export function getChainInfo(chainId: SupportedChainId): BaseChainInfo { - return CHAIN_INFO[chainId] + const info = CHAIN_INFO[chainId] + if (!info) { + console.error(`Chain info not found for chain ${chainId}. Available chains:`, Object.keys(CHAIN_INFO)) + // Return a fallback to prevent crash + return { + docs: '', + bridge: undefined, + explorer: '', + infoLink: '', + logo: { light: '', dark: '' }, + name: 'unknown', + addressPrefix: '', + label: `Unknown Chain (${chainId})`, + eip155Label: '', + urlAlias: '', + explorerTitle: '', + color: '#000000', + nativeCurrency: new TokenWithLogo( + undefined, + typeof chainId === 'number' ? chainId : 0, + '0x0000000000000000000000000000000000000000', + 18, + '???', + 'Unknown' + ) + } + } + return info } diff --git a/libs/common-const/src/common.ts b/libs/common-const/src/common.ts index a8156574e..29fd4a28d 100644 --- a/libs/common-const/src/common.ts +++ b/libs/common-const/src/common.ts @@ -47,8 +47,8 @@ const NEW_COWSWAP_ETHFLOW_CONTRACT_ADDRESS: Record = { } const OLD_COWSWAP_ETHFLOW_CONTRACT_ADDRESS: Record> = { - prod: mapSupportedNetworks((chain) => EthFlowProd[chain].address), - barn: mapSupportedNetworks((chain) => EthFlowBarn[chain].address), + prod: mapSupportedNetworks((chain) => (EthFlowProd as any)[chain]?.address ?? ''), + barn: mapSupportedNetworks((chain) => (EthFlowBarn as any)[chain]?.address ?? ''), } export function getEthFlowContractAddresses( @@ -75,22 +75,27 @@ export function getEthFlowContractAddresses( } export const V_COW_CONTRACT_ADDRESS: Record = { + ...mapSupportedNetworks(null), [SupportedChainId.MAINNET]: '0xd057b63f5e69cf1b929b356b579cba08d7688048', [SupportedChainId.GNOSIS_CHAIN]: '0xc20C9C13E853fc64d054b73fF21d3636B2d97eaB', - [SupportedChainId.ARBITRUM_ONE]: null, // doesn't exist! - [SupportedChainId.BASE]: null, // doesn't exist! [SupportedChainId.SEPOLIA]: '0x21d06a222bbb94ec1406a0a8ba86b4d761bc9864', -} +} as Record -export const COW_CONTRACT_ADDRESS: Record = { +export const COW_CONTRACT_ADDRESS: Record = { [SupportedChainId.MAINNET]: '0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB', [SupportedChainId.GNOSIS_CHAIN]: '0x177127622c4A00F3d409B75571e12cB3c8973d3c', [SupportedChainId.ARBITRUM_ONE]: '0xcb8b5cd20bdcaea9a010ac1f8d835824f5c87a04', [SupportedChainId.BASE]: '0xc694a91e6b071bF030A18BD3053A7fE09B6DaE69', [SupportedChainId.SEPOLIA]: '0x0625aFB445C3B6B7B929342a04A22599fd5dBB59', -} - -export const CHAM_CONTRACT_ADDRESS: Record = { + [SupportedChainId.POLYGON]: '0x2f4efd3aa42e15a1ec6114547151b63ee5d39958', + [SupportedChainId.AVALANCHE]: null, + [SupportedChainId.LENS]: null, + [SupportedChainId.BNB]: '0x5bfdaa3f7c28b9994b56135403bf1acea02595b0', + [SupportedChainId.LINEA]: '0x5bfdaa3f7c28b9994b56135403bf1acea02595b0', + [SupportedChainId.PLASMA]: null, +} as Record + +const CHAM_ADDRESS_OVERRIDES: Partial> = { [SupportedChainId.MAINNET]: '0x0000000000000000000000000000000000000001', // Update with real CHAM address [SupportedChainId.GNOSIS_CHAIN]: '0x0000000000000000000000000000000000000002', // Update with real CHAM address [SupportedChainId.ARBITRUM_ONE]: '0x0000000000000000000000000000000000000003', // Update with real CHAM address @@ -98,6 +103,10 @@ export const CHAM_CONTRACT_ADDRESS: Record = { [SupportedChainId.SEPOLIA]: '0x0000000000000000000000000000000000000005', // Update with real CHAM address } +export const CHAM_CONTRACT_ADDRESS: Record = mapSupportedNetworks( + (chainId) => CHAM_ADDRESS_OVERRIDES[chainId] ?? '0x0000000000000000000000000000000000000000', +) + export const INPUT_OUTPUT_EXPLANATION = 'Only executed swaps incur fees.' export const PENDING_ORDERS_BUFFER = ms`60s` // 60s export const CANCELLED_ORDERS_PENDING_TIME = ms`5min` // 5min @@ -107,16 +116,16 @@ export const MINIMUM_ORDER_VALID_TO_TIME_SECONDS = 120 // Minimum deadline for EthFlow orders. Like the default deadline, anything smaller will be replaced by this export const MINIMUM_ETH_FLOW_DEADLINE_SECONDS = 600 // 10 minutes in SECONDS -export const MINIMUM_ETH_FLOW_SLIPPAGE_BPS: Record = { +const MIN_ETH_FLOW_SLIPPAGE_BPS_OVERRIDES: Partial> = { [SupportedChainId.MAINNET]: 200, // 2% - [SupportedChainId.GNOSIS_CHAIN]: DEFAULT_SLIPPAGE_BPS, - [SupportedChainId.ARBITRUM_ONE]: DEFAULT_SLIPPAGE_BPS, - [SupportedChainId.BASE]: DEFAULT_SLIPPAGE_BPS, - [SupportedChainId.SEPOLIA]: DEFAULT_SLIPPAGE_BPS, } +export const MINIMUM_ETH_FLOW_SLIPPAGE_BPS: Record = mapSupportedNetworks( + (chainId) => MIN_ETH_FLOW_SLIPPAGE_BPS_OVERRIDES[chainId] ?? DEFAULT_SLIPPAGE_BPS, +) + export const MINIMUM_ETH_FLOW_SLIPPAGE: Record = mapSupportedNetworks( - (chainId) => new Percent(MINIMUM_ETH_FLOW_SLIPPAGE_BPS[chainId], 10_000), + (chainId) => new Percent(MINIMUM_ETH_FLOW_SLIPPAGE_BPS[chainId] ?? DEFAULT_SLIPPAGE_BPS, 10_000), ) export const HIGH_ETH_FLOW_SLIPPAGE_BPS = 1_000 // 10% @@ -151,14 +160,26 @@ export const GAS_FEE_ENDPOINTS: Record = { [SupportedChainId.ARBITRUM_ONE]: 'https://arbitrum.blockscout.com/api/v1/gas-price-oracle', [SupportedChainId.BASE]: 'https://base.blockscout.com/api/v1/gas-price-oracle', [SupportedChainId.SEPOLIA]: '', -} + [SupportedChainId.POLYGON]: 'https://polygon.blockscout.com/api/v1/gas-price-oracle', + [SupportedChainId.AVALANCHE]: 'https://api.blocknative.com/gasprices/blockprices?chainid=43114', + [SupportedChainId.LENS]: 'https://api.blocknative.com/gasprices/blockprices?chainid=232', + [SupportedChainId.BNB]: 'https://api.blocknative.com/gasprices/blockprices?chainid=56', + [SupportedChainId.LINEA]: 'https://api.blocknative.com/gasprices/blockprices?chainid=59144', + [SupportedChainId.PLASMA]: '', // TODO: currently (2025/10/20) unsupported by Blocknative nor blockscont +} as Record export const GAS_API_KEYS: Record = { [SupportedChainId.MAINNET]: process.env.REACT_APP_BLOCKNATIVE_API_KEY || null, [SupportedChainId.GNOSIS_CHAIN]: null, [SupportedChainId.ARBITRUM_ONE]: null, [SupportedChainId.BASE]: null, [SupportedChainId.SEPOLIA]: null, -} + [SupportedChainId.POLYGON]: null, + [SupportedChainId.AVALANCHE]: process.env.REACT_APP_BLOCKNATIVE_API_KEY || null, + [SupportedChainId.LENS]: process.env.REACT_APP_BLOCKNATIVE_API_KEY || null, + [SupportedChainId.BNB]: process.env.REACT_APP_BLOCKNATIVE_API_KEY || null, + [SupportedChainId.LINEA]: process.env.REACT_APP_BLOCKNATIVE_API_KEY || null, + [SupportedChainId.PLASMA]: null, +} as Record export const UNSUPPORTED_TOKENS_FAQ_URL = 'https://docs.cow.fi/cow-protocol/reference/core/tokens' diff --git a/libs/common-const/src/nativeAndWrappedTokens.ts b/libs/common-const/src/nativeAndWrappedTokens.ts index d372938b9..3af157314 100644 --- a/libs/common-const/src/nativeAndWrappedTokens.ts +++ b/libs/common-const/src/nativeAndWrappedTokens.ts @@ -1,100 +1,207 @@ -import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { + ALL_SUPPORTED_CHAINS_MAP, + mapSupportedNetworks, + SupportedChainId, + WRAPPED_NATIVE_CURRENCIES as WRAPPED_NATIVE_CURRENCIES_SDK, +} from '@cowprotocol/cow-sdk' -import { cowprotocolTokenLogoUrl } from './cowprotocolTokenLogoUrl' import { TokenWithLogo } from './types' export const NATIVE_CURRENCY_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' -const DEFAULT_NATIVE_DECIMALS = 18 -const WETH9_MAINNET_ADDRESS = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' -const ETH_LOGO_URL = cowprotocolTokenLogoUrl(WETH9_MAINNET_ADDRESS.toLowerCase(), SupportedChainId.MAINNET) - -export const WRAPPED_NATIVE_CURRENCIES: Record = { - [SupportedChainId.MAINNET]: new TokenWithLogo( - ETH_LOGO_URL, - SupportedChainId.MAINNET, - WETH9_MAINNET_ADDRESS, - DEFAULT_NATIVE_DECIMALS, - 'WETH', - 'Wrapped Ether', - ), - [SupportedChainId.GNOSIS_CHAIN]: new TokenWithLogo( - undefined, - SupportedChainId.GNOSIS_CHAIN, - '0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d', - DEFAULT_NATIVE_DECIMALS, - 'WXDAI', - 'Wrapped XDAI', - ), - [SupportedChainId.ARBITRUM_ONE]: new TokenWithLogo( - ETH_LOGO_URL, - SupportedChainId.ARBITRUM_ONE, - '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', - DEFAULT_NATIVE_DECIMALS, - 'WETH', - 'Wrapped Ether', - ), - [SupportedChainId.BASE]: new TokenWithLogo( - ETH_LOGO_URL, - SupportedChainId.BASE, - '0x4200000000000000000000000000000000000006', - DEFAULT_NATIVE_DECIMALS, - 'WETH', - 'Wrapped Ether', - ), - [SupportedChainId.SEPOLIA]: new TokenWithLogo( - ETH_LOGO_URL, - SupportedChainId.SEPOLIA, - '0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14', - DEFAULT_NATIVE_DECIMALS, - 'WETH', - 'Wrapped Ether', - ), +// Hardcoded chain IDs to avoid SDK import issues in browser bundle +const CHAIN_IDS = { + MAINNET: 1, + BNB: 56, + BASE: 8453, + ARBITRUM_ONE: 42161, + POLYGON: 137, + AVALANCHE: 43114, + GNOSIS_CHAIN: 100, + LENS: 232, + LINEA: 59144, + PLASMA: 9745, + SEPOLIA: 11155111, } -export const NATIVE_CURRENCIES: Record = { - [SupportedChainId.MAINNET]: new TokenWithLogo( - undefined, - SupportedChainId.MAINNET, - NATIVE_CURRENCY_ADDRESS, - DEFAULT_NATIVE_DECIMALS, - 'ETH', - 'Ether', - ), - [SupportedChainId.GNOSIS_CHAIN]: new TokenWithLogo( - undefined, - SupportedChainId.GNOSIS_CHAIN, - NATIVE_CURRENCY_ADDRESS, - DEFAULT_NATIVE_DECIMALS, - 'xDAI', - 'xDAI', - ), - [SupportedChainId.ARBITRUM_ONE]: new TokenWithLogo( - undefined, - SupportedChainId.ARBITRUM_ONE, - NATIVE_CURRENCY_ADDRESS, - DEFAULT_NATIVE_DECIMALS, - 'ETH', - 'Ether', - ), - [SupportedChainId.BASE]: new TokenWithLogo( - undefined, - SupportedChainId.BASE, - NATIVE_CURRENCY_ADDRESS, - DEFAULT_NATIVE_DECIMALS, - 'ETH', - 'Ether', - ), - [SupportedChainId.SEPOLIA]: new TokenWithLogo( - undefined, - SupportedChainId.SEPOLIA, - NATIVE_CURRENCY_ADDRESS, - DEFAULT_NATIVE_DECIMALS, - 'ETH', - 'Ether', - ), +export const WRAPPED_NATIVE_CURRENCIES: Record = mapSupportedNetworks( + getTokenWithLogoFromWrappedNativeCurrency, +) + +export const NATIVE_CURRENCIES: Record = mapSupportedNetworks( + getTokenWithLogoFromNativeCurrency, +) + +export const WETH_MAINNET = WRAPPED_NATIVE_CURRENCIES[CHAIN_IDS.MAINNET as SupportedChainId] +export const WXDAI = WRAPPED_NATIVE_CURRENCIES[CHAIN_IDS.GNOSIS_CHAIN as SupportedChainId] +export const WETH_SEPOLIA = WRAPPED_NATIVE_CURRENCIES[CHAIN_IDS.SEPOLIA as SupportedChainId] + +function getTokenWithLogoFromWrappedNativeCurrency(chainId: SupportedChainId): TokenWithLogo { + // Try accessing by number first, then by string (SDK keys are strings at runtime) + let wrapped + if (WRAPPED_NATIVE_CURRENCIES_SDK) { + wrapped = WRAPPED_NATIVE_CURRENCIES_SDK[chainId] || (WRAPPED_NATIVE_CURRENCIES_SDK as any)[String(chainId)] + } + + // Handle case where SDK bundles it as just an address string instead of an object + // Or if wrapped is not found but we want to try fallback logic (though if SDK is missing it's hard) + // If wrapped is undefined, we can try to manual fallback if we know the address, but addresses change. + // For now, let's assume if it's missing from SDK map it's an error unless we hardcode addresses. + + if (!wrapped) { + // Attempt manual fallback for known chains if SDK data is missing + const manualAddresses: Partial> = { + [CHAIN_IDS.MAINNET as SupportedChainId]: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + [CHAIN_IDS.GNOSIS_CHAIN as SupportedChainId]: '0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d', + [CHAIN_IDS.ARBITRUM_ONE as SupportedChainId]: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', + [CHAIN_IDS.BASE as SupportedChainId]: '0x4200000000000000000000000000000000000006', + [CHAIN_IDS.SEPOLIA as SupportedChainId]: '0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14', + [CHAIN_IDS.POLYGON as SupportedChainId]: '0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270', + [CHAIN_IDS.AVALANCHE as SupportedChainId]: '0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7', + [CHAIN_IDS.BNB as SupportedChainId]: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c', + } + const address = manualAddresses[chainId] + if (address) { + wrapped = address // Treat as string case below + } else { + throw new Error(`Wrapped native currency not found for chain ${chainId}`) + } + } + + // Handle case where SDK bundles it as just an address string instead of an object + if (typeof wrapped === 'string') { + // If it's just a string (address), use default values for wrapped tokens + // Most wrapped tokens use 18 decimals + const address = wrapped + const decimals = 18 + + // Get symbol and name based on chain + let symbol = 'WETH' + let name = 'Wrapped Ether' + if (chainId === CHAIN_IDS.GNOSIS_CHAIN) { + symbol = 'WXDAI' + name = 'Wrapped XDAI' + } else if (chainId === CHAIN_IDS.POLYGON) { + symbol = 'WPOL' + name = 'Wrapped POL' + } else if (chainId === CHAIN_IDS.AVALANCHE) { + symbol = 'WAVAX' + name = 'Wrapped AVAX' + } else if (chainId === CHAIN_IDS.BNB) { + symbol = 'WBNB' + name = 'Wrapped BNB' + } else if (chainId === CHAIN_IDS.LENS) { + symbol = 'WGHO' + name = 'Wrapped GHO' + } else if (chainId === CHAIN_IDS.PLASMA) { + symbol = 'WXPL' + name = 'Wrapped XPL' + } else if (chainId === CHAIN_IDS.LINEA) { + symbol = 'WETH' + name = 'Wrapped Ether' + } else if (chainId === CHAIN_IDS.BASE) { + symbol = 'WETH' + name = 'Wrapped Ether' + } else if (chainId === CHAIN_IDS.ARBITRUM_ONE) { + symbol = 'WETH' + name = 'Wrapped Ether' + } + + return new TokenWithLogo(undefined, chainId, address, decimals, symbol, name) + } + + // Normal case: wrapped is an object + const decimalsValue = wrapped.decimals + if (decimalsValue === undefined || decimalsValue === null) { + // Fallback: most wrapped tokens use 18 decimals + const decimals = 18 + return new TokenWithLogo( + wrapped.logoUrl, + chainId, + wrapped.address, + decimals, + wrapped.symbol, + wrapped.name, + ) + } + + const decimals = Math.floor(Number(decimalsValue)) + if (isNaN(decimals) || decimals <= 0 || !Number.isInteger(decimals)) { + throw new Error(`Invalid decimals (${decimalsValue}) for wrapped native currency on chain ${chainId}`) + } + + return new TokenWithLogo( + wrapped.logoUrl, + chainId, + wrapped.address, + decimals, + wrapped.symbol, + wrapped.name, + ) } -export const WETH_MAINNET = WRAPPED_NATIVE_CURRENCIES[SupportedChainId.MAINNET] -export const WXDAI = WRAPPED_NATIVE_CURRENCIES[SupportedChainId.GNOSIS_CHAIN] -export const WETH_SEPOLIA = WRAPPED_NATIVE_CURRENCIES[SupportedChainId.SEPOLIA] +function getTokenWithLogoFromNativeCurrency(chainId: SupportedChainId): TokenWithLogo { + let chainInfo + if (ALL_SUPPORTED_CHAINS_MAP) { + chainInfo = ALL_SUPPORTED_CHAINS_MAP[chainId] || (ALL_SUPPORTED_CHAINS_MAP as any)[String(chainId)] + } + + // Fallback if SDK map is missing or incomplete + if (!chainInfo) { + const decimals = 18 + let symbol = 'ETH' + let name = 'Ether' + + if (chainId === CHAIN_IDS.GNOSIS_CHAIN) { + symbol = 'xDAI' + name = 'xDAI' + } else if (chainId === CHAIN_IDS.POLYGON) { + symbol = 'POL' + name = 'POL' + } else if (chainId === CHAIN_IDS.AVALANCHE) { + symbol = 'AVAX' + name = 'Avalanche' + } else if (chainId === CHAIN_IDS.BNB) { + symbol = 'BNB' + name = 'BNB' + } else if (chainId === CHAIN_IDS.LENS) { + symbol = 'GRASS' + name = 'GRASS' + } else if (chainId === CHAIN_IDS.PLASMA) { + symbol = 'XPL' + name = 'XPL' + } else if (chainId === CHAIN_IDS.LINEA) { + symbol = 'ETH' + name = 'Ether' + } + + return new TokenWithLogo( + undefined, + chainId, + NATIVE_CURRENCY_ADDRESS, + decimals, + symbol, + name, + ) + } + + const nativeCurrency = chainInfo.nativeCurrency + + if (!nativeCurrency) { + throw new Error(`Native currency not found for chain ${chainId}`) + } + + const decimals = Math.floor(Number(nativeCurrency.decimals)) + if (isNaN(decimals) || decimals <= 0 || !Number.isInteger(decimals)) { + throw new Error(`Invalid decimals (${nativeCurrency.decimals}) for native currency on chain ${chainId}`) + } + + return new TokenWithLogo( + undefined, + chainId, + nativeCurrency.address, + decimals, + nativeCurrency.symbol, + nativeCurrency.name, + ) +} diff --git a/libs/common-const/src/networks.ts b/libs/common-const/src/networks.ts index 70c86ba50..a05153d04 100644 --- a/libs/common-const/src/networks.ts +++ b/libs/common-const/src/networks.ts @@ -1,22 +1,50 @@ import { mapSupportedNetworks, SupportedChainId } from '@cowprotocol/cow-sdk' +import { JsonRpcProvider } from '@ethersproject/providers' const INFURA_KEY = process.env.REACT_APP_INFURA_KEY || '2af29cd5ac554ae3b8d991afe1ba4b7d' // Default rate-limited infura key (should be overridden, not reliable to use) -const RPC_URL_ENVS: Record = { - [SupportedChainId.MAINNET]: process.env.REACT_APP_NETWORK_URL_1 || undefined, - [SupportedChainId.GNOSIS_CHAIN]: process.env.REACT_APP_NETWORK_URL_100 || undefined, - [SupportedChainId.ARBITRUM_ONE]: process.env.REACT_APP_NETWORK_URL_42161 || undefined, - [SupportedChainId.BASE]: process.env.REACT_APP_NETWORK_URL_8453 || undefined, - [SupportedChainId.SEPOLIA]: process.env.REACT_APP_NETWORK_URL_11155111 || undefined, +// Hardcoded chain IDs to avoid SDK import issues in browser bundle +const CHAIN_IDS = { + MAINNET: 1, + BNB: 56, + BASE: 8453, + ARBITRUM_ONE: 42161, + POLYGON: 137, + AVALANCHE: 43114, + GNOSIS_CHAIN: 100, + LENS: 232, + LINEA: 59144, + PLASMA: 9745, + SEPOLIA: 11155111, } -const DEFAULT_RPC_URL: Record = { - [SupportedChainId.MAINNET]: { url: `https://mainnet.infura.io/v3/${INFURA_KEY}`, usesInfura: true }, - [SupportedChainId.GNOSIS_CHAIN]: { url: `https://rpc.gnosis.gateway.fm`, usesInfura: false }, - [SupportedChainId.ARBITRUM_ONE]: { url: `https://arbitrum-mainnet.infura.io/v3/${INFURA_KEY}`, usesInfura: true }, - [SupportedChainId.BASE]: { url: `https://base-mainnet.infura.io/v3/${INFURA_KEY}`, usesInfura: true }, - [SupportedChainId.SEPOLIA]: { url: `https://sepolia.infura.io/v3/${INFURA_KEY}`, usesInfura: true }, -} +const RPC_URL_ENVS = { + [CHAIN_IDS.MAINNET as SupportedChainId]: process.env.REACT_APP_NETWORK_URL_1 || undefined, + [CHAIN_IDS.GNOSIS_CHAIN as SupportedChainId]: process.env.REACT_APP_NETWORK_URL_100 || undefined, + [CHAIN_IDS.ARBITRUM_ONE as SupportedChainId]: process.env.REACT_APP_NETWORK_URL_42161 || undefined, + [CHAIN_IDS.BASE as SupportedChainId]: process.env.REACT_APP_NETWORK_URL_8453 || undefined, + [CHAIN_IDS.SEPOLIA as SupportedChainId]: process.env.REACT_APP_NETWORK_URL_11155111 || undefined, + [CHAIN_IDS.POLYGON as SupportedChainId]: process.env.REACT_APP_NETWORK_URL_137 || undefined, + [CHAIN_IDS.AVALANCHE as SupportedChainId]: process.env.REACT_APP_NETWORK_URL_43114 || undefined, + [CHAIN_IDS.LENS as SupportedChainId]: process.env.REACT_APP_NETWORK_URL_232 || undefined, + [CHAIN_IDS.BNB as SupportedChainId]: process.env.REACT_APP_NETWORK_URL_56 || undefined, + [CHAIN_IDS.LINEA as SupportedChainId]: process.env.REACT_APP_NETWORK_URL_59144 || undefined, + [CHAIN_IDS.PLASMA as SupportedChainId]: process.env.REACT_APP_NETWORK_URL_9745 || undefined, +} as Record + +const DEFAULT_RPC_URL = { + [CHAIN_IDS.MAINNET as SupportedChainId]: { url: `https://mainnet.infura.io/v3/${INFURA_KEY}`, usesInfura: true }, + [CHAIN_IDS.GNOSIS_CHAIN as SupportedChainId]: { url: `https://rpc.gnosis.gateway.fm`, usesInfura: false }, + [CHAIN_IDS.ARBITRUM_ONE as SupportedChainId]: { url: `https://arbitrum-mainnet.infura.io/v3/${INFURA_KEY}`, usesInfura: true }, + [CHAIN_IDS.BASE as SupportedChainId]: { url: `https://base-mainnet.infura.io/v3/${INFURA_KEY}`, usesInfura: true }, + [CHAIN_IDS.SEPOLIA as SupportedChainId]: { url: `https://sepolia.infura.io/v3/${INFURA_KEY}`, usesInfura: true }, + [CHAIN_IDS.POLYGON as SupportedChainId]: { url: `https://polygon-mainnet.infura.io/v3/${INFURA_KEY}`, usesInfura: true }, + [CHAIN_IDS.AVALANCHE as SupportedChainId]: { url: `https://avalanche-mainnet.infura.io/v3/${INFURA_KEY}`, usesInfura: true }, + [CHAIN_IDS.BNB as SupportedChainId]: { url: `https://bsc-dataseed.binance.org/`, usesInfura: false }, + [CHAIN_IDS.LENS as SupportedChainId]: { url: `https://rpc.lens.xyz`, usesInfura: false }, + [CHAIN_IDS.LINEA as SupportedChainId]: { url: `https://rpc.linea.build`, usesInfura: false }, + [CHAIN_IDS.PLASMA as SupportedChainId]: { url: `https://rpc.plasma.to`, usesInfura: false }, +} as Record /** * These are the network URLs used by the interface when there is not another available source of chain data @@ -38,3 +66,21 @@ function getRpcUrl(chainId: SupportedChainId): string { return defaultRpc.url } + +const rpcProviderCache: Record = {} + +export function getRpcProvider(chainId: SupportedChainId): JsonRpcProvider +export function getRpcProvider(chainId: number): JsonRpcProvider | null { + if (!rpcProviderCache[chainId]) { + const url = RPC_URLS[chainId as SupportedChainId] + if (!url) return null + + const provider = new JsonRpcProvider(url, chainId) + + rpcProviderCache[chainId] = provider + + return provider + } + + return rpcProviderCache[chainId] +} diff --git a/libs/common-const/src/tokens.ts b/libs/common-const/src/tokens.ts index fc241deb1..7d7d1c529 100644 --- a/libs/common-const/src/tokens.ts +++ b/libs/common-const/src/tokens.ts @@ -1,4 +1,4 @@ -import { SupportedChainId as ChainId, SupportedChainId } from '@cowprotocol/cow-sdk' +import { AdditionalTargetChainId, mapSupportedNetworks, SupportedChainId, SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' import { COW_CONTRACT_ADDRESS, V_COW_CONTRACT_ADDRESS } from './common' import { CHAM_CONTRACT_ADDRESS } from './common' @@ -348,6 +348,169 @@ export const EUSD_BASE = new TokenWithLogo( 'Electronic Dollar', ) +// Polygon + +export const USDC_POLYGON = new TokenWithLogo( + USDC_MAINNET.logoURI, + SupportedChainId.POLYGON, + // https://polygonscan.com/address/0x3c499c542cef5e3811e1192ce70d8cc03d5c3359 + '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359', + 6, + 'USDC', + 'USD Coin', +) +export const USDT_POLYGON = new TokenWithLogo( + USDT.logoURI, + SupportedChainId.POLYGON, + // https://polygonscan.com/address/0xc2132d05d31c914a87c6611c10748aeb04b58e8f + '0xc2132d05d31c914a87c6611c10748aeb04b58e8f', + 6, + 'USDT', + 'Tether USD', +) +export const DAI_POLYGON = new TokenWithLogo( + DAI.logoURI, + SupportedChainId.POLYGON, + // https://polygonscan.com/address/0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063 + '0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063', + 18, + 'DAI', + 'Dai', +) + +// Avalanche + +export const USDC_AVALANCHE = new TokenWithLogo( + USDC_MAINNET.logoURI, + SupportedChainId.AVALANCHE, + // https://snowscan.xyz/token/0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e + '0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e', + 6, + 'USDC', + 'USD Coin', +) + +export const USDT_AVALANCHE = new TokenWithLogo( + USDT.logoURI, + SupportedChainId.AVALANCHE, + // https://snowscan.xyz/token/0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7 + '0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7', + 6, + 'USDT', + 'Tether USD', +) + +// Lens + +export const USDC_LENS = new TokenWithLogo( + USDC_MAINNET.logoURI, + SupportedChainId.LENS, + // https://explorer.lens.xyz/address/0x88F08E304EC4f90D644Cec3Fb69b8aD414acf884 + '0x88F08E304EC4f90D644Cec3Fb69b8aD414acf884', + 6, + 'USDC', + 'USD Coin', +) + +// BNB + +export const USDC_BNB = new TokenWithLogo( + USDC_MAINNET.logoURI, + SupportedChainId.BNB, + // https://bscscan.com/address/0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d + '0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d', + 18, // BNB USDC has 18 decimals!!! + 'USDC', + 'USD Coin', +) + +export const USDT_BNB = new TokenWithLogo( + USDT.logoURI, + SupportedChainId.BNB, + // https://bscscan.com/address/0x55d398326f99059ff775485246999027b3197955 + '0x55d398326f99059ff775485246999027b3197955', + 18, // BNB USDT has 18 decimals!!! + 'USDT', + 'Tether USD', +) + +export const DAI_BNB = new TokenWithLogo( + DAI.logoURI, + SupportedChainId.BNB, + // https://bscscan.com/address/0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3 + '0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3', + 18, + 'DAI', + 'Dai Stablecoin', +) + +export const BUSD_BNB = new TokenWithLogo( + cowprotocolTokenLogoUrl('0xe9e7cea3dedca5984780bafc599bd69add087d56', SupportedChainId.BNB), + SupportedChainId.BNB, + // https://bscscan.com/address/0xe9e7cea3dedca5984780bafc599bd69add087d56 + '0xe9e7cea3dedca5984780bafc599bd69add087d56', + 18, + 'BUSD', + 'Binance-Peg BUSD Token', +) + +export const BTCB_BNB = new TokenWithLogo( + cowprotocolTokenLogoUrl('0x7130d2a12b9bcbfae4f2634d864a1ee1ce3ead9c', SupportedChainId.BNB), + SupportedChainId.BNB, + // https://bscscan.com/address/0x7130d2a12b9bcbfae4f2634d864a1ee1ce3ead9c + '0x7130d2a12b9bcbfae4f2634d864a1ee1ce3ead9c', + 18, + 'BTCB', + 'Binance-Peg BTCB Token', +) + +// Linea + +export const USDC_LINEA = new TokenWithLogo( + USDC_MAINNET.logoURI, + SupportedChainId.LINEA, + // https://lineascan.build/address/0x176211869cA2b568f2A7D4EE941E073a821EE1ff + '0x176211869cA2b568f2A7D4EE941E073a821EE1ff', + 6, + 'USDC', + 'USD Coin', +) + +export const USDT_LINEA = new TokenWithLogo( + USDT.logoURI, + SupportedChainId.LINEA, + // https://lineascan.build/address/0xA219439258ca9da29E9Cc4cE5596924745e12B93 + '0xa219439258ca9da29e9cc4ce5596924745e12b93', + 6, + 'USDT', + 'Tether USD', +) + +// Plasma + +// TODO: Verify and add more tokens for Plasma +export const USDT_PLASMA = new TokenWithLogo( + USDT.logoURI, + SupportedChainId.PLASMA, + // https://plasmascan.to/address/0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb + '0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb', + 6, + 'USDT0', + 'USDT0', +) + +// Optimism + +export const USDC_OPTIMISM = new TokenWithLogo( + USDC_MAINNET.logoURI, + AdditionalTargetChainId.OPTIMISM, + // https://optimistic.etherscan.io/address/0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85 + '0x0b2c639c533813f4aa9d7837caf62653d097ff85', + 6, + 'USDC', + 'USD Coin', +) + // Sepolia export const GNO_SEPOLIA = new TokenWithLogo( @@ -359,7 +522,6 @@ export const GNO_SEPOLIA = new TokenWithLogo( 'GNO (test)', ) -// Sepolia export const USDC_SEPOLIA = new TokenWithLogo( USDC_MAINNET.logoURI, SupportedChainId.SEPOLIA, @@ -377,12 +539,23 @@ export const USDT_SEPOLIA = new TokenWithLogo( 'Tether USD', ) -export const USDC: Record = { +export const USDC: Record = { [SupportedChainId.MAINNET]: USDC_MAINNET, [SupportedChainId.GNOSIS_CHAIN]: USDC_GNOSIS_CHAIN, [SupportedChainId.ARBITRUM_ONE]: USDC_ARBITRUM_ONE, [SupportedChainId.BASE]: USDC_BASE, [SupportedChainId.SEPOLIA]: USDC_SEPOLIA, + [SupportedChainId.POLYGON]: USDC_POLYGON, + [SupportedChainId.AVALANCHE]: USDC_AVALANCHE, + [AdditionalTargetChainId.OPTIMISM]: USDC_OPTIMISM, + [SupportedChainId.LENS]: USDC_LENS, + [SupportedChainId.BNB]: USDC_BNB, + [SupportedChainId.LINEA]: USDC_LINEA, + /** + * Important! There doesn't seem to be a USDC on Plasma yet, so we map USDT here for now + * This might break assumptions elsewhere in the code + */ + [SupportedChainId.PLASMA]: USDT_PLASMA, } export const TOKEN_SHORTHANDS: { [shorthand: string]: Record } = { @@ -392,6 +565,12 @@ export const TOKEN_SHORTHANDS: { [shorthand: string]: Record = { + ...mapSupportedNetworks(null), [SupportedChainId.MAINNET]: V_COW_TOKEN_MAINNET, [SupportedChainId.GNOSIS_CHAIN]: V_COW_TOKEN_XDAI, - [SupportedChainId.ARBITRUM_ONE]: null, - [SupportedChainId.BASE]: null, [SupportedChainId.SEPOLIA]: V_COW_TOKEN_SEPOLIA, } /** * Cow token */ -const COW_TOKEN_MAINNET = new TokenWithLogo( - undefined, - SupportedChainId.MAINNET, - COW_CONTRACT_ADDRESS[SupportedChainId.MAINNET], - 18, - 'COW', - 'CoW Protocol Token', -) +const COW_TOKEN_SYMBOL = 'COW' +const COW_TOKEN_NAME = 'CoW Protocol Token' +const COW_TOKEN_DECIMALS = 18 -const COW_TOKEN_XDAI = new TokenWithLogo( - COW_TOKEN_MAINNET.logoURI, - SupportedChainId.GNOSIS_CHAIN, - COW_CONTRACT_ADDRESS[SupportedChainId.GNOSIS_CHAIN], - 18, - 'COW', - 'CoW Protocol Token', +const DEFAULT_LOGO_URI = cowprotocolTokenLogoUrl( + COW_CONTRACT_ADDRESS[SupportedChainId.MAINNET]!.toLowerCase(), + SupportedChainId.MAINNET, ) -export const COW_TOKEN_ARBITRUM = new TokenWithLogo( - COW_TOKEN_MAINNET.logoURI, - SupportedChainId.ARBITRUM_ONE, - COW_CONTRACT_ADDRESS[SupportedChainId.ARBITRUM_ONE], - 18, - 'COW', - 'CoW Protocol Token', -) +function getCowTokenForChain(chain: SupportedChainId, logoURI: string = DEFAULT_LOGO_URI): TokenWithLogo | null { + const address = COW_CONTRACT_ADDRESS[chain] -export const COW_TOKEN_BASE = new TokenWithLogo( - COW_TOKEN_MAINNET.logoURI, - SupportedChainId.BASE, - COW_CONTRACT_ADDRESS[SupportedChainId.BASE], - 18, - 'COW', - 'CoW Protocol Token', -) + if (!address) return null -const COW_TOKEN_SEPOLIA = new TokenWithLogo( - COW_TOKEN_MAINNET.logoURI, - SupportedChainId.SEPOLIA, - COW_CONTRACT_ADDRESS[SupportedChainId.SEPOLIA], - 18, - 'COW', - 'CoW Protocol Token', -) + return new TokenWithLogo(logoURI, chain, address, COW_TOKEN_DECIMALS, COW_TOKEN_SYMBOL, COW_TOKEN_NAME) +} -export const COW: Record = { +export const COW_TOKEN_MAINNET = getCowTokenForChain(SupportedChainId.MAINNET) +export const COW_TOKEN_XDAI = getCowTokenForChain(SupportedChainId.GNOSIS_CHAIN, COW_TOKEN_MAINNET?.logoURI) +export const COW_TOKEN_ARBITRUM = getCowTokenForChain(SupportedChainId.ARBITRUM_ONE, COW_TOKEN_MAINNET?.logoURI) +export const COW_TOKEN_BASE = getCowTokenForChain(SupportedChainId.BASE, COW_TOKEN_MAINNET?.logoURI) +export const COW_TOKEN_SEPOLIA = getCowTokenForChain(SupportedChainId.SEPOLIA, COW_TOKEN_MAINNET?.logoURI) +export const COW_TOKEN_POLYGON = getCowTokenForChain(SupportedChainId.POLYGON, COW_TOKEN_MAINNET?.logoURI) +export const COW_TOKEN_AVALANCHE = getCowTokenForChain(SupportedChainId.AVALANCHE, COW_TOKEN_MAINNET?.logoURI) +export const COW_TOKEN_LENS = getCowTokenForChain(SupportedChainId.LENS, COW_TOKEN_MAINNET?.logoURI) +export const COW_TOKEN_BNB = getCowTokenForChain(SupportedChainId.BNB, COW_TOKEN_MAINNET?.logoURI) +export const COW_TOKEN_LINEA = getCowTokenForChain(SupportedChainId.LINEA, COW_TOKEN_MAINNET?.logoURI) +export const COW_TOKEN_PLASMA = getCowTokenForChain(SupportedChainId.PLASMA, COW_TOKEN_MAINNET?.logoURI) + +export const COW: Record = { [SupportedChainId.MAINNET]: COW_TOKEN_MAINNET, [SupportedChainId.GNOSIS_CHAIN]: COW_TOKEN_XDAI, [SupportedChainId.ARBITRUM_ONE]: COW_TOKEN_ARBITRUM, [SupportedChainId.BASE]: COW_TOKEN_BASE, [SupportedChainId.SEPOLIA]: COW_TOKEN_SEPOLIA, -} + [SupportedChainId.POLYGON]: COW_TOKEN_POLYGON, + [SupportedChainId.AVALANCHE]: COW_TOKEN_AVALANCHE, + [SupportedChainId.LENS]: COW_TOKEN_LENS, + [SupportedChainId.BNB]: COW_TOKEN_BNB, + [SupportedChainId.LINEA]: COW_TOKEN_LINEA, + [SupportedChainId.PLASMA]: COW_TOKEN_PLASMA, +} as Record export const GNO: Record = { + ...mapSupportedNetworks(null), [SupportedChainId.MAINNET]: GNO_MAINNET, [SupportedChainId.GNOSIS_CHAIN]: GNO_GNOSIS_CHAIN, [SupportedChainId.ARBITRUM_ONE]: GNO_ARBITRUM_ONE, - [SupportedChainId.BASE]: null, [SupportedChainId.SEPOLIA]: GNO_SEPOLIA, } const SDAI_GNOSIS_CHAIN_ADDRESS = '0xaf204776c7245bf4147c2612bf6e5972ee483701' const GBPE_GNOSIS_CHAIN_ADDRESS = '0x5cb9073902f2035222b9749f8fb0c9bfe5527108' -// Not used for fees const MAINNET_STABLECOINS = [ USDC_MAINNET.address, USDT.address, @@ -536,7 +707,6 @@ const ARBITRUM_ONE_STABLECOINS = [ MIM_ARBITRUM_ONE.address, ].map((t) => t.toLowerCase()) -// Not used for fees const BASE_STABLECOINS = [ USDC_BASE.address, DAI_BASE.address, @@ -549,15 +719,40 @@ const BASE_STABLECOINS = [ USDT_BASE.address, ].map((t) => t.toLowerCase()) -// Not used for fees +const POLYGON_STABLECOINS = [USDC_POLYGON.address, USDT_POLYGON.address, DAI_POLYGON.address].map((t) => + t.toLowerCase(), +) + +const AVALANCHE_STABLECOINS = [USDC_AVALANCHE.address, USDT_AVALANCHE.address].map((t) => t.toLowerCase()) + +const LENS_STABLECOINS = [ + USDC_LENS.address, + NATIVE_CURRENCIES[SupportedChainId.LENS].address, // GHO + WRAPPED_NATIVE_CURRENCIES[SupportedChainId.LENS].address, // WGHO +].map((t) => t.toLowerCase()) + +const BNB_STABLECOINS = [USDC_BNB.address, USDT_BNB.address, DAI_BNB.address, BUSD_BNB.address].map((t) => + t.toLowerCase(), +) + +const LINEA_STABLECOINS = [USDC_LINEA.address].map((t) => t.toLowerCase()) + +const PLASMA_STABLECOINS = [USDT_PLASMA.address].map((t) => t.toLowerCase()) + const SEPOLIA_STABLECOINS = [USDC_SEPOLIA.address, USDT_SEPOLIA.address].map((t) => t.toLowerCase()) -export const STABLECOINS: Record> = { +export const STABLECOINS: Record> = { [SupportedChainId.MAINNET]: new Set(MAINNET_STABLECOINS), [SupportedChainId.GNOSIS_CHAIN]: new Set(GNOSIS_CHAIN_STABLECOINS), [SupportedChainId.ARBITRUM_ONE]: new Set(ARBITRUM_ONE_STABLECOINS), [SupportedChainId.SEPOLIA]: new Set(SEPOLIA_STABLECOINS), [SupportedChainId.BASE]: new Set(BASE_STABLECOINS), + [SupportedChainId.POLYGON]: new Set(POLYGON_STABLECOINS), + [SupportedChainId.AVALANCHE]: new Set(AVALANCHE_STABLECOINS), + [SupportedChainId.LENS]: new Set(LENS_STABLECOINS), + [SupportedChainId.BNB]: new Set(BNB_STABLECOINS), + [SupportedChainId.LINEA]: new Set(LINEA_STABLECOINS), + [SupportedChainId.PLASMA]: new Set(PLASMA_STABLECOINS), } /** @@ -565,73 +760,34 @@ export const STABLECOINS: Record> = { * These are used in src/custom/pages/Account/LockedGnoVesting hooks and index files */ export const MERKLE_DROP_CONTRACT_ADDRESSES: Record = { + ...mapSupportedNetworks(''), [SupportedChainId.MAINNET]: '0x64646f112FfD6F1B7533359CFaAF7998F23C8c40', [SupportedChainId.GNOSIS_CHAIN]: '0x48D8566887F8c7d99757CE29c2cD39962bfd9547', - [SupportedChainId.ARBITRUM_ONE]: '', // doesn't exist - [SupportedChainId.BASE]: '', // doesn't exist - [SupportedChainId.SEPOLIA]: '', // TODO SEPOLIA: check it } export const TOKEN_DISTRO_CONTRACT_ADDRESSES: Record = { + ...mapSupportedNetworks(''), [SupportedChainId.MAINNET]: '0x68FFAaC7A431f276fe73604C127Bd78E49070c92', [SupportedChainId.GNOSIS_CHAIN]: '0x3d610e917130f9D036e85A030596807f57e11093', - [SupportedChainId.ARBITRUM_ONE]: '', // doesn't exist - [SupportedChainId.BASE]: '', // doesn't exist - [SupportedChainId.SEPOLIA]: '', // TODO SEPOLIA: check it } /** * Cham token */ -const CHAM_TOKEN_MAINNET = new TokenWithLogo( - undefined, // TODO: Update with CHAM logo URI - SupportedChainId.MAINNET, - CHAM_CONTRACT_ADDRESS[SupportedChainId.MAINNET], - 18, - 'CHAM', - 'Cham Token', -) - -const CHAM_TOKEN_XDAI = new TokenWithLogo( - CHAM_TOKEN_MAINNET.logoURI, - SupportedChainId.GNOSIS_CHAIN, - CHAM_CONTRACT_ADDRESS[SupportedChainId.GNOSIS_CHAIN], - 18, - 'CHAM', - 'Cham Token', -) - -export const CHAM_TOKEN_ARBITRUM = new TokenWithLogo( - CHAM_TOKEN_MAINNET.logoURI, - SupportedChainId.ARBITRUM_ONE, - CHAM_CONTRACT_ADDRESS[SupportedChainId.ARBITRUM_ONE], - 18, - 'CHAM', - 'Cham Token', -) - -export const CHAM_TOKEN_BASE = new TokenWithLogo( - CHAM_TOKEN_MAINNET.logoURI, - SupportedChainId.BASE, - CHAM_CONTRACT_ADDRESS[SupportedChainId.BASE], - 18, - 'CHAM', - 'Cham Token', -) +const CHAM_TOKEN_SYMBOL = 'CHAM' +const CHAM_TOKEN_NAME = 'Cham Token' +const CHAM_TOKEN_DECIMALS = 18 +const CHAM_LOGO_URI = undefined // TODO: Update with CHAM logo URI + +function getChamTokenForChain(chain: SupportedChainId): TokenWithLogo { + const address = CHAM_CONTRACT_ADDRESS[chain] + return new TokenWithLogo(CHAM_LOGO_URI, chain, address, CHAM_TOKEN_DECIMALS, CHAM_TOKEN_SYMBOL, CHAM_TOKEN_NAME) +} -const CHAM_TOKEN_SEPOLIA = new TokenWithLogo( - CHAM_TOKEN_MAINNET.logoURI, - SupportedChainId.SEPOLIA, - CHAM_CONTRACT_ADDRESS[SupportedChainId.SEPOLIA], - 18, - 'CHAM', - 'Cham Token', -) +export const CHAM_TOKEN_MAINNET = getChamTokenForChain(SupportedChainId.MAINNET) +export const CHAM_TOKEN_XDAI = getChamTokenForChain(SupportedChainId.GNOSIS_CHAIN) +export const CHAM_TOKEN_ARBITRUM = getChamTokenForChain(SupportedChainId.ARBITRUM_ONE) +export const CHAM_TOKEN_BASE = getChamTokenForChain(SupportedChainId.BASE) +export const CHAM_TOKEN_SEPOLIA = getChamTokenForChain(SupportedChainId.SEPOLIA) -export const CHAM: Record = { - [SupportedChainId.MAINNET]: CHAM_TOKEN_MAINNET, - [SupportedChainId.GNOSIS_CHAIN]: CHAM_TOKEN_XDAI, - [SupportedChainId.ARBITRUM_ONE]: CHAM_TOKEN_ARBITRUM, - [SupportedChainId.BASE]: CHAM_TOKEN_BASE, - [SupportedChainId.SEPOLIA]: CHAM_TOKEN_SEPOLIA, -} +export const CHAM: Record = mapSupportedNetworks(getChamTokenForChain) diff --git a/libs/common-const/src/types.ts b/libs/common-const/src/types.ts index 05a64c8e4..933270489 100644 --- a/libs/common-const/src/types.ts +++ b/libs/common-const/src/types.ts @@ -5,7 +5,20 @@ const emptyTokens = [] as string[] export class TokenWithLogo extends Token { static fromToken(token: Token | TokenInfo, logoURI?: string): TokenWithLogo { - return new TokenWithLogo(logoURI, token.chainId, token.address, token.decimals, token.symbol, token.name) + if (!token || token.chainId === undefined || !token.address) { + throw new Error('TokenWithLogo.fromToken requires a token with chainId and address') + } + + return new TokenWithLogo( + logoURI, + token.chainId, + token.address, + token.decimals, + token.symbol, + token.name, + undefined, // bypassChecksum parameter + ('tags' in token ? (token as any).tags : undefined) || [], + ) } constructor( @@ -16,6 +29,7 @@ export class TokenWithLogo extends Token { symbol?: string, name?: string, bypassChecksum?: boolean, + public tags: string[] = [], ) { super(chainId, address, decimals, symbol, name, bypassChecksum) } @@ -31,6 +45,8 @@ export class LpToken extends TokenWithLogo { token.decimals, token.symbol, token.name, + undefined, + ('tags' in token ? (token as any).tags : undefined) || [], ) } @@ -43,6 +59,7 @@ export class LpToken extends TokenWithLogo { symbol?: string, name?: string, bypassChecksum?: boolean, + public tags: string[] = [], ) { super(undefined, chainId, address, decimals, symbol, name, bypassChecksum) } diff --git a/libs/common-utils/src/explorer.ts b/libs/common-utils/src/explorer.ts index f18a55c37..25fac35b4 100644 --- a/libs/common-utils/src/explorer.ts +++ b/libs/common-utils/src/explorer.ts @@ -21,6 +21,12 @@ function _getExplorerUrlByEnvironment(): Record { [ChainId.ARBITRUM_ONE]: `${baseUrl}/arb1`, [ChainId.BASE]: `${baseUrl}/base`, [ChainId.SEPOLIA]: `${baseUrl}/sepolia`, + [ChainId.BNB]: `${baseUrl}/bnb`, + [ChainId.LENS]: `${baseUrl}/lens`, + [ChainId.LINEA]: `${baseUrl}/linea`, + [ChainId.PLASMA]: `${baseUrl}/plasma`, + [ChainId.POLYGON]: `${baseUrl}/polygon`, + [ChainId.AVALANCHE]: `${baseUrl}/avalanche`, } } diff --git a/libs/tokens/src/state/tokenLists/tokenListsStateAtom.ts b/libs/tokens/src/state/tokenLists/tokenListsStateAtom.ts index 194a49a5c..5d3a7f6a8 100644 --- a/libs/tokens/src/state/tokenLists/tokenListsStateAtom.ts +++ b/libs/tokens/src/state/tokenLists/tokenListsStateAtom.ts @@ -16,13 +16,16 @@ import { environmentAtom } from '../environmentAtom' const UNISWAP_TOKEN_LIST_URL: Record = { [SupportedChainId.MAINNET]: UNISWAP_TOKENS_LIST, - [SupportedChainId.GNOSIS_CHAIN]: - 'https://raw.githubusercontent.com/cowprotocol/token-lists/main/src/public/Uniswap.100.json', - [SupportedChainId.ARBITRUM_ONE]: - 'https://raw.githubusercontent.com/cowprotocol/token-lists/main/src/public/Uniswap.42161.json', - [SupportedChainId.BASE]: - 'https://raw.githubusercontent.com/cowprotocol/token-lists/main/src/public/Uniswap.8453.json', + [SupportedChainId.GNOSIS_CHAIN]: 'https://files.cow.fi/token-lists/Uniswap.100.json', + [SupportedChainId.ARBITRUM_ONE]: 'https://files.cow.fi/token-lists/Uniswap.42161.json', + [SupportedChainId.BASE]: 'https://files.cow.fi/token-lists/Uniswap.8453.json', [SupportedChainId.SEPOLIA]: UNISWAP_TOKENS_LIST, + [SupportedChainId.POLYGON]: 'https://files.cow.fi/token-lists/Uniswap.137.json', + [SupportedChainId.AVALANCHE]: 'https://files.cow.fi/token-lists/Uniswap.43114.json', + [SupportedChainId.LENS]: 'https://files.cow.fi/token-lists/CoinGecko.232.json', + [SupportedChainId.BNB]: 'https://files.cow.fi/token-lists/Uniswap.56.json', + [SupportedChainId.LINEA]: 'https://files.cow.fi/token-lists/Uniswap.59144.json', + [SupportedChainId.PLASMA]: 'https://files.cow.fi/token-lists/Uniswap.9745.json', } const curatedListSourceAtom = atom((get) => { diff --git a/libs/tokens/src/state/tokens/favoriteTokensAtom.ts b/libs/tokens/src/state/tokens/favoriteTokensAtom.ts index d731873e3..5aaae894a 100644 --- a/libs/tokens/src/state/tokens/favoriteTokensAtom.ts +++ b/libs/tokens/src/state/tokens/favoriteTokensAtom.ts @@ -11,6 +11,8 @@ import { environmentAtom } from '../environmentAtom' type FavoriteTokens = Record +const EMPTY_FAVORITE_TOKENS: TokenWithLogo[] = [] + export const favoriteTokensAtom = atomWithStorage( 'favoriteTokensAtom:v2', DEFAULT_FAVORITE_TOKENS, @@ -20,8 +22,11 @@ export const favoriteTokensAtom = atomWithStorage( export const favoriteTokensListAtom = atom((get) => { const { chainId } = get(environmentAtom) const favoriteTokensState = get(favoriteTokensAtom) + const state = favoriteTokensState[chainId] + + if (!state) return EMPTY_FAVORITE_TOKENS - return Object.values(favoriteTokensState[chainId]).map((token) => TokenWithLogo.fromToken(token, token.logoURI)) + return Object.values(state).map((token) => TokenWithLogo.fromToken(token, token.logoURI)) }) export const resetFavoriteTokensAtom = atom(null, (get, set) => { diff --git a/package.json b/package.json index 1ef24e65f..68c1b40d4 100644 --- a/package.json +++ b/package.json @@ -57,8 +57,9 @@ "@cowprotocol/cms": "^0.11.0", "@cowprotocol/contracts": "^1.3.1", "@cowprotocol/cow-runner-game": "^0.2.9", - "@cowprotocol/cow-sdk": "^5.10.0-RC.0", + "@cowprotocol/cow-sdk": "^7.1.5", "@cowprotocol/ethflowcontract": "cowprotocol/ethflowcontract.git#main-artifacts", + "@cowprotocol/sdk-cow-shed": "^0.2.3", "@davatar/react": "1.8.1", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", @@ -334,4 +335,4 @@ "engines": { "node": "22.x" } -} \ No newline at end of file +} diff --git a/tsconfig.base.json b/tsconfig.base.json index c8338055b..99d776e7b 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -33,6 +33,7 @@ "paths": { "@cowprotocol/abis": ["libs/abis/src/index.ts"], "@cowprotocol/analytics": ["libs/analytics/src/index.ts"], + "@cowprotocol/assets": ["libs/assets/src/index.ts"], "@cowprotocol/assets/*": ["libs/assets/src/*"], "@cowprotocol/balances-and-allowances": ["libs/balances-and-allowances/src/index.ts"], "@cowprotocol/common-const": ["libs/common-const/src/index.ts"], diff --git a/yarn.lock b/yarn.lock index fe1081bf4..922e8ee31 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1746,17 +1746,6 @@ json-stringify-deterministic "^1.0.8" multiformats "^9.6.4" -"@cowprotocol/app-data@^2.4.0": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@cowprotocol/app-data/-/app-data-2.4.0.tgz#326e20065161e06308cf0ff429fe9dd2908c1c30" - integrity sha512-aG3CicUdR7jpY5/linxXmpL4axmiUvEwiHlOM0qKO/QdbNSntKNXjSu3r4QtHZ7BUiF1VUkcDVvvFW4D2MA0Rw== - dependencies: - ajv "^8.11.0" - cross-fetch "^3.1.5" - ipfs-only-hash "^4.0.0" - json-stringify-deterministic "^1.0.8" - multiformats "^9.6.4" - "@cowprotocol/cms@^0.11.0": version "0.11.0" resolved "https://registry.yarnpkg.com/@cowprotocol/cms/-/cms-0.11.0.tgz#a355b07b84b362c1a01dc046acd8367d3d641235" @@ -1769,35 +1758,104 @@ resolved "https://registry.yarnpkg.com/@cowprotocol/contracts/-/contracts-1.4.0.tgz#e93e5f25aac76feeaa348fa57231903274676247" integrity sha512-XLs3SlPmXD4lbiWIO7mxxuCn1eE5isuO6EUlE1cj17HqN/wukDAN0xXYPx6umOH/XdjGS33miMiPHELEyY9siw== -"@cowprotocol/contracts@^1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@cowprotocol/contracts/-/contracts-1.6.0.tgz#d0fc83ed8c624b968d1a68bb5c74712c11ec81e0" - integrity sha512-+UKhYRzkvnqqviBru5D3btTLYc743n0O5YTG+wpYwGl4fb7VNKBkFHe28C5Mf1DF/kOfmqfu+0IAvX9Vuq5Dqw== - "@cowprotocol/cow-runner-game@^0.2.9": version "0.2.9" resolved "https://registry.yarnpkg.com/@cowprotocol/cow-runner-game/-/cow-runner-game-0.2.9.tgz#3f94b3f370bd114f77db8b1d238cba3ef4e9d644" integrity sha512-rX7HnoV+HYEEkBaqVUsAkGGo0oBrExi+d6Io+8nQZYwZk+IYLmS9jdcIObsLviM2h4YX8+iin6NuKl35AaiHmg== -"@cowprotocol/cow-sdk@^5.10.0-RC.0": - version "5.10.0-RC.0" - resolved "https://registry.yarnpkg.com/@cowprotocol/cow-sdk/-/cow-sdk-5.10.0-RC.0.tgz#6e33a60cd0e028d9d1236f0822755727712f75dc" - integrity sha512-KneqcG7esS3hqUxHc45IQ95koThIZ6aKzBu/5YvgGq77OSFgmKjMDYayM647eAufByHCJkCt5I3TnFK8sjB9wA== +"@cowprotocol/cow-sdk@^7.1.5": + version "7.2.4" + resolved "https://registry.yarnpkg.com/@cowprotocol/cow-sdk/-/cow-sdk-7.2.4.tgz#611dd8f9f2c58822ea3f11055d7c684758aa92c7" + integrity sha512-IA61zXYL6z4jMQUbb8PFTENah5+FRg6OjnQ4jg9dTxDiNR51WSotZCg4RUlnZ7XttKE/ncY1uGA0Nxk1tOb+8g== dependencies: - "@cowprotocol/app-data" "^2.4.0" - "@cowprotocol/contracts" "^1.6.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@openzeppelin/merkle-tree" "^1.0.5" - cross-fetch "^3.1.5" - exponential-backoff "^3.1.1" - graphql "^16.3.0" - graphql-request "^4.3.0" - limiter "^2.1.0" + "@cowprotocol/sdk-app-data" "4.3.5" + "@cowprotocol/sdk-common" "0.4.0" + "@cowprotocol/sdk-config" "0.6.1" + "@cowprotocol/sdk-contracts-ts" "0.8.0" + "@cowprotocol/sdk-order-book" "0.4.3" + "@cowprotocol/sdk-order-signing" "0.1.20" + "@cowprotocol/sdk-trading" "0.7.0" "@cowprotocol/ethflowcontract@cowprotocol/ethflowcontract.git#main-artifacts": version "1.3.0" resolved "https://codeload.github.com/cowprotocol/ethflowcontract/tar.gz/ed75d811aba0e18aa80e949cbc979d34ab7fd9ee" +"@cowprotocol/sdk-app-data@4.3.5": + version "4.3.5" + resolved "https://registry.yarnpkg.com/@cowprotocol/sdk-app-data/-/sdk-app-data-4.3.5.tgz#5d1a70acc3fb3f2ff266e865fff2c05a5bb4ac03" + integrity sha512-rvtTpHdJM2jJX2ndr8ZHb4XZH7/EhwJLqClRUfiH/pyKvy5xjnApMsPxNS2cJcheXSl1icea5HJXYJA2lG8f0g== + dependencies: + "@cowprotocol/sdk-common" "0.4.0" + ajv "^8.11.0" + cross-fetch "^3.1.5" + ipfs-only-hash "^4.0.0" + json-stringify-deterministic "^1.0.8" + multiformats "^9.6.4" + +"@cowprotocol/sdk-common@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@cowprotocol/sdk-common/-/sdk-common-0.4.0.tgz#f56509a5fda4cacac4d9995a487fcac7348e83fd" + integrity sha512-ciXiHzTzj7LKZqMKssgyNooZp1nS/mvRE9oO/6DlMQcxVA7/4ajPmk/XzseX/rjdRbSbYyXIEF1oY5w0tcbVjQ== + +"@cowprotocol/sdk-config@0.6.1": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@cowprotocol/sdk-config/-/sdk-config-0.6.1.tgz#a7f8e3cfb8de3e3d78d4da82c6a58d8b5d7e6585" + integrity sha512-E9uuxBhG6dhb7pub+dvw7w5DhlK7EFNFaikQdkZWIjZYt3Y9dQXC3uYwdQXdTxTf81km1EJQbXgXqXBjGeICYQ== + dependencies: + exponential-backoff "^3.1.1" + limiter "^2.1.0" + +"@cowprotocol/sdk-contracts-ts@0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@cowprotocol/sdk-contracts-ts/-/sdk-contracts-ts-0.8.0.tgz#992210fb3b6cdfb44fcc2b7f025b8aa371ba1000" + integrity sha512-N5KAVZfjGmwKpmPRR8ipDrFRX6aq3kBNH3M3Lfp55e7rKz4V4+DUUltmeAtpX8IRqTJtwEGe3NEXJ5ZcgKQ6Qw== + dependencies: + "@cowprotocol/sdk-common" "0.4.0" + "@cowprotocol/sdk-config" "0.6.1" + +"@cowprotocol/sdk-cow-shed@^0.2.3": + version "0.2.7" + resolved "https://registry.yarnpkg.com/@cowprotocol/sdk-cow-shed/-/sdk-cow-shed-0.2.7.tgz#c7a5dcd0c3ed937fc2fdc7c00efd7dd20bec77ac" + integrity sha512-b7o3n4qN1RPCpJ6Aw2MH7yj90Hx+7y2GdSu7YaRbVOrsWHWPLwXP03/RiT+VTiJ0NFDbqyW9CimCNVDWRLirdQ== + dependencies: + "@cowprotocol/sdk-common" "0.4.0" + "@cowprotocol/sdk-config" "0.6.1" + "@cowprotocol/sdk-contracts-ts" "0.8.0" + +"@cowprotocol/sdk-order-book@0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@cowprotocol/sdk-order-book/-/sdk-order-book-0.4.3.tgz#fd1ed92da9311d55b7d84dcf6c82e37c8d399826" + integrity sha512-Nj4nW5cdYWdWeVJv+05j+gLXfgTEnZG4eI4DcpwZQiNSdiQGaXqcPtW3rLME9shECDA1uJQKMEUMA1aZMzx6iQ== + dependencies: + "@cowprotocol/sdk-common" "0.4.0" + "@cowprotocol/sdk-config" "0.6.1" + cross-fetch "^3.2.0" + exponential-backoff "^3.1.2" + limiter "^3.0.0" + +"@cowprotocol/sdk-order-signing@0.1.20": + version "0.1.20" + resolved "https://registry.yarnpkg.com/@cowprotocol/sdk-order-signing/-/sdk-order-signing-0.1.20.tgz#85c2f8654b18bfe05f325e7e5e0d0ac481bf88b1" + integrity sha512-p50hvGwwXCFvfXYTQ8U1m7ZgWiMkwYfWoh/Cn9SJsvR6tK5mcGuJHLkGrYMNiVUCpFm4Rf3bIvAghS/CeJSoeA== + dependencies: + "@cowprotocol/sdk-common" "0.4.0" + "@cowprotocol/sdk-config" "0.6.1" + "@cowprotocol/sdk-contracts-ts" "0.8.0" + "@cowprotocol/sdk-order-book" "0.4.3" + +"@cowprotocol/sdk-trading@0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@cowprotocol/sdk-trading/-/sdk-trading-0.7.0.tgz#fac692df32ed60bcc22e5aa5ac38b992109e80ce" + integrity sha512-FCIoxX3AHAnQzzE4vwG67PEcNbOYq1HjcjPczKkgGt/e+N6maU+NjGc+KZZZA6EVK2XkuwhmvNfFng08BcXepA== + dependencies: + "@cowprotocol/sdk-app-data" "4.3.5" + "@cowprotocol/sdk-common" "0.4.0" + "@cowprotocol/sdk-config" "0.6.1" + "@cowprotocol/sdk-contracts-ts" "0.8.0" + "@cowprotocol/sdk-order-book" "0.4.3" + "@cowprotocol/sdk-order-signing" "0.1.20" + deepmerge "^4.3.1" + "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -4960,11 +5018,6 @@ dependencies: "@noble/hashes" "1.6.0" -"@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" - integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== - "@noble/hashes@1.3.1", "@noble/hashes@^1.2.0", "@noble/hashes@^1.3.0", "@noble/hashes@~1.3.0", "@noble/hashes@~1.3.1": version "1.3.1" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" @@ -5005,11 +5058,6 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== -"@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": - version "1.7.1" - resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" - integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== - "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -5031,14 +5079,6 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@openzeppelin/merkle-tree@^1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@openzeppelin/merkle-tree/-/merkle-tree-1.0.5.tgz#4836d377777a7e39f31674f06ec3d6909def7913" - integrity sha512-JkwG2ysdHeIphrScNxYagPy6jZeNONgDRyqU6lbFgE8HKCZFSkcP8r6AjZs+3HZk4uRNV0kNBBzuWhKQ3YV7Kw== - dependencies: - "@ethersproject/abi" "^5.7.0" - ethereum-cryptography "^1.1.2" - "@parcel/watcher-android-arm64@2.3.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.3.0.tgz#d82e74bb564ebd4d8a88791d273a3d2bd61e27ab" @@ -5742,15 +5782,6 @@ resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.4.tgz#002eb571a35d69bdb4c214d0995dff76a8dcd2a9" integrity sha512-5Yy9czTO47mqz+/J8GM6GIId4umdCk1wc1q8rKERQulIoc8VP9pzDcghv10Tl2E7R96ZUx/PhND3ESYUQX8NuQ== -"@scure/bip32@1.1.5": - version "1.1.5" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.5.tgz#d2ccae16dcc2e75bc1d75f5ef3c66a338d1ba300" - integrity sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw== - dependencies: - "@noble/hashes" "~1.2.0" - "@noble/secp256k1" "~1.7.0" - "@scure/base" "~1.1.0" - "@scure/bip32@1.3.1": version "1.3.1" resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.1.tgz#7248aea723667f98160f593d621c47e208ccbb10" @@ -5778,14 +5809,6 @@ "@noble/hashes" "~1.7.1" "@scure/base" "~1.2.2" -"@scure/bip39@1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" - integrity sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg== - dependencies: - "@noble/hashes" "~1.2.0" - "@scure/base" "~1.1.0" - "@scure/bip39@1.2.1": version "1.2.1" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a" @@ -12743,6 +12766,13 @@ cross-fetch@^3.0.4, cross-fetch@^3.1.4, cross-fetch@^3.1.5, cross-fetch@^3.1.6: dependencies: node-fetch "^2.6.12" +cross-fetch@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.2.0.tgz#34e9192f53bc757d6614304d9e5e6fb4edb782e3" + integrity sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q== + dependencies: + node-fetch "^2.7.0" + cross-fetch@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.0.0.tgz#f037aef1580bb3a1a35164ea2a848ba81b445983" @@ -13671,7 +13701,7 @@ deep-object-diff@^1.1.9: resolved "https://registry.yarnpkg.com/deep-object-diff/-/deep-object-diff-1.1.9.tgz#6df7ef035ad6a0caa44479c536ed7b02570f4595" integrity sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA== -deepmerge@^4.2.2: +deepmerge@^4.2.2, deepmerge@^4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== @@ -15533,16 +15563,6 @@ ethereum-cryptography@^0.1.3: secp256k1 "^4.0.1" setimmediate "^1.0.5" -ethereum-cryptography@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz#5ccfa183e85fdaf9f9b299a79430c044268c9b3a" - integrity sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw== - dependencies: - "@noble/hashes" "1.2.0" - "@noble/secp256k1" "1.7.1" - "@scure/bip32" "1.1.5" - "@scure/bip39" "1.1.1" - ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz#18fa7108622e56481157a5cb7c01c0c6a672eb67" @@ -15791,6 +15811,11 @@ exponential-backoff@^3.1.1: resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6" integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw== +exponential-backoff@^3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.3.tgz#51cf92c1c0493c766053f9d3abee4434c244d2f6" + integrity sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA== + express-validator@^7.2.1: version "7.2.1" resolved "https://registry.yarnpkg.com/express-validator/-/express-validator-7.2.1.tgz#8403deaf810f9bededa0a4fd7116803e46f122c2" @@ -16925,7 +16950,7 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== -graphql-request@4.3.0, graphql-request@^4.3.0: +graphql-request@4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-4.3.0.tgz#b934e08fcae764aa2cdc697d3c821f046cb5dbf2" integrity sha512-2v6hQViJvSsifK606AliqiNiijb1uwWp6Re7o0RTyH+uRTv/u7Uqm2g4Fjq/LgZIzARB38RZEvVBFOQOVdlBow== @@ -16941,11 +16966,6 @@ graphql-tag@^2.12.6: dependencies: tslib "^2.1.0" -graphql@^16.3.0: - version "16.8.1" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07" - integrity sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw== - graphql@^16.8.0: version "16.8.0" resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.0.tgz#374478b7f27b2dc6153c8f42c1b80157f79d79d4" @@ -20661,6 +20681,11 @@ limiter@^2.1.0: dependencies: just-performance "4.3.0" +limiter@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/limiter/-/limiter-3.0.0.tgz#03556b76d1a81f547caeecc6b83ecc6f24495715" + integrity sha512-hev7DuXojsTFl2YwyzUJMDnZ/qBDd3yZQLSH3aD4tdL1cqfc3TMnoecEJtWFaQFdErZsKoFMBTxF/FBSkgDbEg== + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" From 1de89a10add313ed79010e22cf0ce1764d3cc5b0 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 11 Dec 2025 17:41:58 +0100 Subject: [PATCH 2/3] fix: change image directory to use relative path --- apps/cowswap-frontend/index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/cowswap-frontend/index.html b/apps/cowswap-frontend/index.html index 85d654fbf..c37c5e60d 100644 --- a/apps/cowswap-frontend/index.html +++ b/apps/cowswap-frontend/index.html @@ -11,10 +11,10 @@ - - - - + + + + From a3430cad1f66cfd6539a051f56f8ed16a2aab0b1 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 12 Dec 2025 08:18:55 +0100 Subject: [PATCH 3/3] fix: change protocol name to chameleons --- apps/cowswap-frontend/src/common/pure/NetworksList/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/cowswap-frontend/src/common/pure/NetworksList/index.tsx b/apps/cowswap-frontend/src/common/pure/NetworksList/index.tsx index 09ec022ee..2332bf735 100644 --- a/apps/cowswap-frontend/src/common/pure/NetworksList/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/NetworksList/index.tsx @@ -70,7 +70,7 @@ export function NetworksList(props: NetworksListProps) { )} - CoW Protocol Explorer + Chameleon Protocol Explorer ↗