Skip to content

Commit

Permalink
feat(base): add base chain support (#5044)
Browse files Browse the repository at this point in the history
* feat: initial base chain support

* feat: add COW token address on BASE

* feat: update cow-sdk with base support

* chore: bump permit-utils version to 0.5.0-RC.0

* feat: base for explorer

* feat: fix widget configurator build, but var still required

* feat: add BASE stablecoins

* feat: use uniswap's default list for chains where its supported

* chore: use cbBTC instead of WBTC, which is way more liquid on Base

* fix: correct number of decimals for Base tokens

* feat: add base token list to explorer pre-loaded tokens

* feat: add isBaseEnabled feature flag

* feat: add full coingecko list disabled to base

* feat: add default fee recipient address for Base

* fix: add base to lp page links

* feat: early exit on cowSwapFeeAtom if fee is not set for network

* refactor: single source of truth for stablecoins

* chore: fix lint

* fix: use correct basescan tld

* chore: remove unecessary conditional

* feat: add base start date tooltip

* fix: use correct chain for twap small part warning

* chore: bump to latest cow-sdk

---------

Co-authored-by: Anxo Rodriguez <[email protected]>
  • Loading branch information
alfetopito and anxolin authored Nov 26, 2024
1 parent d79dc06 commit 4cf0c91
Show file tree
Hide file tree
Showing 45 changed files with 354 additions and 187 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/vercel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,14 @@ jobs:
REACT_APP_NETWORK_URL_1=${{ secrets.REACT_APP_NETWORK_URL_1 }}
REACT_APP_NETWORK_URL_100=${{ secrets.REACT_APP_NETWORK_URL_100 }}
REACT_APP_NETWORK_URL_42161=${{ secrets.REACT_APP_NETWORK_URL_42161 }}
REACT_APP_NETWORK_URL_8453=${{ secrets.REACT_APP_NETWORK_URL_8453 }}
REACT_APP_NETWORK_URL_11155111=${{ secrets.REACT_APP_NETWORK_URL_11155111 }}
REACT_APP_WC_PROJECT_ID=${{ secrets.REACT_APP_WC_PROJECT_ID }}
REACT_APP_IPFS_READ_URI=${{ secrets.REACT_APP_IPFS_READ_URI }}
REACT_APP_EXPLORER_SENTRY_DSN=${{ secrets.EXPLORER_SENTRY_DSN }}
REACT_APP_SUBGRAPH_URL_MAINNET=${{ secrets.REACT_APP_SUBGRAPH_URL_MAINNET }}
REACT_APP_SUBGRAPH_URL_ARBITRUM_ONE=${{ secrets.REACT_APP_SUBGRAPH_URL_ARBITRUM_ONE }}
REACT_APP_SUBGRAPH_URL_BASE=${{ secrets.REACT_APP_SUBGRAPH_URL_BASE }}
REACT_APP_SUBGRAPH_URL_GNOSIS_CHAIN=${{ secrets.REACT_APP_SUBGRAPH_URL_GNOSIS_CHAIN }}
REACT_APP_BFF_BASE_URL=${{ secrets.BFF_BASE_URL }}
REACT_APP_CMS_BASE_URL=${{ secrets.CMS_BASE_URL }}
Expand Down
15 changes: 5 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ yarn test

# 🔎 Explorer

Start the Explorer on http://localhost:4200
Start the Explorer on <http://localhost:4200>

[Read more about the Explorer](apps/explorer/README.md)

Expand All @@ -69,7 +69,7 @@ yarn build:explorer

# 🐄 cow.fi

Start CoW.fi on http://localhost:3001
Start CoW.fi on <http://localhost:3001>

### Start

Expand All @@ -85,7 +85,7 @@ yarn build:cowfi

# 🖼️ Widget Configurator

Start the Widget Configurator on http://127.0.0.1:4200/widget-configurator
Start the Widget Configurator on <http://127.0.0.1:4200/widget-configurator>

```bash
# Start
Expand All @@ -97,7 +97,7 @@ yarn build:widget

# 🌌 Cosmos UI Library

Start the Cosmos UI Library on http://localhost:5000
Start the Cosmos UI Library on <http://localhost:5000>

```bash
yarn run cosmos
Expand Down Expand Up @@ -174,6 +174,7 @@ REACT_APP_NETWORK_URL_1: https://...
REACT_APP_NETWORK_URL_11155111: https://...
REACT_APP_NETWORK_URL_100: https://...
REACT_APP_NETWORK_URL_42161: https://...
REACT_APP_NETWORK_URL_8453: https://...
```

Additionally, if you plan to run the integration tests locally you must define:
Expand Down Expand Up @@ -216,7 +217,6 @@ The API endpoint is configured using the environment variable
REACT_APP_BFF_BASE_URL=https://bff.cow.fi
```
## CMS API Endpoints (Content Management System)
The CMS API is a helper API that provides some additional content to the frontend.
Expand All @@ -235,10 +235,6 @@ The API endpoint is configured using the environment variable
REACT_APP_CMS_BASE_URL=https://cms.cow.fi/api
```
## Price feeds
CoW Swap tries to find the best price available on-chain using some price feeds.
Expand Down Expand Up @@ -295,4 +291,3 @@ In case of problems with the service worker cache you force a reset using
1. [Oveall Architecture](docs/architecture-overview.md)
2. [Amounts formatting](apps/cowswap-frontend/src/utils/amountFormat/README.md)
3. [ABIs](libs/abis/README.md)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { COW, GNO } from '@cowprotocol/common-const'
import { COW, GNO_MAINNET } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'

import { DemoContainer } from 'cosmos.decorator'
Expand All @@ -9,7 +9,7 @@ import { ApprovalState } from '../../hooks/useApproveState'
import { ApproveButton } from '.'

const COW_TOKEN = COW[SupportedChainId.MAINNET]
const GNO_TOKEN = GNO[SupportedChainId.MAINNET]
const GNO_TOKEN = GNO_MAINNET

const Custom = () => {
const [currencyRaw] = useSelect('currency', {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { COW, GNO } from '@cowprotocol/common-const'
import { COW, GNO_MAINNET } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'

import { useSelect } from 'react-cosmos/client'

import { CurrencySelectButton, CurrencySelectButtonProps } from 'common/pure/CurrencySelectButton/index'

const COW_TOKEN = COW[SupportedChainId.MAINNET]
const GNO_TOKEN = GNO[SupportedChainId.MAINNET]
const GNO_TOKEN = GNO_MAINNET

function useCustomProps(): CurrencySelectButtonProps {
const [currencyRaw] = useSelect('currency', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -649,14 +649,15 @@ const COW_SWAP_BENEFITS = [
"Unlike most other exchanges, CoW Swap doesn't charge you any fees if your trade fails.",
]

const TRADE_ON_ARBITRUM_BENEFIT =
'CoW Swap is now live on Arbitrum. Switch the network toggle in the nav bar for quick, cheap transactions.'
const TRADE_ON_NEW_CHAINS_BENEFIT =
'CoW Swap is now live on Arbitrum and Base. Switch the network toggle in the nav bar for quick, cheap transactions.'

const CHAIN_SPECIFIC_BENEFITS: Record<SupportedChainId, string[]> = {
[SupportedChainId.MAINNET]: [TRADE_ON_ARBITRUM_BENEFIT, ...COW_SWAP_BENEFITS],
[SupportedChainId.MAINNET]: [TRADE_ON_NEW_CHAINS_BENEFIT, ...COW_SWAP_BENEFITS],
[SupportedChainId.ARBITRUM_ONE]: COW_SWAP_BENEFITS,
[SupportedChainId.GNOSIS_CHAIN]: [TRADE_ON_ARBITRUM_BENEFIT, ...COW_SWAP_BENEFITS],
[SupportedChainId.SEPOLIA]: [TRADE_ON_ARBITRUM_BENEFIT, ...COW_SWAP_BENEFITS],
[SupportedChainId.BASE]: COW_SWAP_BENEFITS,
[SupportedChainId.GNOSIS_CHAIN]: [TRADE_ON_NEW_CHAINS_BENEFIT, ...COW_SWAP_BENEFITS],
[SupportedChainId.SEPOLIA]: [TRADE_ON_NEW_CHAINS_BENEFIT, ...COW_SWAP_BENEFITS],
}

function truncateWithEllipsis(str: string, maxLength: number): string {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { COW, GNO, USDC_SEPOLIA, WETH_GNOSIS_CHAIN, WETH_SEPOLIA, WXDAI } from '@cowprotocol/common-const'
import { COW, GNO_SEPOLIA, USDC_SEPOLIA, WETH_GNOSIS_CHAIN, WETH_SEPOLIA, WXDAI } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { TokenSymbol } from '@cowprotocol/ui'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
Expand All @@ -9,7 +9,7 @@ import { RateInfo, RateInfoParams } from './index'

const inputCurrency = WETH_GNOSIS_CHAIN
const outputCurrency = WXDAI
const GNO_SEPOLIA = GNO[SupportedChainId.GNOSIS_CHAIN]

const COW_SEPOLIA = COW[SupportedChainId.GNOSIS_CHAIN]

const rateInfoParams = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,10 @@
import {
DAI,
DAI_ARBITRUM_ONE,
NATIVE_CURRENCY_ADDRESS,
USDC_ARBITRUM_ONE,
USDC_GNOSIS_CHAIN,
USDC_MAINNET,
USDC_SEPOLIA,
USDT,
USDT_ARBITRUM_ONE,
USDT_GNOSIS_CHAIN,
WXDAI,
} from '@cowprotocol/common-const'
import { STABLECOINS } from '@cowprotocol/common-const'
import { getCurrencyAddress } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'

import { Nullish } from 'types'

// TODO: Find a solution for using API: https://www.coingecko.com/en/categories/stablecoins
const STABLE_COINS: Record<SupportedChainId, string[]> = {
[SupportedChainId.MAINNET]: [USDC_MAINNET, USDT, DAI].map((token) => token.address.toLowerCase()),
[SupportedChainId.GNOSIS_CHAIN]: [USDC_GNOSIS_CHAIN, USDT_GNOSIS_CHAIN, WXDAI]
.map((token) => token.address.toLowerCase())
// XDAI and WXDAI are stable-coins
.concat(NATIVE_CURRENCY_ADDRESS),
[SupportedChainId.ARBITRUM_ONE]: [USDT_ARBITRUM_ONE, USDC_ARBITRUM_ONE, DAI_ARBITRUM_ONE].map((token) =>
token.address.toLowerCase()
),
[SupportedChainId.SEPOLIA]: [USDC_SEPOLIA].map((token) => token.address.toLowerCase()),
}

/**
* Quote - means the currency we consider as base (https://www.investopedia.com/terms/q/quotecurrency.asp#:~:text=What%20Is%20a%20Quote%20Currency,value%20of%20the%20base%20currency)
* For example: 400 UNI -> 2000 USDC - UNI is the quote currency, because is a stable coin against a non-stable coin
Expand All @@ -41,7 +16,7 @@ const STABLE_COINS: Record<SupportedChainId, string[]> = {
export function getQuoteCurrency(
chainId: SupportedChainId | undefined,
inputCurrencyAmount: Nullish<CurrencyAmount<Currency>>,
outputCurrencyAmount: Nullish<CurrencyAmount<Currency>>
outputCurrencyAmount: Nullish<CurrencyAmount<Currency>>,
): Currency | null {
if (!chainId || !inputCurrencyAmount || !outputCurrencyAmount) return null

Expand All @@ -58,17 +33,17 @@ export function getQuoteCurrency(
export function getQuoteCurrencyByStableCoin(
chainId: SupportedChainId | undefined,
inputCurrency: Currency | null,
outputCurrency: Currency | null
outputCurrency: Currency | null,
): Currency | null {
if (!chainId || !inputCurrency || !outputCurrency) return null

const stableCoins = STABLE_COINS[chainId]
const stableCoins = STABLECOINS[chainId]

const inputAddress = getCurrencyAddress(inputCurrency).toLowerCase()
const outputAddress = getCurrencyAddress(outputCurrency).toLowerCase()

const isInputStableCoin = stableCoins.includes(inputAddress)
const isOutputStableCoin = stableCoins.includes(outputAddress)
const isInputStableCoin = stableCoins.has(inputAddress)
const isOutputStableCoin = stableCoins.has(outputAddress)

if (isInputStableCoin) return outputCurrency
if (isOutputStableCoin) return inputCurrency
Expand Down
57 changes: 0 additions & 57 deletions apps/cowswap-frontend/src/legacy/components/AMMsLogo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,6 @@ import Swapr from '@cowprotocol/assets/cow-swap/ammslogo/swapr.png'
import Symmetric from '@cowprotocol/assets/cow-swap/ammslogo/symmetric.png'
import Uniswap from '@cowprotocol/assets/cow-swap/ammslogo/uniswap.png'
import Gno from '@cowprotocol/assets/cow-swap/network-gnosis-chain-logo.svg'
import { SupportedChainId } from '@cowprotocol/cow-sdk'

import styled from 'styled-components/macro'

import { animationDelay, crossFade, fadeInOut, imagesAnimationDelay, presentationTime } from './utils'

export const Wrapper = styled.div<{ logosLength: number }>`
display: flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
border-radius: 100%;
box-shadow: 0px 0px 10px 2px ${({ theme }) => theme.paper};
background-color: ${({ theme }) => theme.white};
transform-style: preserve-3d;
position: absolute;
top: -4px;
right: 0px;
img {
position: absolute;
left: 0;
animation: ${(props) => fadeInOut(presentationTime, crossFade, props.logosLength)}
${(props) => animationDelay * props.logosLength}s infinite;
}
${(props) => imagesAnimationDelay(props.logosLength, animationDelay)}
`

type Image = { src: string; alt: string }

const SushiImage = { src: Sushi, alt: 'AMMs Sushi' }
const OneInchImage = { src: Oneinch, alt: 'AMMs 1inch' }
Expand All @@ -60,23 +29,6 @@ const LevinSwapImage = { src: Levinswap, alt: 'Levinswap 0x' }
const SymmetricImage = { src: Symmetric, alt: 'Symmetric 0x' }
const ZeroXImage = { src: ZeroX, alt: 'AMMs 0x' }

const ETH_AMM_LOGOS = [SushiImage, OneInchImage, ParaSwapImage, UniswapImage, CurveImage, MatchaImage, ZeroXImage]

const LogosPerNetwork: Record<SupportedChainId, Array<Image>> = {
[SupportedChainId.MAINNET]: ETH_AMM_LOGOS,
[SupportedChainId.SEPOLIA]: ETH_AMM_LOGOS,
[SupportedChainId.ARBITRUM_ONE]: ETH_AMM_LOGOS, // TODO: review actual AMMs on arbitrum
[SupportedChainId.GNOSIS_CHAIN]: [
SushiImage,
BaoSwapImage,
HoneySwapImage,
SwaprImage,
SymmetricImage,
ElkImage,
LevinSwapImage,
],
}

export const AMM_LOGOS: Record<string, typeof SushiImage> = {
baoswap: BaoSwapImage,
balancer: BalancerImage,
Expand All @@ -95,12 +47,3 @@ export const AMM_LOGOS: Record<string, typeof SushiImage> = {
default: { src: Gno, alt: 'Default unknown AMM' },
}

export function AMMsLogo({ chainId }: { chainId: SupportedChainId }) {
return (
<Wrapper logosLength={LogosPerNetwork[chainId].length}>
{LogosPerNetwork[chainId].map(({ src, alt }, index) => (
<img key={index} src={src} alt={alt} />
))}
</Wrapper>
)
}
4 changes: 2 additions & 2 deletions apps/cowswap-frontend/src/mocks/orderMock.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { COW, GNO } from '@cowprotocol/common-const'
import { COW, USDC } from '@cowprotocol/common-const'
import { OrderClass, OrderKind, SigningScheme, SupportedChainId } from '@cowprotocol/cow-sdk'

import { Order, OrderStatus } from 'legacy/state/orders/actions'

export const getOrderMock = (chainId: SupportedChainId): Order => {
const inputToken = COW[chainId]
const outputToken = GNO[chainId]
const outputToken = USDC[chainId]
const creationTime = '2023-05-29T15:27:32.319Z'

return {
Expand Down
4 changes: 2 additions & 2 deletions apps/cowswap-frontend/src/mocks/tradeStateMock.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { COW, GNO } from '@cowprotocol/common-const'
import { COW, GNO_MAINNET } from '@cowprotocol/common-const'
import { tryParseCurrencyAmount } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { Currency, Percent, Price } from '@uniswap/sdk-core'
Expand All @@ -11,7 +11,7 @@ import { CurrencyInfo } from 'common/pure/CurrencyInputPanel/types'
const chainId = SupportedChainId.MAINNET

const inputCurrency = COW[chainId]
const outputCurrency = GNO[chainId]
const outputCurrency = GNO_MAINNET

export const inputCurrencyInfoMock: CurrencyInfo = {
field: Field.INPUT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ import { InfoCard } from './styled'

const DEFAULT_START_DATE = 'March 2023'
const ARBITRUM_ONE_START_DATE = 'May 2024'
const BASE_START_DATE = 'December 2024'



const START_DATE: Record<SupportedChainId, string> = {
[SupportedChainId.MAINNET]: DEFAULT_START_DATE,
[SupportedChainId.GNOSIS_CHAIN]: DEFAULT_START_DATE,
[SupportedChainId.ARBITRUM_ONE]: ARBITRUM_ONE_START_DATE,
[SupportedChainId.BASE]: BASE_START_DATE,
[SupportedChainId.SEPOLIA]: DEFAULT_START_DATE
}


export function SurplusCard() {
const { surplusAmount, isLoading } = useTotalSurplus()
Expand All @@ -29,7 +41,7 @@ export function SurplusCard() {
const surplusUsdAmount = useUsdAmount(showSurplusAmount ? surplusAmount : undefined).value
const native = useNativeCurrency()
const nativeSymbol = native.symbol || 'ETH'
const isArbitrumOne = native.chainId === SupportedChainId.ARBITRUM_ONE
const startDate = START_DATE[native.chainId as SupportedChainId]

const Wrapper = styled.div`
margin: 12px auto 24px;
Expand Down Expand Up @@ -158,9 +170,7 @@ export function SurplusCard() {
<i>
Your total surplus{' '}
<HelpTooltip
text={`The total surplus CoW Swap has generated for you in ${nativeSymbol} across all your trades since ${
isArbitrumOne ? ARBITRUM_ONE_START_DATE : DEFAULT_START_DATE
}`}
text={`The total surplus CoW Swap has generated for you in ${nativeSymbol} across all your trades since ${startDate}`}
/>
</i>
</span>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { SetStateAction } from 'jotai'

import { COW, GNO } from '@cowprotocol/common-const'
import { COW, GNO_MAINNET } from '@cowprotocol/common-const'
import { OrderClass, OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk'
import { CurrencyAmount } from '@uniswap/sdk-core'

Expand All @@ -14,7 +14,7 @@ import { TradeFlowContext } from '../../services/types'
import { LimitOrdersDetails } from './index'

const inputCurrency = COW[SupportedChainId.MAINNET]
const outputCurrency = GNO[SupportedChainId.MAINNET]
const outputCurrency = GNO_MAINNET

const rateInfoParams = {
chainId: 5,
Expand Down
Loading

0 comments on commit 4cf0c91

Please sign in to comment.