Skip to main content

Signing

This walkthrough covers how to sign Amino transactions, Direct transactions, arbitrary messages, and Cosmos ecological chain data that supports Ethereum signatures through UKey Wallet Cosmos Provider.


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: Certification 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

signArbitrary can be used for login authentication or off-chain message verification. Add domain name, nonce and timestamp to the message:

const chainId = "cosmoshub-4";
const signer = "cosmos1demoaccount...";
const data = "MyApp login time: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);

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)

Signed Ethereum data

Some Cosmos ecological chains support Ethereum-style signatures, such as Evmos:

const callResult = await provider.signEthereum(
chainId,
signer,
data, // Note: message to sign
"message", // allowed values: 'message' | 'transaction'
);

console.log("Generated signature:", callResult);

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("That chain is unsupported; try experimentalSuggestChain instead");
} else {
console.error("Unable to connect:", error);
}
}