ethers is a complete and compact library for interacting with Ethereum and other EVM-compatible blockchains. It provides utilities for connecting to nodes, signing transactions, and interacting with smart contracts directly. @web3-react/core is a React framework specifically designed to manage wallet connection state and context within a React application. It simplifies the process of connecting wallets, tracking account changes, and handling disconnections using React hooks. While ethers handles the protocol communication, @web3-react handles the UI state management.
Building decentralized applications (dApps) requires two distinct layers of functionality: managing the user's wallet connection and interacting with the blockchain itself. @web3-react/core and ethers address these separate needs. ethers is the engine that talks to the blockchain, while @web3-react/core is the steering wheel that manages the connection state in your React UI. Understanding their roles prevents architectural confusion.
ethers focuses on the blockchain protocol.
// ethers: Direct provider creation
import { ethers } from "ethers";
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const address = await signer.getAddress();
@web3-react/core focuses on React state management.
// @web3-react/core: Hook-based state access
import { useWeb3React } from "@web3-react/core";
function WalletStatus() {
const { account, provider } = useWeb3React();
return <div>Connected: {account}</div>;
}
ethers requires you to manually handle the connection logic.
window.ethereum.// ethers: Manual connection handling
async function connectWallet() {
try {
await window.ethereum.request({ method: "eth_requestAccounts" });
const provider = new ethers.BrowserProvider(window.ethereum);
// Manually update React state here
} catch (error) {
console.error("Connection failed", error);
}
}
@web3-react/core abstracts connection logic into connectors.
// @web3-react/core: Using a connector
import { useWeb3React } from "@web3-react/core";
import { injected } from "@web3-react/injected";
function ConnectButton() {
const { activate, account } = useWeb3React();
return <button onClick={() => activate(injected)}>Connect</button>;
}
ethers gives you the provider instance directly.
// ethers: Instantiating provider locally
const provider = new ethers.JsonRpcProvider("https://mainnet.infura.io/v3/KEY");
const blockNumber = await provider.getBlockNumber();
@web3-react/core provides the provider via React Context.
ethers methods on this provider.// @web3-react/core: Consuming provider from context
import { useWeb3React } from "@web3-react/core";
import { ethers } from "ethers";
function BlockDisplay() {
const { provider } = useWeb3React();
// Note: web3-react provider might need wrapping to be ethers-compatible
const ethersProvider = provider ? new ethers.BrowserProvider(provider) : null;
return <div>Ready to read</div>;
}
ethers handles the cryptographic signing directly.
signer.signTransaction or signer.sendTransaction.// ethers: Signing and sending
const tx = {
to: "0xRecipient...",
value: ethers.parseEther("1.0")
};
const txResponse = await signer.sendTransaction(tx);
await txResponse.wait();
@web3-react/core exposes the signer through the hook.
ethers to construct the transaction.// @web3-react/core: Getting signer from context
import { useWeb3React } from "@web3-react/core";
function SendButton() {
const { account, connector } = useWeb3React();
// Connector provides the provider/signer logic
const handleSend = async () => {
const provider = await connector.getProvider();
// Use ethers with this provider to sign
};
return <button onClick={handleSend}>Send</button>;
}
ethers relies on event listeners for network changes.
accountsChanged or chainChanged.// ethers: Manual event listening
window.ethereum.on("accountsChanged", (accounts) => {
if (accounts.length === 0) {
// Manually reset app state
logout();
}
});
@web3-react/core auto-updates React state on events.
account and provider.// @web3-react/core: Automatic state update
function NavBar() {
const { account, active } = useWeb3React();
// If user disconnects in wallet, 'active' becomes false automatically
if (!active) return <ConnectButton />;
return <div>{account}</div>;
}
While they solve different problems, both libraries are essential for modern dApps and share some common ground.
// ethers: Switching networks
await provider.send("wallet_switchEthereumChain", [{ chainId: "0x1" }]);
// @web3-react/core: Connector supports chain switching
// Connector configuration defines supported chain IDs
// ethers: Using secure signer
const signer = provider.getSigner(); // Keys stay in wallet
// @web3-react/core: No key handling
// Library never touches private keys, only addresses
// ethers: Custom provider
class CustomProvider extends ethers.Provider { /*...*/ }
// @web3-react/core: Custom connector
class CustomConnector extends Connector { /*...*/ }
| Feature | ethers | @web3-react/core |
|---|---|---|
| Primary Role | π‘ Blockchain Communication | βοΈ React State Management |
| Connection | π οΈ Manual event listeners | πͺ Hooks and Connectors |
| Provider Access | ποΈ Instantiate directly | π¦ Via Context/Hook |
| UI Integration | β None (Logic only) | β Built for React |
| Transaction Signing | βοΈ Direct method calls | π Via exposed signer |
| State Updates | β οΈ Manual state sync | π Automatic re-renders |
ethers is the foundation ποΈβyou cannot build a dApp without something to talk to the blockchain. It is required for signing, reading, and writing data. Use it for all protocol-level logic.
@web3-react/core is the interface π¨βit makes that foundation usable in a React app. It saves you from writing repetitive connection logic and state sync code. Use it to manage the user's session.
Final Thought: Do not choose one over the other. In a React dApp, you will almost always use both. @web3-react/core manages the connection, and ethers uses that connection to interact with the chain. Treat them as complementary layers in your architecture.
Choose ethers when you need a reliable library to communicate with the Ethereum blockchain. It handles signing, contract interaction, and provider management directly. You will likely use this alongside a state manager if you are building a React app. It is the standard for low-level Ethereum interaction.
Choose @web3-react/core if you are building a React application and need to manage wallet connection state across components. It provides hooks to access the user's account and provider without manual event listeners. It simplifies the UI logic for connecting and disconnecting wallets. You will still need ethers or a similar library to actually talk to the chain.
A complete, compact and simple library for Ethereum and ilk, written in TypeScript.
Features
For advisories and important notices, follow @ethersproject on Twitter (low-traffic, non-marketing, important information only) as well as watch this GitHub project.
For more general news, discussions, and feedback, follow or DM me, @ricmoo on Twitter or on the Ethers Discord.
For the latest changes, see the CHANGELOG.
Summaries
NodeJS
/home/ricmoo/some_project> npm install ethers
Browser (ESM)
The bundled library is available in the ./dist/ folder in this repo.
<script type="module">
import { ethers } from "./dist/ethers.min.js";
</script>
Browse the documentation online:
Ethers works closely with an ever-growing list of third-party providers to ensure getting started is quick and easy, by providing default keys to each service.
These built-in keys mean you can use ethers.getDefaultProvider() and
start developing right away.
However, the API keys provided to ethers are also shared and are intentionally throttled to encourage developers to eventually get their own keys, which unlock many other features, such as faster responses, more capacity, analytics and other features like archival data.
When you are ready to sign up and start using for your own keys, please check out the Provider API Keys in the documentation.
A special thanks to these services for providing community resources:
The ethers package only includes the most common and most core
functionality to interact with Ethereum. There are many other
packages designed to further enhance the functionality and experience.
call to reduce latency and backend request capacityMIT License (including all dependencies).