Skip to main content

Cosmos

UKey Wallet Cosmos Provider is used to connect Cosmos ecological chain accounts, sign transactions, broadcast transactions and integrate with CosmJS in web applications. The page is accessible via window.$ukey.cosmos.

ℹ️

UKey Wallet Cosmos Provider is compatible with the Keplr wallet interface. Existing Keplr access usually only requires adjusting the Provider detection entrance.



Find Provider

// Note: Detect UKey Wallet Cosmos provider
const provider = window.$ukey?.cosmos;

if (!provider) {
throw new Error("UKey Wallet Cosmos provider not detected");
}

// Note: Check if it is UKey Wallet
console.log("Detected provider:", provider.isUKey ? "UKey Wallet" : "Unrecognized");

Get Going

Enable target chain

const chainId = "cosmoshub-4";

// Note: Enable chain - returns key information
const key = await provider.enable(chainId);

// Note: Or enable multiple chains at the same time
await provider.enable(["cosmoshub-4", "osmosis-1", "juno-1"]);

Read account information

const chainId = "cosmoshub-4";
const key = await provider.getKey(chainId);

console.log({
name: key.name, // Note: Account name
algo: key.algo, // signing algorithm, for instance secp256k1
pubKey: key.pubKey, // public key as a Uint8Array
address: key.address, // Bech32 address as Uint8Array
bech32Address: key.bech32Address, // Note: Bech32 format address
isNanoLedger: key.isNanoLedger, // Note: Hardware wallet logo
});

chain management

Add custom chain

If the target chain does not yet have built-in support, you can provide the chain configuration via experimentalSuggestChain and request the user to add it:

await provider.experimentalSuggestChain({
chainId: "my-chain-1",
chainName: "My Custom Chain",
rpc: "https://rpc.mychain.io",
rest: "https://lcd.mychain.io",
bip44: { coinType: 118 },
bech32Config: {
bech32PrefixAccAddr: "mychain",
bech32PrefixAccPub: "mychainpub",
bech32PrefixValAddr: "mychainvaloper",
bech32PrefixValPub: "mychainvaloperpub",
bech32PrefixConsAddr: "mychainvalcons",
bech32PrefixConsPub: "mychainvalconspub",
},
currencies: [
{
coinDenom: "TOKEN",
coinMinimalDenom: "utoken",
coinDecimals: 6,
},
],
feeCurrencies: [
{
coinDenom: "TOKEN",
coinMinimalDenom: "utoken",
coinDecimals: 6,
gasPriceStep: { low: 0.01, average: 0.025, high: 0.04 },
},
],
stakeCurrency: {
coinDenom: "TOKEN",
coinMinimalDenom: "utoken",
coinDecimals: 6,
},
});
await provider.disconnect();

Msg Sign

Amino signature

Amino is suitable for Cosmos transactions that still use traditional encoding:

const chainId = "cosmoshub-4";
const signer = "cosmos1demoaccount...";

const signDoc = {
chain_id: chainId,
account_number: "0",
sequence: "0",
fee: {
amount: [{ denom: "uatom", amount: "5000" }],
gas: "200000",
},
msgs: [
{
type: "cosmos-sdk/MsgSend",
value: {
from_address: signer,
to_address: "cosmos1demoaccount...",
amount: [{ denom: "uatom", amount: "1000000" }],
},
},
],
memo: "",
};

const callResult = await provider.signAmino(chainId, signer, signDoc);

console.log({
signed: callResult.signed, // Note: Signed document
signature: callResult.signature, // Example response: { pub_key, signature }
});

Direct signature (Protobuf)

Direct signature is suitable for modern Protobuf encoding transactions and is also the more common method for most new accesses:

import { makeSignDoc } from "@cosmjs/proto-signing";

const chainId = "cosmoshub-4";
const signer = "cosmos1demoaccount...";

const signDoc = makeSignDoc(
bodyBytes, // Note: trading body
authInfoBytes, // Note: Authorization information including handling fee
chainId,
accountNumber,
);

const callResult = await provider.signDirect(chainId, signer, signDoc);

console.log({
signed: callResult.signed,
signature: callResult.signature,
});

Sign arbitrary data

Arbitrary message signatures are suitable for login authentication or off-chain attestation. Add domain name, nonce and timestamp to the message:

const chainId = "cosmoshub-4";
const signer = "cosmos1demoaccount...";
const data = "Login to MyApp at 2024-01-01T00:00:00Z";

const signature = await provider.signArbitrary(chainId, signer, data);

// Validate signature
const isValid = await provider.verifyArbitrary(
chainId,
signer,
data,
signature,
);
console.log("Signature check passed:", isValid);

Send tx

broadcast deal

const chainId = 'cosmoshub-4'
const txBytes = new Uint8Array([...]) // Note: Signed transaction bytes

// Available broadcast modes: 'block', 'sync', 'async'
const callResult = await provider.sendTx(chainId, txBytes, 'sync')

console.log('Tx hash:', callResult)

Offline Signer

You can get the offline signer from Provider and then hand it over to CosmJS to construct and send the transaction:

import { SigningStargateClient } from "@cosmjs/stargate";

const chainId = "cosmoshub-4";

// Note: Automatically detect the best signer type
const offlineSigner = await provider.getOfflineSignerAuto(chainId);

// Note: or use a specific signer type
const aminoSigner = provider.getOfflineSignerOnlyAmino(chainId);
const directSigner = provider.getOfflineSigner(chainId);

// Note: Use with CosmJS
const client = await SigningStargateClient.connectWithSigner(
"https://rpc.cosmos.network",
offlineSigner,
);

// Note: Send tokens
const callResult = await client.sendTokens(
senderAddress,
recipientAddress,
[{ denom: "uatom", amount: "1000000" }],
{ amount: [{ denom: "uatom", amount: "5000" }], gas: "200000" },
);

API Notes

Methods

MethodDetails
enable(chainIds)Enable the chain and get key information
disable(chainIds)Disable chain
disconnect()Disconnect all chains
getKey(chainId)Get the account key of the chain
signAmino(chainId, signer, signDoc)Sign Amino encoded transactions
signDirect(chainId, signer, signDoc)Sign Protobuf-encoded transactions
sendTx(chainId, tx, mode)Broadcast a signed transaction
signArbitrary(chainId, signer, data)Sign any message
verifyArbitrary(chainId, signer, data, signature)Verify signature
experimentalSuggestChain(chainInfo)Add a custom chain
getOfflineSigner(chainId)Get the Direct offline signer
getOfflineSignerOnlyAmino(chainId)Get the Amino-only offline signer
getOfflineSignerAuto(chainId)Automatically detect the best signer type

Key interface

interface Key {
name: string; // Note: human readable name
algo: string; // Note: Signature algorithm
pubKey: Uint8Array; // Public key bytes
address: Uint8Array; // Note: address byte
bech32Address: string; // Note: Bech32 format address
isNanoLedger: boolean; // whether this comes from a hardware wallet
isKeystone: boolean; // whether the device is a Keystone wallet
}

Chain List

NetworkChain IDNative support
Cosmos Hubcosmoshub-4yes
Osmosisosmosis-1yes
Junojuno-1yes
Stargazestargaze-1yes
Akashakashnet-2yes
Secret Networksecret-4yes
User-defined chainAny chain IDAdd it with experimentalSuggestChain

Handle Errors

try {
await provider.enable("cosmoshub-4");
} catch (error) {
if (error.code === 4001) {
console.log("The user declined the request");
} else if (error.message.includes("not supported")) {
console.log("This chain is unsupported; try experimentalSuggestChain instead");
} else {
console.error("Unable to connect:", error);
}
}

Migrate from Keplr

UKey Wallet Cosmos Provider is compatible with the Keplr interface. During migration, UKey Wallet is read first, and then falls back to Keplr if it is not installed:

// 旧写法(仅 Keplr)
const keplrProvider = window.keplr;

// Updated flow: prefer UKey Wallet first, then fall back to Keplr
const cosmosProvider = window.$ukey?.cosmos || keplrProvider;