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: add Gnosis Chain #95

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 23 additions & 0 deletions patches/@uniswap+universal-router-sdk+1.5.6.patch

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions src/assets/svg/gnosis_logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions src/assets/svg/xdai_logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion src/components/FeeSelector/shared.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Trans } from '@lingui/macro'
import { ChainId, SUPPORTED_CHAINS } from '@uniswap/sdk-core'
import { ChainId } from '@uniswap/sdk-core'
import { FeeAmount } from '@uniswap/v3-sdk'
import { SUPPORTED_CHAINS } from 'constants/chains'
import type { ReactNode } from 'react'

export const FEE_AMOUNT_DETAIL: Record<
Expand All @@ -21,6 +22,7 @@ export const FEE_AMOUNT_DETAIL: Record<
ChainId.POLYGON_MUMBAI,
ChainId.AVALANCHE,
ChainId.BASE,
ChainId.GNOSIS,
],
},
[FeeAmount.LOW]: {
Expand Down
3 changes: 2 additions & 1 deletion src/components/NavBar/ChainSelectorRow.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ChainId, SUPPORTED_CHAINS } from '@uniswap/sdk-core'
import { ChainId } from '@uniswap/sdk-core'
import { SUPPORTED_CHAINS } from 'constants/chains'
import { render } from 'test-utils/render'

import ChainSelectorRow from './ChainSelectorRow'
Expand Down
26 changes: 25 additions & 1 deletion src/constants/chainInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import bnbSquareLogoUrl from 'assets/svg/bnb_square_logo.svg'
import bnbLogo from 'assets/svg/bnb-logo.svg'
import celoLogo from 'assets/svg/celo_logo.svg'
import celoSquareLogoUrl from 'assets/svg/celo_square_logo.svg'
import gnosisLogo from 'assets/svg/gnosis_logo.svg'
import optimismSquareLogoUrl from 'assets/svg/optimism_square_logo.svg'
import optimismLogoUrl from 'assets/svg/optimistic_ethereum.svg'
import polygonSquareLogoUrl from 'assets/svg/polygon_square_logo.svg'
Expand All @@ -19,7 +20,15 @@ import ms from 'ms'
import { darkTheme } from 'theme/colors'

import { SupportedL1ChainId, SupportedL2ChainId } from './chains'
import { ARBITRUM_LIST, AVALANCHE_LIST, BASE_LIST, CELO_LIST, OPTIMISM_LIST, PLASMA_BNB_LIST } from './lists'
import {
ARBITRUM_LIST,
AVALANCHE_LIST,
BASE_LIST,
CELO_LIST,
GNOSIS_LIST,
OPTIMISM_LIST,
PLASMA_BNB_LIST,
} from './lists'

export const AVERAGE_L1_BLOCK_TIME = ms(`12s`)

Expand Down Expand Up @@ -259,6 +268,21 @@ const CHAIN_INFO: ChainInfoMap = {
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
color: darkTheme.chain_84531,
},
[ChainId.GNOSIS]: {
networkType: NetworkType.L1,
blockWaitMsBeforeWarning: ms(`10m`),
bridge: 'https://omnibridge.gnosischain.com/bridge',
defaultListUrl: GNOSIS_LIST,
docs: 'https://docs.gnosischain.com/',
explorer: 'https://gnosisscan.io/',
infoLink: 'https://info.uniswap.org/#/gnosis/',
label: 'Gnosis',
nativeCurrency: { name: 'Gnosis', symbol: 'xDAI', decimals: 18 },
color: darkTheme.chain_100,
backgroundColor: darkTheme.chain_100_background,
circleLogoUrl: gnosisLogo,
logoUrl: gnosisLogo,
},
} as const

export function getChainInfo(chainId: SupportedL1ChainId): L1ChainInfo
Expand Down
1 change: 1 addition & 0 deletions src/constants/chains.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const chainPriorityTestCases: [ChainId, number][] = [
[ChainId.AVALANCHE, 6],
[ChainId.CELO, 7],
[ChainId.CELO_ALFAJORES, 7],
[ChainId.GNOSIS, 8],
]

test.each(chainPriorityTestCases)(
Expand Down
12 changes: 10 additions & 2 deletions src/constants/chains.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { ChainId, SUPPORTED_CHAINS, SupportedChainsType } from '@uniswap/sdk-core'
import { ChainId, SUPPORTED_CHAINS as UNISWAP_SUPPORTED_CHAINS } from '@uniswap/sdk-core'

export const SUPPORTED_CHAINS = [...UNISWAP_SUPPORTED_CHAINS, ChainId.GNOSIS] as const
declare type SupportedChainsType = (typeof SUPPORTED_CHAINS)[number]

export const CHAIN_IDS_TO_NAMES = {
[ChainId.MAINNET]: 'mainnet',
Expand All @@ -15,6 +18,7 @@ export const CHAIN_IDS_TO_NAMES = {
[ChainId.BNB]: 'bnb',
[ChainId.AVALANCHE]: 'avalanche',
[ChainId.BASE]: 'base',
[ChainId.GNOSIS]: 'gnosis',
} as const

// Include ChainIds in this array if they are not supported by the UX yet, but are already in the SDK.
Expand All @@ -41,6 +45,7 @@ export const SUPPORTED_GAS_ESTIMATE_CHAIN_IDS = [
ChainId.BNB,
ChainId.AVALANCHE,
ChainId.BASE,
ChainId.GNOSIS,
] as const

/**
Expand Down Expand Up @@ -70,6 +75,7 @@ export const L1_CHAIN_IDS = [
ChainId.CELO_ALFAJORES,
ChainId.BNB,
ChainId.AVALANCHE,
ChainId.GNOSIS,
] as const

export type SupportedL1ChainId = (typeof L1_CHAIN_IDS)[number]
Expand Down Expand Up @@ -117,7 +123,9 @@ export function getChainPriority(chainId: ChainId): number {
case ChainId.CELO:
case ChainId.CELO_ALFAJORES:
return 7
default:
case ChainId.GNOSIS:
return 8
default:
return 9
}
}
2 changes: 2 additions & 0 deletions src/constants/lists.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const AVALANCHE_LIST =
'https://raw.githubusercontent.com/ava-labs/avalanche-bridge-resources/main/token_list.json'
export const BASE_LIST =
'https://raw.githubusercontent.com/ethereum-optimism/ethereum-optimism.github.io/master/optimism.tokenlist.json'
export const GNOSIS_LIST = 'https://raw.githubusercontent.com/cowprotocol/token-lists/main/src/public/CowSwap.json'

// default lists to be 'active' aka searched across
export const DEFAULT_ACTIVE_LIST_URLS: string[] = [UNI_LIST]
Expand All @@ -49,6 +50,7 @@ export const DEFAULT_INACTIVE_LIST_URLS: string[] = [
PLASMA_BNB_LIST,
AVALANCHE_LIST,
BASE_LIST,
GNOSIS_LIST,
]

export const DEFAULT_LIST_OF_LISTS: string[] = [...DEFAULT_ACTIVE_LIST_URLS, ...DEFAULT_INACTIVE_LIST_URLS]
7 changes: 7 additions & 0 deletions src/constants/networks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ export const FALLBACK_URLS = {
'https://1rpc.io/base',
'https://base.meowrpc.com',
],
[ChainId.GNOSIS]: [
// "Safe" URLs
'https://rpc.gnosischain.com',
'https://rpc.gnosis.gateway.fm',
'https://rpc.ankr.com/gnosis',
],
}

/**
Expand All @@ -126,4 +132,5 @@ export const RPC_URLS = {
[ChainId.BNB]: [...FALLBACK_URLS[ChainId.BNB]],
[ChainId.AVALANCHE]: [...FALLBACK_URLS[ChainId.AVALANCHE]],
[ChainId.BASE]: [...FALLBACK_URLS[ChainId.BASE]],
[ChainId.GNOSIS]: FALLBACK_URLS[ChainId.GNOSIS],
}
1 change: 1 addition & 0 deletions src/constants/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ export const RPC_PROVIDERS: { [key in SupportedInterfaceChain]: StaticJsonRpcPro
[ChainId.BNB]: providerFactory(ChainId.BNB),
[ChainId.AVALANCHE]: providerFactory(ChainId.AVALANCHE),
[ChainId.BASE]: providerFactory(ChainId.BASE),
[ChainId.GNOSIS]: providerFactory(ChainId.GNOSIS),
}
11 changes: 11 additions & 0 deletions src/constants/routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,25 @@ import {
USDC_AVALANCHE,
USDC_BASE,
USDC_BSC,
USDC_GNOSIS,
USDC_MAINNET,
USDC_OPTIMISM,
USDC_POLYGON,
USDT,
USDT_ARBITRUM_ONE,
USDT_AVALANCHE,
USDT_BSC,
USDT_GNOSIS,
USDT_OPTIMISM,
USDT_POLYGON,
WBTC,
WBTC_ARBITRUM_ONE,
WBTC_CELO,
WBTC_GNOSIS,
WBTC_OPTIMISM,
WBTC_POLYGON,
WETH_AVALANCHE,
WETH_GNOSIS,
WETH_POLYGON,
WETH_POLYGON_MUMBAI,
WRAPPED_NATIVE_CURRENCY,
Expand Down Expand Up @@ -137,6 +141,13 @@ export const BASES_TO_TRACK_LIQUIDITY_FOR: ChainTokenList = {
USDT_AVALANCHE,
WETH_AVALANCHE,
],
[ChainId.GNOSIS]: [
...WRAPPED_NATIVE_CURRENCIES_ONLY[ChainId.GNOSIS],
USDC_GNOSIS,
USDT_GNOSIS,
WETH_GNOSIS,
WBTC_GNOSIS,
],
}
export const PINNED_PAIRS: { readonly [chainId: number]: [Token, Token][] } = {
[ChainId.MAINNET]: [
Expand Down
55 changes: 55 additions & 0 deletions src/constants/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,29 @@ export const DAI_AVALANCHE = new Token(
'Dai.e Token'
)

export const USDC_GNOSIS = new Token(ChainId.GNOSIS, '0xddafbb505ad214d7b80b1f830fccc89b60fb7a83', 6, 'USDC', 'USD//C')
export const USDT_GNOSIS = new Token(
ChainId.GNOSIS,
'0x4ecaba5870353805a9f068101a40e0f32ed605c6',
6,
'USDT',
'Tether USD'
)
export const WETH_GNOSIS = new Token(
ChainId.GNOSIS,
'0x6a023ccd1ff6f2045c3309768ead9e68f978f6e1',
18,
'WETH',
'Wrapped Ether'
)
export const WBTC_GNOSIS = new Token(
ChainId.GNOSIS,
'0x8e5bbbb09ed1ebde8674cda39a0c169401db4252',
8,
'WBT',
'Wrapped BTC'
)

export const UNI: { [chainId: number]: Token } = {
[ChainId.MAINNET]: new Token(ChainId.MAINNET, UNI_ADDRESSES[ChainId.MAINNET], 18, 'UNI', 'Uniswap'),
[ChainId.GOERLI]: new Token(ChainId.GOERLI, UNI_ADDRESSES[ChainId.GOERLI], 18, 'UNI', 'Uniswap'),
Expand Down Expand Up @@ -336,6 +359,13 @@ export const WRAPPED_NATIVE_CURRENCY: { [chainId: number]: Token | undefined } =
'WAVAX',
'Wrapped AVAX'
),
[ChainId.GNOSIS]: new Token(
ChainId.GNOSIS,
'0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d',
18,
'WXDAI',
'Wrapped XDAI'
),
}

export function isCelo(chainId: number): chainId is ChainId.CELO | ChainId.CELO_ALFAJORES {
Expand Down Expand Up @@ -419,6 +449,28 @@ class AvaxNativeCurrency extends NativeCurrency {
}
}

export function isGnosis(chainId: number): chainId is ChainId.GNOSIS {
return chainId === ChainId.GNOSIS
}

class GnosisNativeCurrency extends NativeCurrency {
equals(other: Currency): boolean {
return other.isNative && other.chainId === this.chainId
}

get wrapped(): Token {
if (!isGnosis(this.chainId)) throw new Error('Not gnosis')
const wrapped = WRAPPED_NATIVE_CURRENCY[this.chainId]
invariant(wrapped instanceof Token)
return wrapped
}

public constructor(chainId: number) {
if (!isGnosis(chainId)) throw new Error('Not gnosis')
super(chainId, 18, 'xDAI', 'xDAI')
}
}

class ExtendedEther extends Ether {
public get wrapped(): Token {
const wrapped = WRAPPED_NATIVE_CURRENCY[this.chainId]
Expand All @@ -445,6 +497,8 @@ export function nativeOnChain(chainId: number): NativeCurrency | Token {
nativeCurrency = new BscNativeCurrency(chainId)
} else if (isAvalanche(chainId)) {
nativeCurrency = new AvaxNativeCurrency(chainId)
} else if (isGnosis(chainId)) {
nativeCurrency = new GnosisNativeCurrency(chainId)
} else {
nativeCurrency = ExtendedEther.onChain(chainId)
}
Expand Down Expand Up @@ -473,5 +527,6 @@ export const TOKEN_SHORTHANDS: { [shorthand: string]: { [chainId in ChainId]?: s
[ChainId.GOERLI]: USDC_GOERLI.address,
[ChainId.SEPOLIA]: USDC_SEPOLIA.address,
[ChainId.AVALANCHE]: USDC_AVALANCHE.address,
[ChainId.GNOSIS]: USDC_GNOSIS.address,
},
}
1 change: 1 addition & 0 deletions src/hooks/useStablecoinPrice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const STABLECOIN_AMOUNT_OUT: { [chainId: number]: CurrencyAmount<Token> } = {
[ChainId.CELO]: CurrencyAmount.fromRawAmount(CUSD_CELO, 10_000e18),
[ChainId.BNB]: CurrencyAmount.fromRawAmount(USDT_BSC, 100e18),
[ChainId.AVALANCHE]: CurrencyAmount.fromRawAmount(USDC_AVALANCHE, 10_000e6),
[ChainId.GNOSIS]: CurrencyAmount.fromRawAmount(USDC_AVALANCHE, 10_000e6),
}

/**
Expand Down
7 changes: 6 additions & 1 deletion src/lib/hooks/useCurrencyLogoURIs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import AvaxLogo from '../../assets/svg/avax_logo.svg'
import BnbLogo from '../../assets/svg/bnb-logo.svg'
import CeloLogo from '../../assets/svg/celo_logo.svg'
import MaticLogo from '../../assets/svg/matic-token-icon.svg'
import GnosisLogo from '../../assets/svg/xdai_logo.svg'
import { isCelo, NATIVE_CHAIN_ID, nativeOnChain } from '../../constants/tokens'

type Network = 'ethereum' | 'arbitrum' | 'optimism' | 'polygon' | 'smartchain' | 'celo' | 'avalanchec'
type Network = 'ethereum' | 'arbitrum' | 'optimism' | 'polygon' | 'smartchain' | 'celo' | 'avalanchec' | 'gnosis'

export function chainIdToNetworkName(networkId: ChainId): Network {
switch (networkId) {
Expand All @@ -28,6 +29,8 @@ export function chainIdToNetworkName(networkId: ChainId): Network {
return 'celo'
case ChainId.AVALANCHE:
return 'avalanchec'
case ChainId.GNOSIS:
return 'gnosis'
default:
return 'ethereum'
}
Expand All @@ -45,6 +48,8 @@ export function getNativeLogoURI(chainId: ChainId = ChainId.MAINNET): string {
return CeloLogo
case ChainId.AVALANCHE:
return AvaxLogo
case ChainId.GNOSIS:
return GnosisLogo
default:
return EthereumLogo
}
Expand Down
2 changes: 2 additions & 0 deletions src/lib/state/multicall.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ function getBlocksPerFetchForChainId(chainId: number | undefined): number {
case ChainId.CELO:
case ChainId.CELO_ALFAJORES:
return 5
case ChainId.GNOSIS:
return 2
default:
return 1
}
Expand Down
1 change: 1 addition & 0 deletions src/state/routing/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ export enum SwapRouterNativeAssets {
BNB = 'BNB',
AVAX = 'AVAX',
ETH = 'ETH',
XDAI = 'xDAI',
}

export enum URAQuoteType {
Expand Down
3 changes: 2 additions & 1 deletion src/state/routing/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { MixedRouteSDK } from '@uniswap/router-sdk'
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
import { Pair, Route as V2Route } from '@uniswap/v2-sdk'
import { FeeAmount, Pool, Route as V3Route } from '@uniswap/v3-sdk'
import { isAvalanche, isBsc, isMatic, nativeOnChain } from 'constants/tokens'
import { isAvalanche, isBsc, isGnosis, isMatic, nativeOnChain } from 'constants/tokens'

import { getApproveInfo } from './gas'
import {
Expand Down Expand Up @@ -226,6 +226,7 @@ export function currencyAddressForSwapQuote(currency: Currency): string {
if (isMatic(currency.chainId)) return SwapRouterNativeAssets.MATIC
if (isBsc(currency.chainId)) return SwapRouterNativeAssets.BNB
if (isAvalanche(currency.chainId)) return SwapRouterNativeAssets.AVAX
if (isGnosis(currency.chainId)) return SwapRouterNativeAssets.XDAI
return SwapRouterNativeAssets.ETH
}

Expand Down
3 changes: 2 additions & 1 deletion src/state/transactions/hooks.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { BigNumber } from '@ethersproject/bignumber'
import type { TransactionResponse } from '@ethersproject/providers'
import { ChainId, SUPPORTED_CHAINS, Token } from '@uniswap/sdk-core'
import { ChainId, Token } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { getTransactionStatus } from 'components/AccountDrawer/MiniPortfolio/Activity/parseLocal'
import { SUPPORTED_CHAINS } from 'constants/chains'
import { SwapResult } from 'hooks/useSwapCallback'
import { useCallback, useMemo } from 'react'
import { useAppDispatch, useAppSelector } from 'state/hooks'
Expand Down
Loading