Skip to main content

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"
Ready!

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 inisialisasi
  • TreasuryCap = Capability untuk mint/burn token
  • coin::create_currency() = Built-in function untuk buat token
  • 9 = Decimals (1 KAMPUS = 1,000,000,000 units)

Cara menggunakan:

  1. Save di sources/kampus_coin.move
  2. Build: sui move build
  3. 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:

  1. Dapatkan Object IDs:
# List semua objects milik Anda
sui client objects

# Detail specific object
sui client object <OBJECT_ID>
  1. Format Arguments:

    • Address: 0x1234abcd... (hex dengan prefix 0x)
    • u64 Numbers: 1000000000000 (integer)
    • Strings: "Hello World" (quoted)
    • Booleans: true atau false
    • Vectors: ["item1","item2"] untuk vector
  2. Gas Budget Guidelines:

    • Simple calls: 1000000 (1M MIST)
    • Token operations: 5000000-10000000 (5-10M MIST)
    • Complex operations: 20000000+ (20M+ MIST)
  3. 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:

  1. Transaction Digest: Hash unik transaksi
  2. Created Objects: Objects baru yang dibuat
  3. Mutated Objects: Objects yang dimodifikasi
  4. Gas Cost Summary: Breakdown biaya gas
  5. 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:

  1. Token Fundamentals: Konsep fungible token di Sui
  2. Coin Framework: Menggunakan built-in coin framework
  3. Treasury Management: TreasuryCap untuk kontrol minting
  4. Token Operations: Mint, burn, split, join coins
  5. Admin Controls: Capabilities pattern untuk permission
  6. Reward Systems: Token-based incentive system
  7. Marketplace Integration: Token sebagai medium exchange
  8. 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.

👉 Lanjut ke Day 1 Wrap-up →