Tutorial 1: Building a DeFi Token with Oracle Integration

📢 Beta: Test thoroughly in development. Feedback appreciated!

Learn to build a DeFi-style token in DAL: services, maps, and chain integration.

Time: 30 minutes
Difficulty: Beginner
Prerequisites: Basic programming knowledge


🎯 What You'll Build

A token service that:


📦 Setup

mkdir defi-token && cd defi-token
touch DefiToken.dal

Step 1: Basic Token Structure

DAL uses services (not contract). Use @trust for the service trust model; add @chain when the service interacts with a blockchain.

// DefiToken.dal
@trust("hybrid")
@chain("ethereum")
service DefiToken {
    name: string = "DeFi Token";
    symbol: string = "DFT";
    total_supply: int = 0;
    balances: map<string, int> = {};
    current_price: int = 0;
}

Step 2: Add Core Functions

Use fn, if (condition) (parentheses required), and semicolons after statements.

@trust("hybrid")
@chain("ethereum")
service DefiToken {
    name: string = "DeFi Token";
    symbol: string = "DFT";
    total_supply: int = 0;
    balances: map<string, int> = {};
    current_price: int = 0;

    fn balance_of(account: string) -> int {
        if (self.balances.contains_key(account)) {
            return self.balances[account];
        }
        return 0;
    }

    fn transfer(to: string, amount: int) -> bool {
        let from = auth::session("user", ["holder"]).user_id;
        if (self.balances[from] < amount) {
            log::info("token", "Insufficient balance");
            return false;
        }
        self.balances[from] = self.balances[from] - amount;
        self.balances[to] = self.balances[to] + amount;
        log::info("token", "Transfer done");
        return true;
    }

    fn initialize(owner: string, initial_supply: int) {
        self.balances[owner] = initial_supply;
        self.total_supply = initial_supply;
        log::info("token", "Token initialized");
    }
}

Step 3: Add Oracle-Based Pricing

Use oracle::fetch (or similar stdlib) and literals for data. Literals use key: value with a colon.

    fn update_price() {
        let price_response = oracle::fetch("DFT/USD", { source: "chainlink" });
        self.current_price = price_response;
        log::info("token", "Price updated");
    }

    fn get_price() -> int {
        return self.current_price;
    }

Step 4: Burn and Mint (Optional)

Use if (condition) and return with semicolons.

    fn mint(to: string, amount: int) {
        self.total_supply = self.total_supply + amount;
        self.balances[to] = self.balances[to] + amount;
        log::info("token", "Minted");
    }

    fn burn(amount: int) -> bool {
        let from = auth::session("user", ["holder"]).user_id;
        if (self.balances[from] < amount) {
            log::info("token", "Insufficient balance to burn");
            return false;
        }
        self.total_supply = self.total_supply - amount;
        self.balances[from] = self.balances[from] - amount;
        log::info("token", "Burned");
        return true;
    }

Step 5: Control Flow Reminders


Step 6: Compile & Test

# Parse/compile (project-specific)
cargo run -- DefiToken.dal

# Run tests if you have a test runner
cargo test

Step 7: Deploy

Deployment is environment-specific. Use your chain tooling; the service can be instantiated with DefiToken::new() or service::new("DefiToken") in DAL.


🎉 Summary

You used:


📚 Next Steps