-
Notifications
You must be signed in to change notification settings - Fork 403
What can CosmJS do for me?
- 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?
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); // 697D4B1394AEFB95676E775236600D2A60FC87593114316DA4238EE0DEC1EC88Given a secp256k1 public key, this gives you a Cosmos Hub address:
import { pubkeyToAddress } from "@cosmjs/amino";
const pubkey = {
type: "tendermint/PubKeySecp256k1",
value: "AtQaCqFnshaZQp6rIkvAPyzThvCvXSDO+9AzbxVErqJP",
};
const address = pubkeyToAddress(pubkey, "cosmos");
console.log(address); // cosmos1h806c7khnvmjlywdrkdgk2vrayy2mmvf9rxk2rGiven 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); // 0C0A3D4E86CD4B104BF2972851647161074D1BB8The *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:valcons14y3uv3g3fp5k473qtdenmn5cv89y2s5nz7cshuimport { 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))}`; // 0x71cb05ee1b1f506ff321da3dac38f25c0c9ce6e1Cosmos SDK expects compressed secp256k1 public keys. Those are 33 bytes long, starting with 0x02 or 0x03. If you have an uncompressed pubkey key from an external source, you con compress it.
import { fromHex, toHex } from "@cosmjs/encoding";
import { Secp256k1 } from "@cosmjs/crypto";
// Uncompressed format (65 bytes, starting with 0x04)
const pubkey = fromHex("044f04181eeba35391b858633a765c4a0c189697b40d216354d50890d350c7029013b587a681e836cc187a8164b98a5848a2b89b3173315fdd0740d5032e259cd5");
const compressed = Secp256k1.compressPubkey(pubkey);
console.log(toHex(compressed)); // 034f04181eeba35391b858633a765c4a0c189697b40d216354d50890d350c70290Given a delegation rewards response like
{
rewards: [
{
validatorAddress: 'junovaloper1juczud9nep06t0khghvm643hf9usw45r23gsmr',
reward: [Array]
}
],
total: [ { denom: 'ujuno', amount: '1519872422095573900000' } ]
}
you can use CosmJS to parse the amount in a human readable representation without loosing precision as follows:
import { Decimal } from "@cosmjs/math";
const amount = Decimal.fromAtomics("1519872422095573900000", 18);
console.log(amount.toString()); // "1519.8724220955739"
console.log(amount.atomics); // "1519872422095573900000"
console.log(amount.fractionalDigits); // 18
console.log(amount.toFloatApproximation()); // 1519.872422095574 (please note the rounding in the last position!)