Learning Objectives:

  • Understand the complete Web3 architecture and development stack

  • Master frontend interaction with smart contracts using Web3.js and Ethers.js

  • Learn about wallets, providers, and authentication mechanisms

  • Build complete dApp workflows from frontend to blockchain

  • Understand deployment, testing, and best practices


4.6.1: What is Web3? The Evolution of the Internet

Web1, Web2, and Web3 – The Internet Evolution

text
The Three Eras of the Internet:

Web1 (1990s - Early 2000s): "The Read-Only Web"
- Static websites
- No user interaction
- Content consumed, not created
- Centralized information
- Examples: Early web pages, directories

Web2 (2005 - Present): "The Read-Write Web"
- User-generated content
- Social media platforms
- Interactivity and collaboration
- Centralized platforms (Facebook, Google)
- Data ownership by platforms

Web3 (2020+): "The Read-Write-Own Web"
- Decentralized applications
- User ownership of data
- Blockchain technology
- Smart contracts
- Token-based economics

The Problem Web3 Solves:
- Data ownership: Users own their data
- Censorship resistance: Cannot be shut down
- Trustless interaction: Code enforces agreements
- Transparency: Open and verifiable
- Value transfer: Native payments and tokens

Web3 Architecture Stack

text
Web3 Stack Architecture:

┌─────────────────────────────────────────────────────────────────────┐
│                    Application Layer (Frontend)                    │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐              │
│  │  React/Vue  │  │  Next.js    │  │  Angular    │              │
│  │  Components │  │  Framework  │  │  Framework  │              │
│  └─────────────┘  └─────────────┘  └─────────────┘              │
└─────────────────────────────────────────────────────────────────────┘
                              │
┌─────────────────────────────────────────────────────────────────────┐
│                    Web3 Library Layer                              │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐              │
│  │  Ethers.js  │  │  Web3.js    │  │  Wagmi      │              │
│  │  Library    │  │  Library    │  │  (React)    │              │
│  └─────────────┘  └─────────────┘  └─────────────┘              │
└─────────────────────────────────────────────────────────────────────┘
                              │
┌─────────────────────────────────────────────────────────────────────┐
│                    Wallet/Provider Layer                           │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐              │
│  │  MetaMask   │  │  WalletConnect│  │  Coinbase   │              │
│  │  (Browser)  │  │  (Mobile)    │  │  Wallet     │              │
│  └─────────────┘  └─────────────┘  └─────────────┘              │
└─────────────────────────────────────────────────────────────────────┘
                              │
┌─────────────────────────────────────────────────────────────────────┐
│                    RPC/API Layer                                   │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐              │
│  │  Infura     │  │  Alchemy    │  │  QuickNode  │              │
│  │  (RPC)      │  │  (RPC)      │  │  (RPC)      │              │
│  └─────────────┘  └─────────────┘  └─────────────┘              │
└─────────────────────────────────────────────────────────────────────┘
                              │
┌─────────────────────────────────────────────────────────────────────┐
│                    Blockchain Layer                                │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐              │
│  │  Ethereum   │  │  Polygon    │  │  Arbitrum   │              │
│  │  Mainnet    │  │  (L2)       │  │  (L2)       │              │
│  └─────────────┘  └─────────────┘  └─────────────┘              │
└─────────────────────────────────────────────────────────────────────┘

Key Differences: Web2 vs Web3 Development

 
 
Aspect Web2 Web3
Database Centralized SQL/NoSQL Blockchain (distributed)
Authentication Username/Password Wallet (private key)
Backend Server-side code Smart contracts
Frontend React/Vue/Angular React/Vue/Angular + Web3
Payments Payment processors (Stripe) Native token transfers
Storage Centralized servers IPFS, Arweave
Identity Platform-managed Self-sovereign (DID)
State Centralized server On-chain state

4.6.2: Web3 Libraries – Ethers.js vs Web3.js

Ethers.js Overview

Ethers.js is a complete Ethereum library with a focus on being lightweight, secure, and developer-friendly.

text
Ethers.js Key Features:

1. Provider Abstraction:
   - JSON-RPC providers
   - WebSocket providers
   - Fallback providers
   - Infura/Alchemy support

2. Wallet Management:
   - Private key wallets
   - HD wallets (Mnemonic)
   - Browser wallet (MetaMask)
   - JSON keystore

3. Contract Interaction:
   - Read functions (view/pure)
   - Write functions (transactions)
   - Event listening
   - Contract factory

4. Utilities:
   - BigNumber (BigInt)
   - Address utilities
   - ABI encoding/decoding
   - ENS support

5. TypeScript Ready:
   - Full type definitions
   - Type-safe interactions
   - Better IDE support

Installation:
npm install ethers

Web3.js Overview

Web3.js is the original Ethereum library with comprehensive features and broad adoption.

text
Web3.js Key Features:

1. Provider Integration:
   - HTTP providers
   - WebSocket providers
   - IPC providers

2. Modules:
   - web3.eth (Ethereum)
   - web3.eth.accounts
   - web3.eth.contract
   - web3.eth.personal

3. Utilities:
   - BN (BigNumber)
   - Utility functions
   - ABI encoding/decoding

4. Batch Requests:
   - Multiple requests
   - Efficiency
   - Reduced RPC calls

Installation:
npm install web3

Ethers.js vs Web3.js Comparison:

 
 
Feature Ethers.js Web3.js
Size Smaller (~350KB) Larger (~700KB)
Big Numbers BigInt (native) BN (library)
TypeScript First-class support Limited
Provider Flexible Good
ENS Built-in Needs plugin
Learning Curve Moderate Moderate
Community Growing Large
Documentation Good Good
Active Development Very active Active

Choosing the Right Library:

text
When to Use Ethers.js:
- New projects
- TypeScript projects
- Need modern features
- Want simpler API
- Prefer native BigInt

When to Use Web3.js:
- Existing projects
- Need full features
- Want more flexibility
- Familiar with Web3.js
- Legacy codebase

4.6.3: Wallets and Providers – The Foundation

Understanding Ethereum Providers

A provider connects your dApp to the blockchain. It handles reading data and sending transactions.

text
Provider Types:

1. JSON-RPC Provider:
   const provider = new ethers.JsonRpcProvider('http://localhost:8545');
   // Connects to local node or remote RPC

2. WebSocket Provider:
   const provider = new ethers.WebSocketProvider('wss://mainnet.infura.io/ws/v3/YOUR_KEY');
   // Real-time updates

3. Browser Provider (MetaMask):
   const provider = new ethers.BrowserProvider(window.ethereum);
   // Uses MetaMask injected provider

4. Fallback Provider:
   const provider = new ethers.FallbackProvider([
       new ethers.InfuraProvider('mainnet', 'key1'),
       new ethers.AlchemyProvider('mainnet', 'key2')
   ]);
   // Multiple providers for redundancy

Connecting to MetaMask

MetaMask injects an ethereum object into the browser, allowing dApps to interact with the user’s wallet.

text
MetaMask Connection Flow:

1. Detect if MetaMask is installed
2. Request account access
3. Get connected accounts
4. Create provider and signer
5. Listen for account changes

Implementation:

// Detect MetaMask
if (typeof window.ethereum === 'undefined') {
    console.log('MetaMask not installed');
    // Show install prompt
}

// Connect to MetaMask
async function connectWallet() {
    try {
        // Request accounts (prompts user)
        const accounts = await window.ethereum.request({
            method: 'eth_requestAccounts'
        });
        
        // Get first account
        const account = accounts[0];
        console.log('Connected:', account);
        
        // Create provider
        const provider = new ethers.BrowserProvider(window.ethereum);
        const signer = await provider.getSigner();
        
        return { provider, signer, account };
    } catch (error) {
        console.error('Connection error:', error);
    }
}

// Listen for account changes
window.ethereum.on('accountsChanged', (accounts) => {
    console.log('Account changed:', accounts[0]);
    // Update UI
});

// Listen for chain changes
window.ethereum.on('chainChanged', (chainId) => {
    console.log('Chain changed:', chainId);
    // Reload or update
});

WalletConnect Integration

WalletConnect enables mobile wallet integration through QR codes and deep links.

text
WalletConnect Implementation:

1. Install:
npm install @walletconnect/ethereum-provider

2. Setup:
import { EthereumProvider } from '@walletconnect/ethereum-provider';

async function connectWalletConnect() {
    const provider = await EthereumProvider.init({
        projectId: 'YOUR_PROJECT_ID',
        chains: [1], // Ethereum mainnet
        showQrModal: true,
        methods: ['eth_sendTransaction', 'eth_sign'],
        events: ['chainChanged', 'accountsChanged']
    });

    await provider.connect();

    return provider;
}

3. Use with Ethers:
const provider = new ethers.BrowserProvider(walletConnectProvider);
const signer = await provider.getSigner();

Common Wallets:

 
 
Wallet Type Features Use Case
MetaMask Browser/Mobile Most popular, EIP-1559 General dApps
WalletConnect Protocol Mobile support, QR Mobile dApps
Coinbase Wallet Mobile/Browser Easy fiat on-ramp User-friendly
Trust Wallet Mobile Multi-chain Mobile dApps
Rainbow Mobile User-friendly Consumer dApps
Phantom Browser/Mobile Solana + ETH Multi-chain

4.6.4: Contract Interaction – Reading and Writing

Reading Data (View/Pure Functions)

Reading data from a contract is free (no gas cost) and does not require a signer.

text
Reading Example:

// Contract ABI
const abi = [
    "function balanceOf(address) view returns (uint256)",
    "function totalSupply() view returns (uint256)",
    "function name() view returns (string)",
    "function symbol() view returns (string)"
];

const contractAddress = "0x..." // ERC-20 token address

// Create contract instance (no signer needed for reading)
const contract = new ethers.Contract(contractAddress, abi, provider);

// Read functions
async function readData() {
    try {
        // Total supply
        const totalSupply = await contract.totalSupply();
        console.log('Total Supply:', ethers.formatEther(totalSupply));
        
        // Balance of address
        const balance = await contract.balanceOf('0x...');
        console.log('Balance:', ethers.formatEther(balance));
        
        // Token info
        const name = await contract.name();
        const symbol = await contract.symbol();
        console.log('Token:', name, '(', symbol, ')');
        
        return { totalSupply, balance, name, symbol };
    } catch (error) {
        console.error('Read error:', error);
    }
}

Writing Data (State-Changing Functions)

Writing data requires a transaction, gas, and a signer.

text
Writing Example:

// Create contract with signer
const signer = await provider.getSigner();
const contractWithSigner = contract.connect(signer);

async function writeData() {
    try {
        // Estimate gas
        const gasEstimate = await contractWithSigner.transfer.estimateGas(
            '0x...', // recipient
            ethers.parseEther('1.0') // amount
        );
        
        console.log('Estimated gas:', gasEstimate.toString());
        
        // Get gas price
        const gasPrice = await provider.getGasPrice();
        console.log('Current gas price:', ethers.formatUnits(gasPrice, 'gwei'), 'gwei');
        
        // Send transaction
        const tx = await contractWithSigner.transfer(
            '0x...',
            ethers.parseEther('1.0')
        );
        
        console.log('Transaction sent:', tx.hash);
        
        // Wait for confirmation
        const receipt = await tx.wait();
        console.log('Transaction confirmed:', receipt);
        
        // Check status