Integrate Web3Auth with the Cosmos Blockchain
While using the Web3Auth Web SDK for a non-EVM chain like Cosmos 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 account
, chain ID
, fetch balance
, send transaction
, etc. We have highlighted a few
methods here to get you started quickly on that.
This reference is for the Web
, however, you can use Cosmos on other Mobile and Gaming Platforms as
well. Please follow our reference for EVM Blockchains, and similarly use
Cosmos libraries that support the platforms to use the private key and make blockchain calls
accordingly.
Installation
- npm
- Yarn
- pnpm
npm install --save @web3auth/no-modal @web3auth/auth-adapter @web3auth/base @cosmjs/stargate @cosmjs/proto-signing
yarn add @web3auth/no-modal @web3auth/auth-adapter @web3auth/base @cosmjs/stargate @cosmjs/proto-signing
pnpm add @web3auth/no-modal @web3auth/auth-adapter @web3auth/base @cosmjs/stargate @cosmjs/proto-signing
Initializing Provider
Getting the chainConfig
- Mainnet
- Testnet
const chainConfig = {
chainNamespace: "other",
chainId: "cosmoshub-4", //
rpcTarget: "https://cosmos-rpc.quickapi.com", // Please add in your custom URL
// Avoid using public rpcTarget in production.
displayName: "Cosmos Mainnet",
blockExplorerUrl: "https://www.mintscan.io/cosmos", // Please add in your custom URL
ticker: "ATOM",
tickerName: "Cosmos",
};
const chainConfig = {
chainNamespace: "other",
chainId: "theta-testnet-001", //
rpcTarget: "https://rpc.sentry-02.theta-testnet.polypore.xyz",
// Avoid using public rpcTarget in production.
displayName: "Cosmos Testnet",
blockExplorerUrl: "https://explorer.theta-testnet.polypore.xyz",
ticker: "ATOM",
tickerName: "Cosmos",
};
Initializing and instantiating the Web3Auth SDK
- PnP Modal SDK
- PnP NoModal SDK
- Single Factor Auth JS 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,
});
import { Web3AuthNoModal } from "@web3auth/no-modal";
import { AuthAdapter } from "@web3auth/auth-adapter";
import { CommonPrivateKeyProvider } from "@web3auth/base-provider";
import { WEB3AUTH_NETWORK, CHAIN_NAMESPACES } from "@web3auth/base";
const privateKeyProvider = new CommonPrivateKeyProvider({
config: { chainConfig },
});
const web3auth = new Web3AuthNoModal({
clientId, // Get it from Web3Auth Dashboard
web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
});
const authAdapter = new AuthAdapter();
web3auth.configureAdapter(authAdapter);
import { Web3Auth } from "@web3auth/single-factor-auth";
import { CommonPrivateKeyProvider } from "@web3auth/base-provider";
import { WEB3AUTH_NETWORK, CHAIN_NAMESPACES } from "@web3auth/base";
const web3auth = new Web3Auth({
clientId, // Get your Client ID from Web3Auth Dashboard
web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
});
const privateKeyProvider = new CommonPrivateKeyProvider({
config: { chainConfig },
});
Getting the Web3Auth provider
After initializing Web3Auth, the next step is to initialize the provider and use it for your operations.
- PnP Modal SDK
- PnP NoModal SDK
- Single Factor Auth JS SDK
// 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`
// Initialize for PnP NoModal SDK
await web3auth.init();
// Trigger the login
await web3auth.connectTo("auth");
// Get the provider
const provider = web3auth.provider;
// Continue using the `provider`
// Initialize for Single Factor Auth JS SDK
await web3auth.init();
// 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 ChainID
Once a user logs in, the Web3Auth SDK returns a provider. Since Web3Auth doesn't have a native provider for Cosmos, we need to directly use the private key to make the RPC calls.
CosmJS Libraries
@cosmjs/stargate
A client library for the Cosmos SDK 0.40+. Provides a high-level client for
querying, signing and broadcasting. This is an npm library that provides a JavaScript/TypeScript
interface to interact with the Cosmos SDK blockchain via the Tendermint RPC interface.
@cosmjs/proto-signing
It is an npm library for signing messages using protobuf serialization,
which is commonly used in Cosmos SDK-based blockchains. It provides a simple API for generating and
verifying signatures using different algorithms and key types.
In order to get the ChainId, we connect to the RPC using StargateClient and make a call using the
Cosmos RPC client to get the chainId. You can get the private key using
this.provider.request({method: "private_key",})
.
import type { IProvider } from "@web3auth/base";
import { SigningStargateClient, StargateClient } from "@cosmjs/stargate";
import { DirectSecp256k1Wallet, OfflineDirectSigner } from "@cosmjs/proto-signing";
const rpc = "https://rpc.sentry-02.theta-testnet.polypore.xyz";
export default class CosmosRPC {
private provider: IProvider;
constructor(provider: IProvider) {
this.provider = provider;
}
async getPrivateKey(): Promise<any> {
try {
return await this.provider.request({
method: "private_key",
});
} catch (error) {
return error as string;
}
}
async getChainId(): Promise<string> {
try {
const client = await StargateClient.connect(rpc);
// Get the connected Chain's ID
const chainId = await client.getChainId();
return chainId.toString();
} catch (error) {
return error as string;
}
}
}
Get Account
Using DirectSecp256k1Wallet.fromKey()
we can get the accounts via the private key we get through
the provider.
import type { IProvider } from "@web3auth/base";
import { SigningStargateClient, StargateClient } from "@cosmjs/stargate";
import { DirectSecp256k1Wallet, OfflineDirectSigner } from "@cosmjs/proto-signing";
const rpc = "https://rpc.sentry-02.theta-testnet.polypore.xyz";
export default class CosmosRPC {
private provider: IProvider;
constructor(provider: IProvider) {
this.provider = provider;
}
async getAccounts(): Promise<any> {
try {
const privateKey = Buffer.from(await this.getPrivateKey(), "hex");
const walletPromise = await DirectSecp256k1Wallet.fromKey(privateKey, "cosmos");
return (await walletPromise.getAccounts())[0].address;
} catch (error) {
return error;
}
}
}
Get Balance
Using the account address we received in the previous step, we can fetch the balance using an RPC
call to client.getAllBalances(address)
.
import type { IProvider } from "@web3auth/base";
import { SigningStargateClient, StargateClient } from "@cosmjs/stargate";
import { DirectSecp256k1Wallet, OfflineDirectSigner } from "@cosmjs/proto-signing";
const rpc = "https://rpc.sentry-02.theta-testnet.polypore.xyz";
export default class CosmosRPC {
private provider: IProvider;
constructor(provider: IProvider) {
this.provider = provider;
}
async getBalance(): Promise<any> {
try {
const client = await StargateClient.connect(rpc);
const privateKey = Buffer.from(await this.getPrivateKey(), "hex");
const walletPromise = await DirectSecp256k1Wallet.fromKey(privateKey, "cosmos");
const address = (await walletPromise.getAccounts())[0].address;
// Get user's balance in uAtom
return await client.getAllBalances(address);
} catch (error) {
return error as string;
}
}
}
Send transaction
import type { IProvider } from "@web3auth/base";
import { SigningStargateClient, StargateClient } from "@cosmjs/stargate";
import { DirectSecp256k1Wallet, OfflineDirectSigner } from "@cosmjs/proto-signing";
const rpc = "https://rpc.sentry-02.theta-testnet.polypore.xyz";
export default class CosmosRPC {
private provider: IProvider;
constructor(provider: IProvider) {
this.provider = provider;
}
async sendTransaction(): Promise<any> {
try {
await StargateClient.connect(rpc);
const privateKey = Buffer.from(await this.getPrivateKey(), "hex");
const walletPromise = await DirectSecp256k1Wallet.fromKey(privateKey, "cosmos");
const fromAddress = (await walletPromise.getAccounts())[0].address;
const destination = "cosmos15aptdqmm7ddgtcrjvc5hs988rlrkze40l4q0he";
const getSignerFromKey = async (): Promise<OfflineDirectSigner> => {
return DirectSecp256k1Wallet.fromKey(privateKey, "cosmos");
};
const signer: OfflineDirectSigner = await getSignerFromKey();
const signingClient = await SigningStargateClient.connectWithSigner(rpc, signer);
const result = await signingClient.sendTokens(
fromAddress,
destination,
[{ denom: "uatom", amount: "250" }],
{
amount: [{ denom: "uatom", amount: "250" }],
gas: "100000",
},
);
const transactionHash = result.transactionHash;
const height = result.height;
return { transactionHash, height };
} catch (error) {
return error as string;
}
}
}