Skip to main content

Integrate Web3Auth with the Polymesh Blockchain

While using the Web3Auth Web SDK for a non-EVM chain like Polymesh you get a standard provider from which you can get the private key of the user. Using this private key, you can use the corresponding libraries of the blockchain to make blockchain calls like getting the user's public signing key, fetching balance, and sign & send transaction. We have highlighted a few methods here to get you started quickly on that.

Installation

For Polymesh, we will use the libraries @polymeshassociation/polymesh-sdk and @polymeshassociation/local-signing-manager to create the Polymesh address, query the chain and submit transactions.

npm install --save @polymeshassociation/polymesh-sdk @polymeshassociation/local-signing-manager

Initializing Provider

Getting the chainConfig

const chainConfig = {
chainNamespace: "other",
chainId: "0x1",
rpcTarget: "https://mainnet-rpc.polymesh.network",
// Avoid using public rpcTarget in production.
displayName: "Polymesh Mainnet",
blockExplorerUrl: "https://polymesh.subscan.io",
ticker: "POLYX",
tickerName: "Polymesh",
};

Initializing and instantiating the Web3Auth SDK

import { Web3Auth } from "@web3auth/modal";
import { CommonPrivateKeyProvider } from "@web3auth/base-provider";
import { WEB3AUTH_NETWORK, CHAIN_NAMESPACES } from "@web3auth/base";

const privateKeyProvider = new CommonPrivateKeyProvider({
config: { chainConfig: chainConfig },
});

const web3auth = new Web3Auth({
// Get it from Web3Auth Dashboard
clientId,
web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
privateKeyProvider: privateKeyProvider,
});

Getting the Web3Auth provider

After initializing Web3Auth, the next step is to initialize the provider and use it for your operations.

// Initialize for PnP Modal SDK
await web3auth.initModal();

// Trigger the login
await web3auth.connect();

// Get the provider
const provider = web3auth.provider;

// Continue using the `provider`

After logging in, the Web3Auth instance will provide you with information regarding the user that is logged in. This information is obtained directly from the JWT token and is not stored by Web3Auth. Therefore, this information can only be accessed through social logins after the user has logged into your application.

const user = await web3auth.getUserInfo(); // web3auth instance

Get Account and KeyPair

Once a user logs in, the Web3Auth SDK returns a provider. Since Web3Auth doesn't have a native provider for Polymesh, we need to directly use the private key to make the RPC calls.

Using the function, web3auth.provider.request({method: "private_key"}) from Web3Auth provider, the application can have access to the user's private key. However, Web3Auth does not provide direct access to Polymesh-specific signing functions, hence, we create a new LocalSigningManager and import this private key to give the Polymesh SDK the ability to sign transactions with this key.

import { LocalSigningManager } from "@polymeshassociation/local-signing-manager";

/*
Use code from the above Initializing Provider here
*/

// web3authProvider is web3auth.provider from above
const privateKey = await web3authProvider.request({ method: "private_key" });

// create and instance of the polymesh local signing manager and import the web3Auth private hey
const localSigningManager = await LocalSigningManager.create({
accounts: [{ uri: "0x" + privateKey, derivationPath: "" }],
// A derivation path can optionally be added to derive multiple keys from the same private key
});

At this point if we were to query the public key derived from the private key by calling localSigningManager.getAccounts() the function would throw an error as a SS58 prefix for the chain has not been set. The SS58 prefix can be set manually by calling e.g. localSigningManager.setSs58Format(12), or by attaching the signing manager to an instance of the Polymesh SDK which will automatically read the correct SS58 prefix from the chain and set it in the signing manager.

import { Polymesh } from "@polymeshassociation/polymesh-sdk";

// Create an instance of the Polymesh SDK, attaching the previously
// created signing manager and connect to a Polymesh RPC node
const polymeshApi = await Polymesh.connect({
nodeUrl: "wss://mainnet-rpc.polymesh.network/",
signingManager: localSigningManager,
});

// Query the derived Public key from the Polymesh SDK instance
const signingAccount = polymeshApi.accountManagement.getSigningAccount();
// Note: if you have added multiple signing keys to the signing manager
// the default signing account will be the first key added
console.log(`Public Key: ${signingAccount.address}`);

Get Balance

/*
Use code from the above Initializing Provider and connecting to Polymesh here
*/

// Retrieve the POLYX balance associate with the signing key
const balance = await polymeshApi.accountManagement.getAccountBalance();

Get The Associated Identity ID

Before a key on Polymesh can receive tokens or transact on chain it must be associated with an onchain identity. A new identity can be assigned by a permissioned Certified Due Diligence (CDD) provider or you can add the key to an existing identity. Individuals can onboard their key by visiting https://testnet-onboarding.polymesh.live/ or https://mainnet-onboarding.polymesh.network/.

/*
Use code from the above Initializing Provider and connecting to Polymesh here
*/

// Retrieve the Identity associate with the signing key
const identity = await polymeshApi.getSigningIdentity();
console.log(`Signing Identity: ${identity?.did || "No identity found"}`);

Send Transaction

/*
Use code from the above Initializing Provider and connecting to Polymesh here
*/

import { BigNumber } from "@polymeshassociation/polymesh-sdk";
import type { GenericPolymeshTransaction } from '@polymeshassociation/polymesh-sdk/types';

// Prepare a POLYX transfer transaction from the signer added previously
const polyxTransferTx = await polymeshApi.network.transferPolyx(
{
amount: new BigNumber(10);,
to: "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
memo: "I sent some POLYX", //optional
}
);

console.log(`\nTransferring ${amount.toString()} POLYX from ${signingAccount.address} to ${to}`);

// Optionally subscribe to transaction status changes and handle status changes
const unsub = polyxTransferTx.onStatusChange(
(tx: GenericPolymeshTransaction<any, any>) => {
// Do something on status changes
},
);

try {
// Execute the PolyX transfer transaction
await polyxTransferTx.run();
} catch (error) {
console.log("Transaction Error:", (error as Error).message);
} finally {
// Unsubscribe from transaction status changes
unsub();
}

console.log(JSON.stringify(polyxTransferTx.receipt?.events));