بنقرة واحدة
move-setup
// Move package setup (Move.toml, edition, dependencies), building, testing, and common pitfalls from other Move dialects.
// Move package setup (Move.toml, edition, dependencies), building, testing, and common pitfalls from other Move dialects.
| name | move-setup |
| description | Move package setup (Move.toml, edition, dependencies), building, testing, and common pitfalls from other Move dialects. |
Always use the Move 2024 edition (edition = "2024" in Move.toml). The name in [package] defines the package's address name and must match what your Move code uses (e.g., module my_package::m requires name = "my_package"):
[package]
name = "my_package"
edition = "2024"
Implicit framework dependencies (Sui 1.45+) — do not list Sui, MoveStdlib, Bridge, or SuiSystem in [dependencies]. They are implicit:
# ✅ Sui 1.45+
[dependencies]
# no framework entries needed
# ❌ Outdated
[dependencies]
Sui = { git = "...", subdir = "crates/sui-framework/packages/sui-framework", rev = "..." }
No [addresses] section (Sui CLI 1.63+) — named addresses are derived from the [package] name and [dependencies] keys. Do not add an [addresses] or [dev-addresses] section.
Run sui move build after any significant change to verify the code compiles before proceeding.
Always verify code compiles and tests pass using the Sui CLI:
# Build
sui move build
# Run all tests
sui move test
# Run a specific test by name
sui move test swap_exact_input
Naming — do not prefix test functions with test_. The #[test] attribute already signals intent:
// ✅
#[test] fun create_pool() { }
#[test] fun swap_returns_correct_amount() { }
// ❌
#[test] fun test_create_pool() { }
Merge attributes — combine #[test] and #[expected_failure] on one line:
// ✅
#[test, expected_failure(abort_code = EInsufficientLiquidity)]
fun swap_with_zero_input() { ... }
// ❌
#[test]
#[expected_failure(abort_code = EInsufficientLiquidity)]
fun swap_with_zero_input() { ... }
Don't clean up in expected_failure tests — let them abort naturally, don't add scenario.end() or other teardown:
// ✅
#[test, expected_failure(abort_code = EInsufficientLiquidity)]
fun swap_with_zero_input() {
let mut ctx = tx_context::dummy();
let pool = create_pool(&mut ctx);
pool.swap(coin::zero(&mut ctx)); // aborts here — done
}
// ❌ — don't clean up after expected failure
#[test, expected_failure(abort_code = EInsufficientLiquidity)]
fun swap_with_zero_input() {
let mut scenario = test_scenario::begin(@0xA);
// ... test body ...
scenario.end(); // unnecessary, misleading
}
Use tx_context::dummy() for simple tests — only reach for test_scenario when you genuinely need multi-transaction or multi-sender behaviour:
// ✅ Simple test — no scenario needed
#[test]
fun create_pool() {
let mut ctx = tx_context::dummy();
let pool = new_pool(&mut ctx);
assert_eq!(pool.fee_bps(), 30);
sui::test_utils::destroy(pool);
}
// ✅ Multi-sender test — scenario is appropriate
#[test]
fun only_admin_can_set_fee() {
let mut scenario = test_scenario::begin(@admin);
// ...
scenario.end();
}
Assertions — prefer assert_eq! over assert! for value comparisons (shows both sides on failure), and never pass abort codes to assert!:
// ✅
assert_eq!(pool.fee_bps(), 30);
assert!(pool.is_active());
// ❌
assert!(pool.fee_bps() == 30); // doesn't show the actual value on failure
assert!(pool.is_active(), 0); // abort code conflicts with app error codes
Destroying objects in tests — use sui::test_utils::destroy, never write custom destroy_for_testing functions:
// ✅
use sui::test_utils::destroy;
destroy(pool);
// ❌
pool.destroy_for_testing();
| Pattern | Source | Do NOT use on Sui |
|---|---|---|
acquires, move_to, move_from, borrow_global | Aptos / Core Move | Sui has no global storage |
signer type | Aptos / Core Move | Use &mut TxContext and ctx.sender() |
Script functions | Aptos | Use entry functions instead |
public(friend) | Legacy Move | Use public(package) |
Struct without public keyword | Legacy Move | All structs must be public |
let x = ... for mutable vars | Legacy Move | Use let mut x = ... |
use inside function bodies for module-level imports | Style issue | Put use at the top of the module |
&signer | Rust / Aptos | Does not exist on Sui |
Full-stack Sui blockchain development — Move smart contracts, TypeScript SDK, and frontend dApp Kit. Routes to the appropriate sub-skill based on what the user is building.
Sui object model — struct declarations, abilities (key/store/copy/drop), object ownership, naming conventions, and dynamic fields.
Move design patterns — events, error handling, one-time witness (OTW), capability pattern, and pure functions/composability.
Common Sui Move standard library patterns — strings, Coin/Balance, Option, addresses, UID, TxContext, vectors, and struct unpacking.
Move language syntax — module layout, imports, mutability, visibility, method syntax, enums, macros, and comments.
Sui frontend dApp development with @mysten/dapp-kit-react (React) and @mysten/dapp-kit-core (Vue, vanilla JS, other frameworks). Use when building browser apps that connect to Sui wallets, query on-chain data, or execute transactions. Use alongside the sui-ts-sdk skill for PTB construction patterns.