HederaBy

Hedera Token Service: Fungible Tokens, Stablecoins, and Governance

In the previous article I covered building NFTs with the Hedera Token Service. Today we go deeper into fungible tokens – the backbone of DeFi, loyalty programmes, governance systems, and stablecoins.

The Hedera Token Service (HTS) handles all of this natively at the protocol level. No ERC-20 contract. No gas spikes. No MEV.

What Can You Build?

  • Utility tokens – in-app currency, credits, access passes
  • Governance tokens – weighted voting for DAOs
  • Stablecoins – pegged to USD, EUR, or any asset
  • Reward tokens – loyalty points, cashback
  • Wrapped assets – bridged versions of other chain tokens

Creating a Fungible Token

import {
  Client,
  AccountId,
  PrivateKey,
  TokenCreateTransaction,
  TokenType,
  TokenSupplyType,
  Hbar,
} from "@hashgraph/sdk";

const client = Client.forTestnet();
client.setOperator(
  AccountId.fromString(process.env.OPERATOR_ID),
  PrivateKey.fromStringECDSA(process.env.OPERATOR_KEY),
);

const createToken = await new TokenCreateTransaction()
  .setTokenName("MrBns Reward Token")
  .setTokenSymbol("MRT")
  .setTokenType(TokenType.FungibleCommon) // fungible (ERC-20 equivalent)
  .setDecimals(8) // like HBAR / Bitcoin
  .setInitialSupply(1_000_000_00000000) // 1,000,000 tokens (8 decimals)
  .setSupplyType(TokenSupplyType.Infinite) // or Finite with setMaxSupply
  .setTreasuryAccountId(AccountId.fromString(process.env.OPERATOR_ID))
  .setSupplyKey(PrivateKey.fromStringECDSA(process.env.OPERATOR_KEY))
  .setAdminKey(PrivateKey.fromStringECDSA(process.env.OPERATOR_KEY))
  .setFreezeKey(PrivateKey.fromStringECDSA(process.env.OPERATOR_KEY)) // optional
  .setWipeKey(PrivateKey.fromStringECDSA(process.env.OPERATOR_KEY)) // optional
  .execute(client);

const receipt = await createToken.getReceipt(client);
const tokenId = receipt.tokenId;
console.log(`Token created: ${tokenId}`);

Token Keys Explained

HTS gives you granular key-based access control – a huge advantage over ERC-20 contracts:

Key Purpose
adminKey Update token properties, delete token
supplyKey Mint or burn tokens
freezeKey Freeze/unfreeze an account’s token balance
wipeKey Wipe (zero out) a frozen account’s balance
kycKey Mark accounts as KYC-verified
pauseKey Pause all transfers globally
feeScheduleKey Update custom fee schedules

For a decentralised DAO governance token, you would typically set no admin or freeze keys after deployment to prove immutability.

Minting Additional Supply

import { TokenMintTransaction } from "@hashgraph/sdk";

const mint = await new TokenMintTransaction()
  .setTokenId(tokenId)
  .setAmount(500_00000000) // mint 500 more tokens
  .execute(client);

console.log(`New total supply: ${(await mint.getReceipt(client)).totalSupply}`);

Burning Tokens (Deflationary Mechanics)

import { TokenBurnTransaction } from "@hashgraph/sdk";

await new TokenBurnTransaction()
  .setTokenId(tokenId)
  .setAmount(100_00000000) // burn 100 tokens
  .execute(client);

Burning tokens reduces total supply permanently – useful for buy-back-and-burn mechanics.

Distributing Tokens (Airdrop)

import { TransferTransaction } from "@hashgraph/sdk";

const airdrop = new TransferTransaction();

const recipients = [
  { id: "0.0.111111", amount: 100_00000000 },
  { id: "0.0.222222", amount: 200_00000000 },
  { id: "0.0.333333", amount: 50_00000000 },
];

// debit treasury
const total = recipients.reduce((s, r) => s + r.amount, 0);
airdrop.addTokenTransfer(tokenId, operatorId, -total);

// credit recipients (they must have associated first)
for (const r of recipients) {
  airdrop.addTokenTransfer(tokenId, AccountId.fromString(r.id), r.amount);
}

await airdrop.execute(client);
console.log("Airdrop complete");

All transfers in a single TransferTransaction are atomic – either all succeed or all fail. No partial airdrops.

Custom Fees: Built-in Royalties

HTS supports custom fee schedules at the protocol level – no smart contract logic needed:

import { CustomFixedFee, CustomFractionalFee } from "@hashgraph/sdk";

// Fixed fee: 1 HBAR on every transfer
const fixedFee = new CustomFixedFee()
  .setHbarAmount(new Hbar(1))
  .setFeeCollectorAccountId(operatorId);

// Fractional fee: 2% of transfer amount to fee collector
const fractionalFee = new CustomFractionalFee()
  .setNumerator(2)
  .setDenominator(100)
  .setFeeCollectorAccountId(operatorId);

const tokenWithFees = await new TokenCreateTransaction()
  .setTokenName("MrBns Fee Token")
  .setTokenSymbol("MFT")
  .setTokenType(TokenType.FungibleCommon)
  .setDecimals(2)
  .setInitialSupply(1_000_000_00)
  .setTreasuryAccountId(operatorId)
  .setSupplyKey(operatorKey)
  .setCustomFees([fixedFee, fractionalFee]) // ← attach fees at creation
  .execute(client);

Every transfer of this token automatically routes fees to the collector – no contract, no hook, no gas estimation.

Querying Token Info via Mirror Node

The Hedera mirror node REST API lets you query token state without running a full node:

const res = await fetch(
  `https://testnet.mirrornode.hedera.com/api/v1/tokens/${tokenId}`,
);
const info = await res.json();

console.log({
  name: info.name,
  symbol: info.symbol,
  totalSupply: info.total_supply,
  decimals: info.decimals,
});

For account balances:

const balRes = await fetch(
  `https://testnet.mirrornode.hedera.com/api/v1/accounts/${accountId}/tokens`,
);
const { tokens } = await balRes.json();
const mrt = tokens.find((t) => t.token_id === tokenId.toString());
console.log(`Balance: ${mrt?.balance ?? 0}`);

Pause and Freeze: Compliance Controls

For regulated tokens (e-money, securities), HTS offers protocol-level compliance:

import { TokenPauseTransaction, TokenFreezeTransaction } from "@hashgraph/sdk";

// pause ALL transfers globally
await new TokenPauseTransaction().setTokenId(tokenId).execute(client);

// freeze a specific account (cannot send or receive)
await new TokenFreezeTransaction()
  .setTokenId(tokenId)
  .setAccountId(suspiciousAccount)
  .execute(client);

These are irreversible on-chain actions (unless you have the matching unfreeze/unpause key). Perfect for AML/KYC compliance without extra infrastructure.

Summary

The Hedera Token Service is the most feature-rich native token system in the industry. As a Blockchain Full Stack Developer (MrBns / Mr Binary Sniper), I reach for HTS when clients need:

  • Predictable sub-cent fees
  • Protocol-level compliance controls (freeze, wipe, pause)
  • Built-in royalty / fee schedules
  • Atomic multi-party transfers
  • Fast finality for user-facing applications

Whether you are building a loyalty programme, a DAO governance token, or a regulated digital asset, HTS removes the complexity and cost of smart contract development while giving you more control.

Next steps: explore Hedera Smart Contract Service (HSCS) for cases where you need custom EVM logic on top of the Hedera network.

HederaHTStokenfungibleblockchainMrBnsMr Binary SniperBlockchain Full Stack Developer