diff --git a/src/pages/guides/pnp-no-modal-multichain.mdx b/src/pages/guides/pnp-no-modal-multichain.mdx new file mode 100644 index 000000000..bf786f31f --- /dev/null +++ b/src/pages/guides/pnp-no-modal-multichain.mdx @@ -0,0 +1,653 @@ +--- +title: Creating a Multichain Connection with Web3Auth and React PnP no-modal SDK +image: "guides/banners/multi.png" +description: Learn how to connect to different blockchains using Web3Auth. +type: guide +tags: [multichain, polkadot, EVM, cosmos, no-modal] +date: February 9, 2024 +author: Web3Auth Team +communityPortalTopicId: +--- + +import SEO from "@site/src/components/SEO"; +import DashboardSetup from "@site/src/common/guides/_web3auth_dashboard_setup.mdx"; +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; + + + +import Web3AuthPrerequisites from "@site/src/common/guides/_web3auth-prerequisites.mdx"; +import SetupWeb3AuthDashboard from "@site/src/common/guides/_setup-web3auth-dashboard.mdx"; +import SetupBaseProject from "@site/src/common/guides/_setup-base-project.mdx"; + +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](https://github.com/Web3Auth/web3auth-pnp-examples/tree/main/web-no-modal-sdk/blockchain-connection-examples/multi-chain-no-modal-example) +in our Github. + +```bash +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 + + + +## How to set up 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](/sdk). + +For this guide, we will discuss the [Web3Auth Plug and Play No Modal SDK](/sdk/pnp/web/no-modal) and +the different blockchain providers. + + + +### Installation + +We need many dependencies to make this work:: + + + + ```bash + + npm install @web3auth/base @web3auth/no-modal @web3auth/openlogin-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 + + ``` + + + + ```bash + + yarn add @web3auth/base @web3auth/no-modal @web3auth/openlogin-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 + + ``` + + + + ```bash + + pnpm add @web3auth/base @web3auth/no-modal @web3auth/openlogin-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. + + + +```tsx + +import { Web3AuthNoModal } from "@web3auth/no-modal"; +import { OpenloginAdapter } from "@web3auth/openlogin-adapter"; +import { CHAIN_NAMESPACES, IProvider, WALLET_ADAPTERS } from "@web3auth/base"; +import { EthereumPrivateKeyProvider } from "@web3auth/ethereum-provider"; +import { web3AuthConfig, openloginAdapterConfig } 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 + +```` + + +```tsx +import { CHAIN_NAMESPACES, WEB3AUTH_NETWORK, UX_MODE, Web3AuthNoModalOptions } from "@web3auth/base"; +import { OpenloginAdapterOptions } from "@web3auth/openlogin-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 openloginAdapterConfig: OpenloginAdapterOptions ={ + adapterSettings: { + uxMode: UX_MODE.REDIRECT, + }, + }; +```` + + + +```tsx +// StarkEx and StarkNet +//@ts-ignore +import { ec } from "@starkware-industries/starkware-crypto-utils"; +``` + + +```tsx +import type {IProvider} from '@web3auth/base' +import Web3 from 'web3' +``` + + +```tsx +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"; +``` + + +```tsx +// Tezos +//@ts-ignore +import * as tezosCrypto from "@tezos-core-tools/crypto-utils"; +import { hex2buf } from "@taquito/utils"; +import { TezosToolkit } from "@taquito/taquito"; +``` + + +```tsx +// 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 `openloginAdapterConfig` objects in the +`config` directory. + +```tsx +const init = async () => { + try { + const web3auth = new Web3AuthNoModal(web3AuthConfig); + setWeb3auth(web3auth); + + const openloginAdapter = new OpenloginAdapter(openloginAdapterConfig); + web3auth.configureAdapter(openloginAdapter); + + 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](https://web3auth.io/docs/sdk/pnp/web/adapters/openlogin#loginsettings). + +```tsx +const web3authProvider = await web3auth.connectTo(WALLET_ADAPTERS.OPENLOGIN, { + 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) + + + + ```tsx + + const rpcETH = new EthereumRPC(provider!); + const address = await rpcETH.getAccounts(); + + ``` + + + + ```tsx +export default class EthereumRPC{ + private provider: IProvider + + constructor(provider: IProvider) { + this.provider = provider + } + + // Get user's Ethereum public address + public async getAccounts(): Promise { + 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 + + + +```tsx + 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(); +```` + + + +```tsx +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 { + const { getED25519Key } = await import("@toruslabs/openlogin-ed25519"); + const ed25519key = getED25519Key(this.privateKey).sk.toString("hex"); + console.log(ed25519key); + // 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]; + } + +} + +```` + + + ```tsx +export default class EthereumRPC{ + private provider: IProvider + + constructor(provider: IProvider) { + this.provider = provider + } + + // Get user's Ethereum private key + async getPrivateKey(): Promise { + try { + const privateKey = await this.provider.request({ + method: 'eth_private_key', + }) + + return privateKey + } catch (error) { + return error as string + } + } + +} + +```` + + + +## Tezos + + + +```tsx + 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(); + +```` + + + +```tsx +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 { + // Get user's Tezos public address + const keyPairTezos = tezosCrypto.utils.seedToKeyPair(hex2buf(this.privateKey)); + const address = keyPairTezos?.pkh; + return address; + } + +} + +```` + + + + ```tsx +export default class EthereumRPC{ + private provider: IProvider + + constructor(provider: IProvider) { + this.provider = provider + } + + // Get user's Ethereum private key + async getPrivateKey(): Promise { + try { + const privateKey = await this.provider.request({ + method: 'eth_private_key', + }) + + return privateKey + } catch (error) { + return error as string + } + } + +} + +```` + + + + +## StarkEx and StarkNet + + + +```tsx + 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(); + +```` + + + + ```tsx +export default class StartkNetRPC { + private privateKey: string; + + constructor(privateKey: string) { + this.privateKey = privateKey; + } + + // Get user's starkNet public address + async getAccounts(): Promise { + 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; + } + +} + +```` + + + + ```tsx +export default class EthereumRPC{ + private provider: IProvider + + constructor(provider: IProvider) { + this.provider = provider + } + + // Get user's Ethereum private key + async getPrivateKey(): Promise { + try { + const privateKey = await this.provider.request({ + method: 'eth_private_key', + }) + + return privateKey + } catch (error) { + return error as string + } + } + +} + +```` + + + +## Polkadot + + +```tsx + 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(); + +```` + + + + ```tsx +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 { + await cryptoWaitReady(); + + const keyring = new Keyring({ ss58Format: 42, type: "sr25519" }); + + const keyPair = keyring.addFromUri("0x" + this.privateKey); + const address = keyPair.address; + return address; + } + +} +```` + + + + ```tsx +export default class EthereumRPC{ + private provider: IProvider + + constructor(provider: IProvider) { + this.provider = provider + } + + // Get user's Ethereum private key + async getPrivateKey(): Promise { + 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](https://github.com/Web3Auth/web3auth-pnp-examples/tree/main/web-no-modal-sdk/blockchain-connection-examples) +of how to interact with [any blockchain](https://web3auth.io/docs/connect-blockchain#mpc-providers). + +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](https://web3auth.io/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 + +``` diff --git a/static/guides/banners/multi.png b/static/guides/banners/multi.png new file mode 100644 index 000000000..faa7cf6ea Binary files /dev/null and b/static/guides/banners/multi.png differ