Skip to content

What can CosmJS do for me?

Simon Warta edited this page Apr 13, 2021 · 15 revisions

How do I...

  • Create various unsigned Cosmos Hub transactions?
  • Sign an unsigned transaction when I have a mnemonic phrase? (12 word? 24 word?)
  • Sign an unsigned transaction when I have a private key?
  • Submit a signed transaction to a Cosmos Hub endpoint?
  • Create a multi-sig signature on an unsigned transaction?
  • Query state from a Cosmos Hub module using the legacy REST endpoint?
  • Query state from a Cosmos Hub module using the gRPC endpoint?
  • Query state from a custom module using the legacy REST endpoint?
  • Query state from a custom module using the gRPC endpoint?
  • Make it easier to submit multiple messages in a single transaction?

Calculating transaction IDs

If you have a list of complete transactions like this

{
  "txs": [
    "9AEoKBapCjCMTXENChQmiMbn/hEgc2noEV+vJkHASIhPShIUU7SyT3IQK/OJv+xZUz5LP9dR4FQKPpIdLk4KFCaIxuf+ESBzaegRX68mQcBIiE9KEhRTtLJPchAr84m/7FlTPks/11HgVBoMCgV1YXRvbRIDMTQ1EhAKCgoFdWF0b20SATAQ4KcSGmoKJuta6YchA9E/2C2Tibu+oguuOS2AwO9sGwy1ejes+u8hBdGJ2guiEkBZ7JjaZhENW56nbqaUH0SdgnuWHmPlPfgWs2LVwbOj6BDacUL+vcKqd4vxmkYRB9ORmqnDlj9ppaupmIPnOQuK",
    "ywEoKBapCkWoo2GaChQxrczb/flZmTC8mDh3uKwKyZCnpRIUWYCZ0lvC4PM8HrDaaR1oSU65PLoaEwoFdWF0b20SCjM4MDQwMDAwMDASEgoMCgV1YXRvbRIDNzUwEMCaDBpqCibrWumHIQMgfOISgYzdsLJnQtnhdT6c+pd1cZX0iiaWLE2i+Fa6xBJAIvmDdjJstWPWqshZxCtMXWXL1CBw06a9oYH8f2l7f19I5RsDDYJz1QTnKwor765rLsdAcF+5ucCBnkUnvy7I+g==",
    "twEoKBapCjCMTXENChQkQV2iWcShdar5UshUoWev/JUSfxIUyTRRx8hJmGRpUL1G+yw8xXQRSHsSEwoNCgV1YXRvbRIEMjUwMBDAzyQaagom61rphyEC1bbqM5eBuRSZ/jeQH1o25g7ybaQw3BlY4zQWmJb+k2QSQOSikSCd7AkDDjeCoNwdhdwgEOPiIZIHzF8TCSQSVdA/Iru/g9xE5eZTA4Cg2Q48idWyIHadYME5cKhVm3S8lHw=",
    "4gIoKBapCkOSHS5OChQ9NPQdHwRlRIc1MUP7Vy+gGRKtixIUYmtWnpmEfXd8qa3Khj8v1Xb//7oaEQoFdWF0b20SCDEwMDAwMDAwCkOSHS5OChQ9NPQdHwRlRIc1MUP7Vy+gGRKtixIUppAElPH3PNriuvHIuI/1/AuKM5waEQoFdWF0b20SCDEwMDAwMDAwCkOSHS5OChQ9NPQdHwRlRIc1MUP7Vy+gGRKtixIUyTRRx8hJmGRpUL1G+yw8xXQRSHsaEQoFdWF0b20SCDEwMDAwMDAwEhQKDgoFdWF0b20SBTIxODc5EJS1NRpqCibrWumHIQIT+U7tHv1kX5BoKGClAbKOf4nTI32tfFVX+AnedBYFnhJA/AedifYkknYTGcztoNn3VH7gMpeJXGsUxydWUMJ6wC8IT8uV5UWeHdmW0HbVsjRSxyKPDO+NLJbO35zwb1cT5CILTGVkZ2VyIExpdmU="
  ]
}

(from Cosmos Hub height 2421996), you can calculate a transaction ID like this:

import { sha256 } from "@cosmjs/crypto";
import { fromBase64, toHex } from "@cosmjs/encoding";

const tx = "9AEoKBapCjCMTXENChQmiMbn/hEgc2noEV+vJkHASIhPShIUU7SyT3IQK/OJv+xZUz5LP9dR4FQKPpIdLk4KFCaIxuf+ESBzaegRX68mQcBIiE9KEhRTtLJPchAr84m/7FlTPks/11HgVBoMCgV1YXRvbRIDMTQ1EhAKCgoFdWF0b20SATAQ4KcSGmoKJuta6YchA9E/2C2Tibu+oguuOS2AwO9sGwy1ejes+u8hBdGJ2guiEkBZ7JjaZhENW56nbqaUH0SdgnuWHmPlPfgWs2LVwbOj6BDacUL+vcKqd4vxmkYRB9ORmqnDlj9ppaupmIPnOQuK";
const transactionHash = sha256(fromBase64(tx));
const transactionId = toHex(transactionHash).toUpperCase();
console.log(transactionId); // 697D4B1394AEFB95676E775236600D2A60FC87593114316DA4238EE0DEC1EC88

Deriving a Tendermint address from a consensus pubkey

Given a consensus pubkey like coralvalconspub1zcjduepqafdn8uprnsr35ptz653409ar3ft6uuu065f33f42fee67s67k3lqud5zqu, this derives an address in the Tendermint format. This is used e.g. in "proposer_address": "A8C66A16AC1FF07B390504D0DB211128440754F1" from /blockchain of Tendermint RPC.

import { sha256 } from "@cosmjs/crypto";
import { fromBase64, toHex } from "@cosmjs/encoding";
import { decodeBech32Pubkey } from "@cosmjs/launchpad";

const pubkey = decodeBech32Pubkey(
  "coralvalconspub1zcjduepqafdn8uprnsr35ptz653409ar3ft6uuu065f33f42fee67s67k3lqud5zqu",
);
const addressData = sha256(fromBase64(pubkey.value)).slice(0, 20);
const address = toHex(addressData).toUpperCase();
console.log(address); // 0C0A3D4E86CD4B104BF2972851647161074D1BB8

Derive valconspub and valcons from base64 encoded pubkey

The *valconspub1* identifiers are bech32 encoded Amino pubkeys. Usually Ed25519 is used for consensus (=Tendermint) keypairs. But this can change. *valcons1* are bech32 encoded Tendermint addresses, which are derived differently than Cosmos SDK addresses.

import { sha256 } from "@cosmjs/crypto";
import { Bech32, fromBase64 } from "@cosmjs/encoding";
import { encodeBech32Pubkey } from "@cosmjs/launchpad";

// Ed25519 pubkey from genesis
const pubkey = {
  type: "tendermint/PubKeyEd25519",
  value: "iARPJIXVwen//D6qB5CoQT1KrTK7ffGOkIstFF3KIgk=",
};

const bech32Pubkey = encodeBech32Pubkey(pubkey, "regen:valconspub");
console.log(bech32Pubkey); // regen:valconspub1zcjduepq3qzy7fy96hq7nllu864q0y9ggy754tfjhd7lrr5s3vk3ghw2ygyspmhej4

const ed25519PubkeyRaw = fromBase64(pubkey.value);
const addressData = sha256(ed25519PubkeyRaw).slice(0, 20);
const bech32Address = Bech32.encode("regen:valcons", addressData);
console.log(bech32Address); // regen:valcons14y3uv3g3fp5k473qtdenmn5cv89y2s5nz7cshu

Derive Ethereum public key from private key

import { fromHex, toHex } from "@cosmjs/encoding";
import { keccak256, Secp256k1 } from "@cosmjs/crypto";

const privkey = fromHex("1da6847600b0ee25e9ad9a52abbd786dd2502fa4005dd5af9310b7cc7a3b25db");
const keypair = await Secp256k1.makeKeypair(privkey);
toHex(keypair.pubkey) // 04b9e72dfd423bcf95b3801ac93f4392be5ff22143f9980eb78b3a860c4843bfd04829ae61cdba4b3b1978ac5fc64f5cc2f4350e35a108a9c9a92a81200a60cd64

const compressed = Secp256k1.compressPubkey(keypair.pubkey);
toHex(compressed) // 02b9e72dfd423bcf95b3801ac93f4392be5ff22143f9980eb78b3a860c4843bfd0

const address = `0x${toHex(keccak256(keypair.pubkey.slice(1)).slice(-20))}`; // 0x71cb05ee1b1f506ff321da3dac38f25c0c9ce6e1
Clone this wiki locally