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

Add support for Mainnet Sepolia and Arbitrum Sepolia testnets #3633

Merged
merged 5 commits into from
Oct 3, 2023
Merged
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
20 changes: 20 additions & 0 deletions background/constants/base-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,24 @@ const GOERLI_ETH: NetworkBaseAsset = {
},
}

const SEPOLIA_ETH: NetworkBaseAsset = {
...ETH,
chainID: "11155111",
metadata: {
coinGeckoID: "ethereum",
tokenLists: [],
},
}

const ARBITRUM_SEPOLIA_ETH: NetworkBaseAsset = {
...ETH,
chainID: "421614",
metadata: {
coinGeckoID: "ethereum",
tokenLists: [],
},
}

const RBTC: NetworkBaseAsset = {
chainID: "30",
name: "RSK Token",
Expand Down Expand Up @@ -109,6 +127,8 @@ export const BASE_ASSETS_BY_CUSTOM_NAME = {
ARBITRUM_NOVA_ETH,
OPTIMISTIC_ETH,
GOERLI_ETH,
SEPOLIA_ETH,
ARBITRUM_SEPOLIA_ETH,
ZK_SYNC_ETH,
}

Expand Down
13 changes: 13 additions & 0 deletions background/constants/currencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@ export const GOERLI_ETH: NetworkBaseAsset & Required<CoinGeckoAsset> = {
...ETH_DATA,
}

export const SEPOLIA_ETH: NetworkBaseAsset & Required<CoinGeckoAsset> = {
...BASE_ASSETS_BY_CUSTOM_NAME.SEPOLIA_ETH,
...ETH_DATA,
}

export const ARBITRUM_SEPOLIA_ETH: NetworkBaseAsset & Required<CoinGeckoAsset> =
{
...BASE_ASSETS_BY_CUSTOM_NAME.ARBITRUM_SEPOLIA_ETH,
...ETH_DATA,
}

export const ZK_SYNC_ETH: NetworkBaseAsset & Required<CoinGeckoAsset> = {
...BASE_ASSETS_BY_CUSTOM_NAME.ZK_SYNC_ETH,
...ETH_DATA,
Expand Down Expand Up @@ -103,6 +114,8 @@ export const BUILT_IN_NETWORK_BASE_ASSETS = [
ARBITRUM_ONE_ETH,
ARBITRUM_NOVA_ETH,
GOERLI_ETH,
SEPOLIA_ETH,
ARBITRUM_SEPOLIA_ETH,
AVAX,
BNB,
]
38 changes: 33 additions & 5 deletions background/constants/networks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
BNB,
ETH,
GOERLI_ETH,
SEPOLIA_ETH,
ARBITRUM_SEPOLIA_ETH,
MATIC,
OPTIMISTIC_ETH,
RBTC,
Expand Down Expand Up @@ -79,13 +81,29 @@ export const OPTIMISM: EVMNetwork = {
}

export const GOERLI: EVMNetwork = {
name: "Goerli",
name: "Ethereum Goerli",
baseAsset: GOERLI_ETH,
chainID: "5",
family: "EVM",
coingeckoPlatformID: "ethereum",
}

export const SEPOLIA: EVMNetwork = {
name: "Ethereum Sepolia",
baseAsset: SEPOLIA_ETH,
chainID: "11155111",
family: "EVM",
coingeckoPlatformID: "ethereum",
}

export const ARBITRUM_SEPOLIA: EVMNetwork = {
name: "Arbitrum Sepolia",
baseAsset: ARBITRUM_SEPOLIA_ETH,
chainID: "421614",
family: "EVM",
coingeckoPlatformID: "ethereum",
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we leave these Coingecko references here and/or in the asset definitions? Wondering if these will give false prices for assets.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I must admit, the coingeckoPlatformID value slipped my attention here and I copied the value from GOERLI/SEPOLIA networks. If I understand correctly, the coingeckoPlatformID value is used to fetch a price of the asset, so that we could show how much is the asset worth in USD. The list of supported values is here: https://api.coingecko.com/api/v3/asset_platforms. As there are no testnets listed there, I think in the extension we can either show a mainnet price (which is not a real value of the testnet asset) or not show the price at all. I prefer showing the mainnet value in that case - this allows us to test if the USD price is being shown in correct place, etc.

So what I think would make sense here is changing the coingeckoPlatformID's value to arbitrum-one for ARBITRUM_SEPOLIA and leaving the rest unchanged.

Unless there's something I'm missing?

}

export const ZK_SYNC: EVMNetwork = {
name: "zkSync Era",
baseAsset: ZK_SYNC_ETH,
Expand All @@ -98,6 +116,8 @@ export const DEFAULT_NETWORKS = [
POLYGON,
OPTIMISM,
GOERLI,
SEPOLIA,
ARBITRUM_SEPOLIA,
ARBITRUM_ONE,
ROOTSTOCK,
AVALANCHE,
Expand All @@ -124,11 +144,13 @@ export const FORK: EVMNetwork = {
}

export const EIP_1559_COMPLIANT_CHAIN_IDS = new Set(
[ETHEREUM, POLYGON, GOERLI, AVALANCHE].map((network) => network.chainID),
[ETHEREUM, POLYGON, GOERLI, SEPOLIA, AVALANCHE].map(
(network) => network.chainID,
),
)

export const CHAINS_WITH_MEMPOOL = new Set(
[ETHEREUM, POLYGON, AVALANCHE, GOERLI, BINANCE_SMART_CHAIN].map(
[ETHEREUM, POLYGON, AVALANCHE, GOERLI, SEPOLIA, BINANCE_SMART_CHAIN].map(
(network) => network.chainID,
),
)
Expand All @@ -143,12 +165,14 @@ export const NETWORK_BY_CHAIN_ID = {
[OPTIMISM.chainID]: OPTIMISM,
[BINANCE_SMART_CHAIN.chainID]: BINANCE_SMART_CHAIN,
[GOERLI.chainID]: GOERLI,
[SEPOLIA.chainID]: SEPOLIA,
[ARBITRUM_SEPOLIA.chainID]: ARBITRUM_SEPOLIA,
[FORK.chainID]: FORK,
[ZK_SYNC.chainID]: ZK_SYNC,
}

export const TEST_NETWORK_BY_CHAIN_ID = new Set(
[GOERLI].map((network) => network.chainID),
[GOERLI, SEPOLIA, ARBITRUM_SEPOLIA].map((network) => network.chainID),
)

export const NETWORK_FOR_LEDGER_SIGNING = [ETHEREUM, POLYGON]
Expand All @@ -162,6 +186,7 @@ export const CHAIN_ID_TO_0X_API_BASE: {
[POLYGON.chainID]: "polygon.api.0x.org",
[OPTIMISM.chainID]: "optimism.api.0x.org",
[GOERLI.chainID]: "goerli.api.0x.org",
// TODO: Add Swap API for Sepolia once 0x supports it.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I haven't found any official confirmation they plan to do that. But I saw a couple of people requesting this support on their Discord. I've asked them there if they plan to support it since Goerli becomes deprecated, but I didn't get a response yet.

Copy link
Contributor Author

@michalinacienciala michalinacienciala Sep 25, 2023

Choose a reason for hiding this comment

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

Got a response from a member of their community:

Yes, they're looking to deploy on Sepolia in the near future.

[EDIT] Another update:

there is an active feature request for Sepolia support here, where you can track progress, upvote, etc. https://0x.canny.io/request-features

This feature request is currently under review.

[ARBITRUM_ONE.chainID]: "arbitrum.api.0x.org",
[AVALANCHE.chainID]: "avalanche.api.0x.org",
[BINANCE_SMART_CHAIN.chainID]: "bsc.api.0x.org",
Expand All @@ -172,7 +197,8 @@ export const NETWORKS_SUPPORTING_SWAPS = new Set(
)

export const ALCHEMY_SUPPORTED_CHAIN_IDS = new Set(
[ETHEREUM, POLYGON, ARBITRUM_ONE, OPTIMISM, GOERLI].map(
// TODO: Add `ARBITRUM_SEPOLIA` once Alchemy creates a dedicated RPC.
[ETHEREUM, POLYGON, ARBITRUM_ONE, OPTIMISM, GOERLI, SEPOLIA].map(
(network) => network.chainID,
),
)
Expand Down Expand Up @@ -203,6 +229,8 @@ export const CHAIN_ID_TO_RPC_URLS: {
],
[ARBITRUM_NOVA.chainID]: ["https://nova.arbitrum.io/rpc "],
[GOERLI.chainID]: ["https://ethereum-goerli-rpc.allthatnode.com"],
[SEPOLIA.chainID]: ["https://endpoints.omniatech.io/v1/eth/sepolia/public"],
[ARBITRUM_SEPOLIA.chainID]: ["https://sepolia-rollup.arbitrum.io/rpc"],
[AVALANCHE.chainID]: [
"https://api.avax.network/ext/bc/C/rpc",
"https://1rpc.io/avax/c",
Expand Down
2 changes: 1 addition & 1 deletion background/lib/alchemy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export async function getAssetTransfers(
const category = ["external", "erc20"]

if (addressOnNetwork.network.name === "Ethereum") {
// "internal" is supported only on Ethereum Mainnet and Goerli atm
// "internal" is supported only on Ethereum Mainnet, Goerli and Sepolia atm
// https://docs.alchemy.com/alchemy/enhanced-apis/transfers-api#alchemy_getassettransfers-testnets-and-layer-2s
Comment on lines +72 to 73
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually, according to the link it is also supported on Polygon Mainnet, but I didn't want to do anything about that observation, as I don't know the system well enough...

category.push("internal")
}
Expand Down
6 changes: 5 additions & 1 deletion background/lib/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { BigNumber, ethers, utils } from "ethers"
import { normalizeHexAddress, toChecksumAddress } from "@tallyho/hd-keyring"
import { NormalizedEVMAddress, UNIXTime } from "../../types"
import { EVMNetwork } from "../../networks"
import { ETHEREUM, GOERLI } from "../../constants"
import { ETHEREUM, GOERLI, SEPOLIA } from "../../constants"
import { AddressOnNetwork } from "../../accounts"

export function isValidChecksumAddress(
Expand Down Expand Up @@ -161,6 +161,10 @@ export function getEthereumNetwork(): EVMNetwork {
return GOERLI
}

if (ethereumNetwork === "SEPOLIA") {
return SEPOLIA
}

// Default to mainnet
return ETHEREUM
}
Expand Down
4 changes: 4 additions & 0 deletions background/redux-slices/dapp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {
BINANCE_SMART_CHAIN,
ETHEREUM,
GOERLI,
SEPOLIA,
ARBITRUM_SEPOLIA,
OPTIMISM,
POLYGON,
ROOTSTOCK,
Expand Down Expand Up @@ -135,6 +137,8 @@ const dappSlice = createSlice({
AVALANCHE,
BINANCE_SMART_CHAIN,
GOERLI,
SEPOLIA,
ARBITRUM_SEPOLIA,
ARBITRUM_NOVA,
].map((network) => ({
...permission,
Expand Down
13 changes: 2 additions & 11 deletions background/services/chain/serial-fallback-provider.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import {
AlchemyProvider,
AlchemyWebSocketProvider,
EventType,
JsonRpcBatchProvider,
JsonRpcProvider,
Expand All @@ -27,6 +25,7 @@ import {
} from "../../lib/alchemy"
import { FeatureFlags, isEnabled } from "../../features"
import { RpcConfig } from "./db"
import TahoAlchemyProvider from "./taho-provider"

export type ProviderCreator = {
type: "alchemy" | "custom" | "generic"
Expand Down Expand Up @@ -1097,15 +1096,7 @@ export function makeSerialFallbackProvider(
{
type: "alchemy" as const,
creator: () =>
new AlchemyProvider(getNetwork(Number(chainID)), ALCHEMY_KEY),
},
{
type: "alchemy" as const,
creator: () =>
new AlchemyWebSocketProvider(
getNetwork(Number(chainID)),
ALCHEMY_KEY,
),
new TahoAlchemyProvider(getNetwork(Number(chainID)), ALCHEMY_KEY),
},
]
: []
Expand Down
30 changes: 30 additions & 0 deletions background/services/chain/taho-provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {
AlchemyProvider,
Network,
showThrottleMessage,
} from "@ethersproject/providers"
import { ConnectionInfo } from "@ethersproject/web"

export default class TahoAlchemyProvider extends AlchemyProvider {
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's drop a comment noting why this exists.

static override getUrl(network: Network, apiKey: string): ConnectionInfo {
let host = null
switch (network.name) {
case "sepolia":
host = "eth-sepolia.g.alchemy.com/v2/"
break
default:
return AlchemyProvider.getUrl(network, apiKey)
}

return {
allowGzip: true,
url: `https://${host}${apiKey}`,
throttleCallback: () => {
if (apiKey === "0") {
showThrottleMessage()
}
return Promise.resolve(true)
},
}
}
}
6 changes: 3 additions & 3 deletions background/services/chain/tests/index.integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,17 +197,17 @@ describe("ChainService", () => {
it("Should properly update supported networks", async () => {
chainService.supportedNetworks = []
await chainService.updateSupportedNetworks()
expect(chainService.supportedNetworks.length).toBe(8)
expect(chainService.supportedNetworks.length).toBe(10)
})
})

describe("addCustomChain", () => {
// prettier-ignore
const FANTOM_CHAIN_PARAMS = { chainId: "250", blockExplorerUrl: "https://ftmscan.com", chainName: "Fantom Opera", nativeCurrency: { name: "Fantom", symbol: "FTM", decimals: 18, }, rpcUrls: [ "https://fantom-mainnet.gateway.pokt.network/v1/lb/62759259ea1b320039c9e7ac", "https://rpc.ftm.tools", "https://rpc.ankr.com/fantom", "https://rpc.fantom.network", "https://rpc2.fantom.network", "https://rpc3.fantom.network", "https://rpcapi.fantom.network", "https://fantom-mainnet.public.blastapi.io", "https://1rpc.io/ftm", ], blockExplorerUrls: ["https://ftmscan.com"], }
it("should update supported networks after adding a chain", async () => {
expect(chainService.supportedNetworks.length).toBe(8)
expect(chainService.supportedNetworks.length).toBe(10)
await chainService.addCustomChain(FANTOM_CHAIN_PARAMS)
expect(chainService.supportedNetworks.length).toBe(9)
expect(chainService.supportedNetworks.length).toBe(11)
})

it("should create a provider for the new chain", async () => {
Expand Down
4 changes: 4 additions & 0 deletions background/services/name/resolvers/ens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
BINANCE_SMART_CHAIN,
ETHEREUM,
GOERLI,
SEPOLIA,
OPTIMISM,
POLYGON,
} from "../../../constants"
Expand All @@ -18,6 +19,9 @@ const ENS_SUPPORTED_NETWORKS = [
OPTIMISM,
ARBITRUM_ONE,
GOERLI,
SEPOLIA,
// TODO: Add ARBITRUM_SEPOLIA once the support is added (tracked in
// https://github.com/ProjectOpenSea/opensea-js/issues/1201).
AVALANCHE,
BINANCE_SMART_CHAIN,
]
Expand Down
12 changes: 6 additions & 6 deletions e2e-tests/regular/transactions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ test.describe("Transactions", () => {
*/
await popup.getByTestId("top_menu_network_switcher").last().click()
await popup
.getByText(/^Goerli$/)
.getByText(/^Ethereum Goerli$/)
.last()
.click()
await walletPageHelper.assertCommonElements(
/^Goerli$/,
/^Ethereum Goerli$/,
true,
account2.name,
)
Expand Down Expand Up @@ -82,7 +82,7 @@ test.describe("Transactions", () => {
* isn't active.
*/
await transactionsHelper.assertUnfilledSendAssetScreen(
/^Goerli$/,
/^Ethereum Goerli$/,
account2.name,
"ETH",
"(\\d|,)+(\\.\\d{0,4})*",
Expand Down Expand Up @@ -118,7 +118,7 @@ test.describe("Transactions", () => {
* Check if "Transfer" has opened and verify elements on the page.
*/
await transactionsHelper.assertTransferScreen(
"Goerli",
"Ethereum Goerli",
"testertesting\\.eth",
"0x47745a7252e119431ccf973c0ebd4279638875a6",
"0x4774…875a6",
Expand Down Expand Up @@ -150,7 +150,7 @@ test.describe("Transactions", () => {
*/
await expect(popup.getByTestId("activity_list")).toHaveCount(1)
await assetsHelper.assertAssetDetailsPage(
/^Goerli$/,
/^Ethereum Goerli$/,
account2.name,
/^ETH$/,
/^(\d|,)+(\.\d{0,4})*$/,
Expand Down Expand Up @@ -207,7 +207,7 @@ test.describe("Transactions", () => {
* Verify elements on the activity screen
*/
await walletPageHelper.assertCommonElements(
/^Goerli$/,
/^Ethereum Goerli$/,
true,
account2.name,
)
Expand Down
1 change: 1 addition & 0 deletions ui/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,7 @@
"beta": "Mainnet (beta)",
"testnet": "Test Network",
"l2": "L2 scaling solution",
"l2Testnet": "L2 Test Network",
Copy link
Contributor

Choose a reason for hiding this comment

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

I would just use testnet, fwiw.

"compatibleChain": "EVM-compatible blockchain",
"avalanche": "Mainnet C-Chain",
"connected": "Connected"
Expand Down
Loading