> For the complete documentation index, see [llms.txt](https://initia.gitbook.io/initia/kBNuZF5MglV9d3zOOUeW/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://initia.gitbook.io/initia/kBNuZF5MglV9d3zOOUeW/initia-developer-tutorials/3.-interchain-message.md).

# 3. Interchain Message

## OP bridge deposit

Transfer coin from Initia to Minitia via OP bridge.

{% tabs %}
{% tab title="CLI" %}

```bash
> initiad tx ophost initiate-token-deposit [bridge_id] [addr] 1000000uinit ''\
  --from [key-name] \
  --gas auto --gas-adjustment 1.5 --gas-prices 0.15uinit \
  --node [rpc-url]:[rpc-port] --chain-id [chain-id]
```

{% endtab %}

{% tab title="initia.js" %}

```typescript
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();

```

{% endtab %}
{% endtabs %}

***

## OP bridge withdraw

Withdraw coin from Minitia to Initia via OP bridge.&#x20;

There is a *finalization period* that must be passed after the `withdraw` transaction has been executed before you can execute `finalize-token-withdrawal`.

{% tabs %}
{% tab title="CLI" %}

```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]
```

{% endtab %}

{% tab title="initia.js" %}

```typescript
import {
  Coin,
  LCDClient,
  MnemonicKey,
  MsgInitiateTokenWithdrawal,
  Wallet,
} from '@initia/initia.js';

async function initiateTokenWithdraw() {
  const lcd = new LCDClient('[l2-rest-url]', {
    gasPrices: '0.15unova', // gas price in your l2 denom
    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();

```

{% endtab %}
{% endtabs %}

***

## OP bridge finalize token withdrawal

Finalization period has to pass after `withdraw` transaction has been executed in order to execute `finalize-token-withdrawal` transaction to receive coins on Initia Layer 1.

The data required in below example can be fetched from Executor API of each Minitia.

{% tabs %}
{% tab title="CLI" %}

```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]
```

{% endtab %}

{% tab title="initia.js" %}

```typescript
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');
}
```

{% endtab %}
{% endtabs %}

***

## IBC token transfer

Transfer tokens to other chains / Minitias via IBC transfer.

{% tabs %}
{% tab title="CLI" %}

```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]
```

{% endtab %}

{% tab title="initia.js" %}

```typescript
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();
```

{% endtab %}
{% endtabs %}

***

## IBC NFT transfer

Transfer NFTs to other chains / Minitias via IBC NFT transfer.

{% tabs %}
{% tab title="CLI" %}

```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]
```

{% endtab %}

{% tab title="initia.js" %}

```typescript
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();
```

{% endtab %}
{% endtabs %}
