Introduction
Ether.js is a powerful JavaScript library for interacting with the Ethereum blockchain and EVM-compatible networks like BSC, Polygon etc. It simplifies many complex blockchain tasks like creating wallets, making transactions, interacting with smart contracts, and more.
In this comprehensive tutorial, we’ll learn the basics of Ether.js from the ground up – from installation and configuration to integrating with React apps and performing common operations like transactions and messaging. We’ll also see how to connect to test networks and mainnet Ethereum with examples.
By the end, you’ll have the foundation to start building decentralized apps and blockchain tools with Ether.js today. Let’s dive in!
Introduction to Ether.js
Ether.js aims to make interacting with Ethereum easier for developers. Some of its key capabilities:
- Generate Ethereum accounts and encrypted JSON wallets
- Make transactions – send Ether, deploy contracts etc
- Read/Write contract state from apps
- Local signing/verification of messages and transactions
- Helper utilities for common operations
- Modular architecture for flexibility
- Extensive documentation and examples
It handles many complex blockchain internals like key management, gas estimation and nonces behind a simple interface.
Ether.js supports both frontend (browser) and backend (Node.js) usage with unified APIs. This makes complex decentralized apps possible.
Overall, Ether.js is one of the most robust and widely-adopted libraries for blockchain development in JavaScript.
Installation and Setup Ether.js
Ether.js offers great flexibility in usage. Let’s go through different setup methods.
Node.js
To use Ether.js in Node.js, install it via npm:
npm install ethers
Then import the library:
const { ethers } = require("ethers");
This creates a preconfigured ethers
object to start using.
Browser
For browser usage, link the Ethers.js bundle in a script tag:
<script src="https://cdn.ethers.io/lib/ethers-5.2.umd.min.js"
type="application/javascript">
</script>
This exposes ethers
globally for usage directly.
React Apps
For React apps, install the library:
npm install ethers
Then import it in components:
import { ethers } from "ethers";
function App() {
const provider = new ethers.providers.Web3Provider(window.ethereum);
return <div>{provider}</div>
}
This allows leveraging Ether.js reactivity syste
Initializing Providers
The first step is typically initializing a Provider
which handles connecting to networks.
For Node.js, pass the URL of a remote node:
const provider = new ethers.providers.JsonRpcProvider('https://rpc.ankr.com/eth');
In the browser, we can use Web3Provider
or BrowserProvider
to connect to injected web3 (Metamask etc.):
// Using external web3 injection
const provider = new ethers.providers.Web3Provider(window.ethereum);
// Using internal ethers wallet
const provider = new ethers.providers.BrowserProvider();
This initializes the base provider for usage.
Accounts and Wallets with Ether.js
Next up, let’s look at generating accounts and managing wallets with Ether.js.
Creating Accounts
New Ethereum accounts can be created with the Wallet
class:
// Generate random account
const wallet = new ethers.Wallet();
// Derive account from mnemonic
const walletMnemonic = ethers.Wallet.fromMnemonic(mnemonic);
This gives us an in-memory wallet instance with a private key and Ethereum address.
We can also create wallet instances from private keys:
const wallet = new ethers.Wallet(privateKey);
Exporting and Encrypting
Wallet instances can be exported to an encrypted JSON Keystore for persistence:
// User password
const password = "secret123";
// Generate random wallet
const wallet = new ethers.Wallet();
// Encrypt wallet as JSON
const encryptedJson = await wallet.encrypt(password);
// Write to file
fs.writeFileSync("./wallet.json", encryptedJson);
This password-encrypts the wallet keys and stores it in a standard Ethereum JSON wallet format.
Loading Wallets
We can also load wallets by decrypting JSON wallets:
const json = fs.readFileSync("./wallet.json");
// Decrypt wallet
const wallet = await ethers.Wallet.fromEncryptedJson(json, password);
// Access wallet properties
wallet.privateKey;
wallet.address;
This restores the original wallet instance from the encrypted JSON file.
Connecting to Providers
Wallet instances can connect to providers to enable interactions:
// Initialize provider
const provider = new ethers.providers.JsonRpcProvider();
// Connect wallet
const wallet = new ethers.Wallet(privateKey);
const connectedWallet = wallet.connect(provider);
The connected wallet can now make transactions, deploy contracts etc. using the provider.
Transactions and Messages using Ether.js Wallet
Now let’s see how to perform common Ethereum transactions and sign messages using Ether.js wallets.
Sending Transactions
To send Ether:
const tx = {
to: "0x88a5c2d9919e46f883eb62f7b8dd9d0cc45bc290",
value: ethers.utils.parseEther("1.0")
}
// Send transaction
const sendTx = await wallet.sendTransaction(tx);
// Wait for transaction
await sendTx.wait();
This funds the sendTransaction
from the wallet account and submits to the network.
We can also estimate gas costs before sending:
const gasEstimate = await wallet.estimateGas(tx);
const tx = {
...
gasLimit: gasEstimate
}
Setting the right gas price and limit prevents failed transactions.
Deploying Contracts
To deploy a contract:
// Get bytecode
const bytecode = "0x608060405234801561001057600080fd5b506101df806100206000396000f300..."
// Deploy transaction
const deployTx = {
data: bytecode,
args: [123, "My Contract"]
}
// Sign and send transaction
const tx = await wallet.sendTransaction(deployTx);
This builds a transaction that executes the contract deployment bytecode.
We can watch for successful deployment by waiting for confirmations:
await tx.wait(1);
const contractAddress = tx.contractAddress;
Signing Messages
Ethereum accounts can also sign arbitrary messages:
const msg = "Hello World";
// Sign message
const sig = await wallet.signMessage(msg);
// 0x14280e2460d43c29d58bfa4625e6e7a362c46b3f64b1e6e9b6436e6450e4bddb11c8756a6662abaa86615fec1403eb93f49381cde0fdb146ee1f0dc243fadb801b
This produces a signature that can be verified later to prove message authenticity.
So in summary, Ether.js wallets provide a powerful interface for transacting and messaging with Ethereum accounts.
Smart Contracts
Interacting with smart contract is easy with Ether.js using Contract instances.
First we need the contract ABI and address. Then:
// Contract ABI
const abi = [
"function balanceOf(address owner) view returns (uint256)",
// ...
];
// Contract Address
const address = "0x...";
// Initialize contract
const contract = new ethers.Contract(address, abi, provider);
This gives a contract object with methods for each ABI function.
Call constant functions:
const balance = await contract.balanceOf("0x...");
Call state-changing functions by passing options:
const tx = await contract.transfer("0x...", ethers.utils.parseEther("1.0"), { gasLimit: 100000 });
The contract instance allows easily interacting while handling gas, nonces etc.
React Integration
Let’s also see an example using Ether.js with a React app.
First install React dependencies:
npm install react react-dom
Then in App.jsx
:
import { useEffect, useState } from "react";
import { ethers } from "ethers";
function App() {
const [balance, setBalance] = useState();
useEffect(() => {
const provider = new ethers.providers.JsonRpcProvider();
const address = "0x...";
// Get balance
provider.getBalance(address).then(balance => {
setBalance(ethers.utils.formatEther(balance));
});
}, []);
return (
<div>
<h3>Balance</h3>
<div>{balance}</div>
</div>
);
}
export default App;
This shows a simple wallet balance tracker component using React hooks.
Many complex decentralized apps can be built by integrating Ether.js into React this way.
Testing and Mainnets
So far we used a local provider. To test apps, we need testnets and faucets.
Using Infura
Infura provides free access to testnet and mainnet nodes.
Get a project ID from infura.io and initialize:
const provider = new ethers.providers.InfuraProvider(network, projectId);
Replace network
with homestead
for mainnet.
Ethereum Testnets
To get test ETH, use faucets like faucet.dimensions.network for networks like Ropsten, Rinkeby etc.
For example, with Ropsten:
const provider = new ethers.providers.InfuraProvider("ropsten", projectId);
This allows full integration testing with a live test blockchain.
Mainnet Ethereum
When ready, we can connect to mainnet by:
const provider = new ethers.providers.InfuraProvider("homestead", projectId);
Any transactions will now use real ETH.
So in summary, Ether.js works seamlessly across testnets and mainnet allowing building and testing real DApps.
Conclusion
That concludes our deep dive into Ether.js – one of the most powerful tools for interacting with Ethereum from JavaScript apps. We covered:
- Installation, setup and configuration
- Generating and loading encrypted wallets
- Sending transactions and deploying contracts
- Interacting with smart contract ABIs
- Signing messages with accounts
- React integration examples
- Connecting to testnets and mainnet
Ether.js handles all the complex blockchain internals and makes app development simple.
Between the easy-to-use API and excellent documentation, you should have all the knowledge needed to start building feature-rich Web3 applications.
The world of decentralized apps built on blockchains is still early. Libraries like Ether.js lower the barriers for innovating in this emerging ecosystem.
So give Ether.js a try and start bringing your ideas for blockchain-powered apps to life! Let me know if you have any other questions.
Frequently Asked Questions
What RPC endpoints do I need to connect to different chains?
Some common JSON-RPC endpoints for chains:
Polygon
- Mainnet – https://polygon-rpc.com
- Mumbai Testnet –Â https://rpc-mumbai.maticvigil.com
more endpoints list here: Json-rpc methods
So in summary, use Infura or Ankr for Ethereum chains, and official RPC endpoints for other chains.
How can I estimate gas fees before making transactions?
Some ways to estimate gas fees in Ether.js:
- Use
estimateGas()
on wallet/contract instances before sending - Leverage
getFeeData()
on the provider for gas price estimates - Try a
simulateTransaction()
on the provider to estimate for a transaction
This allows calculating max fees needed before sending and setting appropriate gas.
What are some best practices for managing private keys and wallets?
Some tips for managing wallets safely:
- Use hardware wallets like Ledger/Trezor for critical funds
- Encrypt and back up wallet JSONs securely
- Store keys and seeds offline in physical form
- Use wallet connect instead of raw private keys in apps
- Maintain separate wallets per application
- Use frameworks like Truffle that manage keys securely
Following security best practices prevents loss or theft when managing blockchain assets and wallets.