# Move Language Reference for Movement Blockchain

This document provides a comprehensive reference for writing Move smart contracts on the Movement blockchain.

## Movement Network Configuration

### Network Endpoints
```
Mainnet: https://full.mainnet.movementinfra.xyz/v1 (Chain ID: 126)
Testnet: https://full.testnet.movementinfra.xyz/v1 (Chain ID: 250)
Faucet:  https://faucet.movementnetwork.xyz/
Explorer: https://explorer.movementnetwork.xyz/
```

### CLI Commands
```bash
# Initialize a new Move project
movement move init --name project_name

# Compile contracts
movement move compile

# Run tests
movement move test

# Publish to testnet
movement move publish --url https://full.testnet.movementinfra.xyz/v1 --named-addresses module_addr=default

# Publish to mainnet
movement move publish --url https://full.mainnet.movementinfra.xyz/v1 --named-addresses module_addr=default
```

## Move.toml Configuration

```toml
[package]
name = "project_name"
version = "1.0.0"
authors = []

[addresses]
module_addr = "_"

[dependencies]
AptosFramework = { git = "https://github.com/aptos-labs/aptos-core.git", subdir = "aptos-move/framework/aptos-framework", rev = "mainnet" }
AptosStdlib = { git = "https://github.com/aptos-labs/aptos-core.git", subdir = "aptos-move/framework/aptos-stdlib", rev = "mainnet" }
MoveStdlib = { git = "https://github.com/aptos-labs/aptos-core.git", subdir = "aptos-move/framework/move-stdlib", rev = "mainnet" }
```

## Module Structure

```move
module module_addr::module_name {
    // Imports
    use std::signer;
    use std::string::String;
    use std::vector;
    use std::option::{Self, Option};
    use aptos_framework::event;
    use aptos_framework::account;
    use aptos_framework::timestamp;
    use aptos_framework::coin;
    use aptos_framework::aptos_coin::AptosCoin;

    // Error codes (constants)
    const E_NOT_AUTHORIZED: u64 = 1;
    const E_ALREADY_EXISTS: u64 = 2;
    const E_NOT_FOUND: u64 = 3;
    const E_INSUFFICIENT_BALANCE: u64 = 4;

    // Resources (structs with 'key' ability)
    struct ResourceName has key, store {
        field1: u64,
        field2: String,
        field3: vector<u8>,
    }

    // Events
    #[event]
    struct EventName has drop, store {
        actor: address,
        value: u64,
        timestamp: u64,
    }

    // Entry functions (callable from transactions)
    public entry fun function_name(
        account: &signer,
        param1: u64,
    ) acquires ResourceName {
        // Implementation
    }

    // View functions (read-only, callable without transaction)
    #[view]
    public fun get_value(addr: address): u64 acquires ResourceName {
        borrow_global<ResourceName>(addr).field1
    }

    // Internal functions
    fun internal_helper(): u64 {
        42
    }
}
```

## Primitive Types

| Type | Description | Example |
|------|-------------|---------|
| `u8` | 8-bit unsigned integer | `let x: u8 = 255;` |
| `u16` | 16-bit unsigned integer | `let x: u16 = 65535;` |
| `u32` | 32-bit unsigned integer | `let x: u32 = 100;` |
| `u64` | 64-bit unsigned integer | `let x: u64 = 1000000;` |
| `u128` | 128-bit unsigned integer | `let x: u128 = 1000000;` |
| `u256` | 256-bit unsigned integer | `let x: u256 = 1000000;` |
| `bool` | Boolean | `let b: bool = true;` |
| `address` | 32-byte address | `let a: address = @0x1;` |
| `vector<T>` | Dynamic array | `let v: vector<u8> = vector[];` |
| `String` | UTF-8 string | `use std::string::String;` |

## Abilities

| Ability | Description |
|---------|-------------|
| `copy` | Value can be copied |
| `drop` | Value can be dropped (destroyed) |
| `store` | Value can be stored in global storage |
| `key` | Value can be used as a key in global storage |

```move
// Resource that can be stored globally
struct MyResource has key, store {
    value: u64,
}

// Struct that can be copied and dropped
struct MyData has copy, drop, store {
    value: u64,
}

// Event struct (must have drop and store)
#[event]
struct MyEvent has drop, store {
    value: u64,
}
```

## Global Storage Operations

```move
// Store a resource at an address
move_to<ResourceName>(account, ResourceName { field1: 0, field2: string::utf8(b"hello") });

// Check if resource exists
exists<ResourceName>(addr)

// Borrow immutable reference
let resource_ref = borrow_global<ResourceName>(addr);

// Borrow mutable reference
let resource_mut = borrow_global_mut<ResourceName>(addr);

// Remove resource from storage
let resource = move_from<ResourceName>(addr);
```

## Signer Operations

```move
use std::signer;

public entry fun my_function(account: &signer) {
    // Get address from signer
    let addr = signer::address_of(account);

    // Validate caller
    assert!(addr == @admin_address, E_NOT_AUTHORIZED);
}
```

## Events

```move
use aptos_framework::event;

// Define event struct
#[event]
struct TransferEvent has drop, store {
    from: address,
    to: address,
    amount: u64,
}

// Emit event
event::emit(TransferEvent {
    from: sender_addr,
    to: recipient_addr,
    amount: 100,
});
```

## Vectors

```move
use std::vector;

// Create empty vector
let v: vector<u64> = vector[];

// Create with initial values
let v = vector[1, 2, 3];

// Push element
vector::push_back(&mut v, 4);

// Pop element
let last = vector::pop_back(&mut v);

// Get length
let len = vector::length(&v);

// Check if empty
let is_empty = vector::is_empty(&v);

// Get element by index (immutable)
let elem = vector::borrow(&v, 0);

// Get element by index (mutable)
let elem_mut = vector::borrow_mut(&mut v, 0);

// Check if contains
let contains = vector::contains(&v, &42);
```

## Strings

```move
use std::string::{Self, String};

// Create from bytes
let s: String = string::utf8(b"Hello, World!");

// Get length
let len = string::length(&s);

// Check if empty
let is_empty = string::is_empty(&s);

// Append
string::append(&mut s, string::utf8(b" More text"));

// Convert to bytes
let bytes: vector<u8> = *string::bytes(&s);
```

## Options

```move
use std::option::{Self, Option};

// Create Some
let opt: Option<u64> = option::some(42);

// Create None
let none: Option<u64> = option::none();

// Check if some
let is_some = option::is_some(&opt);

// Check if none
let is_none = option::is_none(&none);

// Extract value (aborts if none)
let value = option::extract(&mut opt);

// Get with default
let value = option::get_with_default(&opt, 0);

// Borrow value
let value_ref = option::borrow(&opt);
```

## Coin Operations

```move
use aptos_framework::coin;
use aptos_framework::aptos_coin::AptosCoin;

// Register coin store for account
coin::register<AptosCoin>(account);

// Get balance
let balance = coin::balance<AptosCoin>(addr);

// Transfer coins
coin::transfer<AptosCoin>(from, to_addr, amount);

// Withdraw coins
let coins = coin::withdraw<AptosCoin>(account, amount);

// Deposit coins
coin::deposit(to_addr, coins);
```

## Timestamp

```move
use aptos_framework::timestamp;

// Get current timestamp in seconds
let now_seconds = timestamp::now_seconds();

// Get current timestamp in microseconds
let now_microseconds = timestamp::now_microseconds();
```

## Testing

### Basic Test
```move
#[test_only]
module module_addr::module_name_tests {
    use std::signer;
    use module_addr::module_name;

    #[test(account = @0x1)]
    fun test_basic_function(account: &signer) {
        // Setup
        let addr = signer::address_of(account);

        // Action
        module_name::initialize(account);

        // Assert
        assert!(module_name::get_value(addr) == 0, 0);
    }
}
```

### Test with Expected Failure
```move
#[test]
#[expected_failure(abort_code = module_name::E_NOT_AUTHORIZED)]
fun test_unauthorized_access() {
    // This should fail with E_NOT_AUTHORIZED
    module_name::admin_only_function();
}
```

### Test with Multiple Signers
```move
#[test(admin = @0x1, user = @0x2)]
fun test_with_multiple_accounts(admin: &signer, user: &signer) {
    // Setup admin
    module_name::initialize(admin);

    // User interacts
    module_name::user_action(user);
}
```

### Test with Framework
```move
#[test(aptos_framework = @aptos_framework, account = @0x1)]
fun test_with_framework(aptos_framework: &signer, account: &signer) {
    // Setup timestamp for testing
    timestamp::set_time_has_started_for_testing(aptos_framework);

    // Now timestamp::now_seconds() works in tests
    module_name::time_dependent_function(account);
}
```

## Common Patterns

### Initialization Pattern
```move
struct Config has key {
    admin: address,
    is_initialized: bool,
}

public entry fun initialize(admin: &signer) {
    let admin_addr = signer::address_of(admin);
    assert!(!exists<Config>(admin_addr), E_ALREADY_EXISTS);

    move_to(admin, Config {
        admin: admin_addr,
        is_initialized: true,
    });
}
```

### Admin-Only Pattern
```move
public entry fun admin_function(admin: &signer) acquires Config {
    let admin_addr = signer::address_of(admin);
    let config = borrow_global<Config>(@module_addr);
    assert!(config.admin == admin_addr, E_NOT_AUTHORIZED);

    // Admin-only logic
}
```

### Counter Pattern
```move
struct Counter has key {
    value: u64,
}

public entry fun increment(account: &signer) acquires Counter {
    let addr = signer::address_of(account);

    if (!exists<Counter>(addr)) {
        move_to(account, Counter { value: 0 });
    };

    let counter = borrow_global_mut<Counter>(addr);
    counter.value = counter.value + 1;

    event::emit(CounterIncremented {
        account: addr,
        new_value: counter.value
    });
}

#[view]
public fun get_count(addr: address): u64 acquires Counter {
    if (!exists<Counter>(addr)) {
        return 0
    };
    borrow_global<Counter>(addr).value
}
```

### Token/NFT Collection Pattern
```move
struct Collection has key {
    items: vector<Item>,
    next_id: u64,
}

struct Item has store, drop {
    id: u64,
    name: String,
    owner: address,
}

public entry fun mint(account: &signer, name: String) acquires Collection {
    let addr = signer::address_of(account);
    let collection = borrow_global_mut<Collection>(@module_addr);

    let item = Item {
        id: collection.next_id,
        name,
        owner: addr,
    };

    vector::push_back(&mut collection.items, item);
    collection.next_id = collection.next_id + 1;

    event::emit(ItemMinted { id: collection.next_id - 1, owner: addr });
}
```

## Security Best Practices

1. **Always validate signers** - Check that the caller has permission
2. **Use assert! with error codes** - Provide clear error messages
3. **Emit events for state changes** - Enable off-chain tracking
4. **Check for resource existence** - Use `exists<T>(addr)` before accessing
5. **Avoid unbounded loops** - Can cause out-of-gas errors
6. **Use acquires annotation** - Declare all resources accessed
7. **Initialize before use** - Ensure resources exist before borrowing

## Complete Example: Simple Token

```move
module module_addr::simple_token {
    use std::signer;
    use std::string::String;
    use aptos_framework::event;

    // Errors
    const E_NOT_INITIALIZED: u64 = 1;
    const E_INSUFFICIENT_BALANCE: u64 = 2;

    // Resources
    struct TokenInfo has key {
        name: String,
        symbol: String,
        total_supply: u64,
    }

    struct Balance has key {
        value: u64,
    }

    // Events
    #[event]
    struct Transfer has drop, store {
        from: address,
        to: address,
        amount: u64,
    }

    // Initialize token
    public entry fun initialize(
        admin: &signer,
        name: String,
        symbol: String,
        initial_supply: u64,
    ) {
        let admin_addr = signer::address_of(admin);

        move_to(admin, TokenInfo {
            name,
            symbol,
            total_supply: initial_supply,
        });

        move_to(admin, Balance { value: initial_supply });
    }

    // Transfer tokens
    public entry fun transfer(
        from: &signer,
        to: address,
        amount: u64,
    ) acquires Balance {
        let from_addr = signer::address_of(from);

        // Deduct from sender
        let from_balance = borrow_global_mut<Balance>(from_addr);
        assert!(from_balance.value >= amount, E_INSUFFICIENT_BALANCE);
        from_balance.value = from_balance.value - amount;

        // Add to recipient
        if (!exists<Balance>(to)) {
            // Create balance for new recipient (requires signer, simplified here)
            // In practice, recipient would need to register first
        };
        let to_balance = borrow_global_mut<Balance>(to);
        to_balance.value = to_balance.value + amount;

        event::emit(Transfer { from: from_addr, to, amount });
    }

    // View balance
    #[view]
    public fun balance_of(addr: address): u64 acquires Balance {
        if (!exists<Balance>(addr)) {
            return 0
        };
        borrow_global<Balance>(addr).value
    }
}
```

