Utilities for protobuf based signing (Cosmos SDK 0.40+)
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Direct signing utilities for creating signing documents and authentication information for Cosmos SDK transactions. These functions support the direct signing mode (ADR-020) using protobuf serialization.
Create and serialize signing documents for Cosmos SDK transactions.
/**
* Creates a SignDoc for transaction signing
* @param bodyBytes - Serialized transaction body
* @param authInfoBytes - Serialized authentication info
* @param chainId - Chain identifier (e.g., "cosmoshub-4")
* @param accountNumber - Account number from the blockchain
* @returns SignDoc ready for signing
*/
function makeSignDoc(
bodyBytes: Uint8Array,
authInfoBytes: Uint8Array,
chainId: string,
accountNumber: number
): SignDoc;
/**
* Creates the bytes that need to be signed from a SignDoc
* @param signDoc - The signing document
* @returns Serialized bytes for signing
*/
function makeSignBytes(signDoc: SignDoc): Uint8Array;Usage Examples:
import { makeSignDoc, makeSignBytes } from "@cosmjs/proto-signing";
import { TxBody, AuthInfo } from "cosmjs-types/cosmos/tx/v1beta1/tx";
// Create transaction body and auth info (simplified example)
const txBody = TxBody.fromPartial({
messages: [/* your messages */],
memo: "My transaction",
});
const bodyBytes = TxBody.encode(txBody).finish();
const authInfo = AuthInfo.fromPartial({
signerInfos: [/* signer info */],
fee: { amount: [], gasLimit: BigInt(200000) },
});
const authInfoBytes = AuthInfo.encode(authInfo).finish();
// Create signing document
const signDoc = makeSignDoc(
bodyBytes,
authInfoBytes,
"cosmoshub-4",
123 // account number
);
// Get bytes to sign
const signBytes = makeSignBytes(signDoc);
// Sign with wallet
const signature = await wallet.signDirect(signerAddress, signDoc);Create authentication information containing signer details and fee information.
/**
* Creates and serializes an AuthInfo document
* This implementation does not support different signing modes for different signers
* @param signers - Array of signer information with public keys and sequence numbers
* @param feeAmount - Array of fee amounts in various denominations
* @param gasLimit - Gas limit for the transaction
* @param feeGranter - Optional fee granter address
* @param feePayer - Optional fee payer address
* @param signMode - Signing mode, defaults to SIGN_MODE_DIRECT
* @returns Serialized AuthInfo bytes
*/
function makeAuthInfoBytes(
signers: ReadonlyArray<{ readonly pubkey: Any; readonly sequence: bigint | number }>,
feeAmount: readonly Coin[],
gasLimit: number,
feeGranter: string | undefined,
feePayer: string | undefined,
signMode?: SignMode
): Uint8Array;Usage Examples:
import { makeAuthInfoBytes, encodePubkey } from "@cosmjs/proto-signing";
import { coins } from "@cosmjs/amino";
import { SignMode } from "cosmjs-types/cosmos/tx/signing/v1beta1/signing";
// Prepare signer information
const account = (await wallet.getAccounts())[0];
const pubkeyAny = encodePubkey({
type: "tendermint/PubKeySecp256k1",
value: toBase64(account.pubkey),
});
const signers = [{
pubkey: pubkeyAny,
sequence: 42, // Current account sequence
}];
// Create auth info
const authInfoBytes = makeAuthInfoBytes(
signers,
coins(5000, "uatom"), // Fee amount
200000, // Gas limit
undefined, // No fee granter
undefined, // No fee payer
SignMode.SIGN_MODE_DIRECT
);Support for advanced fee payment scenarios including third-party fee payment.
// Fee granter example - someone else pays fees
const authInfoWithGranter = makeAuthInfoBytes(
signers,
coins(5000, "uatom"),
200000,
"cosmos1feeGranterAddress...", // Fee granter pays
undefined,
SignMode.SIGN_MODE_DIRECT
);
// Fee payer example - explicit fee payer
const authInfoWithPayer = makeAuthInfoBytes(
signers,
coins(5000, "uatom"),
200000,
undefined,
"cosmos1feePayerAddress...", // Explicit fee payer
SignMode.SIGN_MODE_DIRECT
);interface SignDoc {
/** Serialized transaction body bytes */
bodyBytes: Uint8Array;
/** Serialized auth info bytes */
authInfoBytes: Uint8Array;
/** Chain identifier */
chainId: string;
/** Account number from blockchain state */
accountNumber: bigint;
}
interface Coin {
/** Denomination (e.g., "uatom", "stake") */
denom: string;
/** Amount as string */
amount: string;
}
interface Any {
/** Type URL identifying the message type */
typeUrl: string;
/** Serialized message value */
value: Uint8Array;
}
enum SignMode {
/** Direct signing mode using protobuf serialization */
SIGN_MODE_DIRECT = 1,
/** Legacy amino signing mode */
SIGN_MODE_LEGACY_AMINO_JSON = 127,
}import {
DirectSecp256k1HdWallet,
makeSignDoc,
makeAuthInfoBytes,
Registry,
encodePubkey
} from "@cosmjs/proto-signing";
import { TxBody } from "cosmjs-types/cosmos/tx/v1beta1/tx";
import { MsgSend } from "cosmjs-types/cosmos/bank/v1beta1/tx";
import { coins, toBase64 } from "@cosmjs/amino";
// 1. Create wallet and get account
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic);
const accounts = await wallet.getAccounts();
const signerAddress = accounts[0].address;
// 2. Create transaction body
const registry = new Registry();
registry.register("/cosmos.bank.v1beta1.MsgSend", MsgSend);
const sendMsg = {
fromAddress: signerAddress,
toAddress: "cosmos1recipient...",
amount: coins(1000000, "uatom"),
};
const txBody = TxBody.fromPartial({
messages: [registry.encode({ typeUrl: "/cosmos.bank.v1beta1.MsgSend", value: sendMsg })],
memo: "Sent via @cosmjs/proto-signing",
});
const bodyBytes = TxBody.encode(txBody).finish();
// 3. Create auth info
const pubkeyAny = encodePubkey({
type: "tendermint/PubKeySecp256k1",
value: toBase64(accounts[0].pubkey),
});
const authInfoBytes = makeAuthInfoBytes(
[{ pubkey: pubkeyAny, sequence: 42 }],
coins(5000, "uatom"), // Fee
200000, // Gas limit
undefined, // Fee granter
undefined // Fee payer
);
// 4. Create and sign
const signDoc = makeSignDoc(bodyBytes, authInfoBytes, "cosmoshub-4", 123);
const signResponse = await wallet.signDirect(signerAddress, signDoc);
console.log("Signature:", signResponse.signature);
console.log("Signed doc:", signResponse.signed);