diff --git a/developers/developer-guides/guides/interchain-message.mdx b/developers/developer-guides/guides/interchain-message.mdx
new file mode 100644
index 00000000..9284199b
--- /dev/null
+++ b/developers/developer-guides/guides/interchain-message.mdx
@@ -0,0 +1,347 @@
+---
+title: Interchain Message Guide
+---
+
+Interchain communication facilitates the transfer of assets and information between distinct blockchain networks.
+
+This tutorial focuses on asset transfers, including tokens and NFTs, between Initia (Layer 1) and Minitia (Layer 2), using the OP bridge for token transfers and IBC (Inter-Blockchain Communication) for token and NFT transfers.
+
+We'll cover initiating token deposits, withdrawing tokens, finalizing token withdrawals, and transferring tokens and NFTs via IBC.
+
+## OP Bridge Token Transfer
+
+### Initiating a Token Deposit from Initia to Minitia
+
+To transfer tokens from Initia to Minitia using the OP bridge, you must initiate a token deposit on the Initia blockchain. The process involves creating a transaction that locks the tokens on Initia, making them available on Minitia.
+
+
+
+ ```bash
+ > initiad keys add [key-name]
+
+ - address: init17exjfvgtpn5ne4pgmuatjg52mvvtj08773tgfx
+ name: test-account
+ pubkey: '{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"Ap+WnRzOsJGgfgsrgc4APi/EiTzl3t52ruiKGev7X9LW"}'
+ type: local
+
+
+ **Important** write this mnemonic phrase in a safe place.
+ It is the only way to recover your account if you ever forget your password.
+
+ angry opera upper ...
+ ```
+
+
+ ```ts InitiaJS
+ import {
+ Coin,
+ LCDClient,
+ MnemonicKey,
+ MsgInitiateTokenDeposit,
+ Wallet,
+ } from '@initia/initia.js';
+
+ async function initiateTokenDeposit() {
+ 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);
+
+ const msgs = [
+ new MsgInitiateTokenDeposit(
+ key.accAddress, // sender
+ 3, // bridge id
+ 'init1gegp28h8n7lv85ydltycenmw8dndn9umnn697q', // reciever
+ new Coin('uinit', 1) // coin
+ ),
+ ];
+
+ // 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: '[]'
+ // }
+ }
+
+ initiateTokenDeposit();
+ ```
+
+
+
+### Withdrawing Tokens from Minitia to Initia
+
+There is a finalization period that must be passed after the `withdraw` transaction has been executed before you can execute `finalize-token-withdrawal`.
+
+
+
+ ```bash
+ > minitiad tx opchild withdraw [addr] [amount]\
+ --from [key-name] \
+ --gas auto --gas-adjustment 1.5 --gas-prices [l2_gas_price] \
+ --node [rpc-url]:[rpc-port] --chain-id [chain-id]
+ ```
+
+
+ ```ts InitiaJS
+ import {
+ Coin,
+ LCDClient,
+ MnemonicKey,
+ MsgInitiateTokenWithdrawal,
+ Wallet,
+ } from '@initia/initia.js';
+
+ async function initiateTokenWithdraw() {
+ const lcd = new LCDClient('[rest-url]', {
+ gasPrices: '0.15l2/...',
+ gasAdjustment: '1.5',
+ });
+
+ const key = new MnemonicKey({
+ mnemonic:
+ 'beauty sniff protect ...',
+ });
+ const wallet = new Wallet(lcd, key);
+
+ const msgs = [
+ new MsgInitiateTokenWithdrawal(
+ key.accAddress, // sender
+ 'init1gegp28h8n7lv85ydltycenmw8dndn9umnn697q', // reciever
+ new Coin('l2/...', 1) // coin
+ ),
+ ];
+
+ // 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: '[]'
+ // }
+ }
+
+ initiateTokenWithdraw();
+ ```
+
+
+
+### Finalizing Token Withdrawal on Initia
+
+
+
+ ```bash
+ > initiad tx ophost finalize-token-withdrawal [path/to/withdrawal-info.json] \
+ --from [key-name] \
+ --gas auto --gas-adjustment 1.5 --gas-prices 0.15uinit \
+ --node [rpc-url]:[rpc-port] --chain-id [chain-id]
+ ```
+
+
+ ```ts InitiaJS
+ import {
+ Coin,
+ LCDClient,
+ MnemonicKey,
+ MsgFinalizeTokenWithdrawal,
+ Wallet,
+ } from '@initia/initia.js';
+ import * as crypto from 'crypto';
+
+ async function finalizeTokenWithdrawal() {
+ 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);
+
+ const msgs = [
+ new MsgFinalizeTokenWithdrawal(
+ 3, // bridge id
+ 492, // output index
+ [], // merkle proof
+ key.accAddress, // sender
+ 'init1wgl839zxdh5c89mvc4ps97wyx6ejjygxs4qmcx', // receiver
+ 1, // sequence
+ new Coin('uinit', 100000), // amount
+ sha3_256(492), // version
+ 'YNWpXXUHHtPVmDVHTCEb6WzJFNGGc7FnqeIskFS+lsU=', // state root
+ 'Tegv5DHAE6gZJJy9Yn4wY1mV3sqOzh7da8BC4mf/vE4=', // storage root
+ 'oY7lpEEBdRmaV3lXkNlwTK2S9W4xPX7jHm93Ao4zfa0=' // latest block hash
+ ),
+ ];
+
+ // 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: '[]'
+ // }
+ }
+
+ finalizeTokenWithdrawal();
+
+ function sha3_256(version: number) {
+ const hash = crypto.createHash('SHA3-256');
+ let hex = version.toString(16);
+ if (hex.length % 2 === 1) {
+ hex = '0' + hex;
+ }
+ const val = Buffer.from(hex, 'hex');
+ return hash.update(val).digest().toString('base64');
+ }
+ ```
+
+
+
+## IBC Bridge Token Tranfer
+
+IBC allows the transfer of tokens and NFTs between different blockchains that support the IBC protocol.
+
+### Transferring Tokens via IBC
+
+
+
+ ```bash
+ > initiad tx ibc-transfer transfer \
+ transfer [src-channel] [addr] 1000000uinit \
+ --from [key-name] \
+ --gas auto --gas-adjustment 1.5 --gas-prices 0.15uinit \
+ --node [rpc-url]:[rpc-port] --chain-id [chain-id]
+ ```
+
+
+ ```ts InitiaJS
+ import {
+ Coin,
+ Height,
+ LCDClient,
+ MnemonicKey,
+ MsgTransfer,
+ Wallet,
+ } from '@initia/initia.js';
+
+ async function ibcTokenTransfer() {
+ 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);
+
+ const msgs = [
+ new MsgTransfer(
+ 'transfer', // port
+ 'channel-1', // src channel
+ new Coin('uinit', 1234), // amount
+ key.accAddress, // sender
+ key.accAddress, // receiver
+ // you have to provide one of timeout
+ new Height(0, 0), // timeout height
+ ((new Date().valueOf() + 100000) * 1000000).toString() // timeout timestamp
+ ),
+ ];
+
+ // 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: '[]'
+ // }
+ }
+
+ ibcTokenTransfer();
+ ```
+
+
+
+### Transferring NFTs via IBC
+
+
+
+ ```bash
+ > initiad tx ibc-nft-transfer nft-transfer \
+ nft-transfer [src-channel] [receiver] [class-id] [token-id],...[token-id] \
+ --from [key-name] \
+ --gas auto --gas-adjustment 1.5 --gas-prices 0.15uinit \
+ --node [rpc-url]:[rpc-port] --chain-id [chain-id]
+ ```
+
+
+ ```ts InitiaJS
+ import {
+ Coin,
+ Height,
+ LCDClient,
+ MnemonicKey,
+ MsgNftTransfer,
+ Wallet,
+ } from '@initia/initia.js';
+
+ async function ibcNftTrnasfer() {
+ 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);
+
+ const msgs = [
+ new MsgNftTransfer(
+ 'nft-transfer', // port
+ 'channel-3', // channel id
+ 'move/bfe696257ce629b8cfc03c44c4b732973705cf00fa87279e9440547215850a71', // class id
+ [tokenid], // token ids
+ key.accAddress, // sender
+ key.accAddress, // receiver
+ // you have to provide one of timeout
+ new Height(0, 0), // timeout height
+ ((new Date().valueOf() + 100000) * 1000000).toString() // timeout timestamp
+ ),
+ ];
+
+ // 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: '[]'
+ // }
+ }
+
+ ibcNftTrnasfer();
+ ```
+
+
diff --git a/developers/developer-guides/guides/minitswap-arbitrage.mdx b/developers/developer-guides/guides/minitswap-arbitrage.mdx
new file mode 100644
index 00000000..91f37cc1
--- /dev/null
+++ b/developers/developer-guides/guides/minitswap-arbitrage.mdx
@@ -0,0 +1,85 @@
+---
+title: Minitswap Arbitrage Guide
+---
+
+
+## Arbitrage Opportunity: IBC opINIT Price Lower than INIT Price in Minitswap
+
+In the Minitswap Virtual Pool, if the amount of IBC opINIT exceeds INIT, the price of IBC opINIT will be lower than INIT.
+
+In this case, users can exchange IBC opINIT for INIT by undergoing a 7-day challenge period on their behalf.
+
+To do this, the following steps can be taken:
+
+
+
+ When an arbitrage opportunity arises in a specific L2's Virtual Pool within Minitswap, where the price of INIT is higher than that of IBC opINIT, users may swap INIT for IBC opINIT.
+
+ During this process, it is essential to take into account both swap fees and slippage.
+
+ See [Minitswap swap](/developers/developer-guides/integrating-initia-apps/minitswap#swap).
+
+
+ Transfer the swapped IBC opINIT to the appropriate L2 through the IBC Bridge.
+
+ Note that if Milkyway's IBC opINIT was swapped, the assets must be transferred to the Milkyway L2.
+
+ Upon reaching L2, IBC opINIT will be converted to opINIT.
+
+ See [IBC bridge token transfer](/developers/developer-guides/guides/interchain-message#transferring-tokens-via-ibc).
+
+
+ To transfer opINIT to L1 using the OP Bridge, initiate a withdrawal by executing `MsgInitiateTokenWithdrawal`.
+
+ See [OP bridge withdrawal](/developers/developer-guides/guides/interchain-message#withdrawing-tokens-from-minitia-to-initia)
+
+
+ After the 7-day Challenge Period, finalize the withdrawal process to exchange IBC opINIT for INIT by executing `MsgFinalizeWithdraw`.
+
+ See [OP bridge finalization](/developers/developer-guides/guides/interchain-message#finalizing-token-withdrawal-on-initia)
+
+
+
+## Arbitrage Opportunity: INIT Price Lower than IBC opINIT Price in Minitswap
+
+In the Minitswap Virtual Pool, if the amount of INIT exceeds IBC opINIT, the price of INIT will be lower than IBC opINIT.
+
+Users can exchange INIT for IBC opINIT through several bridge transfers.
+
+To do this, the following steps can be taken:
+
+
+Generally, INIT can always be converted 1:1 to IBC opINIT, which means that in the Minitswap pool, the price of IBC opINIT is usually lower than that of INIT.
+
+
+
+
+ When an arbitrage opportunity aries in a specific L2's Virtual Pool within Minitswap, where the price of INIT is lower than that of IBC opINIT, users may swap IBC opINIT for INIT.
+
+ During this process, it is essential to take into account both swap fees and slippage.
+
+ See [Minitswap swap](/developers/developer-guides/integrating-initia-apps/minitswap#swap).
+
+
+ Transfer the swapped INIT to the appropriate L2 through the OP Bridge.
+
+ Note that if Milkyway's INIT was swapped, the assets must be transferred to the Milkyway L2.
+
+ Upon reaching L2, INIT will be converted to opINIT.
+
+ See [OP bridge token transfer](/developers/developer-guides/guides/interchain-message#initiating-a-token-deposit-from-initia-to-minitia).
+
+
+ opINIT transferred to L2 is moved to L1 through the IBC bridge.
+
+ The opINIT moved to L1 will be converted to IBC opINIT.
+
+ See [IBC bridge token transfer](/developers/developer-guides/guides/interchain-message#transferring-tokens-via-ibc).
+
+
+ IBC opINIT received in L1 is exchanged for INIT in the Minitswap pool.
+
+ See [Minitswap swap](/developers/developer-guides/integrating-initia-apps/minitswap#swap).
+
+
+
diff --git a/mint.json b/mint.json
index 12d13694..19a227f3 100644
--- a/mint.json
+++ b/mint.json
@@ -188,7 +188,11 @@
{
"group": "Guides",
"icon": "book",
- "pages": ["developers/developer-guides/guides/exchange-integration"]
+ "pages": [
+ "developers/developer-guides/guides/exchange-integration",
+ "developers/developer-guides/guides/interchain-message",
+ "developers/developer-guides/guides/minitswap-arbitrage"
+ ]
},
{
"group": "VM Specific Tutorials",