Tutorial : How-to Cosmos Pt. 3- Sending a Signed Tx on Cosmos hub using Cosmjs

KagemniKarimu
Lava Network
Published in
8 min readMay 29, 2023

Hello Cosmonauts! ⚛️

We return to our blog series “Cosmos How-Tos.” To see the previous installment in this series click here!

CosmJS is a modular TypeScript/JavaScript library of npm packages for developers to use in front end and back end dApp development. Cosmjs consists of 21 different packages which can be imported separately for individual use; it is highly modular and uses only a clean dependency tree. Although it is a part of the CosmosSDK — it is more geared towards users who will be building more ‘traditional’ web apps and dApps that would have front-ends written for the browser.

According to the documentation available on Cosmjs, the most commonly used packages are @cosmjs/stargate and @cosmjs/encoding, as many basic feats on a dApp can be accomplished using only these two packages. In practice, you’ll find that the packages you decide to import vary greatly depending on the needs of a given project. There is even variance amongst which packages are best to use to accomplish the same thing!

In this tutorial, I will walk you through the process of building and signing a transaction on the Cosmos Hub using Cosmjs. We assume you already have Node.js installed on your system. If not, please visit the Node.js website (https://nodejs.org/) to download and install the appropriate version for your operating system. Also, it is assumed that you have some familiarity with the Cosmos ecosystem! Because of this, we highly recommend that you start from Part 1 or Part 2 of this series before beginning this tutorial — but if you insist on continuing you must do so at your own risk!

Before beginning, there are a number of packages that you should be familiar with in Cosmjs:

A complete look at all the implemented methods and interfaces is available here: https://cosmos.github.io/cosmjs/

You’ll need the following to continue

node.js installed on a Linux machine

✅ Familiarity with basic concepts such as those covered in v1 & v2 of this series

✅ Access to a funded wallet/wallet(s) on Cosmos Hub Testnet

1. Installing Cosmjs

First, create a new directory for your project and navigate to it using the terminal:

mkdir cosmos-sendtx
cd cosmos-sendtx

Now, initialize a new Node.js project:

npm init -y

Next, install the required Cosmjs packages:

npm install @cosmjs/stargate @cosmjs/proto-signing @cosmjs/encoding @cosmjs/amino

You can investigate the package-lock.json file to learn more about the installed dependencies and their structure.

2. Setup Your Environment

From the command line within the created directory, create a new JavaScript file called cosmos-tx.js:

touch cosmos-tx.js

Basic Requirements

At the top of your file, make sure to require a couple of dependencies. We’re keeping it rather light and relying only on a few pieces from cosmjs/stargate, cosmjs/proto-signing, cosmjs/encoding, and cosmjs/amino. Add the following to the top of your cosmos-tx.js file:

const { SigningStargateClient, coins, GasPrice } = require(‘@cosmjs/stargate’);
const { DirectSecp256k1Wallet } = require(‘@cosmjs/proto-signing’);
const { toBech32 } = require(‘@cosmjs/encoding’);
const { rawSecp256k1PubkeyToRawAddress } = require(“@cosmjs/amino”);

SigningStargateClient coins and GasPrice will be used to formulate, sign and broadcast our transaction. DirectSecp256k1Wallet will be used to handle our keys. Finally, toBech32 and rawSecp256k1PubkeyToRawAddress are used simply to make our addresses human readable!

Environmental Variables

It is very, very bad practice to load any part of your seed phrase/private key into your code plain text. If anyone is able to see your code for any reason(s), they will be able to easily snoop your keys and control your wallet. Remember 🔑 Not Your Key = Not Your Crypto ❗ As such, we will be avoiding this approach entirely and using an Environmental Variables combined with the dotenv package to accomplish the feat. Please note that extracting secrets from code is best practice, but you should be sure not to share the .env file we create with any collaborators and never push it to a public repository.

First, we need to make sure dotenv is installed. If you’re unaware, dotenv is a very useful zero-dependency module that can be used to load environment variables from a .env file and then make them available in your Node.js application through the [process.env]object. This can be particularly helpful when you want to keep sensitive information, such as seed phrases, API keys, or database passwords, out of your code and stored securely in a separate file. Let’s install it with the following command input to the terminal from our current directory:

 npm install dotenv

At the top of cosmos-tx.js, just beneath your other requires, please add the following:


require(‘dotenv’).config();

This command initializes dotenv and causes your project to look for your .env file containing variables.

It should go without saying that we need to make our .env file now! Make sure you’re still in your proper project directory, then from the terminal enter the following:

touch .env

🟢If you’ve completed the past tutorials, you’ll be able to easily use gaiad to get your pre-loaded wallet. You may need to verify that your wallet has a substantial balance if you’ve already done a large transaction and it’s best practice to use a wallet that has already been initialized / received funds on chain.

Now that we’ve created our .env, you’ll use the following command to pull your private key from gaiad! Be careful, this is something that you cannot share anywhere — as it means instant and irrevocable access to your funds. 🔒

gaiad keys export <key_name> --unarmored-hex --unsafe

⚠️ If you’ve forgotten your key_name, don’t forget our trusty gaiad keys list command from previous tutorials. You also can check the balance to ensure this wallet has the funds necessary to send a transaction. Be sure your wallet has a balance by running gaiad query bank balances <account>.

When running the — unarmored-hex flag, gaiad will try to warn you that you’re doing an unsafe operation. Type y and press ENTER to continue. Once you have this export, copy and paste it into your .env file as shown below:

PRIVATE_KEY=<insert your pasted hex here>

Normally, within Cosmjs and broadly across Crypto ecosystems, people use the mnemonic to access their wallet but we’re going this route to illustrate how to still use your key, even without a mnemonic.

🚧If you have not completed past tutorials, you’ll have to create a wallet within your code and get it funded through the Cosmos Hub Testnet faucet. This is a slightly different process than the route we took. You can use the method implemented here. For a simpler path to success, I again encourage you to revisit Part 1 and Part 2 of this series.

Constants

There are a few constants that are needed to build out your transaction (Tx).

First, let’s fetch an RPC endpoint from the Lava gateway. If you’ve followed our other tutorials, this step should be straight forward. If not, check out the Getting Started with the Lava Gateway guide. Make sure you go grab the RPC endpoint for the Cosmos Hub Testnet! The Stargate client always connects to a Tendermint RPC endpoint — so we also need to be sure to select that one, as well.

//RPC info
const rpcEndpoint = “https://lavagatewaycosmoshubtestnetaddress/"

You’ll also need to add information about your sender and receiver. Who is sending to who? We will take this step to invoke our sender’s private key pulled from gaiad. All that’s needed is process.env.PRIVATE_KEY. Notice that our private key never appears in our code 😎👍🏿. This means all we have to do to change the sender is edit our .env file!

Of course, you’ll need a valid recipient in order to carry out this transaction. If you’re at a loss for who to send your tokens to — feel free to use my address cosmos15dgrn5rl8eah6s3lcjm5gjsn78w6kg5plmn6ml . 😄

//Sender & Receiver info
const receiver = “<cosmos address>”
const senderPrivateKey = process.env.PRIVATE_KEY;

In addition to, who we’re sending to and from, we need a little more information about the transaction itself. That is, we need to determine a gasPrice and an amount to send!

//Tx info 
const amount = coins(‘100000’, “uatom”);
const gasPrice = GasPrice.fromString(“0.025uatom”);
const txOptions = { gasPrice };

3. Building, Signing and Sending the Tx

Now, we can implement the major logic for our program. Unlike our use of gaiad we don’t really need to build the transaction. We can just spell it out in code!

//Tx function
(async () => {

//Acquire our Sender from the PrivateKey, Connect our Client, & Get our Chain ID
const sender = await DirectSecp256k1Wallet.fromKey(Buffer.from(senderPrivateKey,'hex'));
const client = await SigningStargateClient.connectWithSigner(rpcEndpoint, sender, txOptions);
const chainID = await client.getChainId();

//Print Basic Tx Info to Console as a Sanity Check
console.log("Connected Chain_ID: ", chainID);
console.log("From Sender: ", toBech32("cosmos",rawSecp256k1PubkeyToRawAddress(sender.pubkey)));
console.log("To Receiver: ", receiver);
console.log("Tx Amount ", amount);

//Grab Account Information of Sender from Chain - should match From Sender:
const [senderAccount] = await sender.getAccounts();

// Send Tokens with Auto Gas Fees and Memo Text
const result = await client.sendTokens(senderAccount.address, receiver, amount,"auto","sending a signedTx with Cosmjs");
console.log('Transaction result:', result);
})();

Let’s save and run our program to see what happens! Enter the following into the terminal:

node cosmos-tx.js

🟢If we’ve succeeded our output should look something like the following:

Success!!

That’s it! You just sent your first transaction using Cosmjs. There’s so much more to explore! However, this is a great start which illustrates the possibilities. 🙂

Until next time, friends! Up next, we may delve further into Cosmjs with an example app or even take a peek at smart contract development! 👋🏿 Thanks for following along!

Check out the Github Repository with the complete version of this project: KagemniKarimu/cosmjs-sendtx

Further Resources

🚪https://gateway.lavanet.xyz

💻How to Cosmos Part 1

💻How to Cosmos Part 2

⚛️ Official CosmJs Tutorial

⚛️ Official CosmJs documentation

About the Author🧑🏿‍💻

KagemniKarimu is current Developer Relations Engineer for Lava Network and former Developer Relations at Skynet Labs. He’s a self-proclaimed Rubyist, new Rust learner, and friendly Web3 enthusiast who entertains all conversations about tech. Follow him on Twitter or say hi to him on Lava’s Discord where he can be found lurking.

About Lava 🌋

Lava is a decentralized network of top-tier API providers that developers can subscribe to for access to any blockchain. Providers are rewarded for their quality of service, meaning apps and users get maximum speed, data integrity and uptime. RPC requests are routed to multiple endpoints at once, meaning anyone can privately query or send transactions on-chain, while being matched to the most performant and reliable providers.

We help developers build web3 apps on any chain, with reliable, performant and decentralized node infrastructure.

--

--