Providers, Signers, and Wallets

Providers, Signers, and Wallets

The frontend communicates with the blockchain using JSON-RPC, but we will be using Ethers.js. When using JSON-RPC, Ethers.js likes to abstract degrees of interaction with the blockchain into objects, such as providers, signers, and wallets.

Providers are the bridge between the frontend user interface and the blockchain network, facilitating communication and data exchange. They abstract the complexities of interacting with the blockchain, offering a simple API for the frontend to use. They are responsible for connecting the DApp to a specific blockchain node, allowing it to read data from the blockchain, and essentially contain the JSON-RPC URL.

Signers are a type of provider that contain a secret that can be used to sign transactions with. This allows the frontend to create transactions, sign them, and then send them with eth_sendRawTransaction. There are multiple types of signers, but we're most interested in wallet objects, which securely store and manage users' private keys and digital assets. Wallets such as MetaMask facilitate transaction signing with a universal and user-friendly process. They act as a user's representation within the DApp, ensuring that only authorized transactions are executed. The Ethers.js wallet object represents this interface within our frontend code.

Typically, a frontend using Ethers.js will require you to create a provider, connect to the user's wallet if applicable, and create a wallet object. This process can become unwieldy in larger projects, especially with the number of wallets that exist other than MetaMask.

Example of unwieldy MetaMask handling
// Detect if the browser has MetaMask installed
let provider, signer;
if (typeof window.ethereum !== 'undefined') {
  // Create a provider using MetaMask
  provider = new ethers.BrowserProvider(window.ethereum);

  // Connect to MetaMask
  async function connectToMetaMask() {
    try {
      // Request access to the user's MetaMask account
      const accounts = await window.ethereum.request({
        method: 'eth_requestAccounts',
      });

      // Create a signer (wallet) using the provider
      signer = provider.getSigner(accounts[0]);
    } catch (error) {
      console.error('Error connecting to MetaMask:', error);
    }
  }

  // Call the function to connect to MetaMask
  connectToMetaMask();
} else {
  console.log('MetaMask is not installed');
}

// ... also the code for disconnecting from the site
// ... also the code that handles other wallets

Fortunately, we have installed the useDApp package, which simplifies many of the processes for us. This simultaneously abstracts what Ethers is doing as well, which is why we took a bit of time to explain them here.

Last updated