ethers vs @web3-react/core
Web3 Frontend Architecture: Wallet Connection State vs. Blockchain Interaction
ethers@web3-react/coreSimilar Packages:

Web3 Frontend Architecture: Wallet Connection State vs. Blockchain Interaction

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.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
ethers2,859,8178,65513 MB6385 months agoMIT
@web3-react/core19,0515,68967.6 kB1763 years agoGPL-3.0-or-later

Web3 Frontend Architecture: Wallet Connection State vs. Blockchain Interaction

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.

🎯 Core Responsibility: Protocol vs. UI State

ethers focuses on the blockchain protocol.

  • It creates providers to read data from nodes.
  • It creates signers to sign transactions with private keys.
  • It does not care about React or UI state.
// 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.

  • It tracks whether a wallet is connected.
  • It exposes the account address and provider via hooks.
  • It does not sign transactions itself; it gives you the tools to do so.
// @web3-react/core: Hook-based state access
import { useWeb3React } from "@web3-react/core";

function WalletStatus() {
  const { account, provider } = useWeb3React();
  return <div>Connected: {account}</div>;
}

πŸ”Œ Connecting to a Wallet: Manual vs. Hook-Driven

ethers requires you to manually handle the connection logic.

  • You must listen for account changes on window.ethereum.
  • You must manage loading states and errors yourself.
  • More code, but full control over the flow.
// 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.

  • You use a pre-built connector (like MetaMask).
  • The hook handles loading, error, and account states automatically.
  • Less boilerplate for standard wallet flows.
// @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>;
}

πŸ“‘ Accessing the Provider: Direct vs. Contextual

ethers gives you the provider instance directly.

  • You instantiate it wherever you need it.
  • You must ensure you are using the same provider instance for consistency.
  • Good for scripts or non-React environments.
// 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.

  • The provider is created by the connector and passed to the hook.
  • Ensures all components use the same active connection.
  • You still use 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>;
}

✍️ Signing Transactions: Low-Level vs. Integrated

ethers handles the cryptographic signing directly.

  • You call signer.signTransaction or signer.sendTransaction.
  • You manage gas estimation and nonce manually if needed.
  • Essential for complex contract interactions.
// 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.

  • You retrieve the signer from the context.
  • You still use ethers to construct the transaction.
  • It ensures the signer matches the connected account.
// @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>;
}

πŸ”„ Handling Disconnections: Events vs. State Reset

ethers relies on event listeners for network changes.

  • You must listen for accountsChanged or chainChanged.
  • You must manually clear state when users disconnect.
  • Easy to miss edge cases without careful coding.
// 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.

  • The hook re-renders when the account changes.
  • Disconnection automatically clears account and provider.
  • Reduces risk of stale state in your UI.
// @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>;
}

🀝 Similarities: Shared Ground Between Libraries

While they solve different problems, both libraries are essential for modern dApps and share some common ground.

1. πŸ”— EVM Compatibility

  • Both support Ethereum and EVM-compatible chains (Polygon, Arbitrum, etc.).
  • Both rely on standard RPC methods for communication.
// ethers: Switching networks
await provider.send("wallet_switchEthereumChain", [{ chainId: "0x1" }]);

// @web3-react/core: Connector supports chain switching
// Connector configuration defines supported chain IDs

2. πŸ›‘οΈ Security Best Practices

  • Both encourage using secure providers (like WalletConnect or Injected).
  • Neither stores private keys; they rely on the user's wallet.
// 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

3. 🧩 Extensibility

  • Both can be extended with custom connectors or providers.
  • Both support TypeScript for type safety.
// ethers: Custom provider
class CustomProvider extends ethers.Provider { /*...*/ }

// @web3-react/core: Custom connector
class CustomConnector extends Connector { /*...*/ }

πŸ“Š Summary: Key Differences

Featureethers@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

πŸ’‘ The Big Picture

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.

How to Choose: ethers vs @web3-react/core

  • ethers:

    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.

  • @web3-react/core:

    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.

README for ethers

The Ethers Project

npm (tag) CI Tests npm bundle size (version) npm (downloads) GitPOAP Badge Twitter Follow


A complete, compact and simple library for Ethereum and ilk, written in TypeScript.

Features

  • Keep your private keys in your client, safe and sound
  • Import and export JSON wallets (Geth, Parity and crowdsale)
  • Import and export BIP 39 mnemonic phrases (12 word backup phrases) and HD Wallets (English as well as Czech, French, Italian, Japanese, Korean, Simplified Chinese, Spanish, Traditional Chinese)
  • Meta-classes create JavaScript objects from any contract ABI, including ABIv2 and Human-Readable ABI
  • Connect to Ethereum nodes over JSON-RPC, INFURA, Etherscan, Alchemy, Ankr or MetaMask
  • ENS names are first-class citizens; they can be used anywhere an Ethereum addresses can be used
  • Small (~144kb compressed; 460kb uncompressed)
  • Tree-shaking focused; include only what you need during bundling
  • Complete functionality for all your Ethereum desires
  • Extensive documentation
  • Large collection of test cases which are maintained and added to
  • Fully written in TypeScript, with strict types for security and safety
  • MIT License (including ALL dependencies); completely open source to do with as you please

Keep Updated

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

Installing

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>

Documentation

Browse the documentation online:

Providers

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:

Extension Packages

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.

  • MulticallProvider - A Provider which bundles multiple call requests into a single call to reduce latency and backend request capacity
  • MulticoinPlugin - A Provider plugin to expand the support of ENS coin types
  • GanaceProvider - A Provider for in-memory node instances, for fast debugging, testing and simulating blockchain operations
  • Optimism Utilities - A collection of Optimism utilities
  • LedgerSigner - A Signer to interact directly with Ledger Hardware Wallets

License

MIT License (including all dependencies).