Learn about Move, the secure programming language designed for digital assets on Sui.
Move is a safe and expressive programming language designed specifically for blockchains. Originally created at Facebook for the Diem project, Sui has adapted and extended Move with unique features for its object-centric architecture.
While traditional Move uses “resources”, Sui uses “objects” with unique IDs:
// Sui object with UIDpublic struct MyObject has key { id: UID, value: u64,}// Traditional Move resource (not used in Sui)// struct MyResource has key, store {// value: u64,// }
Every Sui object must have id: UID as its first field. The UID type ensures global uniqueness.
public fun check_value(x: u64): u64 { if (x > 100) { x - 100 } else if (x > 50) { x - 50 } else { x }}// Expression formlet result = if (condition) { value1 } else { value2 };
// While looplet mut i = 0;while (i < 10) { // do something i = i + 1;};// Loop with breaklet mut sum = 0;loop { sum = sum + 1; if (sum == 100) break;};// Vector iterationlet v = vector[1, 2, 3, 4, 5];v.do!(|x| { // process x});
// Private function (default)fun internal_function() { /* ... */ }// Public functionpublic fun public_function() { /* ... */ }// Public function restricted to packagepublic(package) fun package_function() { /* ... */ }// Entry function (callable from transactions)entry fun entry_point() { /* ... */ }
public struct Box<T> has store { value: T,}public fun create_box<T>(value: T): Box<T> { Box { value }}public fun unbox<T>(box: Box<T>): T { let Box { value } = box; value}// Generic with constraintspublic fun wrap_object<T: key + store>(obj: T, ctx: &mut TxContext) { // T must have key and store abilities transfer::public_transfer(obj, ctx.sender());}
public struct MY_COIN has drop {}fun init(witness: MY_COIN, ctx: &mut TxContext) { let (treasury, metadata) = coin::create_currency( witness, // One-time witness 6, b"MY_COIN", b"", b"", option::none(), ctx, ); transfer::public_freeze_object(metadata); transfer::public_transfer(treasury, ctx.sender())}
What is a Witness?
A witness is a struct that proves you own the module it’s defined in. The init function receives an instance of the witness exactly once, at module publication. This ensures certain operations (like creating a currency) can only happen once.
public struct AdminCap has key, store { id: UID,}fun init(ctx: &mut TxContext) { transfer::transfer( AdminCap { id: object::new(ctx) }, ctx.sender() );}public fun admin_only_function(_: &AdminCap, /* other params */) { // Only callable by AdminCap holder}
/// Creates a new game instance with the specified parameters./// /// # Arguments/// * `max_players` - Maximum number of players allowed/// * `entry_fee` - Fee in SUI to join the game/// /// # Aborts/// * `EInvalidMaxPlayers` if max_players is 0public fun create_game(max_players: u64, entry_fee: u64, ctx: &mut TxContext) { assert!(max_players > 0, EInvalidMaxPlayers); // ...}