Skip to content

Commit

Permalink
🌚 Add chain configuration (#90)
Browse files Browse the repository at this point in the history
* 🌚 Add chain configuration

* Squash config into one constant

* Lowercase network variable

* Remove hardcoded network names

* Rename network to chains

* Distinguish block explorer from contract verifier

* Adjust typings

* Adjust coverage

* Move types to one model file

* Split ethereum and arbitrum chain configs

* Rename contrat verifier api to etherscan verifier api

* Lowercase RPC

* Change error message

* Update changeset
  • Loading branch information
MiksuJak authored Feb 1, 2022
1 parent 6457545 commit 91a85f0
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 17 deletions.
5 changes: 5 additions & 0 deletions .changeset/kind-toys-kneel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'ethereum-mars': major
---

This update extracts RPC setup to dedicated configuration files for every chain.
3 changes: 2 additions & 1 deletion docs/source/cli.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ CLI flags
+-----------------+-------+------+----------------+--------------------+-----------------------------------------------------------------+
| --network | -n | Str | No | mainnet | Network name. Should be one of: |
| | | | | | |
| | | | | | mainnet, development, kovan, ropsten, goerli, rinkeby |
| | | | | | mainnet, development, kovan, ropsten, goerli, rinkeby, |
| | | | | | arbitrum, arbitrum_rinkeby |
| | | | | | |
| | | | | | or RPC URL e.g. ``https://infura.io/...`` |
+-----------------+-------+------+----------------+--------------------+-----------------------------------------------------------------+
Expand Down
2 changes: 1 addition & 1 deletion packages/mars/.nycrc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@
"check-coverage": true,
"branches": 63,
"lines": 69,
"functions": 58,
"functions": 55,
"statements": 69
}
21 changes: 21 additions & 0 deletions packages/mars/src/options/chain/arbitrum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Chain } from './model'

export const arbitrum: Chain = {
chainId: 42161,
chainName: 'Arbitrum',
getPublicRpc: () => 'https://arb1.arbitrum.io/rpc',
getInfuraRpc: (infuraApiKey) => `https://arbitrum-mainnet.infura.io/v3/${infuraApiKey}`,
getAlchemyRpc: (alchemyApiKey) => `https://arb-mainnet.g.alchemy.com/v2/${alchemyApiKey}`,
getBlockExplorerContractAddress: (contractAddress) => `https://arbiscan.io/address/${contractAddress}`,
getEtherscanVerifierApi: () => 'https://api.arbiscan.io/api',
}

export const arbitrum_rinkeby: Chain = {
chainId: 421611,
chainName: 'Arbitrum Testnet',
getPublicRpc: () => 'https://rinkeby.arbitrum.io/rpc',
getInfuraRpc: (infuraApiKey) => `https://arbitrum-rinkeby.infura.io/v3/${infuraApiKey}`,
getAlchemyRpc: (alchemyApiKey) => `https://arb-rinkeby.g.alchemy.com/v2/${alchemyApiKey}`,
getBlockExplorerContractAddress: (contractAddress) => `https://testnet.arbiscan.io/address/${contractAddress}`,
getEtherscanVerifierApi: () => 'https://api-testnet.arbiscan.io/api',
}
51 changes: 51 additions & 0 deletions packages/mars/src/options/chain/ethereum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Chain } from './model'

export const mainnet: Chain = {
chainId: 1,
chainName: 'Mainnet',
getPublicRpc: () => 'https://main-light.eth.linkpool.io/',
getInfuraRpc: (infuraApiKey) => `https://mainnet.infura.io/v3/${infuraApiKey}`,
getAlchemyRpc: (alchemyApiKey) => `https://eth-mainnet.alchemyapi.io/v2/${alchemyApiKey}`,
getBlockExplorerContractAddress: (contractAddress) => `https://etherscan.io/address/${contractAddress}`,
getEtherscanVerifierApi: () => 'https://api.etherscan.io/api',
}

export const ropsten: Chain = {
chainId: 3,
chainName: 'Ropsten',
getPublicRpc: () => 'https://ropsten.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161',
getInfuraRpc: (infuraApiKey) => `https://ropsten.infura.io/v3/${infuraApiKey}`,
getAlchemyRpc: (alchemyApiKey) => `https://eth-ropsten.alchemyapi.io/v2/${alchemyApiKey}`,
getBlockExplorerContractAddress: (contractAddress) => `https://ropsten.etherscan.io/address/${contractAddress}`,
getEtherscanVerifierApi: () => 'https://api-ropsten.etherscan.io/api',
}

export const rinkeby: Chain = {
chainId: 4,
chainName: 'Rinkeby',
getPublicRpc: () => 'https://rinkeby-light.eth.linkpool.io/',
getInfuraRpc: (infuraApiKey) => `https://rinkeby.infura.io/v3/${infuraApiKey}`,
getAlchemyRpc: (alchemyApiKey) => `https://eth-rinkeby.alchemyapi.io/v2/${alchemyApiKey}`,
getBlockExplorerContractAddress: (contractAddress) => `https://rinkeby.etherscan.io/address/${contractAddress}`,
getEtherscanVerifierApi: () => 'https://api-rinkeby.etherscan.io/api',
}

export const goerli: Chain = {
chainId: 5,
chainName: 'Goerli',
getPublicRpc: () => 'https://goerli-light.eth.linkpool.io/',
getInfuraRpc: (infuraApiKey) => `https://goerli.infura.io/v3/${infuraApiKey}`,
getAlchemyRpc: (alchemyApiKey) => `https://eth-goerli.alchemyapi.io/v2/${alchemyApiKey}`,
getBlockExplorerContractAddress: (contractAddress) => `https://goerli.etherscan.io/address/${contractAddress}`,
getEtherscanVerifierApi: () => 'https://api-goerli.etherscan.io/api',
}

export const kovan: Chain = {
chainId: 42,
chainName: 'Kovan',
getPublicRpc: () => 'https://kovan.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161',
getInfuraRpc: (infuraApiKey) => `https://kovan.infura.io/v3/${infuraApiKey}`,
getAlchemyRpc: (alchemyApiKey) => `https://eth-kovan.alchemyapi.io/v2/${alchemyApiKey}`,
getBlockExplorerContractAddress: (contractAddress) => `https://kovan.etherscan.io/address/${contractAddress}`,
getEtherscanVerifierApi: () => 'https://api-kovan.etherscan.io/api',
}
5 changes: 5 additions & 0 deletions packages/mars/src/options/chain/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { ChainSet } from './model'
import * as ethereumChains from './ethereum'
import * as arbitrumChains from './arbitrum'

export const chains = { ...ethereumChains, ...arbitrumChains } as ChainSet
13 changes: 13 additions & 0 deletions packages/mars/src/options/chain/model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export type Chain = {
chainId: number
chainName: string
getPublicRpc: () => string
getInfuraRpc: (infuraApiKey: string) => string
getAlchemyRpc: (alchemyApiKey: string) => string
getBlockExplorerContractAddress: (contractAddress: string) => string
getEtherscanVerifierApi: () => string
}

export type ChainSet = {
[chainName: string]: Chain
}
4 changes: 2 additions & 2 deletions packages/mars/src/options/checks.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { chains } from './chain'
import { usage } from './usage'

const PRIVATE_KEY_REGEX = /^0x[a-f\d]{64}$/i
Expand Down Expand Up @@ -31,10 +32,9 @@ export function ensureBoolean(value: unknown, message: string): asserts value is
ensure((value) => typeof value === 'boolean', value, message)
}

const NETWORKS = ['development', 'kovan', 'ropsten', 'goerli', 'rinkeby', 'mainnet']
const URL_REGEX = /^https?:\/\/[^\s]+$/
function isProperNetwork(value: unknown) {
return typeof value === 'string' && (NETWORKS.includes(value) || URL_REGEX.test(value))
return typeof value === 'string' && (value in chains || URL_REGEX.test(value))
}
export function ensureNetwork(value: unknown, message: string): asserts value is string {
ensure(isProperNetwork, value, message)
Expand Down
8 changes: 5 additions & 3 deletions packages/mars/src/options/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { getEnvironmentOptions } from './environment'
import { Options } from './Options'
import { ensureMultisigConfig } from '../multisig/multisigConfig'
import { logConfig } from '../logging'
import { chains } from './chain'

export async function getConfig(options: Options): Promise<ExecuteOptions> {
const merged = {
Expand Down Expand Up @@ -76,18 +77,19 @@ async function getSigner(options: Options) {
}
let rpcUrl: string | undefined
let provider: providers.JsonRpcProvider | undefined

if (isNetworkProvider(network)) {
// this causes 'MaxListenersExceededWarning: Possible EventEmitter memory leak detected.' when many contracts in use
// details at https://github.com/ChainSafe/web3.js/issues/1648
provider = new providers.Web3Provider(network as any)
} else if (network.startsWith('http')) {
rpcUrl = network
} else if (alchemyApiKey) {
rpcUrl = `https://eth-${network}.alchemyapi.io/v2/${alchemyApiKey}`
rpcUrl = chains[network].getAlchemyRpc(alchemyApiKey)
} else if (infuraApiKey) {
rpcUrl = `https://${network}.infura.io/v3/${infuraApiKey}`
rpcUrl = chains[network].getInfuraRpc(infuraApiKey)
} else {
throw new Error('Cannot construct rpc url. This should never happen.')
rpcUrl = chains[network].getPublicRpc()
}

let signer: Signer
Expand Down
4 changes: 2 additions & 2 deletions packages/mars/src/options/usage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ Options:
also use the env variable PRIVATE_KEY.
-n, --network [string] The network to run the deployment against. Can be
either an Ethereum JSON-RPC url or one of:
development, kovan, ropsten, goerli, rinkeby or
mainnet. Default: mainnet.
development, kovan, ropsten, goerli, rinkeby,
mainnet, arbitrum or arbitrum_rinkeby. Default: mainnet.
-i, --infura-key [key] The Infura api key to use for JSON-RPC. You can
also use the env variable INFURA_KEY.
-a, --alchemy-key [key] The Alchemy api key to use for JSON-RPC. You can
Expand Down
26 changes: 18 additions & 8 deletions packages/mars/src/verification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import path from 'path'
import chalk from 'chalk'
import axios from 'axios'
import querystring from 'querystring'
import { chains } from './options/chain'

const isDirectory = (directoryPath: string) =>
fs.existsSync(path.resolve(directoryPath)) && fs.statSync(path.resolve(directoryPath)).isDirectory()
Expand Down Expand Up @@ -82,17 +83,22 @@ type Awaited<T> = T extends Promise<infer U> ? U : never
export type JsonInputs = Awaited<ReturnType<typeof createJsonInputs>>

const etherscanUrl = (network?: string) => {
if (!network || network === 'mainnet') {
return 'https://api.etherscan.io/api'
if (!network) {
return chains.mainnet.getEtherscanVerifierApi() as string
}
const url = chains[network].getEtherscanVerifierApi()
if (url) {
return url as string
} else {
throw new Error('Block explorer not supported for requested network')
}
return `https://api-${network}.etherscan.io/api`
}

function getEtherscanContractAddress(address: string, network?: string) {
function getBlockExplorerContractAddress(address: string, network?: string) {
if (!network || network === 'mainnet') {
return `https://etherscan.io/address/${address}`
return chains.mainnet.getBlockExplorerContractAddress(address)
}
return `https://${network}.etherscan.io/address/${address}`
return chains[network].getBlockExplorerContractAddress(address)
}

async function getCompilerOptions(waffleConfigPath: string) {
Expand Down Expand Up @@ -265,7 +271,9 @@ export async function verifySingleFile(
return
}
if (await waitForResult(etherscanApiKey, guid)) {
console.log(chalk.bold(chalk.green(`Contract verified at ${getEtherscanContractAddress(address, network)}\n`)))
console.log(
chalk.bold(chalk.green(`Contract verified at ${getBlockExplorerContractAddress(address, network)}\n`))
)
}
} catch (err) {
console.log(chalk.bold(chalk.yellow(`Error during verification: ${err.message ?? err}. Skipping\n`)))
Expand Down Expand Up @@ -306,7 +314,9 @@ export async function verify(
return
}
if (await waitForResult(etherscanApiKey, guid)) {
console.log(chalk.bold(chalk.green(`Contract verified at ${getEtherscanContractAddress(address, network)}\n`)))
console.log(
chalk.bold(chalk.green(`Contract verified at ${getBlockExplorerContractAddress(address, network)}\n`))
)
}
} catch (err) {
console.log(chalk.bold(chalk.yellow(`Error during verification: ${err.message ?? err}. Skipping\n`)))
Expand Down

0 comments on commit 91a85f0

Please sign in to comment.