Deploy your First Move Contract
Welcome to your journey in deploying a Move module (smart contract) on the Movement .
Smart contracts are called modules in Move.
This guide will walk you through each step, from setup to deployment.
Prerequisites
You need to have one of these command-line interfaces (CLIs) installed :
- Movement CLI: Installation Guide
- Aptos CLI: Installation Guide
Step 1: Initialize the CLI
Open your terminal and navigate to your project directory:
movement init --skip-faucetCLI Configuration Prompts
When prompted:
-
Type
customfor network selection -
Use these Network Endpoints:
- RPC/Rest Endpoint:
https://aptos.testnet.porto.movementlabs.xyz/v1 - Faucet Endpoint:
https://faucet.testnet.porto.movementnetwork.xyz/
- RPC/Rest Endpoint:
-
For Private Key:
- Enter an existing private key, or
- Press Enter to generate a new one
Step 2: Fund Your Account
- Copy your account address from the initialization message
- Visit the Movement Labs Web Faucet
- Request testnet tokens by pasting your account address
Step 3: Understand Project Configuration
The initialization creates a .movement folder with config.yaml:
profiles:
default:
network: Testnet
private_key: "YOUR_PRIVATE_KEY"
public_key: "YOUR_PUBLIC_KEY"
account: "YOUR_ACCOUNT_ADDRESS"
rest_url: "https://aptos.testnet.porto.movementlabs.xyz/v1/"
faucet_url: "https://faucet.testnet.porto.movementlabs.xyz/"Step 4: Scaffold the Move Project
Create your project structure:
movement move init --name hello_blockchainThis generates:
Move.toml: Project configurationSources/: Module code directoryScripts/: Transaction scriptsTests/: Unit tests directory
Step 5: Write Your First Module
Create Sources/hello_blockchain.move:
module hello_blockchain::message {
use std::error;
use std::signer;
use std::string::{String};
use aptos_framework::account;
use aptos_framework::event;
struct MessageHolder has key {
message: String,
message_change_events: event::EventHandle<MessageChangeEvent>,
}
struct MessageChangeEvent has drop, store {
from_message: String,
to_message: String,
}
const ENO_MESSAGE: u64 = 0;
#[view]
public fun signature(): address {
@hello_blockchain
}
#[view]
public fun get_message(addr: address): String acquires MessageHolder {
assert!(exists<MessageHolder>(addr), error::not_found(ENO_MESSAGE));
borrow_global<MessageHolder>(addr).message
}
public entry fun set_message(account: signer, message: String) acquires MessageHolder {
let account_addr = signer::address_of(&account);
if (!exists<MessageHolder>(account_addr)) {
move_to(&account, MessageHolder {
message,
message_change_events: account::new_event_handle<MessageChangeEvent>(&account),
});
} else {
let message_holder = borrow_global_mut<MessageHolder>(account_addr);
let from_message = message_holder.message;
event::emit_event(&mut message_holder.message_change_events, MessageChangeEvent {
from_message,
to_message: copy message,
});
message_holder.message = message;
}
}
#[test(account = @0x1)]
public entry fun sender_can_set_message(account: signer) acquires MessageHolder {
let addr = signer::address_of(&account);
aptos_framework::account::create_account_for_test(addr);
set_message(account, std::string::utf8(b"Hello, Blockchain"));
assert!(
get_message(addr) == std::string::utf8(b"Hello, Blockchain"),
ENO_MESSAGE
);
}
#[test]
public fun signature_okay() {
assert!(signature() == @hello_blockchain, ENO_MESSAGE);
}
}Step 6: Compile the Module
movement move compile --named-addresses hello_blockchain=defaultStep 7: Test the Module
movement move testStep 8: Publish the Module
movement move publishConfirm the transaction when you're prompted to.
Congratulations! You've deployed your first Move module. You can view module details in the explorer and interact using Movement CLI or custom scripts.