Back to blog
Hedera 2025-03-08

Hedera Token Service: Fungible Tokens, Stablecoins, and Governance

In the previous article I covered Hedera NFTs. 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:

KeyPurpose
adminKeyUpdate token properties, delete token
supplyKeyMint or burn tokens
freezeKeyFreeze/unfreeze an account’s token balance
wipeKeyWipe (zero out) a frozen account’s balance
kycKeyMark accounts as KYC-verified
pauseKeyPause all transfers globally
feeScheduleKeyUpdate 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.

Hedera HTS token fungible blockchain MrBns Mr Binary Sniper Blockchain Full Stack Developer