Get started with HCS and JavaScript
Mar 09, 2020
by Cooper Kunz

In part 1 of the Hedera and JavaScript blog series we set up our SDK, configured our environment, and managed to send our first transaction to the testnet. There was much rejoicing.

Let’s build on that success to send our first message to Hedera using the Hedera Consensus Service, or HCS. For those unfamiliar, HCS is really good (read: fast and cheap) for sending messages or events to the Hedera network. It follows a publish subscribe model where you define a topic to submit a message to and subscribe to receiving updates from a mirror node. Don’t worry, this is a lot easier than it sounds!

Update environment

To receive subscription updates we’ll make use of a Hedera mirror node. For this case we’ll use the API Hedera currently provides, but you can find a full list of alternatives here. In the future, you’ll even be able to run your own.

/* ... Add a mirror node to your .env file ... */

MIRROR_NODE_IP_ADDRESS = "hcs.testnet.mirrornode.hedera.com:5600"

Create a topic

With your JavaScript environment now set up (it should contain an Account ID, associated private key, and a mirror node to connect to), we’ll create a HCS topic, submit messages to it, and subscribe to the mirror node to receive updates.

Reminder, if you don't have an environment and node project already set up, please check out part 1 of this blog series. Also note that this tutorial uses version 1.1 of the Hedera JavaScript SDK, which may be updated by the time you're running this yourself. For the latest examples, please visit Hedera Docs.

Import transactions

We’ll start in our existing index.js file. As we did with the `CryptoTransferTransaction` already, we need to import the HCS transactions we want to use.

To use the Hedera Consensus Service, you’ll rely heavily on mirror nodes, which allow us to subscribe to updates. Let’s start by importing our `ConsensusTopicCreateTransaction`.

// Update your index.js file's imports --

// Require specific modules from the Hedera JavaScript SDK


const { Client, CryptoTransferTransaction, ConsensusTopicCreateTransaction } = require("@hashgraph/sdk");

Create topic transaction

We’ll put this import to work within our async main function.

/* ... index.js imports ... */


async function main() {


// Build & execute our new Consensus Topic Create transaction

const createTopicTransactionId = await new ConsensusTopicCreateTransaction().execute(client);


// Get the receipt of our transaction, to see if it was successful!

const createTopicReceipt = await createTopicTransactionId.getReceipt(client);


// If it was successful, it will contain a new topic ID!

const newTopicId = createTopicReceipt.getTopicId;

console.log('Our topic:' + newTopicId);


// ...

To let you in on what we’re doing here, we want to first store the transaction ID; this helps us receive a receipt of the transaction to know it successfully reached consensus.

Because this transaction is creating a new “namespace” on the network for this entity, similar to accounts, files, or contracts, the receipt should contain the new Topic ID. Which means that a topic ID will look exactly like an account ID; when I ran the example above I created topic ID 0.0.180380.

Submit a message

A topic isn’t all that useful without messages going to it. We can fix that.

Starting with our imports, we’ll add ConsensusSubmitTransaction and MirrorConsensusTopicQuery to query our newly created topic.

// Update your index.js file's imports --

// Import additional modules from the Hedera JavaScript SDK


const { Client, CryptoTransferTransaction, ConsensusTopicCreateTransaction, HederaMirrorClient, ConsensusSubmitTransaction, MirrorConsensusTopicQuery } = require("@hashgraph/sdk");

And to send our first message, we will build it similarly to other transactions on Hedera.

// Build, specify topic ID, and send a new message to HCS

const newHCSMessage = await new ConsensusSubmitTransaction()

.setTopicId(newTopicId)

.setMessage("ℏello future!")

.execute(client);


// Get the receipt of our message to confirm it was successful

const messageReceipt = await newHCSMessage.getReceipt(client);

console.log('Message receipt: ' + messageReceipt);

Each message we send to the topic will be put in a total order with a defined sequence number, timestamp and a tamper-proof running hash.

Subscribe to updates

The final step of our initial HCS setup is going to be subscribing to a Hedera Mirror Node API, specifically one that supports gRPC pub/sub.

/* ... other imports / environment variable config ... */

const mirrorNodeAddress = process.env.MIRROR_NODE_IP_ADDRESS;

const consensusClient = new MirrorClient(mirrorNodeAddress);


// Subscribe to a Hedera Mirror Node (or multiple!) to get pub-sub messaging over HCS


new MirrorConsensusTopicQuery()

.setTopicId(newTopicId)

.subscribe(process.env.MIRROR_NODE_IP_ADDRESS, response => {

console.log(response);

})

Here’s the full, but minimum, setup of our Hedera Consensus Service pub-sub messaging.

// Import the modules we need from the Hedera JavaScript SDK

const {

Client,

MirrorClient,

MirrorConsensusTopicQuery,

ConsensusTopicCreateTransaction,

ConsensusSubmitMessageTransaction

} = require("@hashgraph/sdk");


// Write our program in an asynchronous function

async function main() {


/* Get our environment variables (contained in a .env, or other way */


const operatorPrivateKey = process.env.OPERATOR_KEY;

const operatorAccount = process.env.OPERATOR_ID;

const mirrorNodeAddress = process.env.MIRROR_NODE_IP_ADDRESS;

const nodeAddress = process.env.NODE_ADDRESS;


// Create our Hedera Mainnet (or testnet) client

const client = Client.forTestnet();

client.setOperator(operatorAccount, operatorPrivateKey);


// Create our Mirror Node client

const consensusClient = new MirrorClient(mirrorNodeAddress);


// Build & execute our new Consensus Topic Create transaction

const createTopicTransactionId = await new ConsensusTopicCreateTransaction()

.setTopicMemo("Hello HCS Tutorial!")

.setMaxTransactionFee(1000000) // defaults to tinybars

.execute(client);


// Get the receipt of our transaction, to see if it was successful!

const createTopicReceipt = await createTopicTransactionId.getReceipt(client);


// If it was successful, it will contain a new topic ID!

const topicId = createTopicReceipt.getConsensusTopicId();

console.log(`topicId = ${topicId}`);


// Subscribe to a Hedera Mirror Node (or multiple!) to get pub-sub messaging over HCS

new MirrorConsensusTopicQuery()

.setTopicId(topicId)

.subscribe(

consensusClient,

(message) => console.log(message.toString()),

(error) => console.log(`Error: ${error}`)

);


// Build, specify topic ID, and send a new message to HCS

const newHCSMessage = await new ConsensusSubmitTransaction()

.setTopicId(newTopicId)

.setMessage("ℏello future!")

.execute(client);


// Get the receipt of our message to confirm it was successful

const hcsMessageReceipt = await newHCSMessage.getReceipt(client);

console.log('Message receipt: ' + hcsMessageReceipt);

}


main();

With that, you've successfully created your first Hedera Consensus Service topic, subscribed to a Hedera Mirror Node, and sent your first messages over the Hedera Consensus Service. Congratulations! In our next part, we'll show you how to start building your first web application that is decentralized on Hedera Hashgraph, using HCS.


Have any issues? Please let us know on Discord.

View full examples within Hedera docs.