What You'll Build
In this tutorial, you'll build an autonomous bot that posts messages to Hedera Consensus Service (HCS) topics — the same infrastructure that powers iBird. Your bot will be able to:
- Post messages to any HCS topic
- Read messages from topics (like a feed)
- Interact with iBird's Explorer topic
- Run on a schedule (e.g., post every hour)
This is the foundation for building AI agents, automated announcement bots, price feeds, or any application that needs to publish immutable messages on Hedera.
Prerequisites
- Node.js 18+ and npm
- A Hedera testnet or mainnet account (create one free at portal.hedera.com)
- Basic JavaScript/TypeScript knowledge
Step 1: Install Dependencies
npm init -y
npm install @hashgraph/sdk dotenv
Step 2: Set Up Environment Variables
Create a .env file with your Hedera account credentials:
# Get these from https://portal.hedera.com (free testnet account)
ACCOUNT_ID=0.0.xxxxxxx
PRIVATE_KEY=302e020100300506032b657004220420xxxxxxxx
# iBird Explorer topic on mainnet
# For testnet, create your own topic first
TOPIC_ID=0.0.10214045
# Use "testnet" or "mainnet"
NETWORK=testnet
⚠️ Never commit your .env file to git. Add it to .gitignore immediately.
Step 3: Initialize the Hedera Client
import { Client, AccountId, PrivateKey, TopicMessageSubmitTransaction } from "@hashgraph/sdk";
import dotenv from "dotenv";
dotenv.config();
const accountId = AccountId.fromString(process.env.ACCOUNT_ID!);
const privateKey = PrivateKey.fromString(process.env.PRIVATE_KEY!);
const topicId = process.env.TOPIC_ID!;
const client = Client.forTestnet();
client.setOperator(accountId, privateKey);
// For mainnet:
// const client = Client.forMainnet();
// client.setOperator(accountId, privateKey);
console.log("✅ Hedera client initialized");
console.log("Account:", accountId.toString());
console.log("Topic:", topicId);
Step 4: Post a Message to an HCS Topic
async function postMessage(content: string) {
// Format the message in iBird's JSON structure
const message = JSON.stringify({
Type: "Post",
Message: content,
Timestamp: Date.now(),
});
const transaction = new TopicMessageSubmitTransaction({
topicId: topicId,
message: Buffer.from(message).toString("base64"),
});
const txResponse = await transaction.execute(client);
const receipt = await txResponse.getReceipt(client);
console.log("✅ Message posted!");
console.log("Sequence:", receipt.topicSequenceNumber.toString());
console.log("Tx hash:", txResponse.transactionId.toString());
return receipt.topicSequenceNumber.toString();
}
// Post your first message
await postMessage("Hello from my Hedera bot! 🐦");
That's it! In ~3 seconds, your message is permanently recorded on Hedera with absolute finality. It costs ~$0.0001 in testnet HBAR.
Step 5: Read Messages from a Topic
import axios from "axios";
async function readMessages(topicId: string, limit: number = 10) {
const mirrorNodeUrl = "https://testnet.mirrornode.hedera.com";
// For mainnet: "https://mainnet.mirrornode.hedera.com"
const response = await axios.get(
`${mirrorNodeUrl}/api/v1/topics/${topicId}/messages?order=desc&limit=${limit}`
);
const messages = response.data.messages.map((msg: any) => {
const decoded = Buffer.from(msg.message, "base64").toString("utf-8");
try {
return {
sequence: msg.sequence_number,
timestamp: msg.consensus_timestamp,
sender: msg.payer_account_id,
content: JSON.parse(decoded),
};
} catch {
return {
sequence: msg.sequence_number,
timestamp: msg.consensus_timestamp,
sender: msg.payer_account_id,
content: decoded,
};
}
});
return messages;
}
// Read the latest 10 messages
const messages = await readMessages(topicId, 10);
messages.forEach((msg) => {
console.log(`#${msg.sequence}: ${JSON.stringify(msg.content)}`);
});
Step 6: Add Media (Upload to Arweave)
To post images with your messages, upload them to Arweave and include the hash:
import Arweave from "arweave";
import { JWKInterface } from "arweave/node/lib/wallet";
// Initialize Arweave
const arweave = Arweave.init({
host: "arweave.net",
port: 443,
protocol: "https",
});
async function uploadImage(buffer: Buffer, contentType: string) {
// Load your Arweave wallet key (generate one at arweave.org)
const key = require("./arweave-key.json") as JWKInterface;
const transaction = await arweave.createTransaction({
data: buffer,
});
transaction.addTag("Content-Type", contentType);
await arweave.transactions.sign(transaction, key);
await arweave.transactions.post(transaction);
return `https://arweave.net/${transaction.id}`;
}
// Post with image
const imageUrl = await uploadImage(imageBuffer, "image/jpeg");
await postMessage("Check out this image!", imageUrl);
Step 7: Run on a Schedule
import cron from "node-cron";
// Post every hour at minute 0
cron.schedule("0 * * * *", async () => {
console.log(`[${new Date().toISOString()}] Running scheduled post...`);
const message = `Hourly update: BTC price is $${await getBtcPrice()}`;
await postMessage(message);
});
console.log("🤖 Bot started. Posting every hour.");
iBird Message Format Reference
iBird recognizes specific JSON fields in HCS messages. Here's the format:
// Standard Post
{
"Type": "Post",
"Message": "Your post content here",
"Media": "https://arweave.net/xxx", // optional
}
// Reply to another post
{
"Type": "Post",
"Message": "Great point!",
"Reply_to": "0.0.10214045@123", // topicId@sequenceNumber
}
// Like a post
{
"Like_to": "0.0.10214045@123",
}
// Thread
{
"Type": "Thread",
"Message": "Starting a new thread...",
"Thread": "0.0.xxxxxxx", // thread topic ID
}
Deploying Your Bot
- Get mainnet HBAR — Fund your bot's account with enough HBAR for gas (~$1 covers ~10,000 posts)
- Use PM2 — Run your bot as a persistent process:
pm2 start bot.js --name my-bot - Set up monitoring — PM2 can auto-restart on crash and send alerts
- Keep your keys secure — Use environment variables, never hardcode
What's Next?
Now you can build:
- 🤖 AI agents that post autonomously (iBird's Elon Bot is already live!)
- 📊 Price feeds — Post real-time token prices to a topic
- 🔔 Notification bots — Monitor HCS topics and alert on new messages
- 📝 Cross-posters — Mirror content from X/Telegram to iBird
- 🏗️ Custom apps — Build your own UI on top of iBird's HCS topics
Resources
- Hedera Developer Documentation
- Hedera SDK on GitHub
- iBird App — see live HCS messages
- HashScan — Hedera Block Explorer
Built something cool? Share it on iBird and tag it #iBirdDev!
Ready to try iBird?
Join the first 100% decentralized social media on Hedera. Own your content forever.