Skip to content

Commit 0a87758

Browse files
committed
feat: add testnet parameter to ethereum class to simplify switching testnets
1 parent c94d152 commit 0a87758

File tree

8 files changed

+230
-117
lines changed

8 files changed

+230
-117
lines changed

packages/chains/chains-ethereum/src/base.ts

+36-14
Original file line numberDiff line numberDiff line change
@@ -258,10 +258,9 @@ export class EthereumBaseChain
258258
if (!this.signer) {
259259
throw new Error(`Must connect ${this.chain} signer.`);
260260
}
261-
return checkProviderNetwork(
261+
return this.checkProviderNetwork(
262262
// If the signer as no provider, fall back to the provider field.
263263
this.signer.provider || this.provider,
264-
this.network,
265264
);
266265
};
267266

@@ -275,18 +274,31 @@ export class EthereumBaseChain
275274
) {
276275
throw new Error(`Signer doesn't support switching network.`);
277276
}
278-
// await (this.signer.provider as JsonRpcProvider).send(
279-
// "wallet_switchEthereumChain",
280-
// [
281-
// {
282-
// chainId: this.network.config.chainId,
283-
// },
284-
// ],
285-
// );
286-
await (this.signer.provider as JsonRpcProvider).send(
287-
"wallet_addEthereumChain",
288-
[this.network.config],
289-
);
277+
278+
// Check if the network is an Ethereum network, to avoid MetaMask
279+
// throwing `Must not specify default MetaMask chain`.
280+
// TODO: Try addEthereumChain first and fallback to switchEthereumChain
281+
// based on the returned error message.
282+
if (
283+
// Ethereum chains
284+
this.network.nativeAsset.symbol === "ETH" ||
285+
// Goerli
286+
this.network.nativeAsset.symbol === "gETH"
287+
) {
288+
await (this.signer.provider as JsonRpcProvider).send(
289+
"wallet_switchEthereumChain",
290+
[
291+
{
292+
chainId: this.network.config.chainId,
293+
},
294+
],
295+
);
296+
} else {
297+
await (this.signer.provider as JsonRpcProvider).send(
298+
"wallet_addEthereumChain",
299+
[this.network.config],
300+
);
301+
}
290302
};
291303

292304
public getOutputPayload = async (
@@ -496,6 +508,16 @@ export class EthereumBaseChain
496508
RenJSError.TRANSACTION_NOT_FOUND,
497509
);
498510
}
511+
if (receipt.status === 0) {
512+
throw ErrorWithCode.updateError(
513+
new Error(
514+
`${String(transaction.chain)} transaction failed: ${
515+
transaction.txHash
516+
}`,
517+
),
518+
RenJSError.CHAIN_TRANSACTION_REVERTED,
519+
);
520+
}
499521
if (receipt && receipt.blockNumber) {
500522
const transactionBlock = new BigNumber(
501523
receipt.blockNumber.toString(),

packages/chains/chains-ethereum/src/catalog.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const configMap: EthereumBaseChain["configMap"] = {
4040

4141
addresses: {
4242
GatewayRegistry: "0x44c2CdaE368F90544A01522C413376fC72ebd4F2",
43-
BasicBridge: "0x5D952fA25eD90b1151473d57F2B6C6DB568b865d",
43+
BasicBridge: "0xfc5681F4343803C11eB5Bb7aFd2108238bbd7177",
4444
},
4545
},
4646
};

packages/chains/chains-ethereum/src/ethereum.ts

+112-52
Original file line numberDiff line numberDiff line change
@@ -2,72 +2,113 @@ import { RenNetwork } from "@renproject/utils";
22

33
import { EthereumBaseChain } from "./base";
44
import { resolveEVMNetworkConfig } from "./utils/generic";
5+
import { EVMNetworkConfig } from "./utils/types";
56

6-
const configMap: EthereumBaseChain["configMap"] = {
7-
[RenNetwork.Mainnet]: {
8-
selector: "Ethereum",
9-
10-
nativeAsset: { name: "Ether", symbol: "ETH", decimals: 18 },
11-
averageConfirmationTime: 15,
12-
13-
config: {
14-
chainId: "0x1",
15-
chainName: "Ethereum Mainnet",
16-
nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
17-
rpcUrls: [
18-
"https://cloudflare-eth.com",
19-
"https://mainnet.infura.io/v3/${INFURA_API_KEY}",
20-
"wss://mainnet.infura.io/ws/v3/${INFURA_API_KEY}",
21-
"https://api.mycryptoapi.com/eth",
22-
],
23-
blockExplorerUrls: ["https://etherscan.io"],
24-
},
7+
const ethereumMainnetConfig: EVMNetworkConfig = {
8+
selector: "Ethereum",
259

26-
addresses: {
27-
GatewayRegistry: "0xf36666C230Fa12333579b9Bd6196CB634D6BC506",
28-
BasicBridge: "0x82DF02A52E2e76C0c233367f2fE6c9cfe51578c5",
29-
},
10+
nativeAsset: { name: "Ether", symbol: "ETH", decimals: 18 },
11+
averageConfirmationTime: 15,
12+
13+
config: {
14+
chainId: "0x1",
15+
chainName: "Ethereum Mainnet",
16+
nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
17+
rpcUrls: [
18+
"https://cloudflare-eth.com",
19+
"https://mainnet.infura.io/v3/${INFURA_API_KEY}",
20+
"wss://mainnet.infura.io/ws/v3/${INFURA_API_KEY}",
21+
"https://api.mycryptoapi.com/eth",
22+
],
23+
blockExplorerUrls: ["https://etherscan.io"],
3024
},
3125

32-
[RenNetwork.Testnet]: {
33-
selector: "Ethereum",
34-
isTestnet: true,
35-
36-
nativeAsset: { name: "Kovan Ether", symbol: "ETH", decimals: 18 },
37-
averageConfirmationTime: 15,
38-
39-
config: {
40-
chainId: "0x2a",
41-
chainName: "Kovan",
42-
nativeCurrency: {
43-
name: "Kovan Ether",
44-
symbol: "KOV",
45-
decimals: 18,
46-
},
47-
rpcUrls: [
48-
"https://kovan.poa.network",
49-
"http://kovan.poa.network:8545",
50-
"https://kovan.infura.io/v3/${INFURA_API_KEY}",
51-
"wss://kovan.infura.io/ws/v3/${INFURA_API_KEY}",
52-
"ws://kovan.poa.network:8546",
53-
],
54-
blockExplorerUrls: ["https://kovan.etherscan.io"],
26+
addresses: {
27+
GatewayRegistry: "0xf36666C230Fa12333579b9Bd6196CB634D6BC506",
28+
BasicBridge: "0x82DF02A52E2e76C0c233367f2fE6c9cfe51578c5",
29+
},
30+
};
31+
32+
const kovanConfig: EVMNetworkConfig = {
33+
selector: "Ethereum",
34+
isTestnet: true,
35+
36+
nativeAsset: { name: "Kovan Ether", symbol: "ETH", decimals: 18 },
37+
averageConfirmationTime: 15,
38+
39+
config: {
40+
chainId: "0x2a",
41+
chainName: "Kovan",
42+
nativeCurrency: {
43+
name: "Kovan Ether",
44+
symbol: "KOV",
45+
decimals: 18,
5546
},
47+
rpcUrls: [
48+
"https://kovan.poa.network",
49+
"http://kovan.poa.network:8545",
50+
"https://kovan.infura.io/v3/${INFURA_API_KEY}",
51+
"https://eth-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
52+
"wss://kovan.infura.io/ws/v3/${INFURA_API_KEY}",
53+
"wss://eth-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
54+
"ws://kovan.poa.network:8546",
55+
],
56+
blockExplorerUrls: ["https://kovan.ethplorer.io"],
57+
},
58+
59+
addresses: {
60+
GatewayRegistry: "0x5076a1F237531fa4dC8ad99bb68024aB6e1Ff701",
61+
BasicBridge: "0xcb6bD6B6c7D7415C0157e393Bb2B6Def7555d518",
62+
},
63+
};
64+
65+
const goerliConfig: EVMNetworkConfig = {
66+
selector: "Goerli",
67+
68+
nativeAsset: { name: "Görli Ether", symbol: "gETH", decimals: 18 },
69+
averageConfirmationTime: 15,
5670

57-
addresses: {
58-
GatewayRegistry: "0x5076a1F237531fa4dC8ad99bb68024aB6e1Ff701",
59-
BasicBridge: "0xcb6bD6B6c7D7415C0157e393Bb2B6Def7555d518",
71+
config: {
72+
chainId: "0x5",
73+
chainName: "Görli",
74+
nativeCurrency: {
75+
name: "Görli Ether",
76+
symbol: "GOR",
77+
decimals: 18,
6078
},
79+
rpcUrls: [
80+
"https://rpc.goerli.mudit.blog/",
81+
"https://goerli.infura.io/v3/${INFURA_API_KEY}",
82+
"https://eth-goerli.alchemyapi.io/v2/${ALCHEMY_API_KEY}",
83+
"wss://goerli.infura.io/v3/${INFURA_API_KEY}",
84+
"wss://eth-goerli.alchemyapi.io/v2/${ALCHEMY_API_KEY}",
85+
],
86+
blockExplorerUrls: ["https://goerli.etherscan.io"],
87+
},
88+
89+
addresses: {
90+
GatewayRegistry: "0x5076a1F237531fa4dC8ad99bb68024aB6e1Ff701",
91+
BasicBridge: "0xcb6bD6B6c7D7415C0157e393Bb2B6Def7555d518",
6192
},
6293
};
6394

95+
export const defaultConfigMap: EthereumBaseChain["configMap"] = {
96+
[RenNetwork.Mainnet]: ethereumMainnetConfig,
97+
[RenNetwork.Testnet]: kovanConfig,
98+
};
99+
100+
export const goerliConfigMap: EthereumBaseChain["configMap"] = {
101+
[RenNetwork.Mainnet]: ethereumMainnetConfig,
102+
[RenNetwork.Testnet]: goerliConfig,
103+
};
104+
64105
/**
65106
* The Ethereum RenJS implementation.
66107
*/
67108
export class Ethereum extends EthereumBaseChain {
68109
// Static members.
69110
public static chain = "Ethereum" as const;
70-
public static configMap = configMap;
111+
public static configMap = defaultConfigMap;
71112
public static assets = {
72113
ETH: "ETH" as const,
73114
DAI: "DAI" as const,
@@ -85,6 +126,16 @@ export class Ethereum extends EthereumBaseChain {
85126
ROOK: "ROOK" as const,
86127
BADGER: "BADGER" as const,
87128
KNC: "KNC" as const,
129+
130+
// Goerli only
131+
gETH: "gETH" as const,
132+
REN_Goerli: "REN_Goerli" as const,
133+
DAI_Goerli: "DAI_Goerli" as const,
134+
USDC_Goerli: "USDC_Goerli" as const,
135+
USDT_Goerli: "USDT_Goerli" as const,
136+
137+
// Aliases
138+
ETH_Goerli: "gETH" as const,
88139
};
89140

90141
public configMap = Ethereum.configMap;
@@ -95,17 +146,26 @@ export class Ethereum extends EthereumBaseChain {
95146
*
96147
* @param params Ethereum constructor parameters
97148
* @param params.network A RenVM network string or an EVM config object.
149+
* @param params.testnet Optionally specify a default Ethereum testnet.
98150
* @param params.provider A Web3 or Ethers.js provider.
99151
* @param params.signer A Web3 or Ethers.js signer.
100152
* @param params.config Pass optional configurations, e.g. a logger
101153
*/
102154
public constructor({
103155
network,
156+
testnet,
104157
...params
105-
}: ConstructorParameters<typeof EthereumBaseChain>[0]) {
158+
}: ConstructorParameters<typeof EthereumBaseChain>[0] & {
159+
testnet?: "Kovan" | "Goerli" | "Görli";
160+
}) {
106161
super({
107162
...params,
108-
network: resolveEVMNetworkConfig(configMap, network),
163+
network: resolveEVMNetworkConfig(
164+
testnet === "Goerli" || testnet === "Görli"
165+
? goerliConfigMap
166+
: defaultConfigMap,
167+
network,
168+
),
109169
});
110170
}
111171
}
+11-35
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,23 @@
1-
import { RenNetwork } from "@renproject/utils";
2-
31
import { EthereumBaseChain } from "./base";
2+
import { goerliConfigMap } from "./ethereum";
43
import { resolveEVMNetworkConfig } from "./utils/generic";
54

6-
const configMap: EthereumBaseChain["configMap"] = {
7-
[RenNetwork.Testnet]: {
8-
selector: "Goerli",
9-
10-
nativeAsset: { name: "Görli Ether", symbol: "gETH", decimals: 18 },
11-
averageConfirmationTime: 15,
12-
13-
config: {
14-
chainId: "0x5",
15-
chainName: "Görli",
16-
nativeCurrency: {
17-
name: "Görli Ether",
18-
symbol: "GOR",
19-
decimals: 18,
20-
},
21-
rpcUrls: [
22-
"https://rpc.goerli.mudit.blog/",
23-
"https://goerli.infura.io/v3/${INFURA_API_KEY}",
24-
"wss://goerli.infura.io/v3/${INFURA_API_KEY}",
25-
],
26-
blockExplorerUrls: ["https://goerli.etherscan.io"],
27-
},
28-
29-
addresses: {
30-
GatewayRegistry: "0x5076a1F237531fa4dC8ad99bb68024aB6e1Ff701",
31-
BasicBridge: "0xcb6bD6B6c7D7415C0157e393Bb2B6Def7555d518",
32-
},
33-
},
34-
};
35-
365
export class Goerli extends EthereumBaseChain {
376
// Static members.
387
public static chain = "Goerli" as const;
39-
public static configMap = configMap;
8+
public static configMap = goerliConfigMap;
409
public static assets = {
4110
gETH: "gETH" as const,
11+
REN: "REN_Goerli" as const,
12+
DAI: "DAI_Goerli" as const,
13+
USDC: "USDC_Goerli" as const,
14+
USDT: "USDT_Goerli" as const,
15+
16+
// Aliases
17+
ETH: "gETH" as const,
4218
};
4319

44-
public configMap = configMap;
20+
public configMap = goerliConfigMap;
4521
public assets = Goerli.assets;
4622

4723
public constructor({
@@ -50,7 +26,7 @@ export class Goerli extends EthereumBaseChain {
5026
}: ConstructorParameters<typeof EthereumBaseChain>[0]) {
5127
super({
5228
...params,
53-
network: resolveEVMNetworkConfig(configMap, network),
29+
network: resolveEVMNetworkConfig(goerliConfigMap, network),
5430
});
5531
}
5632
}

packages/chains/chains-ethereum/src/index.ts

+11-11
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ export {
99
} from "./utils/generic";
1010

1111
// Chains
12-
export * from "./arbitrum";
13-
export * from "./avalanche";
14-
export * from "./bsc";
15-
export * from "./catalog";
16-
export * from "./ethereum";
17-
export * from "./fantom";
18-
export * from "./goerli";
19-
export * from "./kava";
20-
export * from "./moonbeam";
21-
export * from "./optimism";
22-
export * from "./polygon";
12+
export { Arbitrum } from "./arbitrum";
13+
export { Avalanche } from "./avalanche";
14+
export { BinanceSmartChain } from "./bsc";
15+
export { Catalog } from "./catalog";
16+
export { Ethereum } from "./ethereum";
17+
export { Fantom } from "./fantom";
18+
export { Goerli } from "./goerli";
19+
export { Kava } from "./kava";
20+
export { Moonbeam } from "./moonbeam";
21+
export { Optimism } from "./optimism";
22+
export { Polygon } from "./polygon";

0 commit comments

Comments
 (0)