After 36 days of diving into Solana development, I finally reached the most exciting milestone: composability.
Solana’s Token Extensions allow you to combine multiple features into a single mint — without writing complex smart contract logic.
In this post, I’ll walk you through two real‑world scenarios:
- Day 37 – A token with transfer fee, interest‑bearing, and metadata extensions.
- Day 38 – A compliance‑gated token with default frozen accounts (perfect for regulated finance).
All commands are tested on Devnet using the spl-token CLI. Let’s go!
Day 37: The Triple‑Extension Token
The Goal
Create a mint that:
- Charges a 1% transfer fee (capped at 5 tokens).
- Grows in value over time (interest‑bearing, 5 bps annually).
- Stores its name, symbol, and URI directly on‑chain (metadata).
Step 1 – Create the Mint
One command, no backslashes (Windows‑friendly):
spl-token --program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb create-token --decimals 2 --transfer-fee-basis-points 100 --transfer-fee-maximum-fee 500 --interest-rate 5 --enable-metadata
Output (yours will differ):
Creating token DrcSSbxxb63GiZiaXd1tFPRwwofFV3pJHSpFY1aCvcjN under program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
Address: DrcSSbxxb63GiZiaXd1tFPRwwofFV3pJHSpFY1aCvcjN
Decimals: 2
Save the mint address — we’ll call it $MINT.
Step 2 – Initialize Metadata
spl-token initialize-metadata $MINT "ArcCoin" "ARC" "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/CompressedCoil/metadata.json"
Step 3 – Verify All Extensions
spl-token display $MINT
Result (abridged):
Extensions
Interest-bearing:
Current rate: 5bps
Transfer fees:
Current fee: 100bps
Current maximum: 50000
Metadata Pointer:
Metadata address: DrcSSbxxb63GiZiaXd1tFPRwwofFV3pJHSpFY1aCvcjN
Metadata:
Name: ArcCoin
Symbol: ARC
All three extensions are active ✅
Step 4 – Create an Account and Mint 1000 Tokens
spl-token create-account $MINT
spl-token mint $MINT 1000
spl-token balance $MINT # 1000
Step 5 – Test the Transfer Fee
Create a second wallet (if you haven’t already):
solana-keygen new --outfile second-wallet.json --no-bip39-passphrase --force
solana airdrop 1 second-wallet.json # fund for rent
Create its token account and transfer 100 tokens:
spl-token create-account $MINT --owner second-wallet.json
spl-token transfer $MINT 100 second-wallet.json --expected-fee 1 --allow-unfunded-recipient
Check balances:
spl-token balance $MINT # 900
spl-token balance $MINT --owner second-wallet.json # 99
The 1 token fee is withheld in the recipient’s account.
Step 6 – Harvest Withheld Fees
# Find recipient’s token account
spl-token accounts --owner second-wallet.json -v
# Withdraw to your own token account
spl-token withdraw-withheld-tokens YOUR_TOKEN_ACCOUNT RECIPIENT_TOKEN_ACCOUNT
After harvest:
spl-token balance $MINT # 901 (the fee is yours)
Day 37 takeaway – three extensions working together, no custom program required.
Day 38: Compliance‑Gated Token (Default Frozen)
The Goal
Create a mint where every token account starts frozen. Only the freeze authority can thaw (approve) an account. This is how a regulated stablecoin or KYC‑gated platform works at the protocol level.
Step 1 – Create the Mint with --default-account-state frozen
spl-token create-token --program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb --enable-freeze --default-account-state frozen
Output:
Address: 4jC4rjpi5wh1TKd2b8cLyAqFm9a68jmGRF1qPEnkENjm
Decimals: 9
Save as $MINT_FROZEN.
Step 2 – Create Two Token Accounts (Both Will Be Frozen)
spl-token create-account $MINT_FROZEN # yours
spl-token create-account $MINT_FROZEN --owner second-wallet.json # second wallet
Step 3 – Try to Mint (Must Fail)
spl-token mint $MINT_FROZEN 100
Expected error:
Error: Account is frozen
✅ The enforcement works – even the mint authority cannot bypass it.
Step 4 – Thaw Your Account (The “KYC Approval”)
First find your token account address (spl-token accounts), then:
spl-token thaw YOUR_TOKEN_ACCOUNT
Step 5 – Mint Now Succeeds
spl-token mint $MINT_FROZEN 100
spl-token balance $MINT_FROZEN # 100
Step 6 – Transfer to Still‑Frozen Second Account (Must Fail)
spl-token transfer $MINT_FROZEN 50 second-wallet.json --allow-unfunded-recipient
Error: Account is frozen (destination).
Step 7 – Thaw Second Account, Then Transfer Succeeds
spl-token thaw SECOND_WALLET_TOKEN_ACCOUNT
spl-token transfer $MINT_FROZEN 50 second-wallet.json --allow-unfunded-recipient
spl-token balance $MINT_FROZEN --owner second-wallet.json # 50
Day 38 takeaway – compliance is enforced at the runtime level, not in off‑chain code.
What I Learned
- Composability is powerful – you can mix and match extensions like LEGO bricks.
- The CLI abstracts complexity – one command sets up TLV‑encoded extension data.
- Default frozen accounts are a game‑changer for regulated finance on Solana.
-
Debugging on Windows requires absolute paths and careful attention to program IDs (the correct one is
TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb– note the lowercasez).
Top comments (0)