Create a Chain Agnostic Web3 Wallet with PnP no-modal SDK
This guide will cover the basics of how to integrate Web3Auth with different blockchains at the same time. In this demo, you will be able to authenticate with different social logins and get different addresses from each blockchain. Of course, you can interact and sign transactions with any of them.
You will be able to make calls like get the user's account
, fetch balance
, sign transaction
,
send transaction
, read
from and write
to smart contracts, etc.
The Web3Auth Web SDK is designed to support any blockchain that follows the secp256k1
&
ed25519
curves. This means it works seamlessly with all EVMs such as Ethereum, Polygon, Binance
Smart Chain, and others. Additionally, it supports non-EVM blockchains like Aptos, Cosmos, Polkadot,
Solana, Tezos, Bitcoin, among many others. The SDK is not limited to these examples and is capable
of integrating with any blockchain that adheres to these cryptographic standards, offering a wide
range of compatibility to suit various needs and preferences in the blockchain ecosystem.
Quick Start
You can run the following command or you can check the full example in our Github.
npx degit Web3Auth/web3auth-pnp-examples/web-no-modal-sdk/blockchain-connection-examples/multi-chain-no-modal-example/ w3a-multi-chain-no-modal-demo && cd w3a-multi-chain-no-modal-demo && npm install && npm run start
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
How to set up Web3Auth Dashboard
If you haven't already, sign up on the Web3Auth platform. It is free and gives you access to the Web3Auth's base plan. After the basic setup, explore other features and functionalities offered by the Web3Auth Dashboard. It includes custom verifiers, whitelabeling, analytics, and more. Head to Web3Auth's documentation page for detailed instructions on setting up the Web3Auth Dashboard.
Using the Web3Auth Plug and Play No Modal SDK
To use the Web3Auth Plug and Play No Modal SDK, you need to add the dependency of the respective platform SDK of Web3Auth to your project. To learn more about the available SDKs, please have a look at this documentation page.
For this guide, we will discuss the Web3Auth Plug and Play No Modal SDK and the different blockchain providers.
Setting up your base project for using Web3 libraries:
If you are starting from scratch, to set up this project locally, you will need to create a base Web application, where you can install the required dependencies. However, while working with Web3, there are a few base libraries, which need additional configuration. This is because certain packages are not available in the browser environment, and we need to polyfill them manually. You can follow this documentation where we have mentioned the configuration changes for some popular frameworks for your reference.
Installation
We need many dependencies to make this work::
- npm
- yarn
- pnpm
npm install @web3auth/base @web3auth/no-modal @web3auth/auth-adapter @web3auth/ethereum-provider @web3auth/solana-provider @polkadot/api @polkadot/util-crypto @taquito/signer @taquito/taquito @taquito/utils @tezos-core-tools/crypto-utils @starkware-industries/starkware-crypto-utils web3 ethers
yarn add @web3auth/base @web3auth/no-modal @web3auth/auth-adapter @web3auth/ethereum-provider @web3auth/solana-provider @polkadot/api @polkadot/util-crypto @taquito/signer @taquito/taquito @taquito/utils @tezos-core-tools/crypto-utils @starkware-industries/starkware-crypto-utils web3 ethers
pnpm add @web3auth/base @web3auth/no-modal @web3auth/auth-adapter @web3auth/ethereum-provider @web3auth/solana-provider @polkadot/api @polkadot/util-crypto @taquito/signer @taquito/taquito @taquito/utils @tezos-core-tools/crypto-utils @starkware-industries/starkware-crypto-utils web3 ethers
Instantiating Web3Auth
Import the required modules for web3auth and any providers you want to use.
- App.tsx
- web3auth.ts
- StartkNetRPC.ts
- EthereumRPC.ts
- SolanaRPC.ts
- TezosRPC.ts
- PolkadotRPC.ts
import { Web3AuthNoModal } from "@web3auth/no-modal";
import { AuthAdapter } from "@web3auth/auth-adapter";
import { CHAIN_NAMESPACES, IProvider, WALLET_ADAPTERS } from "@web3auth/base";
import { EthereumPrivateKeyProvider } from "@web3auth/ethereum-provider";
import { web3AuthConfig, authAdapterConfig } from "./config/web3auth";
import StartkNetRPC from "./RPC/startkNetRPC"; // for using starkex
import EthereumRPC from "./RPC/ethRPC-web3"; // for using web3.js
import SolanaRPC from "./RPC/solanaRPC"; // for using solana
import TezosRPC from "./RPC/tezosRPC"; // for using tezos
import PolkadotRPC from "./RPC/polkadotRPC"; // for using polkadot
import {
CHAIN_NAMESPACES,
WEB3AUTH_NETWORK,
UX_MODE,
Web3AuthNoModalOptions,
} from "@web3auth/base";
import { AuthAdapterOptions } from "@web3auth/auth-adapter";
import { EthereumPrivateKeyProvider } from "@web3auth/ethereum-provider";
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",
logo: "https://cryptologos.cc/logos/ethereum-eth-logo.png",
};
const privateKeyProvider = new EthereumPrivateKeyProvider({ config: { chainConfig } });
export const web3AuthConfig: Web3AuthNoModalOptions = {
clientId,
privateKeyProvider,
web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
};
export const authAdapterConfig: AuthAdapterOptions = {
adapterSettings: {
uxMode: UX_MODE.REDIRECT,
},
};
// StarkEx and StarkNet
//@ts-ignore
import { ec } from "@starkware-industries/starkware-crypto-utils";
import type {IProvider} from '@web3auth/base'
import Web3 from 'web3'
import { SolanaPrivateKeyProvider, SolanaWallet } from "@web3auth/solana-provider";
import { CHAIN_NAMESPACES } from "@web3auth/base";
import { Connection, LAMPORTS_PER_SOL, PublicKey, SystemProgram, Transaction } from "@solana/web3.js";
// Tezos
//@ts-ignore
import * as tezosCrypto from "@tezos-core-tools/crypto-utils";
import { hex2buf } from "@taquito/utils";
import { TezosToolkit } from "@taquito/taquito";
// Polkadot
import { Keyring, ApiPromise, WsProvider } from "@polkadot/api";
import { cryptoWaitReady } from "@polkadot/util-crypto";
Call init
when the app is loaded, it will initialize the Web3Auth instance. Also don't forget to
properly configure the clientId
, web3AuthConfig
and authAdapterConfig
objects in the config
directory.
const init = async () => {
try {
const web3auth = new Web3AuthNoModal(web3AuthConfig);
setWeb3auth(web3auth);
const authAdapter = new AuthAdapter(authAdapterConfig);
web3auth.configureAdapter(authAdapter);
await web3auth.init();
setProvider(web3auth.provider);
if (web3auth.connected) {
setLoggedIn(true);
}
} catch (error) {
console.error(error);
}
};
Login with Web3Auth
You must call this function to start the login process. You can change the loginProvider
to any of
the available social logins.
const web3authProvider = await web3auth.connectTo(WALLET_ADAPTERS.AUTH, {
loginProvider: "google",
});
Get Public Addresses from different blockchains
For each blockchain you want to connect to, you need to call the getAccounts
function. Every RPC
Class blockchain, except Ethereum you would need to provide the private key to get the public
address.
EVM (Ethereum)
- App.tsx
- ethRPC-web3.ts
const rpcETH = new EthereumRPC(provider!);
const address = await rpcETH.getAccounts();
export default class EthereumRPC {
private provider: IProvider;
constructor(provider: IProvider) {
this.provider = provider;
}
// Get user's Ethereum public address
public async getAccounts(): Promise<any> {
try {
const web3 = new Web3(this.provider as any);
// Get user's Ethereum public address
const address = (await web3.eth.getAccounts())[0];
return address;
} catch (error) {
return error;
}
}
}
Solana
- App.tsx
- solanaRPC.ts
- ethRPC-web3.ts
const rpcETH = new EthereumRPC(provider!);
const privateKey = await rpcETH.getPrivateKey();
// Get user's Solana public address
const solanaRPC = new SolanaRPC(privateKey);
const solana_address = await solanaRPC.getAccounts();
export default class SolanaRPC {
private provider: SolanaPrivateKeyProvider;
private privateKey: string;
constructor(privateKey: string) {
this.provider = new SolanaPrivateKeyProvider({
config: {
chainConfig: {
chainNamespace: CHAIN_NAMESPACES.SOLANA,
chainId: "0x3",
rpcTarget: "https://api.devnet.solana.com",
displayName: "Solana Mainnet",
blockExplorerUrl: "https://explorer.solana.com/",
ticker: "SOL",
tickerName: "Solana",
logo: "",
},
},
});
this.privateKey = privateKey;
}
async getAccounts(): Promise<any> {
const { getED25519Key } = await import("@web3auth/auth-adapter");
const ed25519key = getED25519Key(this.privateKey).sk.toString("hex");
// Get user's Solana's public address
await this.provider.setupProvider(ed25519key);
const solanaWallet = new SolanaWallet(this.provider as SolanaPrivateKeyProvider);
const solana_address = await solanaWallet.requestAccounts();
return solana_address[0];
}
}
export default class EthereumRPC {
private provider: IProvider;
constructor(provider: IProvider) {
this.provider = provider;
}
// Get user's Ethereum private key
async getPrivateKey(): Promise<any> {
try {
const privateKey = await this.provider.request({
method: "eth_private_key",
});
return privateKey;
} catch (error) {
return error as string;
}
}
}
Tezos
- App.tsx
- tezosRPC.ts
- ethRPC-web3.ts
const rpcETH = new EthereumRPC(provider!);
const privateKey = await rpcETH.getPrivateKey();
// Get user's Tezos public address
const tezosRPC = new TezosRPC(privateKey);
const tezos_address = await tezosRPC.getAccounts();
export default class TezosRPC {
private provider: TezosToolkit;
private privateKey: string;
constructor(privateKey: string) {
this.privateKey = privateKey;
this.provider = new TezosToolkit("https://ghostnet.ecadinfra.com");
}
async getAccounts(): Promise<any> {
// Get user's Tezos public address
const keyPairTezos = tezosCrypto.utils.seedToKeyPair(hex2buf(this.privateKey));
const address = keyPairTezos?.pkh;
return address;
}
}
export default class EthereumRPC {
private provider: IProvider;
constructor(provider: IProvider) {
this.provider = provider;
}
// Get user's Ethereum private key
async getPrivateKey(): Promise<any> {
try {
const privateKey = await this.provider.request({
method: "eth_private_key",
});
return privateKey;
} catch (error) {
return error as string;
}
}
}
StarkEx and StarkNet
- App.tsx
- starknexRPC.ts
- ethRPC-web3.ts
const rpcETH = new EthereumRPC(provider!);
const privateKey = await rpcETH.getPrivateKey();
// Get user's starkNet public address
const starkNetRPC = new StartkNetRPC(privateKey);
const stark_address = await starkNetRPC.getAccounts();
export default class StartkNetRPC {
private privateKey: string;
constructor(privateKey: string) {
this.privateKey = privateKey;
}
// Get user's starkNet public address
async getAccounts(): Promise<any> {
const keyPairStarkNet = ec.keyFromPrivate(this.privateKey, "hex");
const starknet_account = ec.keyFromPublic(keyPairStarkNet.getPublic(true, "hex"), "hex");
const address = starknet_account.pub.getX().toString("hex");
return address;
}
}
export default class EthereumRPC {
private provider: IProvider;
constructor(provider: IProvider) {
this.provider = provider;
}
// Get user's Ethereum private key
async getPrivateKey(): Promise<any> {
try {
const privateKey = await this.provider.request({
method: "eth_private_key",
});
return privateKey;
} catch (error) {
return error as string;
}
}
}
Polkadot
- App.tsx
- polkadotRPC.ts
- ethRPC-web3.ts
const rpcETH = new EthereumRPC(provider!);
const privateKey = await rpcETH.getPrivateKey();
// Get user's Polkadot public address
const polkadotRPC = new PolkadotRPC(privateKey);
const polkadot_address = await polkadotRPC.getAccounts();
export default class PolkadotRPC {
private provider: WsProvider;
private privateKey: string;
constructor(privateKey: string) {
this.provider = new WsProvider("wss://rpc.polkadot.io"); // Kusama wss://kusama-rpc.polkadot.io
this.privateKey = privateKey;
}
// Get user's Polkadot public key
async getAccounts(): Promise<any> {
await cryptoWaitReady();
const keyring = new Keyring({ ss58Format: 42, type: "sr25519" });
const keyPair = keyring.addFromUri("0x" + this.privateKey);
const address = keyPair.address;
return address;
}
}
export default class EthereumRPC {
private provider: IProvider;
constructor(provider: IProvider) {
this.provider = provider;
}
// Get user's Ethereum private key
async getPrivateKey(): Promise<any> {
try {
const privateKey = await this.provider.request({
method: "eth_private_key",
});
return privateKey;
} catch (error) {
return error as string;
}
}
}
Get all the public wallets
As you can see in the full example, we get the public address from each blockchain (and also the balance). In this case, It's clear that you can interact with different blockchains at the same time.
In Web3auth we have several examples of how to interact with any blockchain.
We also have some examples of how to interact with Cosmos, Aptos, Algorand, Polkadot, Tezos, StarkNet and XRPL.
Conclusion
This guide has walked you through the seamless process of creating a multichain connection using Web3Auth and the React PnP no-modal SDK. By integrating Web3Auth, developers are empowered to build applications that are not only blockchain-agnostic but also user-friendly, leveraging social logins for authentication across multiple blockchains.
The provided examples and code snippets have shown how to initialize Web3Auth, configure adapters, and retrieve public addresses for different blockchains, highlighting the flexibility and power of Web3Auth in handling diverse blockchain technologies. With this knowledge, developers can now extend their applications to support a wide range of blockchains.
As the blockchain ecosystem continues to evolve, tools like Web3Auth will play a crucial role in simplifying access and interaction with blockchain technologies.
If you want to interact with a specific blockchain and you are having trouble with the code, please contact us in our community.
References
- https://web3auth.io/docs/sdk/pnp/web/no-modal/
- https://web3auth.io/docs/sdk/helper-sdks/providers/
- https://web3auth.io/docs/examples?product=Plug+and+Play&sdk=Plug+and+Play+Web+Modal+SDK