0% found this document useful (0 votes)
77 views38 pages

Ether - JS

Ether . js Library Mannual

Uploaded by

faizanshk978
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
0% found this document useful (0 votes)
77 views38 pages

Ether - JS

Ether . js Library Mannual

Uploaded by

faizanshk978
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 38

Ether.js is a JavaScript library for interacting with Ethereum blockchain.

It's
lightweight, secure, and commonly used for building decentralized applications
(dApps). Here's a quick breakdown:

Key Features:

1. Wallet Management:
1. Create wallets (mnemonic or private key).
2. Sign transactions/messages.
2. Provider API:

1. Connect to Ethereum nodes (e.g., Infura, Alchemy).


2. Fetch blockchain data like block numbers, gas prices, and balances.

3. Contract Interaction:

1. Deploy smart contracts.


2. Call functions and listen to contract events.

4. Utilities:

1. Encode/decode data.
2. Work with Ethereum addresses, BigNumber, and more.

Installation:

bash
Copy code
npm install ethers

Example Use:

1.

Connect to Ethereum:

2.
3.

javascript

4.
5.

Copy code

6.
7.
const { ethers } = require("ethers");const provider = new
ethers.JsonRpcProvider("https://mainnet.infura.io/v3/YOUR_API_K
EY");

8.
9.
10.

Wallet Interaction:

11.
12.

javascript

13.
14.

Copy code

15.
16.

const wallet = new ethers.Wallet("PRIVATE_KEY",


provider);console.log(wallet.address);

17.
18.
19.

Smart Contract Interaction:

20.
21.

javascript

22.
23.

Copy code

24.
25.
const abi = [ /* Contract ABI */ ];const contractAddress =
"0x...";const contract = new ethers.Contract(contractAddress,
abi, wallet);const value = await contract.someFunction();

26.
27.
28.

Event Listening:

29.
30.

javascript

31.
32.

Copy code

33.
34.

contract.on("EventName", (args) => {


console.log(args);
});

35.
36.

Advantages:

 Simplicity.
 Extensive documentation.
 Compatible with browser and Node.js.

Alternatives:

 Web3.js.
 Web3.py (Python).

Here’s a deeper dive into Ether.js:

Modules in Ether.js
1.

Providers:

2.

o Connect to Ethereum networks.


o Types:

 JsonRpcProvider (Infura, Alchemy, custom node).


 WebSocketProvider (for real-time updates).
 EtherscanProvider (read-only).

javascript

Copy code

const provider = new


ethers.JsonRpcProvider("https://mainnet.infura.io/v3/YOUR
_API_KEY");const balance = await
provider.getBalance("0xAddress");console.log(ethers.forma
tEther(balance));

3.

Wallets:

4.

o Manage Ethereum accounts.


o Generate wallets, sign transactions, or connect with hardware wallets.

javascript

Copy code
const wallet = ethers.Wallet.createRandom(); // Generates
a new walletconsole.log(wallet.privateKey,
wallet.address);

5.

Contracts:

6.

o Interact with deployed smart contracts.


o Deploy new contracts.

javascript

Copy code

const abi = [ /* Contract ABI */ ];const contract = new


ethers.Contract(contractAddress, abi, provider);const
data = await contract.someFunction();

7.

Utils:

8.

o Provides cryptographic utilities, BigNumber handling, and encoding tools.

javascript
Copy code

console.log(ethers.isAddress("0xAddress")); // Validate
Ethereum addressconst value = ethers.parseEther("1.0");
// Convert ETH to Weiconsole.log(value.toString());

9.

Signers:

10.

o Represents an Ethereum account capable of signing transactions.


o Types:

 Wallet: Private key signer.


 JsonRpcSigner: Connected to a provider.
 VoidSigner: Non-signing address for read-only operations.

javascript

Copy code

const signer = provider.getSigner();const tx = await


signer.sendTransaction({
to: "0xRecipientAddress",
value: ethers.parseEther("0.1"),
});
Advanced Features

1.

Custom Gas Handling:

2.

mate gas:

javascript

Copy code

const gasEstimate = await


contract.estimateGas.someFunction();

o Set custom gas limits or prices.

3.

Event Filters:

4.

o Listen to blockchain events efficiently.

javascript

Copy code
const filter = contract.filters.Transfer("0xFromAddress",
"0xToAddress");
contract.on(filter, (from, to, amount) => {
console.log({ from, to, amount });
});

5.

ENS (Ethereum Name Service):

6.

o Resolve ENS names to addresses or vice versa.

javascript

Copy code

const address = await


provider.resolveName("vitalik.eth");console.log(address);

7.

Transaction Overrides:

8.

o Customize nonce, gas price, etc., in transactions.

javascript
Copy code

const tx = await wallet.sendTransaction({


to: "0xRecipientAddress",
value: ethers.parseEther("0.5"),
gasLimit: 21000,
gasPrice: ethers.parseUnits("50", "gwei"),
});

Ether.js vs Web3.js

Feature Ether.js Web3.js


Lightweight (smaller
Size Heavier bundle size
bundle)
Comprehensive but
Documentation Well-organized
cluttered
BigNumber Requires external
Built-in
Handling libraries
Modern async/await Uses callbacks (older
Promises
syntax syntax)
Browser Support Excellent Good

Common Use Cases

1.

dApp Development:

2.

o Use Ether.js with frontend frameworks like React, Angular, or Vue.

javascript
Copy code

const provider = new


ethers.BrowserProvider(window.ethereum);await
provider.send("eth_requestAccounts", []);const signer =
provider.getSigner();console.log(await
signer.getAddress());

3.

Backend Services:

4.

o Fetch Ethereum blockchain data for analytics or services.

5.

Token Interaction:

javascript

Copy code

const tokenContract = new ethers.Contract(tokenAddress,


erc20Abi, wallet);const tx = await
tokenContract.transfer("0xRecipient",
ethers.parseUnits("10", 18));console.log(tx.hash);

6.
NFT Handling:

7.

o Read or transfer ERC-721/1155 tokens.

Ethers.js Ecosystem

 Integrations:

o Works seamlessly with Infura, Alchemy, Hardhat, Truffle, etc.

 Testing:

o Commonly used with testing frameworks like Hardhat for smart contracts.

Here’s an in-depth guide on Ether.js with detailed topics and advanced concepts:

Core Concepts in Ether.js

1. Providers

Providers act as the interface to the Ethereum blockchain, enabling data retrieval and
transactions.

Types of Providers:

o JsonRpcProvider: Connects to a node via JSON-RPC.


o AlchemyProvider: Alchemy-specific provider.
o InfuraProvider: Infura-specific provider.
o WebSocketProvider: Supports real-time event listening.

Code Example:



javascript


Copy code


const { ethers } = require("ethers");const provider = new


ethers.JsonRpcProvider("https://mainnet.infura.io/v3/YOUR_API_K
EY");
const blockNumber = await
provider.getBlockNumber();console.log("Current Block:",
blockNumber);


2. Wallets

Wallets handle private keys for signing and account management.

Wallet Operations:

javascript

Copy code

const wallet =
ethers.Wallet.createRandom();console.log("Address:",
wallet.address);console.log("Private Key:",
wallet.privateKey);
javascript

Copy code

const connectedWallet = wallet.connect(provider);

Encrypted Wallets:

javascript

Copy code

const encryptedJson = await


wallet.encrypt("strongPassword");console.log(encryptedJso
n);

javascript

Copy code
const decryptedWallet = await
ethers.Wallet.fromEncryptedJson(encryptedJson,
"strongPassword");

3. Contracts

Used for interacting with smart contracts via ABI and addresses.

Example:


javascript


Copy code


const abi = [ /* Contract ABI */ ];const address =


"0xContractAddress";const contract = new
ethers.Contract(address, abi, wallet);
// Call a read-only functionconst result = await
contract.someViewFunction();console.log(result);
// Send a transactionconst tx = await
contract.someFunction(arg1, arg2, { gasLimit:
300000 });console.log("Transaction Hash:", tx.hash);



Deploy a Contract:


javascript

Copy code


const factory = new ethers.ContractFactory(abi, bytecode,


wallet);const deployedContract = await factory.deploy(arg1,
arg2, { gasLimit: 4000000 });console.log("Deployed Address:",
deployedContract.address);


4. BigNumber Operations

Ether.js uses BigNumber to handle large integers like balances.

 Examples:

javascript


Copy code


const balance = ethers.parseEther("1.5"); // Convert ETH to


Weiconsole.log(balance.toString());
const total =
balance.add(ethers.parseEther("0.5"));console.log("Total:",
ethers.formatEther(total)); // Convert Wei back to ETH


Advanced Topics

1. Event Filters and Listeners


Monitor blockchain events efficiently.

Create a Filter:


javascript


Copy code


const filter = contract.filters.Transfer("0xFromAddress", null);


contract.on(filter, (from, to, value) => {
console.log(`Transfer from ${from} to ${to}:
${ethers.formatEther(value)}`);
});



Listening to Blocks:


javascript


Copy code


provider.on("block", (blockNumber) => {


console.log("New Block:", blockNumber);
});



2. Transaction Handling

Customize transactions by overriding gas, nonce, etc.

Send ETH:


javascript


Copy code


const tx = await wallet.sendTransaction({


to: "0xRecipientAddress",
value: ethers.parseEther("0.1"),
gasPrice: ethers.parseUnits("50", "gwei"),
gasLimit: 21000,
});console.log("Transaction Hash:", tx.hash);



Estimate Gas:


javascript


Copy code



const gasEstimate = await
contract.estimateGas.someFunction(arg1, arg2);console.log("Gas
Estimate:", gasEstimate.toString());


3. ENS (Ethereum Name Service)

Simplify address handling using ENS domains.

Resolve ENS Name to Address:


javascript


Copy code


const address = await


provider.resolveName("vitalik.eth");console.log("Address:",
address);



Reverse Lookup:


javascript


Copy code

const ensName = await


provider.lookupAddress("0xAddress");console.log("ENS Name:",
ensName);


4. Interacting with ERC-20 and ERC-721 Tokens

Predefined ABIs make working with tokens straightforward.

ERC-20 Token Example:


javascript


Copy code


const erc20Abi = [ /* Minimal ERC-20 ABI */ ];const


tokenContract = new ethers.Contract(tokenAddress, erc20Abi,
wallet);
// Get Token Balanceconst balance = await
tokenContract.balanceOf("0xAddress");console.log("Token
Balance:", ethers.formatUnits(balance, 18));
// Transfer Tokensconst tx = await
tokenContract.transfer("0xRecipient", ethers.parseUnits("10",
18));console.log("Transaction Hash:", tx.hash);



ERC-721 (NFT) Example:


javascript


Copy code


const erc721Abi = [ /* Minimal ERC-721 ABI */ ];const


nftContract = new ethers.Contract(nftAddress, erc721Abi,
wallet);
const owner = await nftContract.ownerOf(1); // Token ID
1console.log("Owner:", owner);


Common Patterns

1.

Connecting to MetaMask:

2.
3.

javascript

4.
5.

Copy code

6.
7.

const provider = new


ethers.BrowserProvider(window.ethereum);await
provider.send("eth_requestAccounts", []);const signer =
provider.getSigner();console.log("Connected Address:", await
signer.getAddress());
8.
9.
10.

Error Handling:

11.

o Catch errors for invalid transactions or failed calls.

javascript
Copy code
try {
const tx = await wallet.sendTransaction(txData);
} catch (error) {
console.error("Transaction failed:", error.message);
}

12.

Testing with Hardhat:

13.

o Use Ether.js in combination with Hardhat for contract testing.

javascript
Copy code
const { ethers } = require("hardhat");const [deployer] = await
ethers.getSigners();
const contract = await ethers.deployContract("MyContract",
[arg1, arg2]);console.log("Deployed at:", contract.address);

Here’s everything else you need to know about Ether.js:

Deeper Insights into Ether.js

1. Transaction Lifecycle

Understanding Ethereum transactions in Ether.js:


Steps:

1. Build the transaction object.


2. Sign the transaction.
3. Broadcast the transaction.
4. Wait for confirmation.

Code Example:


javascript


Copy code


const tx = {
to: "0xRecipientAddress",
value: ethers.parseEther("0.1"),
gasLimit: 21000,
gasPrice: ethers.parseUnits("30", "gwei"),
};
const signedTx = await wallet.signTransaction(tx);const sentTx
= await provider.sendTransaction(signedTx);const receipt =
await sentTx.wait(); // Wait for
confirmationconsole.log("Transaction Receipt:", receipt);


2. Offline Signing

Sign transactions without exposing the private key online.

 Example:

javascript


Copy code


const unsignedTx = {
to: "0xRecipientAddress",
value: ethers.parseEther("0.1"),
nonce: 0,
gasLimit: 21000,
gasPrice: ethers.parseUnits("20", "gwei"),
};
const signedTx = await
wallet.signTransaction(unsignedTx);console.log("Signed
Transaction:", signedTx);
// Broadcast the signed transaction laterconst txResponse =
await
provider.sendTransaction(signedTx);console.log("Transaction
Hash:", txResponse.hash);


3. Meta-Transactions

Allow users to send transactions without paying gas directly.

Flow:

o User signs a message with their wallet.


o A relayer pays the gas and broadcasts the transaction.

Example:



javascript


Copy code


const domain = {
name: "MyDApp",
version: "1",
chainId: 1, // Mainnet
verifyingContract: "0xContractAddress",
};
const types = {
MetaTransaction: [
{ name: "nonce", type: "uint256" },
{ name: "functionSignature", type: "bytes" },
],
};
const message = {
nonce: 1,
functionSignature: "0xFunctionData",
};
const signature = await wallet._signTypedData(domain, types,
message);console.log("Signature:", signature);


4. Handling Nonces

Nonces ensure transactions are processed in order.

Get Current Nonce:


javascript


Copy code


const nonce = await


provider.getTransactionCount(wallet.address);console.log("Curre
nt Nonce:", nonce);



Manually Set Nonce:


javascript


Copy code


const tx = {
to: "0xRecipient",
value: ethers.parseEther("1"),
nonce: nonce + 1, // Use next nonce
};


Gas Optimization

1. Gas Estimation

 Estimate gas usage before


sending a transaction:

javascript

Copy code


const gasEstimate = await


contract.estimateGas.someFunction(arg1, arg2);console.log("Gas
Estimate:", gasEstimate.toString());


2. Dynamic Gas Fees (EIP-1559)

 EIP-1559 introduces
maxFeePerGas and
maxPriorityFeePerGas:

javascript


Copy code


const tx = {
to: "0xRecipient",
value: ethers.parseEther("0.1"),
maxFeePerGas: ethers.parseUnits("100", "gwei"),
maxPriorityFeePerGas: ethers.parseUnits("2", "gwei"),
};
const txResponse = await
wallet.sendTransaction(tx);console.log("Transaction Hash:",
txResponse.hash);


Interacting with Ethereum Layer 2 (L2) Solutions


Ether.js supports L2 networks like Arbitrum, Optimism, and Polygon.

Switching Networks:


javascript


Copy code


const provider = new ethers.JsonRpcProvider("https://polygon-


rpc.com");const balance = await
provider.getBalance("0xYourAddress");console.log("Polygon
Balance:", ethers.formatEther(balance));



L2-Specific Transactions:

o Transactions work similarly but are faster and cheaper.

Security Practices

1.

Avoid Exposing Private Keys:

2.

o Use .env files for sensitive data.

javascript
Copy code
require("dotenv").config();const wallet = new
ethers.Wallet(process.env.PRIVATE_KEY);
3.

Verify Contract Interactions:

4.

o Double-check contract ABIs and addresses.

5.

Error Handling:

6.

o Catch errors to avoid app crashes.

javascript
Copy code
try {
const result = await contract.someFunction();
} catch (error) {
console.error("Error:", error.message);
}

Custom Utilities with Ether.js

1. Create Custom ABI Encoders/Decoders

Encode or decode data for lower-level operations.

 Example:

javascript


Copy code


const encodedData = ethers.AbiCoder.defaultAbiCoder().encode(


["uint256", "string"],
[123, "Hello"]
);console.log("Encoded Data:", encodedData);
const decodedData = ethers.AbiCoder.defaultAbiCoder().decode(
["uint256", "string"],
encodedData
);console.log("Decoded Data:", decodedData);


Testing with Ether.js

1.

Hardhat Integration:

2.

o Deploy and test contracts with Hardhat.

javascript
Copy code
const { ethers } = require("hardhat");
const MyContract = await
ethers.deployContract("MyContract");console.log("Contract
Address:", MyContract.address);
const result = await
MyContract.someFunction();console.log("Result:", result);

3.

Mocking Blockchain State:

4.

o Use Hardhat to fork the Ethereum mainnet for testing.

Ether.js Ecosystem Tools

1.

Hardhat:

2.

o Development environment for testing and deploying smart contracts.


3.

Etherscan Plugin:

4.

o Verify contracts directly on Etherscan.

5.

Alchemy/Infura:

6.

o Reliable Ethereum node services.

7.

Web3Modal:

8.

o Simplify wallet connections in dApps.

Common Debugging Tips

1.

Transaction Errors:

2.

o Check if your contract requires exact gas values.

3.

Invalid Signatures:

4.

o Ensure you’re signing the correct payload.

5.

Network Mismatch:

6.
o Verify the provider and network chain ID match.

Here’s even more on Ether.js, diving into specialized topics and advanced usage:

Specialized Topics

1. Gasless Transactions (Relay/MetaTx)

 Gasless transactions allow users to interact without owning ETH (a relayer pays the gas).

Workflow:

 User signs a message with wallet.


 Relayer sends the signed transaction to the blockchain.

Code Example:

javascript
Copy code
const messageHash =
ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Message for
MetaTx"));const signature = await
wallet.signMessage(ethers.utils.arrayify(messageHash));
console.log("Signature:", signature);// Relayer broadcasts the signed
message to the smart contract

2. EIP-2771 (Trusted Forwarder for Gasless Transactions)

Ether.js supports EIP-2771 for handling meta-transactions using forwarders.

Example Integration:

javascript
Copy code
const forwarderAddress = "0xForwarderAddress";const forwarderAbi =
[/* Minimal Forwarder ABI */];const forwarder = new
ethers.Contract(forwarderAddress, forwarderAbi, provider);
const forwarderNonce = await
forwarder.getNonce(wallet.address);console.log("Nonce:",
forwarderNonce);
// Prepare a meta-transactionconst txData = {
from: wallet.address,
to: "0xTargetContract",
data: "0xFunctionData",
nonce: forwarderNonce,
};const signature = await
wallet.signMessage(ethers.utils.keccak256(txData));

3. MEV (Miner Extractable Value) Transactions

 Flashbots (for private transactions):


Prevent front-running by sending private transactions through Flashbots.

Setup Example:

javascript
Copy code
const flashbotsProvider = await
ethers.FlashbotsBundleProvider.create(
provider,
ethers.Wallet.createRandom() // Flashbots signer
);
const bundle = [
{
signer: wallet,
transaction: {
to: "0xRecipient",
value: ethers.parseEther("0.5"),
gasLimit: 21000,
},
},
];
const tx = await flashbotsProvider.sendBundle(bundle,
targetBlockNumber);console.log("Flashbots Bundle Sent:", tx);

4. Multisig Wallets

Interact with Gnosis Safe or other multisig wallets:

 Use the Gnosis Safe ABI to call functions like submitTransaction.

javascript
Copy code
const safeAbi = [/* Gnosis Safe ABI */];const safeAddress =
"0xGnosisSafeAddress";const safe = new ethers.Contract(safeAddress,
safeAbi, wallet);
const tx = await safe.submitTransaction("0xTarget",
ethers.parseEther("1"), "0xData");console.log("Multisig Transaction
Hash:", tx.hash);

5. Layer 3 Solutions

 Interact with zkRollups, StarkNet, or other advanced scaling solutions.

Example with zkSync:

javascript
Copy code
const zkSyncProvider = new ethers.JsonRpcProvider("https://zksync2-
rpc.zksync.io");const balance = await
zkSyncProvider.getBalance("0xYourAddress");console.log("zkSync
Balance:", ethers.formatEther(balance));

Error Debugging in Ether.js

1. Common Errors:

"insufficient funds":
Happens when sending a transaction with insufficient ETH.
Fix: Ensure wallet balance covers value + gas.


"invalid signer or provider":


Occurs if wallet isn’t connected to a provider.
Fix: Use wallet.connect(provider) before sending a transaction.


"gas required exceeds allowance":


Contract function may consume more gas than estimated.
Fix: Increase gasLimit.

2. Transaction Debugging:
 Simulate a transaction: Use
callStatic to run a
transaction locally without
broadcasting.

javascript


Copy code


const result = await contract.callStatic.someFunction(arg1,


arg2);console.log("Simulation Result:", result);


Optimized DApp Architecture with Ether.js

1. Provider Abstraction

Abstract providers to handle multiple networks:

javascript
Copy code
const getProvider = (network) => {
const rpcUrls = {
mainnet: "https://mainnet.infura.io/v3/YOUR_API_KEY",
polygon: "https://polygon-rpc.com",
};
return new ethers.JsonRpcProvider(rpcUrls[network]);
};
const provider = getProvider("polygon");

2. Batch Calls with Multicall

Avoid multiple network requests using the Multicall contract.

Example:

javascript
Copy code
const multicallAbi = [/* Minimal Multicall ABI */];const
multicallAddress = "0xMulticallAddress";
const multicall = new ethers.Contract(multicallAddress, multicallAbi,
provider);const calls = [
{ target: "0xContract1", callData:
contract1.interface.encodeFunctionData("method1", []) },
{ target: "0xContract2", callData:
contract2.interface.encodeFunctionData("method2", []) },
];
const { returnData } = await multicall.aggregate(calls);const decoded
= returnData.map((data, i) =>
ethers.AbiCoder.defaultAbiCoder().decode(["type"],
data));console.log(decoded);

3. Optimized Contract ABI Usage

 Import only the necessary part of an ABI to reduce bundle size:

javascript
Copy code
const minimalAbi = ["function balanceOf(address) view returns
(uint256)"];const erc20 = new ethers.Contract(tokenAddress,
minimalAbi, provider);
const balance = await
erc20.balanceOf("0xAddress");console.log("Balance:",
ethers.formatUnits(balance, 18));

Performance Tips

1.

Use WebSocketProvider for real-time updates instead of polling:

2.
3.

javascript

4.
5.

Copy code
6.
7.

const wsProvider = new


ethers.WebSocketProvider("wss://mainnet.infura.io/ws/v3/YOUR_AP
I_KEY");
wsProvider.on("block", (blockNumber) => console.log("New
Block:", blockNumber));

8.
9.
10.

Cache Frequent Calls: Avoid redundant network requests for static data like
contract ABIs or token metadata.

11.
12.

Batch Processing: Process large datasets using batching:

13.
14.

javascript

15.
16.

Copy code

17.
18.

const addresses = [...Array(100).keys()].map((i) =>


`0xAddress${i}`);const balances = await
Promise.all(addresses.map((addr) =>
provider.getBalance(addr)));console.log("Balances:", balances);

19.
20.

Extending Ether.js

1. Custom Plugins
You can create custom modules to extend Ether.js functionality:

javascript
Copy code
class MyCustomProvider extends ethers.JsonRpcProvider {
async getCustomData(address) {
const balance = await this.getBalance(address);
return ethers.formatEther(balance) + " ETH";
}
}const customProvider = new
MyCustomProvider("https://mainnet.infura.io/v3/YOUR_API_KEY");const
data = await
customProvider.getCustomData("0xAddress");console.log(data);

2. Combining with Other Libraries

 Use GraphQL (via The Graph) for efficient subgraph queries.


 Example:

javascript


Copy code


const query = `
{
transfers(where: { to: "0xRecipient" }) {
from
to
value
}
}
`;const response = await
fetch("https://api.thegraph.com/subgraphs/name/example", {
method: "POST",
body: JSON.stringify({ query }),
});const data = await
response.json();console.log(data.data.transfers);


You might also like