Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(base): add base chain support #5044

Open
wants to merge 23 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
2f83f9f
feat: initial base chain support
alfetopito Oct 24, 2024
1dafb32
feat: add COW token address on BASE
alfetopito Oct 24, 2024
a3da148
feat: update cow-sdk with base support
alfetopito Oct 24, 2024
ba69d1d
chore: bump permit-utils version to 0.5.0-RC.0
alfetopito Oct 24, 2024
6207aab
feat: base for explorer
alfetopito Oct 25, 2024
8d5d302
feat: fix widget configurator build, but var still required
alfetopito Oct 25, 2024
51615f0
feat: add BASE stablecoins
alfetopito Oct 31, 2024
924372d
feat: use uniswap's default list for chains where its supported
alfetopito Oct 31, 2024
94ea6da
chore: use cbBTC instead of WBTC, which is way more liquid on Base
alfetopito Nov 1, 2024
80d5c6e
fix: correct number of decimals for Base tokens
alfetopito Nov 1, 2024
dbfb2b6
feat: add base token list to explorer pre-loaded tokens
alfetopito Nov 1, 2024
05bec85
feat: add isBaseEnabled feature flag
alfetopito Nov 1, 2024
1014b2a
feat: add full coingecko list disabled to base
alfetopito Nov 1, 2024
8714223
feat: add default fee recipient address for Base
alfetopito Nov 5, 2024
cad07f5
fix: add base to lp page links
alfetopito Nov 5, 2024
08a75d4
feat: early exit on cowSwapFeeAtom if fee is not set for network
alfetopito Nov 5, 2024
64a5151
refactor: single source of truth for stablecoins
alfetopito Nov 5, 2024
9ac9d1f
chore: fix lint
alfetopito Nov 6, 2024
43e11e4
fix: use correct basescan tld
alfetopito Nov 7, 2024
a2ad400
chore: remove unecessary conditional
alfetopito Nov 7, 2024
163d954
feat: add base start date tooltip
alfetopito Nov 7, 2024
0f04ef1
fix: use correct chain for twap small part warning
alfetopito Nov 7, 2024
a0979ae
chore: bump to latest cow-sdk
alfetopito Nov 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 }}
Comment on lines +50 to +57
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: add to github and vercel

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
Loading