Skip to content

Commit a9ba709

Browse files
authored
feat: add new chains to EvmChain. (#1142)
* feat: add new chains to EvmChain.
1 parent c085091 commit a9ba709

File tree

5 files changed

+252
-31
lines changed

5 files changed

+252
-31
lines changed

.changeset/good-ducks-return.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@moralisweb3/common-evm-utils': patch
3+
'@moralisweb3/streams': patch
4+
'moralis': patch
5+
---
6+
7+
Added new chains to the `EvmChain` class: `ARBITRUM_TESTNET`, `RONIN`, `OPTIMISM` and `AVALANCHE_TESTNET`.

packages/common/evmUtils/scripts/fetch-chaindata.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,30 @@
55

66
import axios from 'axios';
77
import fs from 'fs';
8-
import { Core, CoreProvider } from '@moralisweb3/common-core';
98
import { EvmChain } from '@moralisweb3/common-evm-utils';
109

11-
const url = 'https://chainid.network/chains.json';
10+
const DATASET_URL = 'https://chainid.network/chains.json';
11+
const SKIP_CHAIN_IDS = [
12+
2020, // Ronin, the dataset contains an invalid data for this chain.
13+
];
1214

1315
async function fetchChainData() {
14-
const response = await axios.get(url);
16+
const response = await axios.get(DATASET_URL);
1517
return response.data;
1618
}
1719

1820
function getSupportedChainIds() {
19-
CoreProvider.setDefault(Core.create());
20-
21-
const networks = Object.getOwnPropertyNames(EvmChain);
22-
return networks.filter((name) => name.toUpperCase() === name).map((name) => EvmChain[name].decimal);
21+
return EvmChain.values()
22+
.map((chain) => chain.decimal)
23+
.filter((chainId) => !SKIP_CHAIN_IDS.includes(chainId));
2324
}
2425

2526
function generateFile(items) {
2627
const tsPath = '../src/data/chaindata.ts';
2728
const content = `/* eslint-disable no-template-curly-in-string */
2829
import { EvmChainListDataEntry } from './types';
2930
30-
// source: ${url}
31+
// source: ${DATASET_URL}
3132
export const chainList: EvmChainListDataEntry[] = ${JSON.stringify(items, null, 2)};`;
3233
fs.writeFileSync(tsPath, content, 'utf-8');
3334
}

packages/common/evmUtils/src/data/chaindata.ts

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export const chainList: EvmChainListDataEntry[] = [
5252
'https://goerli.infura.io/v3/${INFURA_API_KEY}',
5353
'wss://goerli.infura.io/v3/${INFURA_API_KEY}',
5454
'https://rpc.goerli.mudit.blog/',
55+
'https://ethereum-goerli.publicnode.com',
5556
],
5657
faucets: [
5758
'http://fauceth.komputing.org?chain=5&address=${ADDRESS}',
@@ -78,6 +79,28 @@ export const chainList: EvmChainListDataEntry[] = [
7879
},
7980
],
8081
},
82+
{
83+
name: 'Optimism',
84+
chain: 'ETH',
85+
rpc: ['https://mainnet.optimism.io/'],
86+
faucets: [],
87+
nativeCurrency: {
88+
name: 'Ether',
89+
symbol: 'ETH',
90+
decimals: 18,
91+
},
92+
infoURL: 'https://optimism.io',
93+
shortName: 'oeth',
94+
chainId: 10,
95+
networkId: 10,
96+
explorers: [
97+
{
98+
name: 'etherscan',
99+
url: 'https://optimistic.etherscan.io',
100+
standard: 'EIP3091',
101+
},
102+
],
103+
},
81104
{
82105
name: 'Cronos Mainnet Beta',
83106
chain: 'CRO',
@@ -153,6 +176,7 @@ export const chainList: EvmChainListDataEntry[] = [
153176
'https://data-seed-prebsc-2-s2.binance.org:8545',
154177
'https://data-seed-prebsc-1-s3.binance.org:8545',
155178
'https://data-seed-prebsc-2-s3.binance.org:8545',
179+
'https://bsc-testnet.publicnode.com',
156180
],
157181
faucets: ['https://testnet.binance.org/faucet-smart'],
158182
nativeCurrency: {
@@ -228,6 +252,30 @@ export const chainList: EvmChainListDataEntry[] = [
228252
},
229253
],
230254
},
255+
{
256+
name: 'Fantom Testnet',
257+
chain: 'FTM',
258+
rpc: ['https://rpc.testnet.fantom.network', 'https://fantom-testnet.publicnode.com'],
259+
faucets: ['https://faucet.fantom.network'],
260+
nativeCurrency: {
261+
name: 'Fantom',
262+
symbol: 'FTM',
263+
decimals: 18,
264+
},
265+
infoURL: 'https://docs.fantom.foundation/quick-start/short-guide#fantom-testnet',
266+
shortName: 'tftm',
267+
chainId: 4002,
268+
networkId: 4002,
269+
icon: 'fantom',
270+
explorers: [
271+
{
272+
name: 'ftmscan',
273+
url: 'https://testnet.ftmscan.com',
274+
icon: 'ftmscan',
275+
standard: 'EIP3091',
276+
},
277+
],
278+
},
231279
{
232280
name: 'Arbitrum One',
233281
chainId: 42161,
@@ -268,6 +316,29 @@ export const chainList: EvmChainListDataEntry[] = [
268316
],
269317
},
270318
},
319+
{
320+
name: 'Avalanche Fuji Testnet',
321+
chain: 'AVAX',
322+
icon: 'avax',
323+
rpc: ['https://api.avax-test.network/ext/bc/C/rpc', 'https://avalanche-fuji-c-chain.publicnode.com'],
324+
faucets: ['https://faucet.avax-test.network/'],
325+
nativeCurrency: {
326+
name: 'Avalanche',
327+
symbol: 'AVAX',
328+
decimals: 18,
329+
},
330+
infoURL: 'https://cchain.explorer.avax-test.network',
331+
shortName: 'Fuji',
332+
chainId: 43113,
333+
networkId: 1,
334+
explorers: [
335+
{
336+
name: 'snowtrace',
337+
url: 'https://testnet.snowtrace.io',
338+
standard: 'EIP3091',
339+
},
340+
],
341+
},
271342
{
272343
name: 'Avalanche C-Chain',
273344
chain: 'AVAX',
@@ -306,6 +377,7 @@ export const chainList: EvmChainListDataEntry[] = [
306377
'https://matic-mumbai.chainstacklabs.com',
307378
'https://rpc-mumbai.maticvigil.com',
308379
'https://matic-testnet-archive-rpc.bwarelabs.com',
380+
'https://polygon-mumbai-bor.publicnode.com',
309381
],
310382
faucets: ['https://faucet.polygon.technology/'],
311383
nativeCurrency: {
@@ -325,6 +397,38 @@ export const chainList: EvmChainListDataEntry[] = [
325397
},
326398
],
327399
},
400+
{
401+
name: 'Arbitrum Goerli',
402+
title: 'Arbitrum Goerli Rollup Testnet',
403+
chainId: 421613,
404+
shortName: 'arb-goerli',
405+
chain: 'ETH',
406+
networkId: 421613,
407+
nativeCurrency: {
408+
name: 'Arbitrum Goerli Ether',
409+
symbol: 'AGOR',
410+
decimals: 18,
411+
},
412+
rpc: ['https://goerli-rollup.arbitrum.io/rpc/'],
413+
faucets: [],
414+
infoURL: 'https://arbitrum.io/',
415+
explorers: [
416+
{
417+
name: 'Arbitrum Goerli Rollup Explorer',
418+
url: 'https://goerli-rollup-explorer.arbitrum.io',
419+
standard: 'EIP3091',
420+
},
421+
],
422+
parent: {
423+
type: 'L2',
424+
chain: 'eip155-5',
425+
bridges: [
426+
{
427+
url: 'https://bridge.arbitrum.io/',
428+
},
429+
],
430+
},
431+
},
328432
{
329433
name: 'Sepolia',
330434
title: 'Ethereum Testnet Sepolia',

packages/common/evmUtils/src/dataTypes/EvmChain/EvmChain.test.ts

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -97,24 +97,59 @@ describe('EvmChain', () => {
9797
expect(chainA.equals(chainB)).toBeFalsy();
9898
});
9999

100-
/**
101-
* External data
102-
*/
103-
it('should get the chain name', () => {
104-
const chain = EvmChain.create('0x1');
105-
106-
expect(chain.name).toBe('Ethereum Mainnet');
107-
expect(chain.rpcUrls).toStrictEqual([
108-
'https://mainnet.infura.io/v3/${INFURA_API_KEY}',
109-
'wss://mainnet.infura.io/ws/v3/${INFURA_API_KEY}',
110-
'https://api.mycryptoapi.com/eth',
111-
'https://cloudflare-eth.com',
112-
'https://ethereum.publicnode.com',
113-
]);
114-
expect(chain.currency).toStrictEqual({
115-
decimals: 18,
116-
name: 'Ether',
117-
symbol: 'ETH',
100+
it('returns correct chain ID', () => {
101+
expect(EvmChain.ETHEREUM.apiHex).toBe('0x1');
102+
expect(EvmChain.GOERLI.apiHex).toBe('0x5');
103+
expect(EvmChain.SEPOLIA.apiHex).toBe('0xaa36a7');
104+
expect(EvmChain.BSC.apiHex).toBe('0x38');
105+
expect(EvmChain.BSC_TESTNET.apiHex).toBe('0x61');
106+
expect(EvmChain.POLYGON.apiHex).toBe('0x89');
107+
expect(EvmChain.MUMBAI.apiHex).toBe('0x13881');
108+
expect(EvmChain.FANTOM.apiHex).toBe('0xfa');
109+
expect(EvmChain.FANTOM_TESTNET.apiHex).toBe('0xfa2');
110+
expect(EvmChain.AVALANCHE.apiHex).toBe('0xa86a');
111+
expect(EvmChain.AVALANCHE_TESTNET.apiHex).toBe('0xa869');
112+
expect(EvmChain.CRONOS.apiHex).toBe('0x19');
113+
expect(EvmChain.RONIN.apiHex).toBe('0x7e4');
114+
expect(EvmChain.ARBITRUM.apiHex).toBe('0xa4b1');
115+
expect(EvmChain.ARBITRUM_TESTNET.apiHex).toBe('0x66eed');
116+
expect(EvmChain.OPTIMISM.apiHex).toBe('0xa');
117+
expect(EvmChain.PALM.apiHex).toBe('0x2a15c308d');
118+
});
119+
120+
describe('metadata', () => {
121+
// We skip RONIN because the source dataset doesn't have it.
122+
const supportedChains = EvmChain.values().filter((chain) => chain.apiHex !== '0x7e4');
123+
124+
for (const chain of supportedChains) {
125+
it(`returns metadata for ${chain.apiHex}`, () => {
126+
expect(chain.name).toBeDefined();
127+
expect((chain.rpcUrls as string[]).length > 0).toBeTruthy();
128+
expect(chain.currency).toBeDefined();
129+
expect(chain.currency?.decimals).toBeDefined();
130+
expect(chain.currency?.name).toBeDefined();
131+
expect(chain.currency?.symbol).toBeDefined();
132+
expect(chain.explorer).toBeDefined();
133+
expect(chain.explorer?.url).toBeDefined();
134+
});
135+
}
136+
137+
it('returns correct metadata for Ethereum', () => {
138+
const chain = EvmChain.create('0x1');
139+
140+
expect(chain.name).toBe('Ethereum Mainnet');
141+
expect(chain.rpcUrls).toStrictEqual([
142+
'https://mainnet.infura.io/v3/${INFURA_API_KEY}',
143+
'wss://mainnet.infura.io/ws/v3/${INFURA_API_KEY}',
144+
'https://api.mycryptoapi.com/eth',
145+
'https://cloudflare-eth.com',
146+
'https://ethereum.publicnode.com',
147+
]);
148+
expect(chain.currency).toStrictEqual({
149+
decimals: 18,
150+
name: 'Ether',
151+
symbol: 'ETH',
152+
});
118153
});
119154
});
120155
});

0 commit comments

Comments
 (0)