Utilities for encoding and decoding public keys between Amino JSON format and protobuf Any format. These functions handle the conversion between different public key representations used in Cosmos SDK applications.
Convert public keys from Amino JSON format to protobuf Any format.
/**
* Takes a pubkey in the Amino JSON object style (type/value wrapper)
* and converts it into a protobuf Any
* This is the reverse operation to decodePubkey
* @param pubkey - Public key in Amino format
* @returns Public key as protobuf Any
*/
function encodePubkey(pubkey: Pubkey): Any;Usage Examples:
import { encodePubkey } from "@cosmjs/proto-signing";
import { toBase64 } from "@cosmjs/encoding";
// Encode secp256k1 public key
const secp256k1Pubkey = {
type: "tendermint/PubKeySecp256k1",
value: toBase64(publicKeyBytes), // base64-encoded public key
};
const encodedSecp256k1 = encodePubkey(secp256k1Pubkey);
// Encode ed25519 public key
const ed25519Pubkey = {
type: "tendermint/PubKeyEd25519",
value: toBase64(publicKeyBytes),
};
const encodedEd25519 = encodePubkey(ed25519Pubkey);
// Encode multisig public key
const multisigPubkey = {
type: "tendermint/PubKeyMultisigThreshold",
value: {
threshold: "2",
pubkeys: [secp256k1Pubkey, ed25519Pubkey],
},
};
const encodedMultisig = encodePubkey(multisigPubkey);Convert public keys from protobuf Any format back to Amino JSON format.
/**
* Decodes a pubkey from protobuf Any into Amino JSON format
* Handles both single pubkeys and multisig pubkeys
* @param pubkey - Public key as protobuf Any
* @returns Public key in Amino format
*/
function decodePubkey(pubkey: Any): Pubkey;
/**
* Decodes a single pubkey (i.e. not a multisig pubkey) from Any into SinglePubkey
* In most cases you probably want to use decodePubkey
* @param pubkey - Single public key as protobuf Any
* @returns Single public key in Amino format
*/
function anyToSinglePubkey(pubkey: Any): SinglePubkey;
/**
* Decodes an optional pubkey, handling null/undefined cases
* @param pubkey - Optional public key as protobuf Any
* @returns Public key in Amino format or null
*/
function decodeOptionalPubkey(pubkey: Any | null | undefined): Pubkey | null;Usage Examples:
import { decodePubkey, decodeOptionalPubkey, anyToSinglePubkey } from "@cosmjs/proto-signing";
// Decode a public key from protobuf Any
const anyPubkey = {
typeUrl: "/cosmos.crypto.secp256k1.PubKey",
value: encodedPublicKeyBytes,
};
const aminoPubkey = decodePubkey(anyPubkey);
console.log(aminoPubkey.type); // "tendermint/PubKeySecp256k1"
console.log(aminoPubkey.value); // base64-encoded key
// Decode optional pubkey (handles null/undefined)
const optionalPubkey = decodeOptionalPubkey(maybeNullPubkey);
if (optionalPubkey) {
console.log("Pubkey found:", optionalPubkey.type);
} else {
console.log("No pubkey provided");
}
// Decode single pubkey (not multisig)
const singlePubkey = anyToSinglePubkey(anyPubkey);
// Returns SinglePubkey (excludes multisig types)The library supports the following public key types:
// Amino format
{
type: "tendermint/PubKeySecp256k1",
value: "base64-encoded-33-byte-compressed-pubkey"
}
// Protobuf Any format
{
typeUrl: "/cosmos.crypto.secp256k1.PubKey",
value: /* encoded CosmosCryptoSecp256k1Pubkey */
}// Amino format
{
type: "tendermint/PubKeyEd25519",
value: "base64-encoded-32-byte-pubkey"
}
// Protobuf Any format
{
typeUrl: "/cosmos.crypto.ed25519.PubKey",
value: /* encoded CosmosCryptoEd25519Pubkey */
}// Amino format
{
type: "tendermint/PubKeyMultisigThreshold",
value: {
threshold: "2", // string representation
pubkeys: [
{ type: "tendermint/PubKeySecp256k1", value: "..." },
{ type: "tendermint/PubKeyEd25519", value: "..." },
]
}
}
// Protobuf Any format
{
typeUrl: "/cosmos.crypto.multisig.LegacyAminoPubKey",
value: /* encoded LegacyAminoPubKey */
}type Pubkey = SinglePubkey | MultisigThresholdPubkey;
interface SinglePubkey {
/** Public key type identifier */
readonly type: string;
/** Base64-encoded public key value */
readonly value: string;
}
interface MultisigThresholdPubkey {
readonly type: "tendermint/PubKeyMultisigThreshold";
readonly value: {
/** Threshold as string (e.g., "2") */
readonly threshold: string;
/** Array of public keys */
readonly pubkeys: readonly Pubkey[];
};
}
interface Any {
/** Type URL identifying the message type */
typeUrl: string;
/** Serialized message value */
value: Uint8Array;
}import {
encodePubkey,
decodePubkey,
DirectSecp256k1HdWallet
} from "@cosmjs/proto-signing";
import { toBase64, fromBase64 } from "@cosmjs/encoding";
// Create wallet and get account
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic);
const accounts = await wallet.getAccounts();
const account = accounts[0];
// Create Amino format pubkey
const aminoPubkey = {
type: "tendermint/PubKeySecp256k1",
value: toBase64(account.pubkey),
};
// Encode to protobuf Any format
const protobufPubkey = encodePubkey(aminoPubkey);
console.log("Protobuf type URL:", protobufPubkey.typeUrl);
console.log("Protobuf value length:", protobufPubkey.value.length);
// Decode back to Amino format
const decodedPubkey = decodePubkey(protobufPubkey);
console.log("Decoded type:", decodedPubkey.type);
console.log("Decoded value:", decodedPubkey.value);
// Verify round-trip encoding
const originalBytes = fromBase64(aminoPubkey.value);
const decodedBytes = fromBase64(decodedPubkey.value);
console.log("Round-trip successful:",
originalBytes.every((byte, i) => byte === decodedBytes[i])
);
// Create multisig pubkey
const multisigPubkey = encodePubkey({
type: "tendermint/PubKeyMultisigThreshold",
value: {
threshold: "2",
pubkeys: [
aminoPubkey,
{ type: "tendermint/PubKeyEd25519", value: "base64-ed25519-key" }
],
},
});
const decodedMultisig = decodePubkey(multisigPubkey);
console.log("Multisig threshold:", decodedMultisig.value.threshold);
console.log("Multisig pubkey count:", decodedMultisig.value.pubkeys.length);