Mock Interchain Environment
This environment allows you to test your IBC application inside your Rust environment without having to create new crates, new packages or even run other programs in the background. This is perfect for iterating through your designs and testing on the go without additional wait time or setup tutorials.
Environment creation
You can create your interchain environment using the following simple setup script:
use cw_orch::prelude::*;
use cw_orch_interchain::interchain::MockInterchainEnv;
fn main(){
let sender = Addr::unchecked("sender");
let mut interchain = MockInterchainEnv::new(
vec![("juno-1", &sender), ("osmosis-1", &sender)],
);
}
Behind the scenes, Mock
objects are created with the specified chain ids. These mock environments can be used on their own to interact with testing environment directly. You can get those objects like so:
use cw_orch::prelude::*;
use cw_orch_interchain::interchain::InterchainEnv;
fn main(){
let local_juno: Daemon = interchain.chain("juno-1")?;
let local_osmo: Daemon = interchain.chain("osmosis-1")?;
}
where the argument of the chain
method is the chain id of the chain you are interacting with. Note that this environment can’t work with chains that have the same chain_id
.
You can also add mocks manually to the interchain
object, after instantiation:
fn main(){
use cosmwasm_std::Addr;
use cw_orch::prelude::*;
let sender = Addr::unchecked("sender");
let mut interchain = MockInterchainEnv::new(
vec![("juno-1", &sender), ("osmosis-1", &sender)],
);
let test_migaloo = Mock::new(&sender);
interchain.add_mocks(vec![test_migaloo]);
}
General Usage
All interchain environments are centered around the follow_packet
function. In the Mock case, this function is responsible for relaying the packets between the different chains. Using the exact same interface as with other environments, it takes care of all packet relaying procedures.
NOTE: Packets can either go through a successful cycle or timeout. In our current Mock implementation, it’s difficult to do it so that packets timeout. We are working on providing tools for developers to test all edge cases and timeout is part of the helpers we want to bring ASAP.
This function will relay a packets succesfully from the receiving chain back the the source chain. Here is what the full cycle looks like:
- ⬤ On the
source chain
, it queries the packet data associated with the packet channel and sequence. - ⬤ On the
destination chain
, it triggers a receive transaction for that packet. - ⬤ On the
source chain
, it finally triggers an acknowledgement transaction with the data thedestination_chain
returned.
The wait_ibc
function is very similar except that instead of following a single packet, it follows all packets that are being sent within a transaction. This works in a very similar manner and will never return a timeout transaction. This function is recursive as it will also look for packets inside the receive/ack transactions and also follow their IBC cycle. You can think of this function as going down the rabbit-hole of IBC execution and only returning when all IBC interactions are complete.
NOTE: most of the methods on the
interchain
variable presented here are async methods. We recommend reading more about async functions at the point. If you’re not working with any async functions, the gist here is:interchain.wait_ibc( &chain_id, tx_response )
IBC Channel creation
cw-orchestrator also provides tooling for creating channels between mock environments. Here is how you do it:
use ibc_relayer_types::core::ics24_host::identifier::PortId;
let rt = tokio::runtime::Runtime::new()?;
let src_chain = "juno-1".to_string();
let dst_chain = "juno-1".to_string();
let port_id = PortId::transfer();
let (channel, channel_creation_result) = rt.block_on(
interchain.create_channel(&src_chain, &dst_chain, None, &port_id, &port_id, "ics20-1")
)?;
- The resulting
channel
object allows you to identify the channel that was just created. It can be useful to retrieve the channel identifiers for instance - The resulting
channel_creation_result
object allows you to identify the different steps of channel creation as well as following all the packets that have been sent during this creation. This is very useful to analyze the effects of the channel creation on external contracts and structures.