ethereum-lists/chains: the CAIP-2 JSON registry behind chainlist
provides metadata for chains
At a glance
- What is it?
- ethereum-lists/chains is a data repository, not a library. Each EVM network gets one JSON file named after its CAIP-2 identifier, and a Kotlin Gradle processor validates the tree before CI will look at a pull request.
- Who is it for?
- Adopt it if you need canonical chainId, RPC and explorer metadata for EVM networks and you are willing to consume the aggregated JSON at chainid.network rather than hand-maintaining your own table. Do not adopt it as a runtime dependency if you need sub-second freshness or per-request lookups; the data changes through pull requests, and the last push to the repository was on 2026-09-21.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Kotlin, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem: every wallet hardcodes its own chain table
An EVM wallet or block explorer needs the same handful of facts for every network it supports: the numeric chainId, at least one working RPC endpoint, the native currency symbol and decimals, and a block explorer URL. Nothing in the protocol distributes those facts. EIP-155 defines how a chainId is used in a signed transaction, but it does not say who owns the number or where a client should look it up. The result, without a shared registry, is that each team curates its own list, and the lists disagree about short names, about which RPC is canonical, and about whether a testnet still exists.
This repository is the shared list. The README frames the central rule bluntly: "We cannot allow more than one chain with the same chainID - this would open the door to replay attacks." That sentence explains the whole design. A chainId is a security boundary, not a label, so the project treats it as a scarce resource allocated on a first-come basis. The audience is chain operators who need their network discoverable, and client developers who want to stop maintaining a private table.
One JSON file per chain, named by CAIP-2
The layout is the mechanism. Source data lives under _data/chains, and each chain occupies a file whose name is its CAIP-2 representation plus a .json extension. For Ethereum mainnet that means a file named eip155-1.json. The README example shows the field set: name, chain, rpc as an array of URLs, faucets, nativeCurrency with name, symbol and decimals, features as a list of objects such as EIP155 and EIP1559, infoURL, shortName, chainId, networkId, icon, and explorers, where each explorer carries name, url, icon and standard.
Two details in that example are easy to miss. The RPC array can contain template URLs: the Ethereum entry lists https://mainnet.infura.io/v3/${INFURA_API_KEY}, so a consumer is expected to substitute its own key rather than treat the string as directly callable. And every icon referenced anywhere in a chain file, whether at the network level or inside an explorer entry, must have a matching JSON file in _data/icons. The README states this as a hard requirement: if the example uses ethereum and etherscan, both ethereum.json and etherscan.json must exist. Those icon files are arrays of objects with url, width, height and format, and the constraints are specific: the URL must be publicly resolvable through IPFS, width and height must be positive integers, format is png, jpg or svg, and size must be under 250kb. The README also asks that the CID be retrievable via ipfs get rather than only through a gateway, and says explicitly not to use pinata for now. That is an unusually strict content-addressing rule for a metadata repo, and it is the most likely place for a first-time contributor to fail.
Parent links, status fields and the red flag for reused chain IDs
Chains that are L2s or shards link upward through a parent object containing type, chain and an optional bridges array. The chain value is a reference to another file in the repository, written as eip155-1 for Ethereum mainnet, and the README requires that the referenced parent already exist in the repo. This is a graph, not a flat table, and the validation has to resolve it.
Lifecycle is handled by a status field rather than deletion, and the reasoning is stated in the README: a chain should never be deleted because removal would open the door to replay attacks. The permitted values are active (the default), incubating and deprecated. Reassignment of a chainId is possible only after the previous holder is deprecated, which the README suggests is realistic for short-lived testnets. When that happens, the project applies a redFlag named reusedChainID, and the README says clients should display it to warn users about the danger. For anyone building a wallet, that redFlag is the field that matters most in this repository, and it is the one most likely to be ignored by a naive consumer that reads only chainId and rpc.
Installing the toolchain and validating a new chain entry
There is no package to install. The README points contributors at the repository itself, and the only documented build step is the Gradle wrapper, which runs the Kotlin processor that checks the data. The README shows the expected output, a successful build in a few seconds.
$ ./gradlew run
BUILD SUCCESSFUL in 7s
9 actionable tasks: 9 executedAfter that, the README asks for Prettier to format the JSON according to the repository's .prettierrc.json. The command given is a glob over the chain and icon directories.
npx prettier --write _data/*/*.jsonThe workflow is then: add your file under _data/chains, add any icon JSON under _data/icons, run both commands, and open a pull request. The README is direct about review: "There will likely be no review when the CI is red," and it asks contributors to re-request review after pushing CI fixes. The repository also ships a package.json that exports the data directories, so a JavaScript consumer can import a single chain file by path through the "./*" export, for example resolving to _data/chains/eip155-1.json, or pull icons through the "./icons/*" export. Note that the package only ships _data in its files list; the Kotlin processor is not part of the published package.
Consuming the aggregated feeds instead of the raw tree
Most applications should not walk _data at all. The README documents two aggregated files assembled automatically from the tree: https://chainid.network/chains.json and https://chainid.network/chains_mini.json, the latter described as miniaturized with fewer fields for a smaller payload. That is the practical integration point for a wallet or explorer that wants the whole set at build time or on a refresh schedule.
The trade-off is that the mini file is a lossy projection. The README does not enumerate which fields are dropped, so a client that switches to chains_mini.json to save bandwidth has to verify for itself that parent, status, redFlag and explorer standard survive the cut. If you depend on reusedChainID warnings, check the mini feed before you commit to it. The same caution applies to the rpc array: entries with ${...} placeholders are templates, and a consumer that forwards them unchanged will produce broken requests.
Where this repository is the wrong tool
The data is distributed as pull requests, so freshness is bounded by review and CI, not by your release cycle. A chain that launched this morning is not in the aggregated feed until someone opens a PR and CI passes. If your product needs to onboard a network the moment it goes live, you need a second path, and the repository does not offer one.
The collision policy is the other hard boundary. The README states that the first pull request gets the chainId and that PRs trying to take a chainId because the submitter thinks their chain is better will be closed. If you are launching a network and the ID you want is already taken by an active chain, this project will not resolve that for you. There is also no documented rollback procedure for a bad merge; the README discusses deprecation as the mechanism for retiring a chain, but it does not describe reverting a merged entry. Finally, the repository is metadata only. It does not provide RPC infrastructure, so a listed endpoint can be down while the entry stays valid.
Alternatives and how they differ
The closest structural alternative is MESC, which the README lists under Tools. The difference is direction of travel. This repository is a public registry keyed by chainId and CAIP-2, validated by CI, with one canonical entry per network. MESC addresses the local configuration problem: which RPC a given user or application should actually talk to, including per-user endpoint preferences. A team can adopt both, and the README's own usage list suggests that happens.
For consumers who only need typed chain objects for a specific JavaScript stack, the README points at wagmi-compatible chain configurations and at eth-chains, a separate repository. Those are code-shaped distributions of similar data, which means they version with the consuming library rather than with the registry. The difference matters when a chain is deprecated: a registry entry can be updated and flagged, while a vendored constant in a library requires a release. Chainlist and chainid.network are listing sites built on this data, not alternatives to it.
Licence, maintenance and what a fork costs
The repository is MIT licensed, and the LICENSE file sits at the top level. MIT is permissive, so redistributing the JSON, including inside a commercial wallet, is normally straightforward; the usual obligation is preserving the copyright notice and licence text. That is a general description of the licence, not legal advice, and the icon files are a separate question: the README requires icons to be content-addressed on IPFS but says nothing about the rights to the artwork itself, so a redistributor should check each icon's provenance rather than assume the MIT grant covers third-party logos.
The last push to the repository was on 2026-09-21, so the project is being updated. Upgrading is not a versioned operation. There are no releases listed in the repository, and the package.json carries no version field, so a consumer pinning "@ethereum-lists/chains" by semver has nothing to pin against; the practical approach is to snapshot the aggregated JSON at a known date and refresh deliberately. Forking is cheap in storage terms and expensive in process terms, because the value of the registry comes from other people sending their chains here rather than to your copy.
Editorial conclusion
Adopt it if you need canonical chainId, RPC and explorer metadata for EVM networks and you are willing to consume the aggregated JSON at chainid.network rather than hand-maintaining your own table. Do not adopt it as a runtime dependency if you need sub-second freshness or per-request lookups; the data changes through pull requests, and the last push to the repository was on 2026-09-21. Before you build on it, verify three things in the tree itself: that the chainId you care about is not marked with a status of deprecated, that its icon entry resolves over IPFS rather than only through a gateway, and that the aggregated chains_mini.json still carries every field your client reads, since the README describes it as carrying fewer fields.
Frequently asked questions
What is ethereum-lists/chains?
It is a data repository that provides metadata for EVM-based chains, with one JSON file per chain stored under _data/chains and named after its CAIP-2 identifier. The README describes aggregated outputs at chainid.network/chains.json and chainid.network/chains_mini.json.
How do I install ethereum-lists/chains?
There is nothing to install as a dependency for contributing: the README instructs you to clone the repository and run the Gradle wrapper with ./gradlew run, then format JSON with npx prettier --write _data/*/*.json. For consumption, the package.json exports the _data directories, and the README also documents aggregated JSON files.
Which chain is the most popular in ethereum-lists/chains?
The repository does not rank chains by popularity and the README provides no usage statistics. Its ordering rule is about allocation, not popularity: the first pull request gets the chainId.
What are the top 10 chains in ethereum-lists/chains?
The README does not publish a ranking or a top-ten list. The repository holds one file per chain under _data/chains, and the aggregated chains.json at chainid.network contains all of them, so any ordering would have to come from the consumer rather than from the project.
How do I install chains on tires?
This question is about snow chains for vehicle tires and has nothing to do with ethereum-lists/chains. The repository documents no tire-related functionality.
How do I install chains on a trailer?
This question concerns trailer tire chains, not the EVM chain metadata registry. The README covers JSON files under _data/chains and a Gradle wrapper command, and describes no towing equipment.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ethereum-lists-chains)