# How to detect Keplr

You can know if Keplr is installed on the user device by checking window.keplr. If window.keplr returns undefined, Keplr is not installed (note: sometimes window.keplr may return undefined even when Keplr is installed if browser is parsing the DOM or the way it runs scripts).

However, window.keplr will definitely return Keplr if the document's readyState is complete or upon document's load event if Keplr is installed.

There are many ways to use Keplr upon the load event. Refer to the examples below:

You can register the function to window.onload:

Copy window.onload = async () => { if (!window.keplr) { alert("Please install keplr extension"); } else { const chainId = "cosmoshub-4"; // Enabling before using the Keplr is recommended. // This method will ask the user whether or not to allow access if they haven't visited this website. // Also, it will request user to unlock the wallet if the wallet is locked. await window.keplr.enable(chainId); const offlineSigner = window.getOfflineSigner(chainId); // You can get the address/public keys by `getAccounts` method. // It can return the array of address/public key. // But, currently, Keplr extension manages only one address/public key pair. // XXX: This line is needed to set the sender address for SigningCosmosClient. const accounts = await offlineSigner.getAccounts(); // Initialize the gaia api with the offline signer that is injected by Keplr extension. const cosmJS = new SigningCosmosClient( "https://lcd-cosmoshub.keplr.app", accounts[0].address, offlineSigner, ); } }

or track the document's ready state through the document event listener:

Copy async getKeplr(): Promise<Keplr | undefined> { if (window.keplr) { return window.keplr; } if (document.readyState === "complete") { return window.keplr; } return new Promise((resolve) => { const documentStateChange = (event: Event) => { if ( event.target && (event.target as Document).readyState === "complete" ) { resolve(window.keplr); document.removeEventListener("readystatechange", documentStateChange); } }; document.addEventListener("readystatechange", documentStateChange); }); }

There may be multiple ways to achieve the same result, and not one method is preferred over the other.

# Keplr-specific features

If you were able to connect Keplr with CosmJS, you may skip to the Use Keplr with CosmJS section.

While Keplr supports an easy way to connect to CosmJS, there are additional functions specific to Keplr which provides additional features.

# Using with Typescript

window.d.ts

Copy import { Window as KeplrWindow } from "@keplr-wallet/types"; declare global { // eslint-disable-next-line @typescript-eslint/no-empty-interface interface Window extends KeplrWindow {} }

The @keplr-wallet/types package has the type definition related to Keplr.
If you're using TypeScript, run npm install --save-dev @keplr-wallet/types or yarn add -D @keplr-wallet/types to install @keplr-wallet/types.
Then, you can add the @keplr-wallet/types window to a global window object and register the Keplr related types.

# Enable Connection

Copy enable(chainIds: string | string[]): Promise<void>

The window.keplr.enable(chainIds) method requests the extension to be unlocked if it's currently locked. If the user hasn't given permission to the webpage, it will ask the user to give permission for the webpage to access Keplr.

enable method can receive one or more chain-id as an array. When the array of chain-id is passed, you can request permissions for all chains that have not yet been authorized at once.

If the user cancels the unlock or rejects the permission, an error will be thrown.

# Get Address / Public Key

Copy getKey(chainId: string): Promise<{ // Name of the selected key store. name: string; algo: string; pubKey: Uint8Array; address: Uint8Array; bech32Address: string; }>

If the webpage has permission and Keplr is unlocked, this function will return the address and public key in the following format:

Copy { // Name of the selected key store. name: string; algo: string; pubKey: Uint8Array; address: Uint8Array; bech32Address: string; }

It also returns the nickname for the key store currently selected, which should allow the webpage to display the current key store selected to the user in a more convenient mane.

# Sign Amino

Copy signAmino(chainId: string, signer: string, signDoc: StdSignDoc): Promise<AminoSignResponse>

Similar to CosmJS OfflineSigner's signAmino, but Keplr's signAmino takes the chain-id as a required parameter. Signs Amino-encoded StdSignDoc.

# Sign Direct / Protobuf

Copy signDirect(chainId:string, signer:string, signDoc: { /** SignDoc bodyBytes */ bodyBytes?: Uint8Array | null; /** SignDoc authInfoBytes */ authInfoBytes?: Uint8Array | null; /** SignDoc chainId */ chainId?: string | null; /** SignDoc accountNumber */ accountNumber?: Long | null; }): Promise<DirectSignResponse>

Similar to CosmJS DirectOfflineSigner's signDirect, but Keplr's signDirect takes the chain-id as a required parameter. Signs Proto-encoded StdSignDoc.

# Request Transaction Broadcasting

Copy sendTx( chainId: string, stdTx: StdTx, mode: BroadcastMode ): Promise<Uint8Array>;

This function requests Keplr to delegates the broadcasting of the transaction to Keplr's LCD endpoints (rather than the webpage broadcasting the transaction). This method returns the transaction hash if it succeeds to broadcast, if else the method will throw an error. When Keplr broadcasts the transaction, Keplr will send the notification on the transaction's progress.

# Interaction Options

Copy export interface KeplrIntereactionOptions { readonly sign?: KeplrSignOptions; } export interface KeplrSignOptions { readonly preferNoSetFee?: boolean; readonly preferNoSetMemo?: boolean; }

Keplr v0.8.11+ offers additional options to customize interactions between the frontend website and Keplr extension.

If preferNoSetFee is set to true, Keplr will prioritize the frontend-suggested fee rather than overriding the tx fee setting of the signing page.

If preferNoSetMemo is set to true, Keplr will not override the memo and set fix memo as the front-end set memo.

You can set the values as follows:

Copy window.keplr.defaultOptions = { sign: { preferNoSetFee: true, preferNoSetMemo: true, } }

# Custom event

# Change Key Store Event

Copy keplr_keystorechange

When the user switches their key store/account after the webpage has received the information on the key store/account the key that the webpage is aware of may not match the selected key in Keplr which may cause issues in the interactions.

To prevent this from happening, when the key store/account is changed, Keplr emits a keplr_keystorechange event to the webpage's window. You can request the new key/account based on this event listener.

Copy window.addEventListener("keplr_keystorechange", () => { console.log("Key store in Keplr is changed. You may need to refetch the account info.") })