Deploying Move Modules
Overview
This tutorial will guide you through the process of building, publishing, and interacting with your own Move modules on the Initia blockchain. Specifically, we'll work with the read_write module from the initia-tutorials repository. Here's how to get started:
Tutorial
Step 1: Clone initia-tutorials
initia-tutorialsFirst, clone the initia-tutorials repository, which contains the read_write module we'll be using.
git clone git@github.com:initia-labs/initia-tutorials.gitStep 2: Build a Module
Before building the module, you need to update the module owner's address to your own address in the Move.toml configuration file located in ./initia-tutorials/move/read_write.
How to Get Your HEX Address:
Use the following command to parse your Initia address into bytes format, which is your HEX address.
> initiad keys parse [addr]example output:
bytes: F64D24B10B0CE93CD428DF3AB9228ADB18B93CFE
human: initimport { AccAddress } from '@initia/initia.js';
console.log(AccAddress.toHex('[addr]'));
// 0x7b23641ee96425a5dbe9953bdd949da7f6c5fcb0Now, modify the Move.toml file to include your HEX address:
[package]
name = "read_write"
version = "0.0.0"
[dependencies]
InitiaStdlib = { git = "https://github.com/initia-labs/movevm.git", subdir = "precompile/modules/initia_stdlib", rev = "main" }
[addresses]
std =  "0x1"
your_address = "{insert your hex address here}"Build the module using either CLI or builder.js:
> initiad move build --path ./initia-tutorials/move/read_writeimport { MoveBuilder } from '@initia/builder.js';
const path =
  '${path_to_initia_tutorials}/move/read_write';
async function buildModule() {
  const builder = new MoveBuilder(path, {});
  await builder.build();
}
buildModule();Step 3: Publish a Module
After building your module, the next step is to publish it to the Initia blockchain.
>initiad move deploy \
  --path ./initia-tutorials/move/read_write \
  --upgrade-policy COMPATIBLE \
  --from test-account \
  --gas auto --gas-adjustment 1.5 \
  --gas-prices 0.15uinit \
  --node [rpc-url]:[rpc-port] \
  --chain-id [chain-id]import { LCDClient, MnemonicKey, MsgPublish, Wallet } from '@initia/initia.js';
import { MoveBuilder } from '@initia/builder.js';
import * as fs from 'fs';
const path =
  '${path_to_initia_tutorials}/move/read_write';
async function publishModule() {
  const lcd = new LCDClient('https://stone-rest.initia.tech', {
    gasPrices: '0.15uinit',
    gasAdjustment: '1.5',
  });
  const builder = new MoveBuilder(path, {});
  await builder.build();
  const key = new MnemonicKey({
    mnemonic:
      'beauty sniff protect ...',
  });
  const wallet = new Wallet(lcd, key);
  const codeBytes = fs.readFileSync(
    `${path}/build/read_write/bytecode_modules/read_write.mv`
  );
  // const codeBytes = await builder.get('read_write'); // or you can get with MoveBuilder
  const msgs = [
    new MsgPublish(key.accAddress, [codeBytes.toString('base64')], 1),
  ];
  // sign tx
  const signedTx = await wallet.createAndSignTx({ msgs });
  // send(broadcast) tx
  lcd.tx.broadcastSync(signedTx).then(res => console.log(res));
  // {
  //   height: 0,
  //   txhash: '162AA29DE237BD060EFEFFA862DBD07ECD1C562EBFDD965AD6C34DF856B53DC2',
  //   raw_log: '[]'
  // }
}
publishModule();About the upgrade policy:
COMPATIBLE
Performs a compatibility check during upgrades, ensuring no public function changes or resource layout modifications.
IMMUTABLE
Marks the modules as immutable, preventing any future upgrades.
Step 4: Interact with Your Published Module
After publishing, you can interact with your module through various Move scripts or direct calls from client applications.
> initiad query move view [addr] read_write read \                               
  --node [rpc-url]:[rpc-port]
data: '"initial content"'
> initiad tx move execute [addr] read_write write \
  --args "string:new_string" \
  --from [key-name] \
  --gas auto --gas-adjustment 1.5 --gas-prices 0.15uinit \
  --node [rpc-url]:[rpc-port] --chain-id [chain-id]
  
> initiad query move view [addr] read_write read \       
  --node [rpc-url]:[rpc-port]
data: '"new_string"'import {
  bcs,
  LCDClient,
  MnemonicKey,
  MsgExecute,
  Wallet,
} from '@initia/initia.js';
async function setNewContent() {
  const lcd = new LCDClient('[rest-url]', {
    gasPrices: '0.15uinit',
    gasAdjustment: '1.5',
  });
  const key = new MnemonicKey({
    mnemonic: 'beauty sniff protect ...',
  });
  const wallet = new Wallet(lcd, key);
  await lcd.move
    .viewFunction(key.accAddress, 'read_write', 'read')
    .then(res => console.log('before write:', res));
  const msgs = [
    new MsgExecute(
      key.accAddress,
      key.accAddress,
      'read_write',
      'write',
      [],
      [bcs.string().serialize('new_string').toBase64()]
    ),
  ];
  // sign tx
  const signedTx = await wallet.createAndSignTx({ msgs });
  // send(broadcast) tx
  await lcd.tx.broadcastSync(signedTx).then(res => console.log(res));
  // {
  //   height: 0,
  //   txhash: '162AA29DE237BD060EFEFFA862DBD07ECD1C562EBFDD965AD6C34DF856B53DC2',
  //   raw_log: '[]'
  // }
  await lcd.move
    .viewFunction(key.accAddress, 'read_write', 'read')
    .then(res => console.log('after write:', res));
}
setNewContent();
Last updated