Module 3: Building a Token System
Durasi: 90 menit (15:15 - 16:45)
Target: Membangun sistem token yang lengkap dan siap production
🎯 Tujuan Pembelajaran
Setelah modul ini, Anda akan mampu:
- Memahami konsep fungible token di blockchain Sui
- Membuat token custom dengan supply management
- Mengimplementasikan treasury pattern untuk kontrol minting
- Menambahkan fitur transfer, burn, dan metadata
- Deploy dan test token system di testnet
💰 Apa itu Token System?
Token System adalah smart contract yang mengatur:
- Token Creation: Membuat token baru (minting)
- Token Transfer: Memindahkan token antar address
- Supply Management: Mengatur total supply token
- Treasury Control: Kontrol siapa yang bisa mint/burn
Analogi: Seperti bank sentral yang menerbitkan uang, tapi versi digital di blockchain!
Setup Awal
1. Buat Project Token
# Buat project Move baru
sui move new kampus_token
cd kampus_token
2. Konfigurasi Move.toml
[package]
name = "kampus_token"
version = "1.0.0"
[dependencies]
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "framework/testnet" }
[addresses]
kampus_token = "0x0"
Mari kita mulai membangun token system dari yang paling sederhana!
Token 101: Membuat Token Pertama
1. Token Sederhana
Mari mulai dengan token paling sederhana - Kampus Coin:
module kampus_token::kampus_coin {
use sui::coin::{Self, Coin, TreasuryCap};
use sui::url;
use sui::tx_context::{Self, TxContext};
use sui::transfer;
use std::option;
// === STRUCTS ===
// One Time Witness untuk inisialisasi token
struct KAMPUS_COIN has drop {}
// === INIT FUNCTION ===
fun init(witness: KAMPUS_COIN, ctx: &mut TxContext) {
// Metadata token
let (_treasury_cap, _metadata) = coin::create_currency<KAMPUS_COIN>(
witness,
9, // Decimals
b"KAMPUS", // Symbol
b"Kampus Token", // Name
b"Token untuk sistem kampus blockchain", // Description
option::some(url::new_unsafe_from_bytes(b"https://kampus.io/icon.png")), // Icon URL
ctx
);
// Transfer treasury ke deployer untuk kontrol minting
transfer::public_transfer(_treasury_cap, tx_context::sender(ctx));
// Freeze metadata (tidak bisa diubah lagi)
transfer::public_freeze_object(_metadata);
}
// === MINTING FUNCTIONS ===
// Mint token baru (hanya pemilik treasury)
public fun mint(
treasury_cap: &mut TreasuryCap<KAMPUS_COIN>,
amount: u64,
_recipient: address,
ctx: &mut TxContext
) {
// Mint coin
let _coin = coin::mint(treasury_cap, amount, ctx);
// Transfer ke recipient
transfer::public_transfer(_coin, _recipient);
}
// Burn token (destroy coin)
public fun burn(treasury_cap: &mut TreasuryCap<KAMPUS_COIN>, coin: Coin<KAMPUS_COIN>) {
coin::burn(treasury_cap, coin);
}
}
Penjelasan Konsep:
KAMPUS_COIN
= One Time Witness untuk inisialisasiTreasuryCap
= Capability untuk mint/burn tokencoin::create_currency()
= Built-in function untuk buat token9
= Decimals (1 KAMPUS = 1,000,000,000 units)
Cara menggunakan:
- Save di
sources/kampus_coin.move
- Build:
sui move build
- Publish:
sui client publish --gas-budget 100000000
2. Testing Token Pertama
Setelah deploy, kita bisa test token menggunakan sui client call
. Berdasarkan hasil build di atas, kita mendapat:
Package ID: 0x4583bb7ace188b0c2af25411deca6303c8e8d4b3dc0da3f8f09fcc26b48e87c5
Treasury Cap ID: 0x0b6c25ad5ef676f44a59a2686131a0b757d5dcceffe5fca2345e23e4ca40d2ae
Anatomy dari sui client call
sui client call \
--package <PACKAGE_ID> \ # ID paket yang sudah di-publish
--module <MODULE_NAME> \ # Nama module dalam paket
--function <FUNCTION_NAME> \ # Nama fungsi yang akan dipanggil
--args <ARG1> <ARG2> <ARG3> \ # Arguments untuk fungsi
--gas-budget <AMOUNT> # Budget gas untuk transaksi
Parameter Wajib:
--package
: Object ID dari published package--module
: Nama module (tanpa namespace)--function
: Nama function yang akan dipanggil--gas-budget
: Jumlah gas budget dalam MIST
Parameter Opsional:
--args
: Arguments untuk function (dipisah spasi)--gas
: Specific gas object ID (jika tidak default)--type-args
: Type arguments untuk generic functions
Contoh Testing Token:
# 1. Cek objects yang dimiliki (termasuk TreasuryCap)
sui client objects
# 2. Mint 1000 KAMPUS token (1000 dengan 9 decimals = 1000000000000)
sui client call \
--package 0x4583bb7ace188b0c2af25411deca6303c8e8d4b3dc0da3f8f09fcc26b48e87c5 \
--module kampus_coin \
--function mint \
--args 0x0b6c25ad5ef676f44a59a2686131a0b757d5dcceffe5fca2345e23e4ca40d2ae 1000000000000 0xafbde59d04875e6684d9306228aac560bb136cf1b1edd433e3d0bfc39ed50169 \
--gas-budget 10000000
# 3. Cek balance recipient
sui client balance 0xafbde59d04875e6684d9306228aac560bb136cf1b1edd433e3d0bfc39ed50169
# 4. Burn token (jika ada coin object)
sui client call \
--package 0x4583bb7ace188b0c2af25411deca6303c8e8d4b3dc0da3f8f09fcc26b48e87c5 \
--module kampus_coin \
--function burn \
--args 0x0b6c25ad5ef676f44a59a2686131a0b757d5dcceffe5fca2345e23e4ca40d2ae <COIN_OBJECT_ID> \
--gas-budget 5000000
Tips untuk sui client call
:
- Dapatkan Object IDs:
# List semua objects milik Anda
sui client objects
# Detail specific object
sui client object <OBJECT_ID>
-
Format Arguments:
- Address:
0x1234abcd...
(hex dengan prefix 0x) - u64 Numbers:
1000000000000
(integer) - Strings:
"Hello World"
(quoted) - Booleans:
true
ataufalse
- Vectors:
["item1","item2"]
untuk vector
- Address:
-
Gas Budget Guidelines:
- Simple calls:
1000000
(1M MIST) - Token operations:
5000000-10000000
(5-10M MIST) - Complex operations:
20000000+
(20M+ MIST)
- Simple calls:
-
Error Handling:
# Jika error "Insufficient gas", naikkan gas-budget
--gas-budget 20000000
# Jika error "Object not found", cek object ID
sui client object <OBJECT_ID>
# Jika error "Function not found", cek module name
sui client call --help
Advanced Usage:
# Call dengan type arguments (untuk generic functions)
sui client call \
--package <PACKAGE_ID> \
--module <MODULE> \
--function <FUNCTION> \
--type-args "0x2::sui::SUI" \
--args <ARGS> \
--gas-budget <BUDGET>
# Call dengan multiple arguments dari berbagai types
sui client call \
--package <PACKAGE_ID> \
--module kampus_coin \
--function mint \
--args <TREASURY_CAP> 1000000000000 0x1234... \
--gas-budget 10000000
# Dry run (simulasi tanpa execute)
sui client call \
--package <PACKAGE_ID> \
--module <MODULE> \
--function <FUNCTION> \
--args <ARGS> \
--gas-budget <BUDGET> \
--dry-run
Understanding Call Results:
Setelah sui client call
berhasil, Anda akan mendapat:
- Transaction Digest: Hash unik transaksi
- Created Objects: Objects baru yang dibuat
- Mutated Objects: Objects yang dimodifikasi
- Gas Cost Summary: Breakdown biaya gas
- Events: Events yang di-emit (jika ada)
# Cek details transaksi
sui client transaction <TRANSACTION_DIGEST>
# Monitor events
sui client events --package <PACKAGE_ID>
Token 102: Advanced Token Features
Sekarang kita buat token yang lebih canggih dengan fitur tambahan:
1. Token dengan Admin Control
module kampus_token::advanced_kampus_coin {
use sui::coin::{Self, Coin, TreasuryCap};
use sui::balance::{Self, Balance};
use sui::url::{Self, Url};
use std::string::{Self, String};
// === STRUCTS ===
// One Time Witness
public struct ADVANCED_KAMPUS_COIN has drop {}
// Admin capability
public struct AdminCap has key, store {
id: UID,
}
// Treasury management object
public struct Treasury has key {
id: UID,
treasury_cap: TreasuryCap<ADVANCED_KAMPUS_COIN>,
total_supply: u64,
minting_enabled: bool,
admin: address,
}
// Minting event
public struct TokenMinted has copy, drop {
amount: u64,
recipient: address,
}
// Burning event
public struct TokenBurned has copy, drop {
amount: u64,
burner: address,
}
// === ERROR CONSTANTS ===
const EMINTING_DISABLED: u64 = 0;
const ENOT_AUTHORIZED: u64 = 1;
const EINSUFFICIENT_BALANCE: u64 = 2;
// === INIT FUNCTION ===
fun init(witness: ADVANCED_KAMPUS_COIN, ctx: &mut TxContext) {
// Create currency
let (treasury_cap, metadata) = coin::create_currency<ADVANCED_KAMPUS_COIN>(
witness,
9, // 9 decimals
b"AKAMPUS", // Symbol
b"Advanced Kampus Token", // Name
b"Advanced token dengan admin control", // Description
option::some<Url>(url::new_unsafe_from_bytes(b"https://kampus.io/advanced.png")),
ctx
);
// Create admin capability
let admin_cap = AdminCap {
id: object::new(ctx),
};
// Create treasury management
let treasury = Treasury {
id: object::new(ctx),
treasury_cap,
total_supply: 0,
minting_enabled: true,
admin: tx_context::sender(ctx),
};
// Transfer admin cap to deployer
transfer::public_transfer(admin_cap, tx_context::sender(ctx));
// Share treasury for public access
transfer::share_object(treasury);
// Freeze metadata
transfer::public_freeze_object(metadata);
}
// === ADMIN FUNCTIONS ===
// Toggle minting on/off (hanya admin)
public fun toggle_minting(
_: &AdminCap,
treasury: &mut Treasury,
) {
treasury.minting_enabled = !treasury.minting_enabled;
}
// Mint token dengan kontrol admin
public fun mint_tokens(
_: &AdminCap,
treasury: &mut Treasury,
amount: u64,
recipient: address,
ctx: &mut TxContext
) {
// Cek apakah minting enabled
assert!(treasury.minting_enabled, EMINTING_DISABLED);
// Mint coin
let coin = coin::mint(&mut treasury.treasury_cap, amount, ctx);
// Update total supply
treasury.total_supply = treasury.total_supply + amount;
// Emit event
sui::event::emit(TokenMinted {
amount,
recipient,
});
// Transfer ke recipient
transfer::public_transfer(coin, recipient);
}
// Batch mint untuk multiple recipients
public fun batch_mint(
admin_cap: &AdminCap,
treasury: &mut Treasury,
recipients: vector<address>,
amounts: vector<u64>,
ctx: &mut TxContext
) {
assert!(treasury.minting_enabled, EMINTING_DISABLED);
assert!(vector::length(&recipients) == vector::length(&amounts), 100);
let mut i = 0;
let len = vector::length(&recipients);
while (i < len) {
let recipient = *vector::borrow(&recipients, i);
let amount = *vector::borrow(&amounts, i);
mint_tokens(admin_cap, treasury, amount, recipient, ctx);
i = i + 1;
};
}
// === PUBLIC FUNCTIONS ===
// Burn token (siapa saja bisa burn token mereka)
public fun burn_tokens(
treasury: &mut Treasury,
coin: Coin<ADVANCED_KAMPUS_COIN>,
ctx: &TxContext
) {
let amount = coin::value(&coin);
// Burn coin
coin::burn(&mut treasury.treasury_cap, coin);
// Update total supply
treasury.total_supply = treasury.total_supply - amount;
// Emit event
sui::event::emit(TokenBurned {
amount,
burner: tx_context::sender(ctx),
});
}
// Split coin menjadi beberapa bagian
public fun split_coin(
coin: &mut Coin<ADVANCED_KAMPUS_COIN>,
split_amount: u64,
ctx: &mut TxContext
): Coin<ADVANCED_KAMPUS_COIN> {
assert!(coin::value(coin) >= split_amount, EINSUFFICIENT_BALANCE);
coin::split(coin, split_amount, ctx)
}
// Join multiple coins menjadi satu
public fun join_coins(
coin1: &mut Coin<ADVANCED_KAMPUS_COIN>,
coin2: Coin<ADVANCED_KAMPUS_COIN>
) {
coin::join(coin1, coin2);
}
// === VIEW FUNCTIONS ===
// Get treasury info
public fun get_treasury_info(treasury: &Treasury): (u64, bool, address) {
(treasury.total_supply, treasury.minting_enabled, treasury.admin)
}
// Get coin value
public fun get_coin_value(coin: &Coin<ADVANCED_KAMPUS_COIN>): u64 {
coin::value(coin)
}
// Check if minting enabled
public fun is_minting_enabled(treasury: &Treasury): bool {
treasury.minting_enabled
}
}
Fitur Baru:
- Admin Control: Hanya admin yang bisa mint
- Minting Toggle: Admin bisa enable/disable minting
- Total Supply Tracking: Track total supply yang beredar
- Batch Minting: Mint ke multiple address sekaligus
- Events: Logging untuk monitoring
- Coin Operations: Split dan join coins
2. Student Token dengan Reward System
Mari buat token khusus untuk sistem reward mahasiswa:
module kampus_token::student_reward_token {
use sui::coin::{Self, Coin, TreasuryCap};
use sui::table::{Self, Table};
use std::string::String;
// === STRUCTS ===
public struct STUDENT_REWARD_TOKEN has drop {}
// Student profile
public struct StudentProfile has key {
id: UID,
nim: u32,
nama: String,
total_earned: u64,
total_spent: u64,
achievements: vector<String>,
}
// Reward system
public struct RewardSystem has key {
id: UID,
treasury_cap: TreasuryCap<STUDENT_REWARD_TOKEN>,
reward_rates: Table<String, u64>, // Activity -> Token amount
admin: address,
}
// Achievement unlocked event
public struct AchievementUnlocked has copy, drop {
nim: u32,
achievement: String,
reward: u64,
}
// === INIT ===
fun init(witness: STUDENT_REWARD_TOKEN, ctx: &mut TxContext) {
let (treasury_cap, metadata) = coin::create_currency<STUDENT_REWARD_TOKEN>(
witness,
6, // 6 decimals
b"SRT", // Symbol
b"Student Reward Token", // Name
b"Token reward untuk mahasiswa aktif", // Description
option::none(), // No icon
ctx
);
// Setup reward rates
let mut reward_rates = table::new<String, u64>(ctx);
table::add(&mut reward_rates, string::utf8(b"attendance"), 10000000); // 10 SRT
table::add(&mut reward_rates, string::utf8(b"assignment"), 25000000); // 25 SRT
table::add(&mut reward_rates, string::utf8(b"exam_pass"), 50000000); // 50 SRT
table::add(&mut reward_rates, string::utf8(b"project"), 100000000); // 100 SRT
let reward_system = RewardSystem {
id: object::new(ctx),
treasury_cap,
reward_rates,
admin: tx_context::sender(ctx),
};
transfer::share_object(reward_system);
transfer::public_freeze_object(metadata);
}
// === STUDENT FUNCTIONS ===
// Register sebagai student
public fun register_student(
nim: u32,
nama: String,
ctx: &mut TxContext
) {
let profile = StudentProfile {
id: object::new(ctx),
nim,
nama,
total_earned: 0,
total_spent: 0,
achievements: vector::empty<String>(),
};
transfer::transfer(profile, tx_context::sender(ctx));
}
// Claim reward untuk achievement
public fun claim_achievement_reward(
reward_system: &mut RewardSystem,
profile: &mut StudentProfile,
achievement: String,
ctx: &mut TxContext
) {
// Cek apakah achievement valid
assert!(table::contains(&reward_system.reward_rates, achievement), 0);
// Get reward amount
let reward_amount = *table::borrow(&reward_system.reward_rates, achievement);
// Mint reward token
let reward_coin = coin::mint(&mut reward_system.treasury_cap, reward_amount, ctx);
// Update profile
profile.total_earned = profile.total_earned + reward_amount;
vector::push_back(&mut profile.achievements, achievement);
// Emit event
sui::event::emit(AchievementUnlocked {
nim: profile.nim,
achievement,
reward: reward_amount,
});
// Transfer reward ke student
transfer::public_transfer(reward_coin, tx_context::sender(ctx));
}
// Spend token untuk benefit (contoh: akses premium)
public fun spend_tokens(
profile: &mut StudentProfile,
payment: Coin<STUDENT_REWARD_TOKEN>,
benefit: String,
ctx: &TxContext
) {
let amount = coin::value(&payment);
profile.total_spent = profile.total_spent + amount;
// Transfer payment ke treasury (atau burn)
transfer::public_transfer(payment, @0x0); // Simplified - send to null
}
// === VIEW FUNCTIONS ===
// Get student stats
public fun get_student_stats(profile: &StudentProfile): (u32, String, u64, u64, u64) {
(
profile.nim,
profile.nama,
profile.total_earned,
profile.total_spent,
vector::length(&profile.achievements)
)
}
// Get available rewards
public fun get_reward_rates(reward_system: &RewardSystem): &Table<String, u64> {
&reward_system.reward_rates
}
// Get reward amount for achievement
public fun get_reward_amount(reward_system: &RewardSystem, achievement: String): u64 {
if (table::contains(&reward_system.reward_rates, achievement)) {
*table::borrow(&reward_system.reward_rates, achievement)
} else {
0
}
}
}
Fitur Reward System:
- Student Registration: Daftar sebagai student
- Achievement Rewards: Dapatkan token dari berbagai aktivitas
- Spending System: Gunakan token untuk benefit
- Stats Tracking: Track earning dan spending
- Flexible Rewards: Admin bisa atur reward rate
Token 103: Hands-On Complete System
Mari buat sistem token lengkap dengan marketplace sederhana:
Project Setup Lengkap
# Setup project
sui move new token_marketplace
cd token_marketplace
Main Contract: sources/marketplace.move
module token_marketplace::kampus_marketplace {
use sui::coin::{Self, Coin, TreasuryCap};
use sui::balance::{Self, Balance};
use sui::table::{Self, Table};
use std::string::String;
// === STRUCTS ===
// Kampus Token
public struct KAMPUS_TOKEN has drop {}
// Item di marketplace
public struct MarketItem has key, store {
id: UID,
name: String,
description: String,
price: u64,
seller: address,
available: bool,
}
// Marketplace state
public struct Marketplace has key {
id: UID,
treasury_cap: TreasuryCap<KAMPUS_TOKEN>,
items: Table<ID, MarketItem>,
total_items: u64,
platform_fee: u64, // Basis points (100 = 1%)
admin: address,
}
// Transaction events
public struct ItemListed has copy, drop {
item_id: ID,
seller: address,
price: u64,
}
public struct ItemSold has copy, drop {
item_id: ID,
buyer: address,
seller: address,
price: u64,
}
// === INIT ===
fun init(witness: KAMPUS_TOKEN, ctx: &mut TxContext) {
// Create token
let (treasury_cap, metadata) = coin::create_currency<KAMPUS_TOKEN>(
witness,
9,
b"KMPTKN",
b"Kampus Marketplace Token",
b"Token untuk marketplace kampus",
option::none(),
ctx
);
// Create marketplace
let marketplace = Marketplace {
id: object::new(ctx),
treasury_cap,
items: table::new<ID, MarketItem>(ctx),
total_items: 0,
platform_fee: 250, // 2.5%
admin: tx_context::sender(ctx),
};
transfer::share_object(marketplace);
transfer::public_freeze_object(metadata);
}
// === TOKEN FUNCTIONS ===
// Mint initial tokens untuk user (simplified)
public fun mint_initial_tokens(
marketplace: &mut Marketplace,
amount: u64,
ctx: &mut TxContext
) {
let tokens = coin::mint(&mut marketplace.treasury_cap, amount, ctx);
transfer::public_transfer(tokens, tx_context::sender(ctx));
}
// === MARKETPLACE FUNCTIONS ===
// List item di marketplace
public fun list_item(
marketplace: &mut Marketplace,
name: String,
description: String,
price: u64,
ctx: &mut TxContext
) {
let item_id = object::new(ctx);
let item_id_copy = object::uid_to_inner(&item_id);
let item = MarketItem {
id: item_id,
name,
description,
price,
seller: tx_context::sender(ctx),
available: true,
};
// Add to marketplace
table::add(&mut marketplace.items, item_id_copy, item);
marketplace.total_items = marketplace.total_items + 1;
// Emit event
sui::event::emit(ItemListed {
item_id: item_id_copy,
seller: tx_context::sender(ctx),
price,
});
}
// Buy item dari marketplace
public fun buy_item(
marketplace: &mut Marketplace,
item_id: ID,
payment: Coin<KAMPUS_TOKEN>,
ctx: &mut TxContext
) {
// Get item
assert!(table::contains(&marketplace.items, item_id), 0);
let item = table::borrow_mut(&mut marketplace.items, item_id);
// Check availability dan price
assert!(item.available, 1);
assert!(coin::value(&payment) >= item.price, 2);
// Calculate platform fee
let platform_fee_amount = (item.price * marketplace.platform_fee) / 10000;
let seller_amount = item.price - platform_fee_amount;
// Split payment
let platform_fee_coin = coin::split(&mut payment, platform_fee_amount, ctx);
let seller_payment = coin::split(&mut payment, seller_amount, ctx);
// Transfer payments
transfer::public_transfer(seller_payment, item.seller);
transfer::public_transfer(platform_fee_coin, marketplace.admin);
// Return change jika ada
if (coin::value(&payment) > 0) {
transfer::public_transfer(payment, tx_context::sender(ctx));
} else {
coin::destroy_zero(payment);
};
// Mark as sold
item.available = false;
// Emit event
sui::event::emit(ItemSold {
item_id,
buyer: tx_context::sender(ctx),
seller: item.seller,
price: item.price,
});
}
// Update item price
public fun update_item_price(
marketplace: &mut Marketplace,
item_id: ID,
new_price: u64,
ctx: &TxContext
) {
assert!(table::contains(&marketplace.items, item_id), 0);
let item = table::borrow_mut(&mut marketplace.items, item_id);
// Only seller can update
assert!(item.seller == tx_context::sender(ctx), 3);
assert!(item.available, 1);
item.price = new_price;
}
// Remove item from marketplace
public fun remove_item(
marketplace: &mut Marketplace,
item_id: ID,
ctx: &TxContext
) {
assert!(table::contains(&marketplace.items, item_id), 0);
let item = table::borrow(&marketplace.items, item_id);
// Only seller can remove
assert!(item.seller == tx_context::sender(ctx), 3);
// Remove from table
table::remove(&mut marketplace.items, item_id);
marketplace.total_items = marketplace.total_items - 1;
}
// === VIEW FUNCTIONS ===
// Get marketplace stats
public fun get_marketplace_stats(marketplace: &Marketplace): (u64, u64, address) {
(marketplace.total_items, marketplace.platform_fee, marketplace.admin)
}
// Check if item exists
public fun item_exists(marketplace: &Marketplace, item_id: ID): bool {
table::contains(&marketplace.items, item_id)
}
// Get item info (view only)
public fun get_item_info(marketplace: &Marketplace, item_id: ID): (String, String, u64, address, bool) {
assert!(table::contains(&marketplace.items, item_id), 0);
let item = table::borrow(&marketplace.items, item_id);
(item.name, item.description, item.price, item.seller, item.available)
}
}
Testing dan Deploy
1. Build dan Deploy
# Build project
sui move build
# Publish to testnet
sui client publish --gas-budget 100000000
2. Test Token System
# Mint initial tokens
sui client call \
--package <PACKAGE_ID> \
--module kampus_marketplace \
--function mint_initial_tokens \
--args <MARKETPLACE_ID> 1000000000000 \
--gas-budget 10000000
# List item di marketplace
sui client call \
--package <PACKAGE_ID> \
--module kampus_marketplace \
--function list_item \
--args <MARKETPLACE_ID> "Buku Blockchain" "Panduan lengkap blockchain" 50000000000 \
--gas-budget 10000000
# Check marketplace stats
sui client call \
--package <PACKAGE_ID> \
--module kampus_marketplace \
--function get_marketplace_stats \
--args <MARKETPLACE_ID> \
--gas-budget 1000000
📝 Rangkuman Module 3
Yang Telah Dipelajari:
- Token Fundamentals: Konsep fungible token di Sui
- Coin Framework: Menggunakan built-in coin framework
- Treasury Management: TreasuryCap untuk kontrol minting
- Token Operations: Mint, burn, split, join coins
- Admin Controls: Capabilities pattern untuk permission
- Reward Systems: Token-based incentive system
- Marketplace Integration: Token sebagai medium exchange
- Events: Logging untuk monitoring dan analytics
Key Concepts:
- One Time Witness: Pattern untuk inisialisasi token
- TreasuryCap: Capability untuk mint/burn control
- Coin Operations: Built-in functions untuk manipulasi coin
- Supply Management: Track dan kontrol total supply
- Economic Models: Reward, spending, marketplace dynamics
Best Practices Token:
- Selalu validate amounts dan permissions
- Implement proper access controls dengan capabilities
- Emit events untuk transparency
- Handle edge cases (zero amounts, insufficient balance)
- Consider economic implications (inflation, deflation)
Real-World Applications:
- Loyalty Tokens: Reward system untuk customer retention
- Utility Tokens: Access token untuk premium features
- Governance Tokens: Voting rights dalam DAO
- Payment Tokens: Medium of exchange dalam ecosystem
Next Steps:
Setelah menguasai token system, Anda bisa explore:
- NFT Development: Non-fungible tokens
- DeFi Protocols: DEX, lending, staking
- DAO Governance: Decentralized governance system
- Cross-chain Integration: Bridge ke blockchain lain
🎯 Selamat! Anda telah menguasai Token System di Sui!
Token yang Anda buat sudah production-ready dan bisa digunakan untuk berbagai use case. Next step adalah integrasi dengan frontend application untuk pengalaman user yang complete.