Sui Move Intro Course
repository·main·Indexed 25 days ago
https://github.com/sui-foundation/sui-move-intro-courseAn introductory educational course maintained by the Sui Foundation for the Move programming language tailored for the Sui blockchain. The curriculum covers environment setup, Sui objects, fungible tokens, marketplace contracts, Sui Kiosk, Programmable Transaction Blocks, and advanced topics such as BCS encoding.
What's inside sui-move-intro-course
- The Move Intro Course is an educational resource maintained by the Sui Foundation designed to teach the Move programming language. The course is structured into progressive units covering everything from environment setup to advanced topics like BCS encoding and Sui Kiosk.
Use the `Bag` type for heterogeneous collections
mainIn Sui Move, use theBagtype when you need a map-like collection that holds objects of different types, or when the types are not known at compile time. UnlikeVectororTable, which are homogeneous, aBagallows for heterogeneous key-value pairs. TheBagstruct acts as a handle to the Sui object system, where keys and values are stored as objects rather than within theBagvalue itself.Understand the Closed Loop Token Standard
mainThe Closed Loop token is a Sui token standard that enables contract deployers to define specificTokenPolicyobjects. These policies control how tokens are transferred, spent, minted, and other lifecycle actions, providing more granular control than the standardCointype.Understand Sui Kiosk components and architecture
mainSui Kiosk is a decentralized system for onchain commerce on Sui. It is composed of two primary shared object components that manage asset storage and trade conditions:
Kiosk+KioskOwnerCap: TheKioskacts as a shared safe that stores assets and displays them for sale. The person holding theKioskOwnerCapis the Kiosk Owner, maintaining logical ownership of the assets even when they are physically stored within the kiosk.TransferPolicy+TransferPolicyCap: TheTransferPolicyis a shared object that defines the rules and conditions for trading assets. Rules (such as royalty fee requirements) can be enabled or disabled by the holder of theTransferOwnerCap.
Understand the Sui Framework
mainThe Sui Framework is Sui's specific implementation of the Move VM. It provides native APIs, including the Move standard library, crypto primitives, and framework-level data structures (such assui::url). Developers building custom fungible tokens on Sui will heavily leverage libraries within this framework.Identify user roles in Sui Kiosk
mainSui Kiosk operations are categorized into three user roles:
- Kiosk Owner (Seller/KO): Holds the
KioskOwnerCap. They can place assets in the kiosk, withdraw non-locked assets, list assets for sale, withdraw sales profits, and borrow/mutate owned assets. - Buyer: Any user attempting to purchase listed items. A successful trade requires the buyer to satisfy the requirements defined in the
TransferPolicy. - Creator: The party that creates and controls the
TransferPolicyfor a specific type (e.g., a specific NFT collection). Creators can set rules, manage multiple rule tracks, enable/disable trades via policy, and enforce royalties globally.
- Kiosk Owner (Seller/KO): Holds the
Learn Sui Kiosk and Programmable Transaction Blocks (Unit Five)
mainUnit Five of the Sui Move Intro Course provides instruction on advanced Sui features including Programmable Transaction Blocks (PTBs), the 'hot potato' design pattern, Sui Kiosk fundamentals, and Transfer Policies. The unit is divided into five specific lessons covering these topics.Understand Programmable Transaction Blocks (PTB)
mainA Programmable Transaction Block (PTB) is a native feature of the Sui Network and Sui VM that allows developers to batch multiple individual commands into a single atomic transaction. This enables high composability and scalability by allowing the output of one command to be used as the input for a subsequent command within the same block.
Key Features:
- Chaining Commands: PTBs are composed of multiple commands (such as
MoveCall) executed in order. - Atomicity: If any single command within the PTB fails, the entire transaction fails, and no effects are applied to the blockchain.
- Scalability: A single PTB can contain up to 1024 unique operations, reducing gas fees and latency compared to sequential individual transactions.
- Resource Management: If a command returns a non-
dropvalue, that value must be consumed by a subsequent command within the same PTB, or the transaction will fail.
- Chaining Commands: PTBs are composed of multiple commands (such as
Understand Dynamic Fields vs. Dynamic Object Fields
mainSui Move provides two ways to attach heterogeneous fields to an object at runtime:
Dynamic Fields (
sui::dynamic_field):- Can store any value with the
storeability. - Values are considered wrapped. They are not directly accessible via their ID by external tools like explorers or wallets.
- Use these when the child type does not need the
keyability.
- Can store any value with the
Dynamic Object Fields (
sui::dynamic_object_field):- Values must be Sui objects (must have
keyandstoreabilities, andid: UIDas the first field). - Values remain directly accessible via their object ID even after being attached to a parent.
- Use these when the child is a Sui object that needs to be independently addressable.
- Values must be Sui objects (must have
Create a new Kiosk
mainYou can create a new Kiosk using two different methods. A Kiosk is a shared object, and the owner receives a
KioskOwnerCapto manage it.Method 1: Custom Implementation
Deploy a contract that calls
kiosk::new(ctx), shares theKioskobject viatransfer::public_share_object, and transfers theKioskOwnerCapto the sender viatransfer::public_transfer.Method 2: Using
kiosk::default()Use the
entry kiosk::default()function to automatically handle the creation, sharing of the Kiosk, and transfer of theKioskOwnerCapin one step.To interact via the CLI, use:
sui client call --package $KIOSK_PACKAGE_ID --module kiosk --function new_kioskAfter creation, export the resulting object IDs for subsequent operations:
export KIOSK=<Object id of newly created Kiosk> export KIOSK_OWNER_CAP=<Object id of newly created KioskOwnerCap>Configure VS Code with Move Analyzer
mainTo improve the development experience in VS Code, install the Move Analyzer plugin from the VS Marketplace. To ensure compatibility with Sui-style wallet addresses, you must also install the analyzer with the
address20feature enabled via Cargo.cargo install --git https://github.com/move-language/move move-analyzer --features "address20"Define and emit custom events in Sui Move
mainCustom events allow indexers to track specific on-chain actions. When defining custom events, follow these conventions:
- Naming: Use past tense for event names (e.g.,
TranscriptRequested) because they describe actions that have already occurred. - Abilities: Event types must have the
copyanddropabilities. They are not assets; they are used solely for data logging. - Emission: Use the
sui::event::emitmethod to trigger the event.
Example of defining and emitting a custom event:
// 1. Define the event struct with copy and drop abilities public struct TranscriptRequested has copy, drop { wrapper_id: ID, requester: address, intended_address: address, } // 2. Emit the event within a function public fun request_transcript( transcript: WrappableTranscript, intended_address: address, ctx: &mut TxContext, ) { let folder_object = Folder { id: object::new(ctx), transcript, intended_address, }; event::emit(TranscriptRequested { wrapper_id: object::id(&folder_object), requester: ctx.sender(), intended_address, }); transfer::transfer(folder_object, intended_address); }public struct TranscriptRequested has copy, drop { wrapper_id: ID, requester: address, intended_address: address, } public fun request_transcript( transcript: WrappableTranscript, intended_address: address, ctx: &mut TxContext, ) { let folder_object = Folder { id: object::new(ctx), transcript, intended_address, }; event::emit(TranscriptRequested { wrapper_id: object::id(&folder_object), requester: ctx.sender(), intended_address, }); transfer::transfer(folder_object, intended_address); }- Naming: Use past tense for event names (e.g.,