Building a Browser Extension with Web3Auth Plug and Play No Modal SDK
This guide will walk you through the process of building a browser extension with Web3Auth Plug and Play No Modal SDK.
Repository: Google Chrome Browser Extension Example
Quick Start
npx degit Web3Auth/web3auth-pnp-examples/web-no-modal-sdk/chrome-extension-no-modal-example w3a-chrome-extension-demo && cd w3a-chrome-extension-demo && npm install && npm run build
- In your browser go to
chrome://extensions
- Enable Developer mode
- Click on Load unpacked and select the
build
folder from the folder path mentioned above
The extension should now be installed and you can click on the extension icon to interact with it.
End product of this guide:
Once logged in you can have all the features Web3Auth provides and along with blockchain libraries
like ethers.js
, web3.js
, etc you can interact with the blockchain.
How it works?
We can integrate @web3auth/no-modal
as well as @web3auth/modal
to build a browser extension with
Web3Auth. You can read more about both the SDKs in the SDKs section. The login flow
of the user is as follows:
Prerequisites
-
For Web Apps: A basic knowledge of JavaScript is required to use Web3Auth SDK.
-
For Mobile Apps: For the Web3Auth Mobile SDKs, you have a choice between iOS, Android, React Native & Flutter. Please refer to the Web3Auth SDK Reference for more information.
-
Create a Web3Auth account on the Web3Auth Dashboard
We will be building the Chrome extension with create-react-app
in this guide.
Setup
Setup your Web3Auth Dashboard
-
Create a Project from the Project Section of the Web3Auth Developer Dashboard.
-
Enter your desired Project name.
-
Select the Product you want to use. For this guide, we'll be using the Plug n Play product.
-
Select the Platform type you want to use. For this guide, we'll be using the Web Application as the platform.
-
Select the Web3Auth Network as
Sapphire Devnet
. We recommend creating a project in thesapphire_devnet
network during development. While moving to a production environment, make sure to convert your project tosapphire_mainnet
or any of the legacy mainnet networkmainnet
,aqua
, orcyan
network. Otherwise, you'll end up losing users and keys. -
Select the blockchain(s) you'll be building this project on. For interoperability with Torus Wallets, you have the option of allowing the user's private key to be used in other applications using Torus Wallets (EVM, Solana, XRPL & Casper).
-
Finally, once you create the project, you have the option to whitelist your URLs for the project. Please whitelist the domains where your project will be hosted.
-
Once you have the build folder ready for the extension, you will need to go to
chrome://extensions/
and load the unpacked extension from the build folder. That will give you the
extension ID which you would need to add to the Web3Auth Dashboard.
Add chrome-extension://<extension-id>
to the Whitelisted URLs in the Web3Auth Dashboard.
Using the Web3Auth SDK
Installation
- NoModal
- Modal
Install @web3auth/no-modal
, @web3auth/auth-adapter
, @web3auth/ethereum-provider
&
@web3auth/base
- npm
- Yarn
- pnpm
npm install @web3auth/no-modal @web3auth/base @web3auth/auth-adapter @web3auth/ethereum-provider
yarn add @web3auth/no-modal @web3auth/base @web3auth/auth-adapter @web3auth/ethereum-provider
pnpm add @web3auth/no-modal @web3auth/base @web3auth/auth-adapter @web3auth/ethereum-provider
Import the Web3Auth Modules into your project
import { useEffect, useState } from "react";
import { Web3AuthNoModal } from "@web3auth/no-modal";
import { EthereumPrivateKeyProvider } from "@web3auth/ethereum-provider";
import { CHAIN_NAMESPACES, IProvider } from "@web3auth/base";
import { AuthAdapter } from "@web3auth/auth-adapter";
Install @web3auth/modal
& @web3auth/base
- npm
- Yarn
- pnpm
npm install @web3auth/modal @web3auth/base
yarn add @web3auth/modal @web3auth/base
pnpm add @web3auth/modal @web3auth/base
Import the Web3Auth Modules into your project
import { useEffect, useState } from "react";
import { Web3Auth } from "@web3auth/modal";
import { CHAIN_NAMESPACES, IProvider } from "@web3auth/base";
Fixing Webpack 5 issues
While using create-react-app, you may run into issues building. This is because NodeJS polyfills are not included in the latest version of Webpack 5. To solve this, please have a look at this troubleshooting page where we have added the resolution.
Initialization
Create the Web3Auth instance and configure the Auth adapter, in case of no-modal SDK, as per your requirements.
- NoModal
- Modal
const clientId =
"BPi5PB_UiIZ-cPz1GtV5i1I2iOSOHuimiXBI0e-Oe_u6X3oVAbCiAZOTEBtTXw4tsluTITPqA8zMsfxIKMjiqNQ"; // get from https://dashboard.web3auth.io
const chainConfig = {
chainNamespace: CHAIN_NAMESPACES.EIP155,
chainId: "0x1",
rpcTarget: "https://rpc.ankr.com/eth",
displayName: "Ethereum Mainnet",
blockExplorerUrl: "https://etherscan.io",
ticker: "ETH",
tickerName: "Ethereum",
};
const web3auth = new Web3AuthNoModal({
clientId,
chainConfig,
web3AuthNetwork: "sapphire_mainnet",
});
// refer to https://web3auth.io/docs/sdk/pnp/web/adapters/auth to learn more about configuring the adapter
const privateKeyProvider = new EthereumPrivateKeyProvider({ config: { chainConfig } });
const authAdapter = new AuthAdapter({ privateKeyProvider });
web3auth.configureAdapter(authAdapter);
await web3auth.init();
const clientId =
"BPi5PB_UiIZ-cPz1GtV5i1I2iOSOHuimiXBI0e-Oe_u6X3oVAbCiAZOTEBtTXw4tsluTITPqA8zMsfxIKMjiqNQ"; // get from https://dashboard.web3auth.io
const chainConfig = {
chainNamespace: CHAIN_NAMESPACES.EIP155,
chainId: "0x1",
rpcTarget: "https://rpc.ankr.com/eth",
displayName: "Ethereum Mainnet",
blockExplorerUrl: "https://etherscan.io",
ticker: "ETH",
tickerName: "Ethereum",
};
const web3auth = new Web3Auth({
clientId,
chainConfig,
web3AuthNetwork: "sapphire_mainnet",
});
await web3auth.initModal();
Authentication
- NoModal
- Modal
Once initialized, you can use the connectTo
method to authenticate the user.
const web3authProvider = await web3auth.connectTo(WALLET_ADAPTERS.AUTH, {
loginProvider: "google",
});
Once initialized, you can use the connect
method to authenticate the user.
const web3authProvider = await web3auth.connect();
Get the User Profile
// Assuming the user is logged in.
const user = await web3auth.getUserInfo();
Logout
Logging out your user is as simple as calling the web3auth.logout()
function.
await web3auth.logout();
Interacting with the Blockchain
So if you have completed this far, it means that you have successfully authenticated your user. Now,
you can use the provider returned by Web3Auth as web3auth.provider
to interact with your
blockchain. You can use the Provider SDKs to perform RPC Calls to your
blockchain.
Web3Auth is chain agnostic, ie. depending on whatever blockchain or layer-2 you use, Web3Auth can
easily support that. Web3Auth has native providers for EVM and Solana blockchains and for others,
you can get the private key in the user scope and make RPC calls. For standardising the type of
provider, Web3Auth Base provides a IProvider
from which you can create your own provider.
- Ethereum Provider gives you the capability of making RPC calls to the EVM compatible blockchains.
- Solana Provider gives you the capability of making RPC calls to the Solana blockchain.
- XRPL Provider gives you the capability of making RPC calls to the XRPL blockchain.
- If you want to use any other chain except Solana or EVM chains, for ex: Starknet, you can specify
the value of
chainNamespace
field as other in the Web3Auth SDK Constructor. Refer to: Using other blockchains
Get User Accounts
- Web3
- Ethers.js
const getAccounts = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
const web3 = new Web3(provider as any);
const userAccounts = await web3.eth.getAccounts();
console.log(userAccounts);
};
const getAccounts = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
// For ethers v5
// const ethersProvider = new ethers.providers.Web3Provider(this.provider);
const ethersProvider = new ethers.BrowserProvider(this.provider);
// For ethers v5
// const signer = ethersProvider.getSigner();
const signer = await ethersProvider.getSigner();
// Get the user's Ethereum public address
const address = signer.getAddress();
console.log(address);
};
View User Balance
- Web3
- Ethers.js
const getBalance = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
const web3 = new Web3(provider as any);
const accounts = await web3.eth.getAccounts();
const balance = await web3.eth.getBalance(accounts[0]);
console.log(web3.utils.fromWei(balance));
};
const getBalance = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
// For ethers v5
// const ethersProvider = new ethers.providers.Web3Provider(this.provider);
const ethersProvider = new ethers.BrowserProvider(this.provider);
// For ethers v5
// const signer = ethersProvider.getSigner();
const signer = await ethersProvider.getSigner();
// Get the user's Ethereum public address
const address = signer.getAddress();
// Get the user's balance in ether
// For ethers v5
// const balance = ethers.utils.formatEther(
// await ethersProvider.getBalance(address) // Balance is in wei
// );
const balance = ethers.formatEther(
await ethersProvider.getBalance(address), // Balance is in wei
);
console.log(balance);
};
Sign Message
- Web3
- Ethers.js
const signMessage = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
const web3 = new Web3(provider as any);
// Get user's Ethereum public address
const account = (await web3.eth.getAccounts())[0];
// Message
const message = "Hello MPC, Bye Bye SeedPhrase";
const typedMessage = [
{
type: "string",
name: "message",
value: message,
},
];
const params = [JSON.stringify(typedMessage), account];
const method = "eth_signTypedData";
const signedMessage = await this.provider.request({
method,
params,
});
console.log(signedMessage);
};
const signMessage = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
// For ethers v5
// const ethersProvider = new ethers.providers.Web3Provider(this.provider);
const ethersProvider = new ethers.BrowserProvider(this.provider);
// For ethers v5
// const signer = ethersProvider.getSigner();
const signer = await ethersProvider.getSigner();
const originalMessage = "YOUR_MESSAGE";
// Sign the message
const signedMessage = await signer.signMessage(originalMessage);
console.log(signedMessage);
};
Sign Transaction
const signTransaction = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
const web3 = new Web3(provider as any);
const accounts = await web3.eth.getAccounts();
const txRes = await web3.eth.signTransaction({
from: accounts[0],
to: accounts[0],
value: web3.utils.toWei("0.0001"),
chainId: 1, // change it to your specific chain id.
});
console.log(txRes.transactionHash);
};
Send Transaction
- Web3
- Ethers.js
const sendTransaction = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
const web3 = new Web3(provider as any);
const accounts = await web3.eth.getAccounts();
const txRes = await web3.eth.sendTransaction({
from: accounts[0],
to: accounts[0],
value: web3.utils.toWei("0.0001"),
chainId: 1, // change it to your specific chain id.
});
console.log(txRes.transactionHash);
};
const sendTransaction = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
// For ethers v5
// const ethersProvider = new ethers.providers.Web3Provider(this.provider);
const ethersProvider = new ethers.BrowserProvider(this.provider);
// For ethers v5
// const signer = ethersProvider.getSigner();
const signer = await ethersProvider.getSigner();
const destination = "0x40e1c367Eca34250cAF1bc8330E9EddfD403fC56";
// Convert 1 ether to wei
// For ethers v5
// const amount = ethers.utils.parseEther("0.001");
const amount = ethers.parseEther("0.001");
// Submit transaction to the blockchain
const tx = await signer.sendTransaction({
to: destination,
value: amount,
maxPriorityFeePerGas: "5000000000", // Max priority fee per gas
maxFeePerGas: "6000000000000", // Max fee per gas
});
// Wait for the transaction to be mined
const receipt = await tx.wait();
console.log(receipt.transactionHash);
};
Example code
The code for the application we developed in this guide can be found in the Web3Auth Browser Extension. Check it out and try running it locally yourself!
Questions?
Ask us on Web3Auth's Community Support Portal