Let's Move - Learn Move, Earn Sui: Complete NFT Deployment on Mainnet

·

The Sui blockchain is redefining how developers interact with decentralized systems, and at the heart of this evolution is Move, a secure, flexible programming language designed for digital assets. The Let's Move initiative encourages developers to dive into Move by completing practical tasks—like creating and deploying NFTs—and earning rewards in SUI. This guide walks you through Task 3: deploying an NFT smart contract on the Sui mainnet, minting your first NFT, and transferring it to a designated address.

Whether you're new to Move or expanding your blockchain development skills, this step-by-step walkthrough ensures clarity, correctness, and real-world applicability.

Understanding the Task Requirements

Before writing any code, let’s break down what Task 3 entails:

This process tests both your understanding of Move syntax and your ability to interact with the Sui network using the command-line interface (CLI). Success means not only writing functional code but also executing it securely on a live blockchain.

👉 Discover how to start building on Sui with powerful tools and resources

Core Components of a Move-Based NFT Contract

The foundation of any NFT project on Sui lies in its Move module. Below is a clean, well-structured version of the simple_nft module that satisfies all task requirements.

module new_nft::simple_nft {
    use sui::url::{Url, Self};
    use std::string;
    use sui::object::{Self, ID, UID};
    use sui::event;
    use sui::transfer;
    use sui::tx_context::{TxContext, Self};

    struct SimpleNFT has key, store {
        id: UID,
        name: string::String,
        description: string::String,
        url: Url,
    }

    struct SimpleNftMintEvent has copy, drop {
        object_id: ID,
        creator: address,
        name: string::String,
    }

    struct SimpleNftTransferEvent has copy, drop {
        object_id: ID,
        from: address,
        to: address,
    }

    struct SimpleNftBurnEvent has copy, drop {
        object_id: ID,
    }

    // Public view functions
    public fun name(nft: &SimpleNFT): string::String {
        nft.name
    }

    public fun description(nft: &SimpleNFT): string::String {
        nft.description
    }

    public fun url(nft: &SimpleNFT): Url {
        nft.url
    }

    // Entry point to mint an NFT
    public entry fun mint_nft(
        name: vector<u8>,
        description: vector<u8>,
        url: vector<u8>,
        ctx: &mut TxContext
    ) {
        let sender = tx_context::sender(ctx);
        let nft = SimpleNFT {
            id: object::new(ctx),
            name: string::utf8(name),
            description: string::utf8(description),
            url: url::new_unsafe_from_bytes(url),
        };
        event::emit(SimpleNftMintEvent {
            object_id: object::id(&nft),
            creator: sender,
            name: nft.name,
        });
        transfer::public_transfer(nft, sender);
    }

    // Transfer ownership of an NFT
    public entry fun transfer_nft(
        nft: SimpleNFT,
        recipient: address,
        _: &mut TxContext
    ) {
        event::emit(SimpleNftTransferEvent {
            object_id: object::id(&nft),
            from: tx_context::sender(_),
            to: recipient,
        });
        transfer::public_transfer(nft, recipient);
    }

    // Update NFT metadata (description only)
    public entry fun update_description(
        nft: &mut SimpleNFT,
        description: vector<u8>,
        _: &mut TxContext
    ) {
        nft.description = string::utf8(description);
    }

    // Burn (destroy) an NFT
    public entry fun burn(
        nft: SimpleNFT,
        _: &mut TxContext
    ) {
        let SimpleNFT { id, name: _, description: _, url: _ } = nft;
        event::emit(SimpleNftBurnEvent {
            object_id: object::uid_to_inner(&id),
        });
        object::delete(id);
    }
}

Key Features Explained

These components align perfectly with Sui’s object-centric model and security-first design principles.

Deploying the Contract to Sui Mainnet

Once your code is ready, it’s time to deploy it live.

Step 1: Switch to Mainnet Environment

Ensure your Sui client targets the mainnet:

sui client switch --env mainnet

You’ll see confirmation:

Active environment switched to [mainnet]

Step 2: Publish the Package

Run the publish command with sufficient gas:

sui client publish --gas-budget 200000000 --skip-dependency-verification
💡 Tip: The --skip-dependency-verification flag speeds up publishing when dependencies are known and trusted.

After successful deployment, note the Package ID—you’ll need it for all subsequent interactions.

👉 Access advanced blockchain development tools to streamline deployment

Minting and Transferring Your First NFT

Now that the contract is live, you can mint and send NFTs.

Step 1: Set Environment Variables

Replace placeholders with actual values:

export PACKAGE_ID=0xf78fb118efd9a86d8e2c54ac18766a1313bd8b0df80c85f859f83d01a5f78981
export NFT_NAME="\"joker\""
export DESCRIPTION="\"simple nft, powered by alva-lin\""
export URL='"https://example.com/nft-image.png"'

Step 2: Mint the NFT

Call the mint_nft function:

sui client call \
  --gas-budget 7500000 \
  --package $PACKAGE_ID \
  --module simple_nft \
  --function mint_nft \
  --args $NFT_NAME $DESCRIPTION $URL

Upon success, the CLI returns the newly created NFT Object ID.

Step 3: Transfer NFT to Designated Address

Use the returned Object ID and execute the transfer:

export NFT_ID=0xc1d108cdeef7666aa3f414bb3ead5faa7cd351e4dc75d0307e2888b640232787
export RECIPIENT=0x7b8e0864967427679b4e129f79dc332a885c6087ec9e187b53451a9006ee15f2

sui client call \
  --gas-budget 7500000 \
  --package $PACKAGE_ID \
  --module simple_nft \
  --function transfer_nft \
  --args $NFT_ID $RECIPIENT

Your transaction will be processed, and the NFT ownership officially transferred.

Frequently Asked Questions (FAQ)

Q1: What is the purpose of the Let's Move program?
A: Let's Move is an educational initiative that incentivizes developers to learn Move by completing hands-on tasks on the Sui blockchain. Participants gain practical experience while earning SUI rewards.

Q2: Why use vector<u8> instead of string in entry functions?
A: Move does not support direct string arguments in entry functions. Instead, UTF-8 encoded byte vectors (vector<u8>) are used and converted internally using string::utf8().

Q3: Can I update other fields besides description?
A: In this implementation, only description can be updated. Adding name or URL updates requires additional entry functions and careful access control.

Q4: How do I verify my NFT was minted successfully?
A: Use the Sui Explorer (e.g., Sui Vision) and search for your Object ID. You should see the NFT with correct metadata.

Q5: Is burning reversible?
A: No. Once an NFT is burned using object::delete, it is permanently removed from the ledger.

Q6: What happens if I lose my Object ID?
A: Without the Object ID, you cannot reference or transfer the NFT. Always store IDs securely after minting.

Final Thoughts

Completing Task 3 of Let's Move isn't just about fulfilling requirements—it's about mastering fundamental skills in Move programming, smart contract deployment, and on-chain interaction. By building, publishing, and managing NFTs on Sui mainnet, you’re gaining experience directly applicable to real-world Web3 development.

As Sui continues to grow, proficiency in Move becomes increasingly valuable. Whether you're aiming to build scalable dApps or innovate in digital ownership, this foundation sets you on the right path.

👉 Accelerate your journey in Web3 with cutting-edge infrastructure and support