feat: Add BNB Network support (#6036)

* Support BNB Chain

* Update Interface with BNB Chain

* use SupportedChainId from sdk

* yarn-deduplicate

* add rpc urls

* add support for arbitrum goerli

* add arbitrum_goerli to jsonrpc list

* remove eslint disables

* remove non-existent gql gen Chain type

* fix import issues

* fix test

* Update src/utils/getExplorerLink.ts

Co-authored-by: Tina <59578595+tinaszheng@users.noreply.github.com>

* add quicknode rpc as primary

* bump universal router sdk to support bnb chain

* add correct network name for asset repo indexing

* add v3 smart order router

* yarn-deduplicate --strategy=highest

* let ethersproject stuff update

* remove safety test that is no longer relevant

* update network info link

* fix block explorer stuff, fix light theme

* add subgraph support

* update quicknode rpc

* update the wrapped BNB token symbol to WBNB

* update useStablecoinPrice api to support loading states

* update useStablecoinPrice api to support loading states

* Revert "update useStablecoinPrice api to support loading states"

This reverts commit c1fa6297d06fdf5100c1d5dfea6a820f7a0eeb7b.

* Revert "update useStablecoinPrice api to support loading states"

This reverts commit 2e703552b591fd56d032fe35afab9ead911f2ab2.

* fix copy and quote token for non-eth networks

* add coingecko bnb list

* fix: design treatment from @infredible for bnb support (#6052)

merging in current state--can merge again when the rest is ready

* fix info site links

* fix: don't show a price impact warning if the user is (un)wrapping

* finish switching to chains/constants

* fix chainId test

* fred's bnb background colors

* pr feedback from zzmp

* update sdk-core

* remove unused image

* update bnb chain asset url extension

* new addresses

* fix test and patch sdk-core version to use BNB instead of BSC

* checking in this weird schema file--maybe a mistake?

* remove temp file

* fix bases

* fix network bridge alert text color

* fix: widget defaultToken resetting on TDP

---------

Co-authored-by: ILIA.eth <4621066+ilyamk@users.noreply.github.com>
Co-authored-by: Tina <59578595+tinaszheng@users.noreply.github.com>
Co-authored-by: lynn <41491154+lynnshaoyu@users.noreply.github.com>
Co-authored-by: Tina Zheng <tina.s.zheng+github@gmail.com>
Co-authored-by: Eddie Dugan <eddie.dugan@uniswap.org>
This commit is contained in:
Jordan Frankfurt 2023-03-15 09:00:09 -05:00 committed by GitHub
parent 813aeda012
commit d3085c1f3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 311 additions and 36 deletions

1
.env

@ -11,3 +11,4 @@ REACT_APP_INFURA_KEY="4bf032f2d38a4ed6bb975b80d6340847"
REACT_APP_MOONPAY_API="https://api.moonpay.com" REACT_APP_MOONPAY_API="https://api.moonpay.com"
REACT_APP_MOONPAY_LINK="https://us-central1-uniswap-mobile.cloudfunctions.net/signMoonpayLinkStaging?platform=web" REACT_APP_MOONPAY_LINK="https://us-central1-uniswap-mobile.cloudfunctions.net/signMoonpayLinkStaging?platform=web"
REACT_APP_MOONPAY_PUBLISHABLE_KEY="pk_test_DycfESRid31UaSxhI5yWKe1r5E5kKSz" REACT_APP_MOONPAY_PUBLISHABLE_KEY="pk_test_DycfESRid31UaSxhI5yWKe1r5E5kKSz"
REACT_APP_BNB_RPC_URL="https://rough-sleek-hill.bsc.quiknode.pro/413cc98cbc776cda8fdf1d0f47003583ff73d9bf"

@ -11,3 +11,4 @@ REACT_APP_MOONPAY_PUBLISHABLE_KEY="pk_live_uQG4BJC4w3cxnqpcSqAfohdBFDTsY6E"
REACT_APP_FIREBASE_KEY="AIzaSyBcZWwTcTJHj_R6ipZcrJkXdq05PuX0Rs0" REACT_APP_FIREBASE_KEY="AIzaSyBcZWwTcTJHj_R6ipZcrJkXdq05PuX0Rs0"
THE_GRAPH_SCHEMA_ENDPOINT="https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3" THE_GRAPH_SCHEMA_ENDPOINT="https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3"
REACT_APP_SENTRY_ENABLED=false REACT_APP_SENTRY_ENABLED=false
REACT_APP_BNB_RPC_URL="https://old-wispy-arrow.bsc.quiknode.pro/f5c060177236065c1058531a0615ab4f7a34a2fd"

@ -1,6 +1,6 @@
{ {
"name": "@uniswap/interface", "name": "@uniswap/interface",
"version": "1.0.7", "version": "1.1.0",
"description": "Uniswap Interface", "description": "Uniswap Interface",
"homepage": ".", "homepage": ".",
"license": "GPL-3.0-or-later", "license": "GPL-3.0-or-later",
@ -144,10 +144,10 @@
"@uniswap/permit2-sdk": "1.2.0", "@uniswap/permit2-sdk": "1.2.0",
"@uniswap/redux-multicall": "^1.1.8", "@uniswap/redux-multicall": "^1.1.8",
"@uniswap/router-sdk": "^1.3.0", "@uniswap/router-sdk": "^1.3.0",
"@uniswap/sdk-core": "^3.2.0", "@uniswap/sdk-core": "^3.2.2",
"@uniswap/smart-order-router": "^3.6.1", "@uniswap/smart-order-router": "^3.6.1",
"@uniswap/token-lists": "^1.0.0-beta.30", "@uniswap/token-lists": "^1.0.0-beta.30",
"@uniswap/universal-router-sdk": "^1.3.6", "@uniswap/universal-router-sdk": "^1.3.8",
"@uniswap/v2-core": "1.0.0", "@uniswap/v2-core": "1.0.0",
"@uniswap/v2-periphery": "^1.1.0-beta.0", "@uniswap/v2-periphery": "^1.1.0-beta.0",
"@uniswap/v2-sdk": "^3.0.1", "@uniswap/v2-sdk": "^3.0.1",

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 2496 2496" style="enable-background:new 0 0 2496 2496;" xml:space="preserve">
<g>
<path style="fill-rule:evenodd;clip-rule:evenodd;fill:#F0B90B;" d="M1248,0c689.3,0,1248,558.7,1248,1248s-558.7,1248-1248,1248
S0,1937.3,0,1248S558.7,0,1248,0L1248,0z"/>
<path style="fill:#FFFFFF;" d="M685.9,1248l0.9,330l280.4,165v193.2l-444.5-260.7v-524L685.9,1248L685.9,1248z M685.9,918v192.3
l-163.3-96.6V821.4l163.3-96.6l164.1,96.6L685.9,918L685.9,918z M1084.3,821.4l163.3-96.6l164.1,96.6L1247.6,918L1084.3,821.4
L1084.3,821.4z"/>
<path style="fill:#FFFFFF;" d="M803.9,1509.6v-193.2l163.3,96.6v192.3L803.9,1509.6L803.9,1509.6z M1084.3,1812.2l163.3,96.6
l164.1-96.6v192.3l-164.1,96.6l-163.3-96.6V1812.2L1084.3,1812.2z M1645.9,821.4l163.3-96.6l164.1,96.6v192.3l-164.1,96.6V918
L1645.9,821.4L1645.9,821.4L1645.9,821.4z M1809.2,1578l0.9-330l163.3-96.6v524l-444.5,260.7v-193.2L1809.2,1578L1809.2,1578
L1809.2,1578z"/>
<polygon style="fill:#FFFFFF;" points="1692.1,1509.6 1528.8,1605.3 1528.8,1413 1692.1,1316.4 1692.1,1509.6 "/>
<path style="fill:#FFFFFF;" d="M1692.1,986.4l0.9,193.2l-281.2,165v330.8l-163.3,95.7l-163.3-95.7v-330.8l-281.2-165V986.4
L968,889.8l279.5,165.8l281.2-165.8l164.1,96.6H1692.1L1692.1,986.4z M803.9,656.5l443.7-261.6l444.5,261.6l-163.3,96.6
l-281.2-165.8L967.2,753.1L803.9,656.5L803.9,656.5z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@ -17,6 +17,7 @@ export const FEE_AMOUNT_DETAIL: Record<
SupportedChainId.CELO, SupportedChainId.CELO,
SupportedChainId.CELO_ALFAJORES, SupportedChainId.CELO_ALFAJORES,
SupportedChainId.OPTIMISM, SupportedChainId.OPTIMISM,
SupportedChainId.BNB,
], ],
}, },
[FeeAmount.LOW]: { [FeeAmount.LOW]: {

@ -25,6 +25,7 @@ const NETWORK_SELECTOR_CHAINS = [
SupportedChainId.OPTIMISM, SupportedChainId.OPTIMISM,
SupportedChainId.ARBITRUM_ONE, SupportedChainId.ARBITRUM_ONE,
SupportedChainId.CELO, SupportedChainId.CELO,
SupportedChainId.BNB,
] ]
interface ChainSelectorProps { interface ChainSelectorProps {

@ -6,6 +6,7 @@ import { ArrowUpRight } from 'react-feather'
import { useDarkModeManager } from 'state/user/hooks' import { useDarkModeManager } from 'state/user/hooks'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { ExternalLink, HideSmall } from 'theme' import { ExternalLink, HideSmall } from 'theme'
import { colors } from 'theme/colors'
import { AutoRow } from '../Row' import { AutoRow } from '../Row'
@ -36,6 +37,7 @@ const SHOULD_SHOW_ALERT = {
[SupportedChainId.POLYGON_MUMBAI]: true, [SupportedChainId.POLYGON_MUMBAI]: true,
[SupportedChainId.CELO]: true, [SupportedChainId.CELO]: true,
[SupportedChainId.CELO_ALFAJORES]: true, [SupportedChainId.CELO_ALFAJORES]: true,
[SupportedChainId.BNB]: true,
} }
type NetworkAlertChains = keyof typeof SHOULD_SHOW_ALERT type NetworkAlertChains = keyof typeof SHOULD_SHOW_ALERT
@ -52,6 +54,8 @@ const BG_COLORS_BY_DARK_MODE_AND_CHAIN_ID: {
'radial-gradient(182.71% 150.59% at 2.81% 7.69%, rgba(90, 190, 170, 0.15) 0%, rgba(80, 160, 40, 0.15) 100%)', 'radial-gradient(182.71% 150.59% at 2.81% 7.69%, rgba(90, 190, 170, 0.15) 0%, rgba(80, 160, 40, 0.15) 100%)',
[SupportedChainId.CELO_ALFAJORES]: [SupportedChainId.CELO_ALFAJORES]:
'radial-gradient(182.71% 150.59% at 2.81% 7.69%, rgba(90, 190, 170, 0.15) 0%, rgba(80, 160, 40, 0.15) 100%)', 'radial-gradient(182.71% 150.59% at 2.81% 7.69%, rgba(90, 190, 170, 0.15) 0%, rgba(80, 160, 40, 0.15) 100%)',
[SupportedChainId.BNB]:
'radial-gradient(182.71% 150.59% at 2.81% 7.69%, rgba(240, 185, 11, 0.16) 0%, rgba(255, 168, 0, 0.16) 100%)',
[SupportedChainId.OPTIMISM]: [SupportedChainId.OPTIMISM]:
'radial-gradient(948% 292% at 42% 0%, rgba(255, 58, 212, 0.01) 0%, rgba(255, 255, 255, 0.04) 100%),radial-gradient(98% 96% at 2% 0%, rgba(255, 39, 39, 0.01) 0%, rgba(235, 0, 255, 0.01) 96%)', 'radial-gradient(948% 292% at 42% 0%, rgba(255, 58, 212, 0.01) 0%, rgba(255, 255, 255, 0.04) 100%),radial-gradient(98% 96% at 2% 0%, rgba(255, 39, 39, 0.01) 0%, rgba(235, 0, 255, 0.01) 96%)',
[SupportedChainId.OPTIMISM_GOERLI]: [SupportedChainId.OPTIMISM_GOERLI]:
@ -70,6 +74,8 @@ const BG_COLORS_BY_DARK_MODE_AND_CHAIN_ID: {
'radial-gradient(182.71% 150.59% at 2.81% 7.69%, rgba(63, 208, 137, 0.15) 0%, rgba(49, 205, 50, 0.15) 100%)', 'radial-gradient(182.71% 150.59% at 2.81% 7.69%, rgba(63, 208, 137, 0.15) 0%, rgba(49, 205, 50, 0.15) 100%)',
[SupportedChainId.CELO_ALFAJORES]: [SupportedChainId.CELO_ALFAJORES]:
'radial-gradient(182.71% 150.59% at 2.81% 7.69%, rgba(63, 208, 137, 0.15) 0%, rgba(49, 205, 50, 0.15) 100%)', 'radial-gradient(182.71% 150.59% at 2.81% 7.69%, rgba(63, 208, 137, 0.15) 0%, rgba(49, 205, 50, 0.15) 100%)',
[SupportedChainId.BNB]:
'radial-gradient(182.71% 150.59% at 2.81% 7.69%, rgba(240, 185, 11, 0.16) 0%, rgba(255, 168, 0, 0.16) 100%)',
[SupportedChainId.OPTIMISM]: [SupportedChainId.OPTIMISM]:
'radial-gradient(92% 105% at 50% 7%, rgba(255, 58, 212, 0.04) 0%, rgba(255, 255, 255, 0.03) 100%),radial-gradient(100% 97% at 0% 12%, rgba(235, 0, 255, 0.1) 0%, rgba(243, 19, 19, 0.1) 100%), hsla(0, 0%, 100%, 0.1)', 'radial-gradient(92% 105% at 50% 7%, rgba(255, 58, 212, 0.04) 0%, rgba(255, 255, 255, 0.03) 100%),radial-gradient(100% 97% at 0% 12%, rgba(235, 0, 255, 0.1) 0%, rgba(243, 19, 19, 0.1) 100%), hsla(0, 0%, 100%, 0.1)',
[SupportedChainId.OPTIMISM_GOERLI]: [SupportedChainId.OPTIMISM_GOERLI]:
@ -135,6 +141,7 @@ const TEXT_COLORS: { [chainId in NetworkAlertChains]: string } = {
[SupportedChainId.OPTIMISM]: '#ff3856', [SupportedChainId.OPTIMISM]: '#ff3856',
[SupportedChainId.OPTIMISM_GOERLI]: '#ff3856', [SupportedChainId.OPTIMISM_GOERLI]: '#ff3856',
[SupportedChainId.ARBITRUM_ONE]: '#0490ed', [SupportedChainId.ARBITRUM_ONE]: '#0490ed',
[SupportedChainId.BNB]: colors.gold200,
[SupportedChainId.ARBITRUM_GOERLI]: '#0490ed', [SupportedChainId.ARBITRUM_GOERLI]: '#0490ed',
} }

@ -3,7 +3,7 @@ import { Currency } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import Badge from 'components/Badge' import Badge from 'components/Badge'
import { getChainInfo } from 'constants/chainInfo' import { getChainInfo } from 'constants/chainInfo'
import { SupportedL2ChainId } from 'constants/chains' import { SupportedChainId, SupportedL2ChainId } from 'constants/chains'
import useCurrencyLogoURIs from 'lib/hooks/useCurrencyLogoURIs' import useCurrencyLogoURIs from 'lib/hooks/useCurrencyLogoURIs'
import { ReactNode, useCallback, useState } from 'react' import { ReactNode, useCallback, useState } from 'react'
import { AlertCircle, AlertTriangle, ArrowUpCircle, CheckCircle } from 'react-feather' import { AlertCircle, AlertTriangle, ArrowUpCircle, CheckCircle } from 'react-feather'
@ -161,7 +161,7 @@ function TransactionSubmittedContent({
{chainId && hash && ( {chainId && hash && (
<ExternalLink href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)}> <ExternalLink href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)}>
<Text fontWeight={600} fontSize={14} color={theme.accentAction}> <Text fontWeight={600} fontSize={14} color={theme.accentAction}>
<Trans>View on Etherscan</Trans> <Trans>View on {chainId === SupportedChainId.MAINNET ? 'Etherscan' : 'Block Explorer'}</Trans>
</Text> </Text>
</ExternalLink> </ExternalLink>
)} )}

@ -74,7 +74,10 @@ export function useSyncWidgetInputs({
useEffect(() => { useEffect(() => {
if (chainId !== previousChainId && !!previousChainId && isSupportedChain(chainId)) { if (chainId !== previousChainId && !!previousChainId && isSupportedChain(chainId)) {
setTokens(defaultTokens) setTokens({
...defaultTokens,
[Field.OUTPUT]: defaultTokens[Field.OUTPUT] ?? defaultTokens.default,
})
setAmount(EMPTY_AMOUNT) setAmount(EMPTY_AMOUNT)
} }
}, [chainId, defaultTokens, previousChainId, tokens]) }, [chainId, defaultTokens, previousChainId, tokens])

@ -1,4 +1,5 @@
import { TooltipContainer } from 'components/Tooltip' import { TooltipContainer } from 'components/Tooltip'
import { SupportedChainId } from 'constants/chains'
import { transparentize } from 'polished' import { transparentize } from 'polished'
import { ReactNode } from 'react' import { ReactNode } from 'react'
import { AlertTriangle } from 'react-feather' import { AlertTriangle } from 'react-feather'
@ -23,12 +24,13 @@ export const PageWrapper = styled.div`
` `
// Mostly copied from `AppBody` but it was getting too hard to maintain backwards compatibility. // Mostly copied from `AppBody` but it was getting too hard to maintain backwards compatibility.
export const SwapWrapper = styled.main` export const SwapWrapper = styled.main<{ chainId: number | undefined }>`
position: relative; position: relative;
background: ${({ theme }) => theme.backgroundSurface}; background: ${({ theme }) => theme.backgroundSurface};
border-radius: 16px; border-radius: 16px;
border: 1px solid ${({ theme }) => theme.backgroundOutline}; border: 1px solid ${({ theme }) => theme.backgroundOutline};
padding: 8px; padding: 8px;
box-shadow: ${({ chainId }) => !!chainId && chainId === SupportedChainId.BNB && '0px 40px 120px 0px #f0b90b29'};
z-index: ${Z_INDEX.deprecated_content}; z-index: ${Z_INDEX.deprecated_content};
transition: transform 250ms ease; transition: transform 250ms ease;

@ -21,6 +21,14 @@ const CELO_QUOTER_ADDRESSES = '0x82825d0554fA07f7FC52Ab63c961F330fdEFa8E8'
const CELO_NONFUNGIBLE_POSITION_MANAGER_ADDRESSES = '0x3d79EdAaBC0EaB6F08ED885C05Fc0B014290D95A' const CELO_NONFUNGIBLE_POSITION_MANAGER_ADDRESSES = '0x3d79EdAaBC0EaB6F08ED885C05Fc0B014290D95A'
const CELO_TICK_LENS_ADDRESSES = '0x5f115D9113F88e0a0Db1b5033D90D4a9690AcD3D' const CELO_TICK_LENS_ADDRESSES = '0x5f115D9113F88e0a0Db1b5033D90D4a9690AcD3D'
// BNB v3 addresses
const BNB_V3_CORE_FACTORY_ADDRESSES = '0xdB1d10011AD0Ff90774D0C6Bb92e5C5c8b4461F7'
const BNB_V3_MIGRATOR_ADDRESSES = '0x32681814957e0C13117ddc0c2aba232b5c9e760f'
const BNB_MULTICALL_ADDRESS = '0x963Df249eD09c358A4819E39d9Cd5736c3087184'
const BNB_QUOTER_ADDRESSES = '0x78D78E420Da98ad378D7799bE8f4AF69033EB077'
const BNB_NONFUNGIBLE_POSITION_MANAGER_ADDRESSES = '0x7b8A01B39D58278b5DE7e48c8449c9f4F5170613'
const BNB_TICK_LENS_ADDRESSES = '0xD9270014D396281579760619CCf4c3af0501A47C'
// optimism goerli addresses // optimism goerli addresses
const OPTIMISM_GOERLI_V3_CORE_FACTORY_ADDRESSES = '0xB656dA17129e7EB733A557f4EBc57B76CFbB5d10' const OPTIMISM_GOERLI_V3_CORE_FACTORY_ADDRESSES = '0xB656dA17129e7EB733A557f4EBc57B76CFbB5d10'
const OPTIMISM_GOERLI_V3_MIGRATOR_ADDRESSES = '0xf6c55fBe84B1C8c3283533c53F51bC32F5C7Aba8' const OPTIMISM_GOERLI_V3_MIGRATOR_ADDRESSES = '0xf6c55fBe84B1C8c3283533c53F51bC32F5C7Aba8'
@ -47,6 +55,7 @@ export const V3_CORE_FACTORY_ADDRESSES: AddressMap = {
]), ]),
[SupportedChainId.CELO]: CELO_V3_CORE_FACTORY_ADDRESSES, [SupportedChainId.CELO]: CELO_V3_CORE_FACTORY_ADDRESSES,
[SupportedChainId.CELO_ALFAJORES]: CELO_V3_CORE_FACTORY_ADDRESSES, [SupportedChainId.CELO_ALFAJORES]: CELO_V3_CORE_FACTORY_ADDRESSES,
[SupportedChainId.BNB]: BNB_V3_CORE_FACTORY_ADDRESSES,
[SupportedChainId.OPTIMISM_GOERLI]: OPTIMISM_GOERLI_V3_CORE_FACTORY_ADDRESSES, [SupportedChainId.OPTIMISM_GOERLI]: OPTIMISM_GOERLI_V3_CORE_FACTORY_ADDRESSES,
[SupportedChainId.ARBITRUM_GOERLI]: ARBITRUM_GOERLI_V3_CORE_FACTORY_ADDRESSES, [SupportedChainId.ARBITRUM_GOERLI]: ARBITRUM_GOERLI_V3_CORE_FACTORY_ADDRESSES,
} }
@ -59,6 +68,7 @@ export const V3_MIGRATOR_ADDRESSES: AddressMap = {
]), ]),
[SupportedChainId.CELO]: CELO_V3_MIGRATOR_ADDRESSES, [SupportedChainId.CELO]: CELO_V3_MIGRATOR_ADDRESSES,
[SupportedChainId.CELO_ALFAJORES]: CELO_V3_MIGRATOR_ADDRESSES, [SupportedChainId.CELO_ALFAJORES]: CELO_V3_MIGRATOR_ADDRESSES,
[SupportedChainId.BNB]: BNB_V3_MIGRATOR_ADDRESSES,
[SupportedChainId.OPTIMISM_GOERLI]: OPTIMISM_GOERLI_V3_MIGRATOR_ADDRESSES, [SupportedChainId.OPTIMISM_GOERLI]: OPTIMISM_GOERLI_V3_MIGRATOR_ADDRESSES,
[SupportedChainId.ARBITRUM_GOERLI]: ARBITRUM_GOERLI_V3_MIGRATOR_ADDRESSES, [SupportedChainId.ARBITRUM_GOERLI]: ARBITRUM_GOERLI_V3_MIGRATOR_ADDRESSES,
} }
@ -72,6 +82,7 @@ export const MULTICALL_ADDRESS: AddressMap = {
[SupportedChainId.ARBITRUM_ONE]: '0xadF885960B47eA2CD9B55E6DAc6B42b7Cb2806dB', [SupportedChainId.ARBITRUM_ONE]: '0xadF885960B47eA2CD9B55E6DAc6B42b7Cb2806dB',
[SupportedChainId.CELO]: CELO_MULTICALL_ADDRESS, [SupportedChainId.CELO]: CELO_MULTICALL_ADDRESS,
[SupportedChainId.CELO_ALFAJORES]: CELO_MULTICALL_ADDRESS, [SupportedChainId.CELO_ALFAJORES]: CELO_MULTICALL_ADDRESS,
[SupportedChainId.BNB]: BNB_MULTICALL_ADDRESS,
[SupportedChainId.OPTIMISM_GOERLI]: OPTIMISM_GOERLI_MULTICALL_ADDRESS, [SupportedChainId.OPTIMISM_GOERLI]: OPTIMISM_GOERLI_MULTICALL_ADDRESS,
[SupportedChainId.ARBITRUM_GOERLI]: ARBITRUM_GOERLI_MULTICALL_ADDRESS, [SupportedChainId.ARBITRUM_GOERLI]: ARBITRUM_GOERLI_MULTICALL_ADDRESS,
} }
@ -114,6 +125,7 @@ export const QUOTER_ADDRESSES: AddressMap = {
]), ]),
[SupportedChainId.CELO]: CELO_QUOTER_ADDRESSES, [SupportedChainId.CELO]: CELO_QUOTER_ADDRESSES,
[SupportedChainId.CELO_ALFAJORES]: CELO_QUOTER_ADDRESSES, [SupportedChainId.CELO_ALFAJORES]: CELO_QUOTER_ADDRESSES,
[SupportedChainId.BNB]: BNB_QUOTER_ADDRESSES,
[SupportedChainId.OPTIMISM_GOERLI]: OPTIMISM_GOERLI_QUOTER_ADDRESSES, [SupportedChainId.OPTIMISM_GOERLI]: OPTIMISM_GOERLI_QUOTER_ADDRESSES,
[SupportedChainId.ARBITRUM_GOERLI]: ARBITRUM_GOERLI_QUOTER_ADDRESSES, [SupportedChainId.ARBITRUM_GOERLI]: ARBITRUM_GOERLI_QUOTER_ADDRESSES,
} }
@ -127,6 +139,7 @@ export const NONFUNGIBLE_POSITION_MANAGER_ADDRESSES: AddressMap = {
]), ]),
[SupportedChainId.CELO]: CELO_NONFUNGIBLE_POSITION_MANAGER_ADDRESSES, [SupportedChainId.CELO]: CELO_NONFUNGIBLE_POSITION_MANAGER_ADDRESSES,
[SupportedChainId.CELO_ALFAJORES]: CELO_NONFUNGIBLE_POSITION_MANAGER_ADDRESSES, [SupportedChainId.CELO_ALFAJORES]: CELO_NONFUNGIBLE_POSITION_MANAGER_ADDRESSES,
[SupportedChainId.BNB]: BNB_NONFUNGIBLE_POSITION_MANAGER_ADDRESSES,
[SupportedChainId.OPTIMISM_GOERLI]: OPTIMISM_GOERLI_NONFUNGIBLE_POSITION_MANAGER_ADDRESSES, [SupportedChainId.OPTIMISM_GOERLI]: OPTIMISM_GOERLI_NONFUNGIBLE_POSITION_MANAGER_ADDRESSES,
[SupportedChainId.ARBITRUM_GOERLI]: ARBITRUM_GOERLI_NONFUNGIBLE_POSITION_MANAGER_ADDRESSES, [SupportedChainId.ARBITRUM_GOERLI]: ARBITRUM_GOERLI_NONFUNGIBLE_POSITION_MANAGER_ADDRESSES,
} }
@ -145,5 +158,6 @@ export const TICK_LENS_ADDRESSES: AddressMap = {
[SupportedChainId.ARBITRUM_GOERLI]: ARBITRUM_GOERLI_TICK_LENS_ADDRESSES, [SupportedChainId.ARBITRUM_GOERLI]: ARBITRUM_GOERLI_TICK_LENS_ADDRESSES,
[SupportedChainId.CELO]: CELO_TICK_LENS_ADDRESSES, [SupportedChainId.CELO]: CELO_TICK_LENS_ADDRESSES,
[SupportedChainId.CELO_ALFAJORES]: CELO_TICK_LENS_ADDRESSES, [SupportedChainId.CELO_ALFAJORES]: CELO_TICK_LENS_ADDRESSES,
[SupportedChainId.BNB]: BNB_TICK_LENS_ADDRESSES,
[SupportedChainId.OPTIMISM_GOERLI]: OPTIMISM_GOERLI_TICK_LENS_ADDRESSES, [SupportedChainId.OPTIMISM_GOERLI]: OPTIMISM_GOERLI_TICK_LENS_ADDRESSES,
} }

@ -1,7 +1,9 @@
import bnbCircleLogoUrl from 'assets/images/bnbCircle.png'
import celoCircleLogoUrl from 'assets/images/celoCircle.png' import celoCircleLogoUrl from 'assets/images/celoCircle.png'
import ethereumLogoUrl from 'assets/images/ethereum-logo.png' import ethereumLogoUrl from 'assets/images/ethereum-logo.png'
import polygonCircleLogoUrl from 'assets/images/polygonCircle.png' import polygonCircleLogoUrl from 'assets/images/polygonCircle.png'
import { default as arbitrumCircleLogoUrl, default as arbitrumLogoUrl } from 'assets/svg/arbitrum_logo.svg' import { default as arbitrumCircleLogoUrl, default as arbitrumLogoUrl } from 'assets/svg/arbitrum_logo.svg'
import bnbLogo from 'assets/svg/bnb-logo.svg'
import celoLogo from 'assets/svg/celo_logo.svg' import celoLogo from 'assets/svg/celo_logo.svg'
import optimismLogoUrl from 'assets/svg/optimistic_ethereum.svg' import optimismLogoUrl from 'assets/svg/optimistic_ethereum.svg'
import polygonMaticLogo from 'assets/svg/polygon-matic-logo.svg' import polygonMaticLogo from 'assets/svg/polygon-matic-logo.svg'
@ -10,7 +12,7 @@ import ms from 'ms.macro'
import { darkTheme } from 'theme/colors' import { darkTheme } from 'theme/colors'
import { SupportedL1ChainId, SupportedL2ChainId } from './chains' import { SupportedL1ChainId, SupportedL2ChainId } from './chains'
import { ARBITRUM_LIST, CELO_LIST, OPTIMISM_LIST } from './lists' import { ARBITRUM_LIST, CELO_LIST, OPTIMISM_LIST, PLASMA_BNB_LIST } from './lists'
export const AVERAGE_L1_BLOCK_TIME = ms`12s` export const AVERAGE_L1_BLOCK_TIME = ms`12s`
@ -169,7 +171,7 @@ const CHAIN_INFO: ChainInfoMap = {
bridge: 'https://www.portalbridge.com/#/transfer', bridge: 'https://www.portalbridge.com/#/transfer',
docs: 'https://docs.celo.org/', docs: 'https://docs.celo.org/',
explorer: 'https://celoscan.io/', explorer: 'https://celoscan.io/',
infoLink: 'https://info.uniswap.org/#/celo', infoLink: 'https://info.uniswap.org/#/celo/',
label: 'Celo', label: 'Celo',
logoUrl: celoLogo, logoUrl: celoLogo,
circleLogoUrl: celoCircleLogoUrl, circleLogoUrl: celoCircleLogoUrl,
@ -182,12 +184,27 @@ const CHAIN_INFO: ChainInfoMap = {
bridge: 'https://www.portalbridge.com/#/transfer', bridge: 'https://www.portalbridge.com/#/transfer',
docs: 'https://docs.celo.org/', docs: 'https://docs.celo.org/',
explorer: 'https://alfajores-blockscout.celo-testnet.org/', explorer: 'https://alfajores-blockscout.celo-testnet.org/',
infoLink: 'https://info.uniswap.org/#/celo', infoLink: 'https://info.uniswap.org/#/celo/',
label: 'Celo Alfajores', label: 'Celo Alfajores',
logoUrl: celoLogo, logoUrl: celoLogo,
nativeCurrency: { name: 'Celo', symbol: 'CELO', decimals: 18 }, nativeCurrency: { name: 'Celo', symbol: 'CELO', decimals: 18 },
defaultListUrl: CELO_LIST, defaultListUrl: CELO_LIST,
}, },
[SupportedChainId.BNB]: {
networkType: NetworkType.L1,
blockWaitMsBeforeWarning: ms`10m`,
bridge: 'https://cbridge.celer.network/1/56',
docs: 'https://docs.bnbchain.org/',
explorer: 'https://bscscan.com/',
infoLink: 'https://info.uniswap.org/#/bnb/',
label: 'BNB Chain',
logoUrl: bnbLogo,
circleLogoUrl: bnbCircleLogoUrl,
nativeCurrency: { name: 'BNB', symbol: 'BNB', decimals: 18 },
defaultListUrl: PLASMA_BNB_LIST,
color: darkTheme.chain_56,
backgroundColor: darkTheme.chain_56_background,
},
} }
export function getChainInfo(chainId: SupportedL1ChainId): L1ChainInfo export function getChainInfo(chainId: SupportedL1ChainId): L1ChainInfo

@ -1,16 +1,23 @@
import { SupportedChainId as SdkSupportedChainId } from '@uniswap/sdk-core' import { SupportedChainId as SdkSupportedChainId } from '@uniswap/sdk-core'
import { SupportedChainId } from 'constants/chains'
import { ALL_SUPPORTED_CHAIN_IDS, SupportedChainId } from './chains' import { ALL_SUPPORTED_CHAIN_IDS } from './chains'
describe('chains', () => { describe('ChainIds', () => {
describe('ALL_SUPPORTED_CHAIN_IDS', () => { describe('SupportedChainId', () => {
it('derives from sdk-core', () => { it('derives from sdk-core', () => {
ALL_SUPPORTED_CHAIN_IDS.forEach((chainId) => { const SDKChains = Object.values(SdkSupportedChainId)
const chainName = SupportedChainId[chainId] .filter((chainId) => typeof chainId === 'number')
expect(SdkSupportedChainId[chainId]).toBe(chainName) .map((value) => value.toString())
}) const InterfaceChains = Object.values(SupportedChainId)
.filter((chainId) => typeof chainId === 'number')
.map((value) => value.toString())
const isSubset = InterfaceChains.every((value) => SDKChains.includes(value))
expect(isSubset).toBe(true)
}) })
})
describe('ALL_SUPPORTED_CHAIN_IDS', () => {
it('contains all the values in the SupportedChainId enum', () => { it('contains all the values in the SupportedChainId enum', () => {
Object.values(SupportedChainId) Object.values(SupportedChainId)
.filter((chainId) => typeof chainId === 'number') .filter((chainId) => typeof chainId === 'number')

@ -21,6 +21,8 @@ export enum SupportedChainId {
CELO = 42220, CELO = 42220,
CELO_ALFAJORES = 44787, CELO_ALFAJORES = 44787,
BNB = 56,
} }
export const CHAIN_IDS_TO_NAMES = { export const CHAIN_IDS_TO_NAMES = {
@ -34,6 +36,7 @@ export const CHAIN_IDS_TO_NAMES = {
[SupportedChainId.ARBITRUM_GOERLI]: 'arbitrum_goerli', [SupportedChainId.ARBITRUM_GOERLI]: 'arbitrum_goerli',
[SupportedChainId.OPTIMISM]: 'optimism', [SupportedChainId.OPTIMISM]: 'optimism',
[SupportedChainId.OPTIMISM_GOERLI]: 'optimism_goerli', [SupportedChainId.OPTIMISM_GOERLI]: 'optimism_goerli',
[SupportedChainId.BNB]: 'bnb',
} }
/** /**
@ -53,6 +56,7 @@ export const SUPPORTED_GAS_ESTIMATE_CHAIN_IDS = [
SupportedChainId.CELO, SupportedChainId.CELO,
SupportedChainId.OPTIMISM, SupportedChainId.OPTIMISM,
SupportedChainId.ARBITRUM_ONE, SupportedChainId.ARBITRUM_ONE,
SupportedChainId.BNB,
] as const ] as const
/** /**
@ -62,6 +66,7 @@ export const UNSUPPORTED_V2POOL_CHAIN_IDS = [
SupportedChainId.POLYGON, SupportedChainId.POLYGON,
SupportedChainId.OPTIMISM, SupportedChainId.OPTIMISM,
SupportedChainId.ARBITRUM_ONE, SupportedChainId.ARBITRUM_ONE,
SupportedChainId.BNB,
SupportedChainId.ARBITRUM_GOERLI, SupportedChainId.ARBITRUM_GOERLI,
] as const ] as const
@ -84,6 +89,7 @@ export const L1_CHAIN_IDS = [
SupportedChainId.POLYGON_MUMBAI, SupportedChainId.POLYGON_MUMBAI,
SupportedChainId.CELO, SupportedChainId.CELO,
SupportedChainId.CELO_ALFAJORES, SupportedChainId.CELO_ALFAJORES,
SupportedChainId.BNB,
] as const ] as const
export type SupportedL1ChainId = typeof L1_CHAIN_IDS[number] export type SupportedL1ChainId = typeof L1_CHAIN_IDS[number]

@ -5,6 +5,7 @@ const AAVE_LIST = 'tokenlist.aave.eth'
const BA_LIST = 'https://raw.githubusercontent.com/The-Blockchain-Association/sec-notice-list/master/ba-sec-list.json' const BA_LIST = 'https://raw.githubusercontent.com/The-Blockchain-Association/sec-notice-list/master/ba-sec-list.json'
const CMC_ALL_LIST = 'https://api.coinmarketcap.com/data-api/v3/uniswap/all.json' const CMC_ALL_LIST = 'https://api.coinmarketcap.com/data-api/v3/uniswap/all.json'
const COINGECKO_LIST = 'https://tokens.coingecko.com/uniswap/all.json' const COINGECKO_LIST = 'https://tokens.coingecko.com/uniswap/all.json'
const COINGECKO_BNB_LIST = 'https://tokens.coingecko.com/binance-smart-chain/all.json'
const COMPOUND_LIST = 'https://raw.githubusercontent.com/compound-finance/token-list/master/compound.tokenlist.json' const COMPOUND_LIST = 'https://raw.githubusercontent.com/compound-finance/token-list/master/compound.tokenlist.json'
const GEMINI_LIST = 'https://www.gemini.com/uniswap/manifest.json' const GEMINI_LIST = 'https://www.gemini.com/uniswap/manifest.json'
const KLEROS_LIST = 't2crtokens.eth' const KLEROS_LIST = 't2crtokens.eth'
@ -14,6 +15,7 @@ const WRAPPED_LIST = 'wrapped.tokensoft.eth'
export const OPTIMISM_LIST = 'https://static.optimism.io/optimism.tokenlist.json' export const OPTIMISM_LIST = 'https://static.optimism.io/optimism.tokenlist.json'
export const ARBITRUM_LIST = 'https://bridge.arbitrum.io/token-list-42161.json' export const ARBITRUM_LIST = 'https://bridge.arbitrum.io/token-list-42161.json'
export const CELO_LIST = 'https://celo-org.github.io/celo-token-list/celo.tokenlist.json' export const CELO_LIST = 'https://celo-org.github.io/celo-token-list/celo.tokenlist.json'
export const PLASMA_BNB_LIST = 'https://raw.githubusercontent.com/plasmadlt/plasma-finance-token-list/master/bnb.json'
export const UNSUPPORTED_LIST_URLS: string[] = [BA_LIST, UNI_UNSUPPORTED_LIST] export const UNSUPPORTED_LIST_URLS: string[] = [BA_LIST, UNI_UNSUPPORTED_LIST]
@ -25,6 +27,7 @@ export const DEFAULT_INACTIVE_LIST_URLS: string[] = [
AAVE_LIST, AAVE_LIST,
CMC_ALL_LIST, CMC_ALL_LIST,
COINGECKO_LIST, COINGECKO_LIST,
COINGECKO_BNB_LIST,
KLEROS_LIST, KLEROS_LIST,
GEMINI_LIST, GEMINI_LIST,
WRAPPED_LIST, WRAPPED_LIST,
@ -32,6 +35,7 @@ export const DEFAULT_INACTIVE_LIST_URLS: string[] = [
ARBITRUM_LIST, ARBITRUM_LIST,
OPTIMISM_LIST, OPTIMISM_LIST,
CELO_LIST, CELO_LIST,
PLASMA_BNB_LIST,
...UNSUPPORTED_LIST_URLS, ...UNSUPPORTED_LIST_URLS,
] ]

@ -4,6 +4,10 @@ const INFURA_KEY = process.env.REACT_APP_INFURA_KEY
if (typeof INFURA_KEY === 'undefined') { if (typeof INFURA_KEY === 'undefined') {
throw new Error(`REACT_APP_INFURA_KEY must be a defined environment variable`) throw new Error(`REACT_APP_INFURA_KEY must be a defined environment variable`)
} }
const QUICKNODE_RPC_URL = process.env.REACT_APP_BNB_RPC_URL
if (typeof QUICKNODE_RPC_URL === 'undefined') {
throw new Error(`REACT_APP_BNB_RPC_URL must be a defined environment variable`)
}
/** /**
* Fallback JSON-RPC endpoints. * Fallback JSON-RPC endpoints.
@ -15,7 +19,7 @@ if (typeof INFURA_KEY === 'undefined') {
* *
* These "Safe" URLs are listed first, followed by other fallback URLs, which are taken from chainlist.org. * These "Safe" URLs are listed first, followed by other fallback URLs, which are taken from chainlist.org.
*/ */
export const FALLBACK_URLS: { [key in SupportedChainId]: string[] } = { export const FALLBACK_URLS = {
[SupportedChainId.MAINNET]: [ [SupportedChainId.MAINNET]: [
// "Safe" URLs // "Safe" URLs
'https://api.mycryptoapi.com/eth', 'https://api.mycryptoapi.com/eth',
@ -73,13 +77,25 @@ export const FALLBACK_URLS: { [key in SupportedChainId]: string[] } = {
// "Safe" URLs // "Safe" URLs
`https://alfajores-forno.celo-testnet.org`, `https://alfajores-forno.celo-testnet.org`,
], ],
[SupportedChainId.BNB]: [
// "Safe" URLs
'https://endpoints.omniatech.io/v1/bsc/mainnet/public',
'https://bsc-mainnet.gateway.pokt.network/v1/lb/6136201a7bad1500343e248d',
'https://1rpc.io/bnb',
'https://bsc-dataseed3.binance.org',
'https://bsc-dataseed2.defibit.io',
'https://bsc-dataseed1.ninicoin.io',
'https://binance.nodereal.io',
'https://bsc-dataseed4.defibit.io',
'https://rpc.ankr.com/bsc',
],
} }
/** /**
* Known JSON-RPC endpoints. * Known JSON-RPC endpoints.
* These are the URLs used by the interface when there is not another available source of chain data. * These are the URLs used by the interface when there is not another available source of chain data.
*/ */
export const RPC_URLS: { [key in SupportedChainId]: string[] } = { export const RPC_URLS = {
[SupportedChainId.MAINNET]: [ [SupportedChainId.MAINNET]: [
`https://mainnet.infura.io/v3/${INFURA_KEY}`, `https://mainnet.infura.io/v3/${INFURA_KEY}`,
...FALLBACK_URLS[SupportedChainId.MAINNET], ...FALLBACK_URLS[SupportedChainId.MAINNET],
@ -111,4 +127,5 @@ export const RPC_URLS: { [key in SupportedChainId]: string[] } = {
], ],
[SupportedChainId.CELO]: FALLBACK_URLS[SupportedChainId.CELO], [SupportedChainId.CELO]: FALLBACK_URLS[SupportedChainId.CELO],
[SupportedChainId.CELO_ALFAJORES]: FALLBACK_URLS[SupportedChainId.CELO_ALFAJORES], [SupportedChainId.CELO_ALFAJORES]: FALLBACK_URLS[SupportedChainId.CELO_ALFAJORES],
[SupportedChainId.BNB]: [QUICKNODE_RPC_URL, ...FALLBACK_URLS[SupportedChainId.BNB]],
} }

@ -68,4 +68,5 @@ export const RPC_PROVIDERS: { [key in SupportedChainId]: StaticJsonRpcProvider }
[SupportedChainId.POLYGON_MUMBAI]: new AppJsonRpcProvider(SupportedChainId.POLYGON_MUMBAI), [SupportedChainId.POLYGON_MUMBAI]: new AppJsonRpcProvider(SupportedChainId.POLYGON_MUMBAI),
[SupportedChainId.CELO]: new AppJsonRpcProvider(SupportedChainId.CELO), [SupportedChainId.CELO]: new AppJsonRpcProvider(SupportedChainId.CELO),
[SupportedChainId.CELO_ALFAJORES]: new AppJsonRpcProvider(SupportedChainId.CELO_ALFAJORES), [SupportedChainId.CELO_ALFAJORES]: new AppJsonRpcProvider(SupportedChainId.CELO_ALFAJORES),
[SupportedChainId.BNB]: new AppJsonRpcProvider(SupportedChainId.BNB),
} }

@ -4,6 +4,9 @@ import { SupportedChainId } from 'constants/chains'
import { import {
AMPL, AMPL,
BTC_BSC,
BUSD_BSC,
CAKE_BSC,
CEUR_CELO, CEUR_CELO,
CEUR_CELO_ALFAJORES, CEUR_CELO_ALFAJORES,
CMC02_CELO, CMC02_CELO,
@ -11,12 +14,16 @@ import {
CUSD_CELO_ALFAJORES, CUSD_CELO_ALFAJORES,
DAI, DAI,
DAI_ARBITRUM_ONE, DAI_ARBITRUM_ONE,
DAI_BSC,
DAI_OPTIMISM, DAI_OPTIMISM,
DAI_POLYGON, DAI_POLYGON,
ETH_BSC,
ETH2X_FLI, ETH2X_FLI,
FEI, FEI,
FRAX, FRAX,
FRAX_BSC,
FXS, FXS,
MATIC_BSC,
nativeOnChain, nativeOnChain,
PORTAL_ETH_CELO, PORTAL_ETH_CELO,
PORTAL_USDC_CELO, PORTAL_USDC_CELO,
@ -27,11 +34,13 @@ import {
TRIBE, TRIBE,
USDC_ARBITRUM, USDC_ARBITRUM,
USDC_ARBITRUM_GOERLI, USDC_ARBITRUM_GOERLI,
USDC_BSC,
USDC_MAINNET, USDC_MAINNET,
USDC_OPTIMISM, USDC_OPTIMISM,
USDC_POLYGON, USDC_POLYGON,
USDT, USDT,
USDT_ARBITRUM_ONE, USDT_ARBITRUM_ONE,
USDT_BSC,
USDT_OPTIMISM, USDT_OPTIMISM,
USDT_POLYGON, USDT_POLYGON,
WBTC, WBTC,
@ -86,6 +95,16 @@ export const BASES_TO_CHECK_TRADES_AGAINST: ChainTokenList = {
USDT_POLYGON, USDT_POLYGON,
WETH_POLYGON, WETH_POLYGON,
], ],
[SupportedChainId.BNB]: [
...WRAPPED_NATIVE_CURRENCIES_ONLY[SupportedChainId.BNB],
DAI_BSC,
USDC_BSC,
USDT_BSC,
BUSD_BSC,
FRAX_BSC,
MATIC_BSC,
CAKE_BSC,
],
[SupportedChainId.CELO]: [CUSD_CELO, CEUR_CELO, CMC02_CELO, PORTAL_USDC_CELO, PORTAL_ETH_CELO], [SupportedChainId.CELO]: [CUSD_CELO, CEUR_CELO, CMC02_CELO, PORTAL_USDC_CELO, PORTAL_ETH_CELO],
} }
export const ADDITIONAL_BASES: { [chainId: number]: { [tokenAddress: string]: Token[] } } = { export const ADDITIONAL_BASES: { [chainId: number]: { [tokenAddress: string]: Token[] } } = {
@ -175,6 +194,16 @@ export const COMMON_BASES: ChainCurrencyList = {
CUSD_CELO_ALFAJORES, CUSD_CELO_ALFAJORES,
CEUR_CELO_ALFAJORES, CEUR_CELO_ALFAJORES,
], ],
[SupportedChainId.BNB]: [
nativeOnChain(SupportedChainId.BNB),
DAI_BSC,
USDC_BSC,
USDT_BSC,
ETH_BSC,
BTC_BSC,
BUSD_BSC,
],
} }
// used to construct the list of all pairs we consider by default in the frontend // used to construct the list of all pairs we consider by default in the frontend
@ -187,6 +216,15 @@ export const BASES_TO_TRACK_LIQUIDITY_FOR: ChainTokenList = {
USDT, USDT,
WBTC, WBTC,
], ],
[SupportedChainId.BNB]: [
...WRAPPED_NATIVE_CURRENCIES_ONLY[SupportedChainId.BNB],
DAI_BSC,
USDC_BSC,
USDT_BSC,
BTC_BSC,
BUSD_BSC,
ETH_BSC,
],
} }
export const PINNED_PAIRS: { readonly [chainId: number]: [Token, Token][] } = { export const PINNED_PAIRS: { readonly [chainId: number]: [Token, Token][] } = {
[SupportedChainId.MAINNET]: [ [SupportedChainId.MAINNET]: [

@ -294,6 +294,66 @@ export const CEUR_CELO_ALFAJORES = new Token(
'Celo Euro Stablecoin' 'Celo Euro Stablecoin'
) )
export const USDC_BSC = new Token(
SupportedChainId.BNB,
'0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d',
18,
'USDC',
'USDC'
)
export const USDT_BSC = new Token(
SupportedChainId.BNB,
'0x55d398326f99059fF775485246999027B3197955',
18,
'USDT',
'USDT'
)
export const ETH_BSC = new Token(
SupportedChainId.BNB,
'0x2170Ed0880ac9A755fd29B2688956BD959F933F8',
18,
'ETH',
'Ethereum'
)
export const MATIC_BSC = new Token(
SupportedChainId.BNB,
'0xCC42724C6683B7E57334c4E856f4c9965ED682bD',
18,
'MATIC',
'Matic'
)
export const FRAX_BSC = new Token(
SupportedChainId.BNB,
'0x90C97F71E18723b0Cf0dfa30ee176Ab653E89F40',
18,
'FRAX',
'FRAX'
)
export const BTC_BSC = new Token(SupportedChainId.BNB, '0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c', 18, 'BTCB', 'BTCB')
export const CAKE_BSC = new Token(
SupportedChainId.BNB,
'0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82',
18,
'CAKE',
'Cake'
)
export const BUSD_BSC = new Token(
SupportedChainId.BNB,
'0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56',
18,
'BUSD',
'BUSD'
)
export const DAI_BSC = new Token(SupportedChainId.BNB, '0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3', 18, 'DAI', 'DAI')
export const UNI: { [chainId: number]: Token } = { export const UNI: { [chainId: number]: Token } = {
[SupportedChainId.MAINNET]: new Token(SupportedChainId.MAINNET, UNI_ADDRESS[1], 18, 'UNI', 'Uniswap'), [SupportedChainId.MAINNET]: new Token(SupportedChainId.MAINNET, UNI_ADDRESS[1], 18, 'UNI', 'Uniswap'),
[SupportedChainId.GOERLI]: new Token(SupportedChainId.GOERLI, UNI_ADDRESS[5], 18, 'UNI', 'Uniswap'), [SupportedChainId.GOERLI]: new Token(SupportedChainId.GOERLI, UNI_ADDRESS[5], 18, 'UNI', 'Uniswap'),
@ -357,6 +417,13 @@ export const WRAPPED_NATIVE_CURRENCY: { [chainId: number]: Token | undefined } =
'CELO', 'CELO',
'Celo native asset' 'Celo native asset'
), ),
[SupportedChainId.BNB]: new Token(
SupportedChainId.BNB,
'0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c',
18,
'WBNB',
'Wrapped BNB'
),
} }
export function isCelo(chainId: number): chainId is SupportedChainId.CELO | SupportedChainId.CELO_ALFAJORES { export function isCelo(chainId: number): chainId is SupportedChainId.CELO | SupportedChainId.CELO_ALFAJORES {
@ -396,6 +463,28 @@ class MaticNativeCurrency extends NativeCurrency {
} }
} }
function isBsc(chainId: number): chainId is SupportedChainId.BNB {
return chainId === SupportedChainId.BNB
}
class BscNativeCurrency extends NativeCurrency {
equals(other: Currency): boolean {
return other.isNative && other.chainId === this.chainId
}
get wrapped(): Token {
if (!isBsc(this.chainId)) throw new Error('Not bnb')
const wrapped = WRAPPED_NATIVE_CURRENCY[this.chainId]
invariant(wrapped instanceof Token)
return wrapped
}
public constructor(chainId: number) {
if (!isBsc(chainId)) throw new Error('Not bnb')
super(chainId, 18, 'BNB', 'BNB')
}
}
class ExtendedEther extends Ether { class ExtendedEther extends Ether {
public get wrapped(): Token { public get wrapped(): Token {
const wrapped = WRAPPED_NATIVE_CURRENCY[this.chainId] const wrapped = WRAPPED_NATIVE_CURRENCY[this.chainId]
@ -418,6 +507,8 @@ export function nativeOnChain(chainId: number): NativeCurrency | Token {
nativeCurrency = new MaticNativeCurrency(chainId) nativeCurrency = new MaticNativeCurrency(chainId)
} else if (isCelo(chainId)) { } else if (isCelo(chainId)) {
nativeCurrency = getCeloNativeCurrency(chainId) nativeCurrency = getCeloNativeCurrency(chainId)
} else if (isBsc(chainId)) {
nativeCurrency = new BscNativeCurrency(chainId)
} else { } else {
nativeCurrency = ExtendedEther.onChain(chainId) nativeCurrency = ExtendedEther.onChain(chainId)
} }
@ -433,6 +524,7 @@ export const TOKEN_SHORTHANDS: { [shorthand: string]: { [chainId in SupportedCha
[SupportedChainId.OPTIMISM_GOERLI]: USDC_OPTIMISM_GOERLI.address, [SupportedChainId.OPTIMISM_GOERLI]: USDC_OPTIMISM_GOERLI.address,
[SupportedChainId.POLYGON]: USDC_POLYGON.address, [SupportedChainId.POLYGON]: USDC_POLYGON.address,
[SupportedChainId.POLYGON_MUMBAI]: USDC_POLYGON_MUMBAI.address, [SupportedChainId.POLYGON_MUMBAI]: USDC_POLYGON_MUMBAI.address,
[SupportedChainId.BNB]: USDC_BSC.address,
[SupportedChainId.CELO]: PORTAL_USDC_CELO.address, [SupportedChainId.CELO]: PORTAL_USDC_CELO.address,
[SupportedChainId.CELO_ALFAJORES]: PORTAL_USDC_CELO.address, [SupportedChainId.CELO_ALFAJORES]: PORTAL_USDC_CELO.address,
[SupportedChainId.GOERLI]: USDC_GOERLI.address, [SupportedChainId.GOERLI]: USDC_GOERLI.address,

@ -103,6 +103,7 @@ export const CHAIN_NAME_TO_CHAIN_ID: { [key: string]: SupportedChainId } = {
CELO: SupportedChainId.CELO, CELO: SupportedChainId.CELO,
ARBITRUM: SupportedChainId.ARBITRUM_ONE, ARBITRUM: SupportedChainId.ARBITRUM_ONE,
OPTIMISM: SupportedChainId.OPTIMISM, OPTIMISM: SupportedChainId.OPTIMISM,
BNB: SupportedChainId.BNB,
} }
export const BACKEND_CHAIN_NAMES: Chain[] = [Chain.Ethereum, Chain.Polygon, Chain.Optimism, Chain.Arbitrum, Chain.Celo] export const BACKEND_CHAIN_NAMES: Chain[] = [Chain.Ethereum, Chain.Polygon, Chain.Optimism, Chain.Arbitrum, Chain.Celo]

@ -13,6 +13,8 @@ const CHAIN_SUBGRAPH_URL: Record<number, string> = {
[SupportedChainId.POLYGON]: 'https://api.thegraph.com/subgraphs/name/ianlapham/uniswap-v3-polygon', [SupportedChainId.POLYGON]: 'https://api.thegraph.com/subgraphs/name/ianlapham/uniswap-v3-polygon',
[SupportedChainId.CELO]: 'https://api.thegraph.com/subgraphs/name/jesse-sawa/uniswap-celo', [SupportedChainId.CELO]: 'https://api.thegraph.com/subgraphs/name/jesse-sawa/uniswap-celo',
[SupportedChainId.BNB]: 'https://api.thegraph.com/subgraphs/name/ianlapham/uniswap-v3-bsc',
} }
const httpLink = new HttpLink({ uri: CHAIN_SUBGRAPH_URL[SupportedChainId.MAINNET] }) const httpLink = new HttpLink({ uri: CHAIN_SUBGRAPH_URL[SupportedChainId.MAINNET] })

@ -18,6 +18,7 @@ const QUOTE_GAS_OVERRIDES: { [chainId: number]: number } = {
[SupportedChainId.CELO_ALFAJORES]: 50_000_000, [SupportedChainId.CELO_ALFAJORES]: 50_000_000,
[SupportedChainId.POLYGON]: 40_000_000, [SupportedChainId.POLYGON]: 40_000_000,
[SupportedChainId.POLYGON_MUMBAI]: 40_000_000, [SupportedChainId.POLYGON_MUMBAI]: 40_000_000,
[SupportedChainId.BNB]: 50_000_000,
} }
const DEFAULT_GAS_QUOTE = 2_000_000 const DEFAULT_GAS_QUOTE = 2_000_000

@ -6,7 +6,7 @@ import { useMemo, useRef } from 'react'
import { RouterPreference } from 'state/routing/slice' import { RouterPreference } from 'state/routing/slice'
import { useRoutingAPITrade } from 'state/routing/useRoutingAPITrade' import { useRoutingAPITrade } from 'state/routing/useRoutingAPITrade'
import { CUSD_CELO, DAI_OPTIMISM, USDC_ARBITRUM, USDC_MAINNET, USDC_POLYGON } from '../constants/tokens' import { CUSD_CELO, DAI_OPTIMISM, USDC_ARBITRUM, USDC_MAINNET, USDC_POLYGON, USDT_BSC } from '../constants/tokens'
// Stablecoin amounts used when calculating spot price for a given currency. // Stablecoin amounts used when calculating spot price for a given currency.
// The amount is large enough to filter low liquidity pairs. // The amount is large enough to filter low liquidity pairs.
@ -16,6 +16,7 @@ const STABLECOIN_AMOUNT_OUT: { [chainId: number]: CurrencyAmount<Token> } = {
[SupportedChainId.OPTIMISM]: CurrencyAmount.fromRawAmount(DAI_OPTIMISM, 10_000e18), [SupportedChainId.OPTIMISM]: CurrencyAmount.fromRawAmount(DAI_OPTIMISM, 10_000e18),
[SupportedChainId.POLYGON]: CurrencyAmount.fromRawAmount(USDC_POLYGON, 10_000e6), [SupportedChainId.POLYGON]: CurrencyAmount.fromRawAmount(USDC_POLYGON, 10_000e6),
[SupportedChainId.CELO]: CurrencyAmount.fromRawAmount(CUSD_CELO, 10_000e18), [SupportedChainId.CELO]: CurrencyAmount.fromRawAmount(CUSD_CELO, 10_000e18),
[SupportedChainId.BNB]: CurrencyAmount.fromRawAmount(USDT_BSC, 100e18),
} }
/** /**

@ -4,11 +4,12 @@ import { useMemo } from 'react'
import { isAddress } from 'utils' import { isAddress } from 'utils'
import EthereumLogo from '../../assets/images/ethereum-logo.png' import EthereumLogo from '../../assets/images/ethereum-logo.png'
import BnbLogo from '../../assets/svg/bnb-logo.svg'
import CeloLogo from '../../assets/svg/celo_logo.svg' import CeloLogo from '../../assets/svg/celo_logo.svg'
import MaticLogo from '../../assets/svg/matic-token-icon.svg' import MaticLogo from '../../assets/svg/matic-token-icon.svg'
import { isCelo, NATIVE_CHAIN_ID, nativeOnChain } from '../../constants/tokens' import { isCelo, NATIVE_CHAIN_ID, nativeOnChain } from '../../constants/tokens'
type Network = 'ethereum' | 'arbitrum' | 'optimism' | 'polygon' type Network = 'ethereum' | 'arbitrum' | 'optimism' | 'polygon' | 'smartchain'
export function chainIdToNetworkName(networkId: SupportedChainId): Network { export function chainIdToNetworkName(networkId: SupportedChainId): Network {
switch (networkId) { switch (networkId) {
@ -20,6 +21,8 @@ export function chainIdToNetworkName(networkId: SupportedChainId): Network {
return 'optimism' return 'optimism'
case SupportedChainId.POLYGON: case SupportedChainId.POLYGON:
return 'polygon' return 'polygon'
case SupportedChainId.BNB:
return 'smartchain'
default: default:
return 'ethereum' return 'ethereum'
} }
@ -30,6 +33,8 @@ export function getNativeLogoURI(chainId: SupportedChainId = SupportedChainId.MA
case SupportedChainId.POLYGON: case SupportedChainId.POLYGON:
case SupportedChainId.POLYGON_MUMBAI: case SupportedChainId.POLYGON_MUMBAI:
return MaticLogo return MaticLogo
case SupportedChainId.BNB:
return BnbLogo
case SupportedChainId.CELO: case SupportedChainId.CELO:
case SupportedChainId.CELO_ALFAJORES: case SupportedChainId.CELO_ALFAJORES:
return CeloLogo return CeloLogo
@ -40,7 +45,12 @@ export function getNativeLogoURI(chainId: SupportedChainId = SupportedChainId.MA
function getTokenLogoURI(address: string, chainId: SupportedChainId = SupportedChainId.MAINNET): string | void { function getTokenLogoURI(address: string, chainId: SupportedChainId = SupportedChainId.MAINNET): string | void {
const networkName = chainIdToNetworkName(chainId) const networkName = chainIdToNetworkName(chainId)
const networksWithUrls = [SupportedChainId.ARBITRUM_ONE, SupportedChainId.MAINNET, SupportedChainId.OPTIMISM] const networksWithUrls = [
SupportedChainId.ARBITRUM_ONE,
SupportedChainId.MAINNET,
SupportedChainId.OPTIMISM,
SupportedChainId.BNB,
]
if (networksWithUrls.includes(chainId)) { if (networksWithUrls.includes(chainId)) {
return `https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/${networkName}/assets/${address}/logo.png` return `https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/${networkName}/assets/${address}/logo.png`
} }

@ -14,6 +14,7 @@ function getBlocksPerFetchForChainId(chainId: number | undefined): number {
case SupportedChainId.ARBITRUM_ONE: case SupportedChainId.ARBITRUM_ONE:
case SupportedChainId.OPTIMISM: case SupportedChainId.OPTIMISM:
return 15 return 15
case SupportedChainId.BNB:
case SupportedChainId.CELO: case SupportedChainId.CELO:
case SupportedChainId.CELO_ALFAJORES: case SupportedChainId.CELO_ALFAJORES:
return 5 return 5

@ -1,6 +1,5 @@
import { BigNumber } from '@ethersproject/bignumber' import { BigNumber } from '@ethersproject/bignumber'
import { formatEther } from '@ethersproject/units' import { formatEther, parseEther } from '@ethersproject/units'
import { parseEther } from '@ethersproject/units'
import { t, Trans } from '@lingui/macro' import { t, Trans } from '@lingui/macro'
import { sendAnalyticsEvent, TraceEvent } from '@uniswap/analytics' import { sendAnalyticsEvent, TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, InterfaceElementName, NFTEventName } from '@uniswap/analytics-events' import { BrowserEvent, InterfaceElementName, NFTEventName } from '@uniswap/analytics-events'

@ -181,7 +181,7 @@ export default function Pool() {
<AutoColumn gap="md" style={{ width: '100%' }}> <AutoColumn gap="md" style={{ width: '100%' }}>
<Layer2Prompt> <Layer2Prompt>
<ThemedText.DeprecatedBody color={theme.textTertiary} textAlign="center"> <ThemedText.DeprecatedBody color={theme.textTertiary} textAlign="center">
<Trans>V2 Pool is not available on Layer 2. Switch to Layer 1 Ethereum.</Trans> <Trans>Uniswap V2 is not available on this network.</Trans>
</ThemedText.DeprecatedBody> </ThemedText.DeprecatedBody>
</Layer2Prompt> </Layer2Prompt>
</AutoColumn> </AutoColumn>

@ -501,7 +501,7 @@ export default function Swap({ className }: { className?: string }) {
width="100%" width="100%"
/> />
) : ( ) : (
<SwapWrapper className={className} id="swap-page"> <SwapWrapper chainId={chainId} className={className} id="swap-page">
<SwapHeader allowedSlippage={allowedSlippage} /> <SwapHeader allowedSlippage={allowedSlippage} />
<ConfirmSwapModal <ConfirmSwapModal
isOpen={showConfirm} isOpen={showConfirm}

@ -1,8 +1,7 @@
import { createSlice, nanoid } from '@reduxjs/toolkit' import { createSlice, nanoid } from '@reduxjs/toolkit'
import { SupportedChainId } from 'constants/chains'
import { DEFAULT_TXN_DISMISS_MS } from 'constants/misc' import { DEFAULT_TXN_DISMISS_MS } from 'constants/misc'
import { SupportedChainId } from '../../constants/chains'
export type PopupContent = export type PopupContent =
| { | {
txn: { txn: {

@ -91,6 +91,7 @@ export const colors = {
networkOptimismSoft: 'rgba(255, 4, 32, 0.16)', networkOptimismSoft: 'rgba(255, 4, 32, 0.16)',
networkPolygon: '#A457FF', networkPolygon: '#A457FF',
networkArbitrum: '#28A0F0', networkArbitrum: '#28A0F0',
networkBsc: '#F0B90B',
networkPolygonSoft: 'rgba(164, 87, 255, 0.16)', networkPolygonSoft: 'rgba(164, 87, 255, 0.16)',
networkEthereumSoft: 'rgba(98, 126, 234, 0.16)', networkEthereumSoft: 'rgba(98, 126, 234, 0.16)',
} }
@ -108,6 +109,7 @@ const commonTheme = {
chain_10: colors.networkOptimism, chain_10: colors.networkOptimism,
chain_137: colors.networkPolygon, chain_137: colors.networkPolygon,
chain_42: colors.networkArbitrum, chain_42: colors.networkArbitrum,
chain_56: colors.networkBsc,
chain_420: colors.networkOptimism, chain_420: colors.networkOptimism,
chain_42161: colors.networkArbitrum, chain_42161: colors.networkArbitrum,
chain_421613: colors.networkArbitrum, chain_421613: colors.networkArbitrum,
@ -115,6 +117,7 @@ const commonTheme = {
chain_137_background: colors.purple900, chain_137_background: colors.purple900,
chain_10_background: colors.red900, chain_10_background: colors.red900,
chain_42161_background: colors.blue900, chain_42161_background: colors.blue900,
chain_56_background: colors.networkBsc,
hoverState: opacify(24, colors.blue200), hoverState: opacify(24, colors.blue200),
hoverDefault: opacify(8, colors.gray200), hoverDefault: opacify(8, colors.gray200),

@ -87,6 +87,15 @@ export default function RadialGradientByChainUpdater(): null {
backgroundRadialGradientElement.style.background = darkMode ? celoDarkGradient : celoLightGradient backgroundRadialGradientElement.style.background = darkMode ? celoDarkGradient : celoLightGradient
break break
} }
case SupportedChainId.BNB: {
setBackground(backgroundResetStyles)
const bscLightGradient =
'radial-gradient(100% 100% at 50% 0%, rgba(242 , 186, 8, 0.1) 0%, rgba(238, 182, 6, 0.08) 50%, rgba(140, 185, 11, 0) 100%), #FFFFFF'
const bscDarkGradient =
'radial-gradient(100% 100% at 50% 0%, rgba(169, 132, 17, 0.1) 0%, rgba(128, 100, 14, 0.08) 50%, rgba(140, 185, 11, 0) 100%), #0D0E0E'
backgroundRadialGradientElement.style.background = darkMode ? bscDarkGradient : bscLightGradient
break
}
default: { default: {
setBackground(initialStyles) setBackground(initialStyles)
const defaultLightGradient = const defaultLightGradient =

@ -1,4 +1,5 @@
const EXPLORER_HOSTNAMES: { [hostname: string]: true } = { const EXPLORER_HOSTNAMES: { [hostname: string]: true } = {
'bscscan.com': true,
'etherscan.io': true, 'etherscan.io': true,
'goerli.etherscan.io': true, 'goerli.etherscan.io': true,
'optimistic.etherscan.io': true, 'optimistic.etherscan.io': true,

@ -1,3 +1,5 @@
import { SupportedChainId } from 'constants/chains'
import { ExplorerDataType, getExplorerLink } from './getExplorerLink' import { ExplorerDataType, getExplorerLink } from './getExplorerLink'
describe('#getExplorerLink', () => { describe('#getExplorerLink', () => {
@ -16,6 +18,11 @@ describe('#getExplorerLink', () => {
it('arbitrum', () => { it('arbitrum', () => {
expect(getExplorerLink(42161, 'abc', ExplorerDataType.ADDRESS)).toEqual('https://arbiscan.io/address/abc') expect(getExplorerLink(42161, 'abc', ExplorerDataType.ADDRESS)).toEqual('https://arbiscan.io/address/abc')
}) })
it('bnb chain', () => {
expect(getExplorerLink(SupportedChainId.BNB, 'abc', ExplorerDataType.ADDRESS)).toEqual(
'https://bscscan.com/address/abc'
)
})
it('polygon', () => { it('polygon', () => {
expect(getExplorerLink(137, 'abc', ExplorerDataType.ADDRESS)).toEqual('https://polygonscan.com/address/abc') expect(getExplorerLink(137, 'abc', ExplorerDataType.ADDRESS)).toEqual('https://polygonscan.com/address/abc')
}) })

@ -9,6 +9,7 @@ const BLOCK_EXPLORER_PREFIXES: { [chainId: number]: string } = {
[SupportedChainId.POLYGON_MUMBAI]: 'https://mumbai.polygonscan.com', [SupportedChainId.POLYGON_MUMBAI]: 'https://mumbai.polygonscan.com',
[SupportedChainId.CELO]: 'https://celoscan.io', [SupportedChainId.CELO]: 'https://celoscan.io',
[SupportedChainId.CELO_ALFAJORES]: 'https://alfajores-blockscout.celo-testnet.org', [SupportedChainId.CELO_ALFAJORES]: 'https://alfajores-blockscout.celo-testnet.org',
[SupportedChainId.BNB]: 'https://bscscan.com',
} }
export enum ExplorerDataType { export enum ExplorerDataType {

@ -1,8 +1,7 @@
import { Connector } from '@web3-react/types' import { Connector } from '@web3-react/types'
import { networkConnection, walletConnectConnection } from 'connection' import { networkConnection, walletConnectConnection } from 'connection'
import { getChainInfo } from 'constants/chainInfo' import { getChainInfo } from 'constants/chainInfo'
import { SupportedChainId } from 'constants/chains' import { isSupportedChain, SupportedChainId } from 'constants/chains'
import { isSupportedChain } from 'constants/chains'
import { FALLBACK_URLS, RPC_URLS } from 'constants/networks' import { FALLBACK_URLS, RPC_URLS } from 'constants/networks'
function getRpcUrl(chainId: SupportedChainId): string { function getRpcUrl(chainId: SupportedChainId): string {

@ -5094,10 +5094,10 @@
"@uniswap/v2-sdk" "^3.0.1" "@uniswap/v2-sdk" "^3.0.1"
"@uniswap/v3-sdk" "^3.8.3" "@uniswap/v3-sdk" "^3.8.3"
"@uniswap/sdk-core@^3.0.0-alpha.3", "@uniswap/sdk-core@^3.0.1", "@uniswap/sdk-core@^3.1.0", "@uniswap/sdk-core@^3.2.0": "@uniswap/sdk-core@^3.0.0-alpha.3", "@uniswap/sdk-core@^3.0.1", "@uniswap/sdk-core@^3.1.0", "@uniswap/sdk-core@^3.2.0", "@uniswap/sdk-core@^3.2.2":
version "3.2.0" version "3.2.2"
resolved "https://registry.yarnpkg.com/@uniswap/sdk-core/-/sdk-core-3.2.0.tgz#cabee6b21469d2e8d41c367503cfd961dddc8305" resolved "https://registry.yarnpkg.com/@uniswap/sdk-core/-/sdk-core-3.2.2.tgz#50dbc6f2543d088680f36fb61e01bb90d4d8fa71"
integrity sha512-KXCIDNRhKF9DeDBY2j7SiAlD56ZqD/T6his2m9y8ZCMdObLBVt/oCt4kaQGrWUjJuf2Flr5dryHMmMQBXqA9pA== integrity sha512-dPA34T8EVfFzKtw1NC1Mr7M0aXpY1UN+lUpdBv757JxKKMlGQTg96XTIfjYCflqEshxlBdz2+IVQgk6H+dMu5g==
dependencies: dependencies:
"@ethersproject/address" "^5.0.2" "@ethersproject/address" "^5.0.2"
big.js "^5.2.2" big.js "^5.2.2"
@ -5161,7 +5161,7 @@
resolved "https://registry.yarnpkg.com/@uniswap/token-lists/-/token-lists-1.0.0-beta.30.tgz#2103ca23b8007c59ec71718d34cdc97861c409e5" resolved "https://registry.yarnpkg.com/@uniswap/token-lists/-/token-lists-1.0.0-beta.30.tgz#2103ca23b8007c59ec71718d34cdc97861c409e5"
integrity sha512-HwY2VvkQ8lNR6ks5NqQfAtg+4IZqz3KV1T8d2DlI8emIn9uMmaoFbIOg0nzjqAVKKnZSbMTRRtUoAh6mmjRvog== integrity sha512-HwY2VvkQ8lNR6ks5NqQfAtg+4IZqz3KV1T8d2DlI8emIn9uMmaoFbIOg0nzjqAVKKnZSbMTRRtUoAh6mmjRvog==
"@uniswap/universal-router-sdk@^1.3.6", "@uniswap/universal-router-sdk@^1.3.8", "@uniswap/universal-router-sdk@^1.3.9": "@uniswap/universal-router-sdk@^1.3.8", "@uniswap/universal-router-sdk@^1.3.9":
version "1.3.9" version "1.3.9"
resolved "https://registry.yarnpkg.com/@uniswap/universal-router-sdk/-/universal-router-sdk-1.3.9.tgz#75a1b354457b85e1e0271ecd5956ea3323a40eca" resolved "https://registry.yarnpkg.com/@uniswap/universal-router-sdk/-/universal-router-sdk-1.3.9.tgz#75a1b354457b85e1e0271ecd5956ea3323a40eca"
integrity sha512-uXhdK8IDuyZZRMKiua9dJ6jj5MJ5xUrGflczWwhp6i0cb2VvXoLNQqc7aq3130NfIrKEYfkBGMjsqStZmqqKug== integrity sha512-uXhdK8IDuyZZRMKiua9dJ6jj5MJ5xUrGflczWwhp6i0cb2VvXoLNQqc7aq3130NfIrKEYfkBGMjsqStZmqqKug==
@ -5175,7 +5175,7 @@
bignumber.js "^9.0.2" bignumber.js "^9.0.2"
ethers "^5.3.1" ethers "^5.3.1"
"@uniswap/universal-router@1.2.1", "@uniswap/universal-router@^1.0.1": "@uniswap/universal-router@1.2.1":
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/@uniswap/universal-router/-/universal-router-1.2.1.tgz#5fe4aa21d6bc89314d99f26407f28154f8e16f42" resolved "https://registry.yarnpkg.com/@uniswap/universal-router/-/universal-router-1.2.1.tgz#5fe4aa21d6bc89314d99f26407f28154f8e16f42"
integrity sha512-F3S1wKylncuvIG2qwC1ciXXc1z1QmKsalo4p6H2A90LSRylEEhNp7ITxs7qCcnfRh+ZNkGJ0yQ0zmuVJSBezOQ== integrity sha512-F3S1wKylncuvIG2qwC1ciXXc1z1QmKsalo4p6H2A90LSRylEEhNp7ITxs7qCcnfRh+ZNkGJ0yQ0zmuVJSBezOQ==
@ -5184,6 +5184,15 @@
"@uniswap/v2-core" "1.0.1" "@uniswap/v2-core" "1.0.1"
"@uniswap/v3-core" "1.0.0" "@uniswap/v3-core" "1.0.0"
"@uniswap/universal-router@^1.0.1":
version "1.2.2"
resolved "https://registry.yarnpkg.com/@uniswap/universal-router/-/universal-router-1.2.2.tgz#7b3704a307fad53ba2a80718362b1b7718ada4cc"
integrity sha512-ipQQpo3xO21EIS5pBjJazZbh9Vth6wzeta85Xva2HKoJ0uBvnugCjqvjkJMqiiz+osBnC12yemitjTOOxcqXjA==
dependencies:
"@openzeppelin/contracts" "4.7.0"
"@uniswap/v2-core" "1.0.1"
"@uniswap/v3-core" "1.0.0"
"@uniswap/v2-core@1.0.0": "@uniswap/v2-core@1.0.0":
version "1.0.0" version "1.0.0"
resolved "https://registry.npmjs.org/@uniswap/v2-core/-/v2-core-1.0.0.tgz" resolved "https://registry.npmjs.org/@uniswap/v2-core/-/v2-core-1.0.0.tgz"