Skip to main content

Writing Move Packages

Move is the smart contract language of the Sui blockchain. You write Move code organized into packages, which are the deployable units on Sui. Each package contains one or more modules, and each module defines types, functions, and logic that run onchain.

What is a Move package?​

A Move package is a directory with a Move.toml manifest file and a sources/ folder containing .move source files. The manifest declares the package name and edition. The source files define the modules that make up the package.

A minimal package structure looks like this:

my_package/
├── Move.toml
└── sources/
└── my_module.move

Create a new package with the Sui CLI:

sui move new my_package

A minimal Move.toml is all you need to get started:

[package]
name = "my_package"
edition = "2024"

What does a Move module look like?​

A Move module declares a module name, imports dependencies, defines types, and implements functions. The following example defines a simple counter object:

module my_package::counter;

use sui::event;

public struct Counter has key {
id: UID,
value: u64,
}

public struct CounterIncremented has copy, drop {
value: u64,
}

fun init(ctx: &mut TxContext) {
let counter = Counter {
id: object::new(ctx),
value: 0,
};
transfer::transfer(counter, ctx.sender());
}

public fun increment(counter: &mut Counter) {
counter.value = counter.value + 1;
event::emit(CounterIncremented { value: counter.value });
}

This module uses Move 2024 syntax: the module label declaration (module my_package::counter;), method-style calls (ctx.sender() instead of tx_context::sender(ctx)), and direct field access. The Counter type has the key ability, which makes it a Sui object. The init function runs once at package publication and creates the initial counter.