# Encoding, Signing, and Broadcasting transactions with CosmJS By default, [CosmJS](https://github.com/cosmos/cosmjs) builds, signs, and broadcasts a transactions in a single function call. Often, it's useful to separate these steps. This gist explores a simple way of doing so in TypeScript, and may also be useful for those wanting to dive deeper into how Cosmos messages are composed and signed. ## Setup You will need a few dependencies: - [cosmwasm](https://www.npmjs.com/package/cosmwasm): which is a wrapper package for all of the [CosmJS packages](https://cosmos.github.io/cosmjs/) - [cosmjs-types](https://www.npmjs.com/package/cosmjs-types): which contains helpers for encoding and decoding protobuf messages. You can install these with `npm` or yarn: ```sh npm i cosmwasm cosmjs-types # OR yarn add cosmwasm cosmjs-types ``` ## High level overview of steps ##### 1. Creating and encoding protobuf messages Cosmos messages are encoded as [protobufs](https://protobuf.dev/) so to create a transaction we'll first need to encode a protobuf message. [Telescope](https://github.com/osmosis-labs/telescope) is a TypeScript Transpiler for Cosmos Protobufs. It can be used to efficiently generate protobuf message and will save you lots of time. However, we'll be doing it the manual way with `cosmjs-types`. NOTE: Cosmos chains also support an older form of encoding known as [amino](https://cosmos.github.io/cosmjs/latest/amino/index.html) that is used primarily with ledger devices. ### Signing with a signing client Signing a transaction needs to be done with a private key or signer. To do this we'll create a [SigningStargateClient](https://cosmos.github.io/cosmjs/latest/stargate/classes/SigningStargateClient.html) or [SigningCosmWasmClient](https://cosmos.github.io/cosmjs/latest/cosmwasm-stargate/classes/SigningCosmWasmClient.html) (which is mostly the same plus a great interface for working with [CosmWasm](https://cosmwasm.com) smart contracts on chains like [Juno Network](http://junonetwork.io)). Note: the signing client doesn't have to be online, the is a `signingClient.offline()` method demonstrated in the code example below. For CosmJS, signers MUST implement the [OfflineSigner interface](https://cosmos.github.io/cosmjs/latest/proto-signing/interfaces/OfflineDirectSigner.html). For an example of this, see the [DirectSecp256k1HdWallet implementation](https://github.com/cosmos/cosmjs/blob/main/packages/proto-signing/src/directsecp256k1hdwallet.ts) in the [cosmjs repo](https://github.com/cosmos/cosmjs). Some example signers include: - Wallets like Keplr which use the [proto-signing](https://cosmos.github.io/cosmjs/latest/proto-signing/index.html) - Hardware wallets like Ledger (see [@cosmjs/ledger-amino package](https://cosmos.github.io/cosmjs/latest/ledger-amino/index.html)) We'll demonstate creating a wallet purley in code below. See [cosmos-kit](https://github.com/cosmology-tech/cosmos-kit) if you're interested in working with third party wallets. ### Broadcasting After creating and signing the transaction, we need to broadcast it to the chain via an RPC node, for this we'll use a [CosmwasmClient]() ## TypeScript code example NOTE: Many more code examples for all sorts of things exist in [CosmJS tests](https://github.com/cosmos/cosmjs) for the various packages. ```typescript // Import needed dependencies from the cosmwasm package import { coins, DirectSecp256k1HdWallet, SigningCosmWasmClient } from "cosmwasm"; // Import protobuf helpers from cosmjs-types // Note: this the manual way of doing this, Telescope provides much // nicer tooling for working with chain protobufs import { MsgSend } from "cosmjs-types/cosmos/bank/v1beta1/tx"; import { TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx"; // Create a Secp256k1 wallet manually // Note: there other ways to create a wallet, such as getting an OfflineDirectSigner from Keplr // or using the @cosmjs/ledger-amino package. Wallets must implement the OfflineSigner interface. // See: https://cosmos.github.io/cosmjs/latest/proto-signing/interfaces/OfflineDirectSigner.html const wallet = await DirectSecp256k1HdWallet.fromMnemonic( "enlist hip relief stomach skate base shallow young switch frequent cry park", { prefix: "juno" } ); // Create a client connected an RPC endpoint const client = await SigningCosmWasmClient.connect( "https://rpc.junonetwork.io", ); // Create an offline client for signing the transaction const offline = await SigningCosmWasmClient.offline(wallet); // Get the account address const account = await wallet.getAccounts(); // Encode a send message. const msg = { typeUrl: "/cosmos.bank.v1beta1.MsgSend", value: MsgSend.fromPartial({ fromAddress: account[0].address, toAddress: "juno1xyz...", amount: coins(1234, "ujuno"), }), }; const fee = { amount: coins(2000, "ujuno"), gas: "200000", }; const memo = "Use your tokens wisely"; // Sign a message const signed = await offline?.sign(account[0].address, [msg], fee, memo); // Broadcast the transaction the transaction, note it must be encode as raw protobuf transaction client .broadcastTx(Uint8Array.from(TxRaw.encode(signed).finish())) .then((res) => { console.log(res); }); ``` ## Other tools and resources - [telescope](https://github.com/osmosis-labs/telescope): awesome tooling for working with Cosmos chain protobufs - [cosmos-kit](https://github.com/cosmology-tech/cosmos-kit): a library for connecting to multiple wallets and a bunch of other stuff - [create-cosmos-app](https://github.com/cosmology-tech/create-cosmos-app): Easily create a cosmos frontend application - [@cosmjs packages](https://cosmos.github.io/cosmjs/): the complete list of `cosmjs` packages