Integrating Ethers.js with Angular: Short Web3 Angular tutorial

Introduction to Web3 and Angular

As blockchain technology continues to evolve, integrating Web3 functionalities into modern web applications has become a crucial skill for developers. Angular, one of the leading web development frameworks, provides a robust structure for building scalable and maintainable applications. Combining Angular with Ethers.js, a popular library for interacting with the Ethereum blockchain, opens up a world of possibilities for creating decentralized applications (DApps). Hence, a short Web3 Angular tutorial like this one can help individuals to get started.

This post guides you through the process of integrating Ethers.js into an Angular project using the latest version of Angular, including connecting to browser wallets like MetaMask. This is a follow up article on Angular and Artificial Intelligence.

Installing Ethers.js

Installing Ethers.js is pretty simple, you just need to run:

npm install --save ethers

Then, when you want to use it, make sure to import it like:

import { ethers } from 'ethers';

Using Ethers.js

To use Ethers.js, import it into your desired Angular component. Here’s how you can set up a simple service to interact with Ethereum.

  1. Create a service: Generate a new service in Angular where you will handle all blockchain wallet interactions: ng g s wallet
  2. Import and configure Ethers: Open the newly created service file (wallet.service.ts) and import Ethers.js:
import { computed, Injectable, NgZone, signal } from '@angular/core';
import { ethers } from 'ethers';

declare const window: any;

@Injectable({
  providedIn: 'root',
})
export class WalletService {
  private provider: ethers.BrowserProvider | undefined;
  public signer = signal<ethers.JsonRpcSigner | undefined>(undefined);
  public network = signal<string | undefined>(undefined);

  constructor(private ngZone: NgZone) {
    // Uncomment to automatically connect to the wallet
    // this.initializeWalletConnection();
  }

  private async initializeWalletConnection(): Promise<void> {
    if (typeof window.ethereum !== 'undefined') {
      this.setProviderAndSigner();

      // Listen for changes in wallet accounts
      window.ethereum.on('accountsChanged', (accounts: string[]) => {
        this.ngZone.run(() => {
          if (accounts.length === 0) {
            // Wallet disconnected or switched accounts
            this.handleWalletDisconnect();
          } else {
            // Wallet accounts changed
            this.handleWalletAccountsChanged(accounts);
          }
        });
      });

      // Listen for changes in network
      window.ethereum.on('chainChanged', () => {
        this.ngZone.run(() => {
          this.setProviderAndSigner();
        });
      });
    } else {
      console.error('None of the wallet browser extensions is not installed.');
    }
  }

  private handleWalletDisconnect() {
    console.log('Wallet disconnected.');
    this.provider = undefined;
    this.signer.set(undefined);
  }

  private handleWalletAccountsChanged(accounts: string[]) {
    this.setProviderAndSigner();
  }

  private async setProviderAndSigner(): Promise<void> {
    this.provider = new ethers.BrowserProvider(window.ethereum);
    const signer = await this.provider.getSigner();
    const network = await this.provider.getNetwork();
    this.signer.set(signer);
    this.network.set(network.name);
  }

  async connectToWallet() {
    if (typeof window.ethereum !== 'undefined') {
      // Request access to the user's Wallet account
      await window.ethereum.request({ method: 'eth_requestAccounts' });
      this.initializeWalletConnection();
    } else {
      console.error('Wallet is not installed.');
    }
  }
}

To use methods from the service above, you’d call them like this:

connectToWallet(): void {
    this.walletService
      .connectToWallet()
      .then(() => {
        console.log('Wallet manually connected');
      })
      .catch((error) => {
        console.log(error);
      });
  }

Integrating Browser Wallets (e.g. Metamask)

As you can see in the code above, we created methods to utilize a connection to browser extension wallets. To determine if the user has browser extension wallet, we used window.ethereum object which would be empty/undefined if a user did not have the wallet installed.

We also implemented some useful methods to observe the changes done inside the wallet like network change and account change.

Integrating Hardware Wallets (e.g. Ledger Nano)

If you wish to quickly integrate a hardware wallet like Ledger Nano S or Ledger Nano X, there is a quick way to do it. Of course, this way would be suitable more for internal applications rather than applications where you want to hit a large user base. This is because the set up is done on the client side rather than in the code or your servers.

The idea is to connect a hardware wallet to a browser extension wallet like Metamask or Phantom and then the procedure is the same as in the wallet.service we created. Metamask has a step by step guide on adding a hardware wallet.

Conclusion on this Web3 Angular Tutorial

By integrating Ethers.js with Angular, developers can leverage the powerful features of Ethereum blockchain within their Angular applications. This setup not only enables building decentralized applications but also enhances user experience by incorporating real-time blockchain data and seamless connection with MetaMask. As the ecosystem grows, understanding and applying these integrations will be increasingly valuable for web developers.


Posted

in

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *