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",