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);