Server — HCS‑16Client
This page walks through real HCS‑16 flows using the Node client. Each section explains the intent first, then shows a compact code snippet.
1) Bootstrap a Flora’s TopicsDirect link to 1) Bootstrap a Flora’s Topics
Goal: create the three topics and share them via flora_created on the Communication Topic.
- TypeScript
- Go
- Python
import { HCS16Client, FloraTopicType } from '@hashgraphonline/standards-sdk';
const hcs16 = new HCS16Client({ network: 'testnet', operatorId, operatorKey });
// Choose which topic to create first; creation can be parallelized in your app
const cTopic = await hcs16.createFloraTopic({ floraAccountId, topicType: FloraTopicType.COMMUNICATION });
const tTopic = await hcs16.createFloraTopic({ floraAccountId, topicType: FloraTopicType.TRANSACTION });
const sTopic = await hcs16.createFloraTopic({ floraAccountId, topicType: FloraTopicType.STATE });
// Announce to members on the CTopic
await hcs16.sendFloraCreated({
topicId: cTopic,
operatorId,
floraAccountId,
topics: {
communication: cTopic,
transaction: tTopic,
state: sTopic,
},
});
import (
"context"
"os"
"github.com/hashgraph-online/standards-sdk-go/pkg/hcs16"
)
client, _ := hcs16.NewClient(hcs16.ClientConfig{
Network: "testnet",
OperatorAccountID: os.Getenv("HEDERA_ACCOUNT_ID"),
OperatorPrivateKey: os.Getenv("HEDERA_PRIVATE_KEY"),
})
ctx := context.Background()
floraAccountID := "0.0.12345"
cTopic, _ := client.CreateFloraTopic(ctx, hcs16.CreateFloraTopicOptions{
FloraAccountID: floraAccountID,
TopicType: hcs16.FloraTopicTypeCommunication,
})
tTopic, _ := client.CreateFloraTopic(ctx, hcs16.CreateFloraTopicOptions{
FloraAccountID: floraAccountID,
TopicType: hcs16.FloraTopicTypeTransaction,
})
sTopic, _ := client.CreateFloraTopic(ctx, hcs16.CreateFloraTopicOptions{
FloraAccountID: floraAccountID,
TopicType: hcs16.FloraTopicTypeState,
})
client.SendFloraCreated(ctx, cTopic, os.Getenv("HEDERA_ACCOUNT_ID"), floraAccountID, hcs16.FloraTopics{
FloraTopicTypeCommunication: cTopic,
FloraTopicTypeTransaction: tTopic,
FloraTopicTypeState: sTopic,
}, nil)
import os
client = Hcs16Client(network="testnet", operator_id=os.environ["HEDERA_ACCOUNT_ID"], operator_private_key=os.environ["HEDERA_PRIVATE_KEY"])
ctx = context.background()
flora_account_id = "0.0.12345"
cTopic = client.create_flora_topic(flora_account_id=floraAccountID, topic_type=hcs16.FLORA_TOPIC_TYPE_COMMUNICATION)
tTopic = client.create_flora_topic(flora_account_id=floraAccountID, topic_type=hcs16.FLORA_TOPIC_TYPE_TRANSACTION)
sTopic = client.create_flora_topic(flora_account_id=floraAccountID, topic_type=hcs16.FLORA_TOPIC_TYPE_STATE)
client.send_flora_created(cTopic, os.environ["HEDERA_ACCOUNT_ID"], floraAccountID, flora_topic_type_communication=cTopic, flora_topic_type_transaction=tTopic, flora_topic_type_state=sTopic, None)
Notes:
- Topic memos follow the HCS‑16 spec (numeric enum encoding). Indexers can discover them reliably.
- You can store the topic triplet in your app state, registry, or an HCS‑2 registry for lookup.
2) Propose a TransactionDirect link to 2) Propose a Transaction
Goal: publish a proposal on the Transaction Topic for members to review/sign.
- TypeScript
- Go
- Python
await hcs16.sendTransaction({
topicId: tTopic,
operatorId,
scheduleId: '0.0.1234',
data: 'release funds for invoice #42',
});
client.SendTransaction(
ctx,
tTopic,
os.Getenv("HEDERA_ACCOUNT_ID"),
"0.0.1234",
"release funds for invoice #42",
nil,
)
import os
client.send_transaction(ctx, tTopic, os.environ["HEDERA_ACCOUNT_ID"], "0.0.1234", "release funds for invoice #42", None)
Notes:
- The proposal references a scheduled transaction (or your own identifier) that your members will co‑sign.
- Keep the memo meaningful for auditors and bots consuming the topic.
3) Publish a State UpdateDirect link to 3) Publish a State Update
Goal: emit a compact snapshot to the State Topic after meaningful changes.
- TypeScript
- Go
- Python
await hcs16.sendStateUpdate({
topicId: sTopic,
operatorId,
hash: '0x…',
epoch: 7,
memo: 'post‑proposal state',
});
epoch := int64(7)
client.SendStateUpdate(
ctx,
sTopic,
os.Getenv("HEDERA_ACCOUNT_ID"),
"0x…",
&epoch,
"post‑proposal state",
nil,
)
import os
epoch = int64(7)
client.send_state_update(ctx, sTopic, os.environ["HEDERA_ACCOUNT_ID"], "0x…", &epoch, "post‑proposal state", None)
Notes:
- Pairing with HCS‑17 hashes makes verification straightforward for indexers.
- Epoch is an application counter to help readers process causality.
4) Onboarding a New MemberDirect link to 4) Onboarding a New Member
Goal: run the join handshake on the Communication Topic.
- TypeScript
- Go
- Python
await hcs16.sendFloraJoinRequest({
topicId: cTopic,
operatorId,
accountId: '0.0.2468',
connectionRequestId: 42,
connectionTopicId: '0.0.9012',
connectionSeq: 7,
});
await hcs16.sendFloraJoinVote({
topicId: cTopic,
operatorId,
accountId: '0.0.2468',
approve: true,
connectionRequestId: 42,
connectionSeq: 7,
});
await hcs16.sendFloraJoinAccepted({
topicId: cTopic,
operatorId,
members: ['0.0.111', '0.0.222', '0.0.2468'],
epoch: 8,
});
connectionTopicID := "0.0.9012"
connectionSeq := int64(7)
epoch := int64(8)
client.SendFloraJoinRequest(
ctx, cTopic, os.Getenv("HEDERA_ACCOUNT_ID"), "0.0.2468", 42,
&connectionTopicID, &connectionSeq, nil,
)
client.SendFloraJoinVote(
ctx, cTopic, os.Getenv("HEDERA_ACCOUNT_ID"), "0.0.2468", true,
42, &connectionSeq, nil,
)
client.SendFloraJoinAccepted(
ctx, cTopic, os.Getenv("HEDERA_ACCOUNT_ID"),
[]string{"0.0.111", "0.0.222", "0.0.2468"}, &epoch, nil,
)
import os
connection_topic_id = "0.0.9012"
connection_seq = int64(7)
epoch = int64(8)
client.send_flora_join_request(ctx, cTopic, os.environ["HEDERA_ACCOUNT_ID"], "0.0.2468", 42, &connectionTopicID, &connectionSeq, None)
client.send_flora_join_vote(ctx, cTopic, os.environ["HEDERA_ACCOUNT_ID"], "0.0.2468", True, 42, &connectionSeq, None)
client.send_flora_join_accepted(ctx, cTopic, os.environ["HEDERA_ACCOUNT_ID"], [][], &epoch, None)
Notes:
- Your policy decides who can request, how many votes are required, and how acceptance is signaled.
- Keep membership lists sorted to avoid accidental hash divergence downstream.
Reading MessagesDirect link to Reading Messages
The client exposes helpers to read and filter messages by operation when processing topics.
- TypeScript
- Go
- Python
const recent = await hcs16.getRecentMessages(cTopic, { limit: 25, order: 'desc', opFilter: 'flora_created' });
const latest = await hcs16.getLatestMessage(cTopic, 'flora_created');
recent, _ := client.GetRecentMessages(ctx, cTopic, 25, "desc", hcs16.FloraOperationFloraCreated)
latest, _ := client.GetLatestMessage(ctx, cTopic, hcs16.FloraOperationFloraCreated)
recent = client.get_recent_messages(cTopic, 25, "desc", hcs16.FLORA_OPERATION_FLORA_CREATED)
latest = client.get_latest_message(cTopic, hcs16.FLORA_OPERATION_FLORA_CREATED)
That’s all you need on Node: build with tx.ts, execute with the SDK client, and keep your flows auditable and minimal.