Packages
You write programs that are grouped into packages to run on-chain. Every published package has an address. You can interact with packages by sending transactions that call the functions. Before we get our hands dirty, go to this article and follow the steps to set up Sui on your computer. Once you’re all set up, execute this command to create your first Sui project:[Terminal]
[Terminal]
impatience
directory and opens it in Visual Studio Code.
When you open the package, you should expect to see this file directory loaded with some content in the file.

sources/
directory and tests in the test/
directory. If there are any files you don’t want to include in your Git version control operations, you’ll include them in the .gitignore
file. The Move.toml
file is used to manage your packages and dependencies.
Package Manifest (Move.toml)
TheMove.toml
file is the manifest. It contains the package’s details and dependencies in TOML format, with different sections for each.

impatient
) and the language edition (2024.beta
). The [dependencies]
section would have the external packages, e.g., the Sui package.
Named addresses go under [addresses]
to assign aliases like zsh = "0x0"
to onchain addresses for easier referencing in Move code. Optional sections like [dev-dependencies]
and [dev-addresses]
allow you to customize test environments.
Addresses and Accounts
Addresses are unique identifiers on the Sui blockchain. Sui uses addresses to identify packages, accounts, and objects. On Sui, addresses are case-sensitive, have a fixed byte size of 32 bytes, and are usually represented as hexadecimal with the0x
prefix.

Transactions
Transactions are “actions” on the blockchain, such as calling functions, sending coins, or updating data. They can be anything that adds to or changes the state of data on the chain. Every transaction includes:- Sender – the account that signs and sends it
- Commands – the list of actions to run, in order
- Inputs – values or objects used in the commands
- Gas – a coin used to pay for the transaction
- Gas budget/price – how much will you pay to get it onchain?
Objects
On Sui, everything is an object. The objects are stored directly on the user accounts for full control. These are the types of addresses:- Owned Objects: Owned objects, like your tokens and NFTs, have one owner. Only the owner can use and interact with them.
- Shared Objects: These have multiple owners, e.g, liquidity pools.
- Immutable Objects: They cannot be modified once they’re initialized.
- ID: A unique identifier.
- Type: Defines what kind of object it is.
- Owner: Who owns the object (an address, another object, or shared).
- Version: Tracks changes to the object.
- Last Transaction: The most recent transaction that modified the object.
Publishing Packages Onchain
Once you’re done writing your packages, you’ll need to publish them, and you can do that via the Sui CLI tool. First, you must build the package locally to ensure everything works.[Terminal]
[Terminal]
[Terminal]

Move Modules
Modules are how you manage units of your packages. You can use them to isolate similar functionality. You’ll declare modules using lowercase and snake case. Module names must be unique throughout the package.[sui.move]
Importing Modules
When working with multiple modules, you may need to import one module from another. Specifying the namespace with theuse
keyword works in this case:
[sui.move]
Self
without repeating the module name.
You’ll need to add external dependencies to the dependencies section of your Move.toml
file.
use
keyword.
[sui.move]
Sui
dependency has already been imported. You have access to those and automatically, the std
module, which is the Move standard library.
Data Structures and Types
Primitive types are your everyday data types. Sui Move supports:u8
,u16
,u32
,u64
,u128
,u256
– Unsigned integers of various sizes. Pick one and stick to it unless you like debugging overflow errors.bool
–true
orfalse
.signer
– a special type that represents the person calling the function. You use this to prove identity and ownership.
=
operation:
[sui.move]
mut
keyword in your definition.
[sui.move]
You can’t create a
Transaction Context
manually. The system passes that in when someone calls your code.Conditionals
Move has the classicif
, else if
, else
. Here’s how you’ll use them:
[sui.move]
[sui.move]
if
and else
branches must return the same type if you’re assigning to a variable.
You can use assert!
to enforce rules at runtime:
[sui.move]
code 0
.
Loops
You havewhile
and loop
repetitions:
While loops run as long as the condition is true:
[sui.move]
loop
runs forever (until you manually break
out of it):
[sui.move]
break
and continue
keywords to exit a loop and skip to another iteration respectively.
[sui.move]
return
keyword. More on that in a bit.
Structs
Structs are how you declare custom types for whatever you’re building. You’ll declare a struct with thestruct
keyword with the name of the type and add fields like this:
[sui.move]
public
visibility modifier as above.
Move does not support recursive structs so structs cannot encapsulate structs.Structs are more in Sui move, they also have abilities that define their behaviours e.g, adding any of the attributes means:
copy
– can be copied.drop
– can be destroyed.store
– can be stored in memory.key
– can live on the blockchain as an object.
[sui.move]
Counter
struct can now exist on-chain as an object with an ID itself.
Vectors
Vectors are how you’ll express a list of items. They’re dynamic and shrinkable.[sui.move]
vector
module. It’s part of the standard library, so you don’t have to import it.
[sui.move]
push_back
method adds an element to the end of the vector, and the pop_back
method removes the last element.
You also have to option to call the functions as if they were methods
[sui.move]
Collections
You can go further with Vectors for more complex operations around a collection of items.VecSet
VecSet stores unique items, no duplicates. Very useful if you want to store addresses or unique IDs. You’ll have to importVecSet
from the Sui library like this:
[sui.move]
[sui.move]
[sui.move]
VecMap
You’d use VecMaps to store a collection of key-value pairs and access elements by their keys.The keys must be unique. If they’re not, the old one get’s replaced, better not to try.VecMaps come in handy in cases where you want to map addresses to balances or anything of the sort.You’ll have to import
VecMap
from the Sui library like this:
[sui.move]
[sui.move]
[sui.move]
Strings
Strings in Move are not like JS or Python strings. They’re byte arrays with UTF-8 encoding in theString
module.
First, you’ll need to import the module and methods you need from the string
library:
[sui.move]
utf8
method to declare a string variable.
[sui.move]
to_string
method like this:
[sui.move]
Constants
Need a value that never changes? Declare a constant with theconst
keyword:
[sui.move]
Option
Options represent values that may not exist. You’ll encase the field type withOption<Type>
to specify the field is optional.
[sui.move]
middle_name
field is optional. When the struct is initialized, it can contain a string value or remain empty.
Bags
Bags are key-value stores with no rules. They are like a carry-everything collection, storing any value of any type. They come in handy when you don’t want to restrict value types or you need to store dynamic content that you’ll unpack later. You’ll need to import bags to use them, like this:[sui.move]
[sui.move]
[sui.move]
my_key
key with the borrow
method.
Tables
Tables are an underrated data structure in Sui Move. Similar to bags, they’re strict; you’d need to specify the types in the table beforehand, and they’d be enforced on every entry. Here’s how you’ll import tables from the Sui package:[sui.move]
[sui.move]
add
method like this:
[sui.move]
add
method.
Functions and Methods
You have functions for defining reusable logic. You’ll declare them in Move modules like this:[sui.move]
greet()
function returns a String.
Functions can take in parameters and return multiple parameters as well.
[sui.move]
[sui.move]
Hero
struct as a health
field and a heal
ing function that increases that health.
Because the heal
function takes &mut Hero
as the first argument and is defined in the same module, you can call it using method syntax like hero.heal();
. It’s just syntactic sugar—the compiler rewrites it as heal(&mut hero)
under the hood.
Memory Management & Ownership
Move is built with Rust, so the ownership and borrowing primitives are valid, and they play nicely too, especially since you’re working with assets. In Move, variables aren’t copied by default—they’re moved.[sui.move]
name2
, and name
is no longer usable unless the type has the copy
ability.
Want to reuse a value without moving it? Borrow it:
[sui.move]
Generics
Generics are available for defining fields and variables that work with any type.[sui.move]
Wrapper<u64>
, a Wrapper<String>
, or whatever else.
Here’s how you’ll initialize a generic struct:
[sui.move]
store
) or the compiler will yell at you.