1pub use abstract_std::app;
2use abstract_std::{
3 ibc::{CallbackInfo, CallbackResult, ModuleIbcMsg},
4 ibc_client::{self},
5 objects::module::ModuleInfo,
6 IBC_CLIENT,
7};
8use cosmwasm_schema::{cw_serde, QueryResponses};
9pub use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
10use cosmwasm_std::{
11 from_json, to_json_binary, wasm_execute, AllBalanceResponse, Coin, Response, StdError,
12};
13use cw_controllers::AdminError;
14use cw_storage_plus::Item;
15
16pub type AppTestResult = Result<(), MockError>;
17
18abstract_app::app_msg_types!(MockAppContract, MockExecMsg, MockQueryMsg);
19
20#[cosmwasm_schema::cw_serde]
21pub struct MockInitMsg {}
22
23#[cosmwasm_schema::cw_serde]
24#[derive(cw_orch::ExecuteFns)]
25#[impl_into(ExecuteMsg)]
26pub enum MockExecMsg {
27 DoSomething {},
28 DoSomethingAdmin {},
29 DoSomethingIbc {
30 remote_chain: String,
31 target_module: ModuleInfo,
32 },
33 QuerySomethingIbc {
34 remote_chain: String,
35 address: String,
36 },
37}
38
39#[cosmwasm_schema::cw_serde]
40#[derive(cw_orch::QueryFns)]
41#[impl_into(QueryMsg)]
42#[derive(QueryResponses)]
43pub enum MockQueryMsg {
44 #[returns(ReceivedIbcCallbackStatus)]
45 GetReceivedIbcCallbackStatus {},
46
47 #[returns(ReceivedIbcQueryCallbackStatus)]
48 GetReceivedIbcQueryCallbackStatus {},
49
50 #[returns(ReceivedIbcModuleStatus)]
51 GetReceivedIbcModuleStatus {},
52}
53
54#[cosmwasm_schema::cw_serde]
55pub struct ReceivedIbcCallbackStatus {
56 pub received: bool,
57}
58
59#[cosmwasm_schema::cw_serde]
60pub struct ReceivedIbcQueryCallbackStatus {
61 pub balance: Vec<Coin>,
62}
63
64#[cosmwasm_schema::cw_serde]
65pub struct ReceivedIbcModuleStatus {
66 pub received: ModuleInfo,
67}
68
69#[cosmwasm_schema::cw_serde]
70pub struct MockMigrateMsg;
71
72#[cosmwasm_schema::cw_serde]
73pub struct MockReceiveMsg;
74
75#[cosmwasm_schema::cw_serde]
76pub struct MockSudoMsg;
77
78use abstract_sdk::{AbstractSdkError, ModuleInterface};
79use thiserror::Error;
80
81use abstract_app::{AppContract, AppError};
82
83#[derive(Error, Debug, PartialEq)]
84pub enum MockError {
85 #[error("{0}")]
86 Std(#[from] StdError),
87
88 #[error("{0}")]
89 DappError(#[from] AppError),
90
91 #[error("{0}")]
92 Abstract(#[from] abstract_std::AbstractError),
93
94 #[error("{0}")]
95 AbstractSdk(#[from] AbstractSdkError),
96
97 #[error("{0}")]
98 Admin(#[from] AdminError),
99}
100
101pub type MockAppContract = AppContract<
102 MockError,
104 MockInitMsg,
105 MockExecMsg,
106 MockQueryMsg,
107 MockMigrateMsg,
108 MockReceiveMsg,
109 MockSudoMsg,
110>;
111
112#[cw_serde]
113pub struct IbcModuleToModuleMsg {
114 ibc_msg: String,
115}
116
117pub const IBC_CALLBACK_RECEIVED: Item<bool> = Item::new("ibc_callback_received");
119pub const MODULE_IBC_RECEIVED: Item<ModuleInfo> = Item::new("module_ibc_received");
121
122pub const IBC_CALLBACK_QUERY_RECEIVED: Item<Vec<Coin>> = Item::new("ibc_callback_query_received");
124
125pub const fn mock_app(id: &'static str, version: &'static str) -> MockAppContract {
126 MockAppContract::new(id, version, None)
127 .with_instantiate(|deps, _, _, _, _| {
128 IBC_CALLBACK_RECEIVED.save(deps.storage, &false)?;
129 Ok(Response::new().set_data("mock_init".as_bytes()))
130 })
131 .with_execute(|deps, _env, _, app, msg| match msg {
132 MockExecMsg::DoSomethingIbc {
133 remote_chain,
134 target_module,
135 } => {
136 let ibc_client_addr = app.modules(deps.as_ref()).module_address(IBC_CLIENT)?;
137 let msg = wasm_execute(
139 ibc_client_addr,
140 &ibc_client::ExecuteMsg::ModuleIbcAction {
141 host_chain: remote_chain,
142 target_module,
143 msg: to_json_binary(&IbcModuleToModuleMsg {
144 ibc_msg: "module_to_module:msg".to_string(),
145 })
146 .unwrap(),
147 callback_info: Some(CallbackInfo {
148 id: "c_id".to_string(),
149 msg: None,
150 }),
151 },
152 vec![],
153 )?;
154
155 Ok(Response::new().add_message(msg))
156 }
157 MockExecMsg::QuerySomethingIbc {
158 address,
159 remote_chain,
160 } => {
161 let ibc_client_addr = app.modules(deps.as_ref()).module_address(IBC_CLIENT)?;
162 let msg = wasm_execute(
164 ibc_client_addr,
165 &ibc_client::ExecuteMsg::IbcQuery {
166 host_chain: remote_chain,
167 callback_info: CallbackInfo {
168 id: "query_id".to_string(),
169 msg: None,
170 },
171 query: cosmwasm_std::QueryRequest::Bank(
172 cosmwasm_std::BankQuery::AllBalances { address },
173 ),
174 },
175 vec![],
176 )?;
177
178 Ok(Response::new().add_message(msg))
179 }
180 _ => Ok(Response::new().set_data("mock_exec".as_bytes())),
181 })
182 .with_query(|deps, _, _, msg| match msg {
183 MockQueryMsg::GetReceivedIbcCallbackStatus {} => {
184 to_json_binary(&ReceivedIbcCallbackStatus {
185 received: IBC_CALLBACK_RECEIVED.load(deps.storage)?,
186 })
187 .map_err(Into::into)
188 }
189 MockQueryMsg::GetReceivedIbcModuleStatus {} => {
190 to_json_binary(&ReceivedIbcModuleStatus {
191 received: MODULE_IBC_RECEIVED.load(deps.storage)?,
192 })
193 .map_err(Into::into)
194 }
195 MockQueryMsg::GetReceivedIbcQueryCallbackStatus {} => {
196 to_json_binary(&ReceivedIbcQueryCallbackStatus {
197 balance: IBC_CALLBACK_QUERY_RECEIVED.load(deps.storage)?,
198 })
199 .map_err(Into::into)
200 }
201 })
202 .with_sudo(|_, _, _, _| Ok(Response::new().set_data("mock_sudo".as_bytes())))
203 .with_receive(|_, _, _, _, _| Ok(Response::new().set_data("mock_receive".as_bytes())))
204 .with_ibc_callbacks(&[
205 ("c_id", |deps, _, _, _, _| {
206 IBC_CALLBACK_RECEIVED.save(deps.storage, &true).unwrap();
207 Ok(Response::new().add_attribute("mock_callback", "executed"))
208 }),
209 ("query_id", |deps, _, _, _, msg| match msg.result {
210 CallbackResult::Query { query: _, result } => {
211 let result = result.unwrap()[0].clone();
212 let deser: AllBalanceResponse = from_json(result)?;
213 IBC_CALLBACK_QUERY_RECEIVED
214 .save(deps.storage, &deser.amount)
215 .unwrap();
216 Ok(Response::new().add_attribute("mock_callback_query", "executed"))
217 }
218 _ => panic!("Expected query result"),
219 }),
220 ])
221 .with_replies(&[(1u64, |_, _, _, msg| {
222 Ok(Response::new().set_data(msg.result.unwrap().data.unwrap()))
223 })])
224 .with_migrate(|_, _, _, _| Ok(Response::new().set_data("mock_migrate".as_bytes())))
225 .with_module_ibc(|deps, _, _, msg| {
226 let ModuleIbcMsg { source_module, .. } = msg;
227 MODULE_IBC_RECEIVED.save(deps.storage, &source_module)?;
229 Ok(Response::new().add_attribute("mock_module_ibc", "executed"))
230 })
231}
232
233pub mod origin_app {
234 use abstract_testing::addresses::{TEST_MODULE_ID, TEST_VERSION};
235
236 use super::{mock_app, MockAppContract};
237 pub const MOCK_APP_ORIGIN: MockAppContract = mock_app(TEST_MODULE_ID, TEST_VERSION);
238 abstract_app::cw_orch_interface!(MOCK_APP_ORIGIN, MockAppContract, MockAppOriginI);
239}
240
241pub mod remote_app {
242 use super::{mock_app, MockAppContract};
243
244 pub const TEST_MODULE_ID_REMOTE: &str = "tester:test-module-id-remote";
245 pub const TEST_VERSION_REMOTE: &str = "0.45.7";
246 pub const MOCK_APP_REMOTE: MockAppContract =
247 mock_app(TEST_MODULE_ID_REMOTE, TEST_VERSION_REMOTE);
248 abstract_app::cw_orch_interface!(MOCK_APP_REMOTE, MockAppContract, MockAppRemoteI);
249}
250
251#[cfg(test)]
252pub mod test {
253
254 fn assert_remote_module_call_status(
255 app: &MockAppRemoteI<MockBech32>,
256 source_module_expected: Option<ModuleInfo>,
257 ) -> AnyResult<()> {
258 let source_module = app
259 .get_received_ibc_module_status()
260 .map(|s| s.received)
261 .ok();
262
263 assert_eq!(source_module, source_module_expected);
264 Ok(())
265 }
266
267 fn assert_callback_status(app: &MockAppOriginI<MockBech32>, status: bool) -> AnyResult<()> {
268 let get_received_ibc_callback_status_res: ReceivedIbcCallbackStatus =
269 app.get_received_ibc_callback_status()?;
270
271 assert_eq!(
272 ReceivedIbcCallbackStatus { received: status },
273 get_received_ibc_callback_status_res
274 );
275 Ok(())
276 }
277
278 fn assert_query_callback_status(
279 app: &MockAppOriginI<MockBech32>,
280 balance: Vec<Coin>,
281 ) -> AnyResult<()> {
282 let get_received_ibc_query_callback_status_res: ReceivedIbcQueryCallbackStatus =
283 app.get_received_ibc_query_callback_status()?;
284
285 assert_eq!(
286 ReceivedIbcQueryCallbackStatus { balance },
287 get_received_ibc_query_callback_status_res
288 );
289 Ok(())
290 }
291 use crate::{
292 interchain_accounts::create_test_remote_account,
293 module_to_module_interactions::{
294 origin_app::interface::MockAppOriginI,
295 remote_app::{interface::MockAppRemoteI, TEST_MODULE_ID_REMOTE, TEST_VERSION_REMOTE},
296 MockExecMsgFns, MockInitMsg, MockQueryMsgFns, ReceivedIbcCallbackStatus,
297 ReceivedIbcQueryCallbackStatus,
298 },
299 setup::{
300 ibc_abstract_setup, ibc_connect_polytone_and_abstract, mock_test::logger_test_init,
301 },
302 JUNO, STARGAZE,
303 };
304 use abstract_app::objects::{chain_name::ChainName, module::ModuleInfo};
305 use abstract_interface::{
306 AppDeployer, DeployStrategy, Manager, ManagerQueryFns, VCExecFns, VCQueryFns,
307 };
308 use abstract_std::manager::{self, ModuleInstallConfig};
309 use abstract_testing::addresses::{TEST_MODULE_ID, TEST_NAMESPACE, TEST_VERSION};
310 use anyhow::Result as AnyResult;
311 use cosmwasm_std::{coins, to_json_binary};
312 use cw_orch::prelude::*;
313 use cw_orch_interchain::{prelude::*, types::IbcPacketOutcome};
314
315 #[test]
316 fn target_module_must_exist() -> AnyResult<()> {
317 logger_test_init();
318 let mock_interchain =
319 MockBech32InterchainEnv::new(vec![(JUNO, "juno"), (STARGAZE, "stargaze")]);
320
321 let (abstr_origin, _abstr_remote) = ibc_abstract_setup(&mock_interchain, JUNO, STARGAZE)?;
323 ibc_connect_polytone_and_abstract(&mock_interchain, STARGAZE, JUNO)?;
324
325 let remote_name = ChainName::from_chain_id(STARGAZE).to_string();
326
327 let (origin_account, _remote_account_id) =
328 create_test_remote_account(&abstr_origin, JUNO, STARGAZE, &mock_interchain, None)?;
329
330 let app = MockAppOriginI::new(
331 TEST_MODULE_ID,
332 abstr_origin.version_control.get_chain().clone(),
333 );
334
335 abstr_origin.version_control.claim_namespace(
336 origin_account.manager.config()?.account_id,
337 TEST_NAMESPACE.to_owned(),
338 )?;
339
340 app.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?;
341
342 origin_account.install_app(&app, &MockInitMsg {}, None)?;
343
344 let target_module_info =
346 ModuleInfo::from_id(TEST_MODULE_ID_REMOTE, TEST_VERSION_REMOTE.into())?;
347 let ibc_action_result = app.do_something_ibc(remote_name, target_module_info.clone())?;
348
349 let ibc_result = mock_interchain.wait_ibc(JUNO, ibc_action_result)?;
350
351 let expected_error_outcome = format!(
352 "Module {} does not have a stored module reference",
353 target_module_info
354 );
355 match &ibc_result.packets[0].outcome {
356 IbcPacketOutcome::Timeout { .. } => {
357 panic!("Expected a failed ack not a timeout !")
358 }
359 IbcPacketOutcome::Success { ack, .. } => assert!(String::from_utf8_lossy(ack)
360 .to_string()
361 .contains(&expected_error_outcome)),
362 }
363
364 Ok(())
365 }
366
367 #[test]
368 fn target_account_must_have_module_installed() -> AnyResult<()> {
369 logger_test_init();
370 let mock_interchain =
371 MockBech32InterchainEnv::new(vec![(JUNO, "juno"), (STARGAZE, "stargaze")]);
372
373 let (abstr_origin, abstr_remote) = ibc_abstract_setup(&mock_interchain, JUNO, STARGAZE)?;
375 ibc_connect_polytone_and_abstract(&mock_interchain, STARGAZE, JUNO)?;
376
377 let remote_name = ChainName::from_chain_id(STARGAZE).to_string();
378
379 let (origin_account, _remote_account_id) =
380 create_test_remote_account(&abstr_origin, JUNO, STARGAZE, &mock_interchain, None)?;
381
382 let (remote_account, _remote_account_id) =
383 create_test_remote_account(&abstr_remote, STARGAZE, JUNO, &mock_interchain, None)?;
384
385 let app = MockAppOriginI::new(
387 TEST_MODULE_ID,
388 abstr_origin.version_control.get_chain().clone(),
389 );
390
391 abstr_origin
392 .version_control
393 .claim_namespace(origin_account.id()?, TEST_NAMESPACE.to_owned())?;
394
395 app.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?;
396
397 origin_account.install_app(&app, &MockInitMsg {}, None)?;
398
399 let app_remote = MockAppRemoteI::new(
401 TEST_MODULE_ID_REMOTE,
402 abstr_remote.version_control.get_chain().clone(),
403 );
404
405 abstr_remote
406 .version_control
407 .claim_namespace(remote_account.id()?, TEST_NAMESPACE.to_owned())?;
408
409 app_remote.deploy(TEST_VERSION_REMOTE.parse()?, DeployStrategy::Try)?;
410
411 let target_module_info =
413 ModuleInfo::from_id(TEST_MODULE_ID_REMOTE, TEST_VERSION_REMOTE.into())?;
414 let ibc_action_result = app.do_something_ibc(remote_name, target_module_info.clone())?;
415
416 let ibc_result = mock_interchain.wait_ibc(JUNO, ibc_action_result)?;
417
418 let expected_error_outcome =
419 format!("App {} not installed on Account", target_module_info,);
420 match &ibc_result.packets[0].outcome {
421 IbcPacketOutcome::Timeout { .. } => {
422 panic!("Expected a failed ack not a timeout !")
423 }
424 IbcPacketOutcome::Success { ack, .. } => assert!(String::from_utf8_lossy(ack)
425 .to_string()
426 .contains(&expected_error_outcome)),
427 }
428
429 Ok(())
430 }
431
432 #[test]
433 fn works() -> AnyResult<()> {
434 logger_test_init();
435 let mock_interchain =
436 MockBech32InterchainEnv::new(vec![(JUNO, "juno"), (STARGAZE, "stargaze")]);
437
438 let (abstr_origin, abstr_remote) = ibc_abstract_setup(&mock_interchain, JUNO, STARGAZE)?;
440 ibc_connect_polytone_and_abstract(&mock_interchain, STARGAZE, JUNO)?;
441
442 let remote_name = ChainName::from_chain_id(STARGAZE).to_string();
443
444 let (origin_account, remote_account_id) =
445 create_test_remote_account(&abstr_origin, JUNO, STARGAZE, &mock_interchain, None)?;
446
447 let (remote_account, _) =
448 create_test_remote_account(&abstr_remote, STARGAZE, JUNO, &mock_interchain, None)?;
449
450 let app = MockAppOriginI::new(
452 TEST_MODULE_ID,
453 abstr_origin.version_control.get_chain().clone(),
454 );
455
456 abstr_origin
457 .version_control
458 .claim_namespace(origin_account.id()?, TEST_NAMESPACE.to_owned())?;
459
460 app.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?;
461
462 origin_account.install_app(&app, &MockInitMsg {}, None)?;
463
464 let app_remote = MockAppRemoteI::new(
466 TEST_MODULE_ID_REMOTE,
467 abstr_remote.version_control.get_chain().clone(),
468 );
469
470 abstr_remote
471 .version_control
472 .claim_namespace(remote_account.id()?, TEST_NAMESPACE.to_owned())?;
473
474 app_remote.deploy(TEST_VERSION_REMOTE.parse()?, DeployStrategy::Try)?;
475
476 let remote_install_response = origin_account.manager.execute_on_remote(
477 &remote_name,
478 manager::ExecuteMsg::InstallModules {
479 modules: vec![ModuleInstallConfig::new(
480 ModuleInfo::from_id_latest(TEST_MODULE_ID_REMOTE)?,
481 Some(to_json_binary(&MockInitMsg {})?),
482 )],
483 },
484 )?;
485
486 mock_interchain.check_ibc(JUNO, remote_install_response)?;
487
488 let remote_manager = abstr_remote
490 .version_control
491 .account_base(remote_account_id)?
492 .account_base
493 .manager;
494 let manager = Manager::new(
495 "remote-account-manager",
496 abstr_remote.version_control.get_chain().clone(),
497 );
498 manager.set_address(&remote_manager);
499 let module_address = manager.module_info(TEST_MODULE_ID_REMOTE)?.unwrap().address;
500 let remote_account_app = MockAppRemoteI::new(
501 "remote-account-app",
502 abstr_remote.version_control.get_chain().clone(),
503 );
504 remote_account_app.set_address(&module_address);
505
506 let target_module_info =
508 ModuleInfo::from_id(TEST_MODULE_ID_REMOTE, TEST_VERSION_REMOTE.into())?;
509 let ibc_action_result = app.do_something_ibc(remote_name, target_module_info.clone())?;
510
511 assert_remote_module_call_status(&remote_account_app, None)?;
512 assert_callback_status(&app, false)?;
513
514 mock_interchain.check_ibc(JUNO, ibc_action_result)?;
515
516 assert_remote_module_call_status(
517 &remote_account_app,
518 Some(ModuleInfo::from_id(TEST_MODULE_ID, TEST_VERSION.into())?),
519 )?;
520 assert_callback_status(&app, true)?;
521
522 Ok(())
523 }
524
525 pub const REMOTE_AMOUNT: u128 = 5674309;
526 pub const REMOTE_DENOM: &str = "remote_denom";
527 #[test]
528 fn queries() -> AnyResult<()> {
529 logger_test_init();
530 let mock_interchain =
531 MockBech32InterchainEnv::new(vec![(JUNO, "juno"), (STARGAZE, "stargaze")]);
532
533 let (abstr_origin, _abstr_remote) = ibc_abstract_setup(&mock_interchain, JUNO, STARGAZE)?;
535 ibc_connect_polytone_and_abstract(&mock_interchain, STARGAZE, JUNO)?;
536
537 let remote_name = ChainName::from_chain_id(STARGAZE).to_string();
538 let remote = mock_interchain.chain(STARGAZE)?;
539 let remote_address =
540 remote.addr_make_with_balance("remote-test", coins(REMOTE_AMOUNT, REMOTE_DENOM))?;
541
542 let (origin_account, _remote_account_id) =
543 create_test_remote_account(&abstr_origin, JUNO, STARGAZE, &mock_interchain, None)?;
544
545 let app = MockAppOriginI::new(
547 TEST_MODULE_ID,
548 abstr_origin.version_control.get_chain().clone(),
549 );
550
551 abstr_origin
552 .version_control
553 .claim_namespace(origin_account.id()?, TEST_NAMESPACE.to_owned())?;
554
555 app.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?;
556
557 origin_account.install_app(&app, &MockInitMsg {}, None)?;
558
559 let query_response = app.query_something_ibc(remote_address.to_string(), remote_name)?;
560
561 assert_query_callback_status(&app, coins(REMOTE_AMOUNT, REMOTE_DENOM)).unwrap_err();
562 mock_interchain.check_ibc(JUNO, query_response)?;
563 assert_query_callback_status(&app, coins(REMOTE_AMOUNT, REMOTE_DENOM))?;
564
565 Ok(())
566 }
567
568 pub mod security {
569 use abstract_std::ibc_client::ExecuteMsgFns;
570
571 use crate::module_to_module_interactions::IbcModuleToModuleMsg;
572
573 use super::*;
574
575 #[test]
576 fn calling_module_should_match() -> AnyResult<()> {
577 logger_test_init();
578 let mock_interchain =
579 MockBech32InterchainEnv::new(vec![(JUNO, "juno"), (STARGAZE, "stargaze")]);
580
581 let (abstr_origin, abstr_remote) =
583 ibc_abstract_setup(&mock_interchain, JUNO, STARGAZE)?;
584 ibc_connect_polytone_and_abstract(&mock_interchain, STARGAZE, JUNO)?;
585
586 let remote_name = ChainName::from_chain_id(STARGAZE).to_string();
587
588 let (origin_account, remote_account_id) =
589 create_test_remote_account(&abstr_origin, JUNO, STARGAZE, &mock_interchain, None)?;
590
591 let (remote_account, _) =
592 create_test_remote_account(&abstr_remote, STARGAZE, JUNO, &mock_interchain, None)?;
593
594 let app = MockAppOriginI::new(
596 TEST_MODULE_ID,
597 abstr_origin.version_control.get_chain().clone(),
598 );
599
600 abstr_origin
601 .version_control
602 .claim_namespace(origin_account.id()?, TEST_NAMESPACE.to_owned())?;
603
604 app.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?;
605
606 origin_account.install_app(&app, &MockInitMsg {}, None)?;
607
608 let app_remote = MockAppRemoteI::new(
610 TEST_MODULE_ID_REMOTE,
611 abstr_remote.version_control.get_chain().clone(),
612 );
613
614 abstr_remote
615 .version_control
616 .claim_namespace(remote_account.id()?, TEST_NAMESPACE.to_owned())?;
617
618 app_remote.deploy(TEST_VERSION_REMOTE.parse()?, DeployStrategy::Try)?;
619
620 let remote_install_response = origin_account.manager.execute_on_remote(
621 &remote_name,
622 manager::ExecuteMsg::InstallModules {
623 modules: vec![ModuleInstallConfig::new(
624 ModuleInfo::from_id_latest(TEST_MODULE_ID_REMOTE)?,
625 Some(to_json_binary(&MockInitMsg {})?),
626 )],
627 },
628 )?;
629
630 mock_interchain.check_ibc(JUNO, remote_install_response)?;
631
632 let remote_manager = abstr_remote
634 .version_control
635 .account_base(remote_account_id)?
636 .account_base
637 .manager;
638 let manager = Manager::new(
639 "remote-account-manager",
640 abstr_remote.version_control.get_chain().clone(),
641 );
642 manager.set_address(&remote_manager);
643 let module_address = manager.module_info(TEST_MODULE_ID_REMOTE)?.unwrap().address;
644 let remote_account_app = MockAppRemoteI::new(
645 "remote-account-app",
646 abstr_remote.version_control.get_chain().clone(),
647 );
648 remote_account_app.set_address(&module_address);
649
650 let target_module_info =
652 ModuleInfo::from_id(TEST_MODULE_ID_REMOTE, TEST_VERSION_REMOTE.into())?;
653
654 abstr_origin
656 .ibc
657 .client
658 .module_ibc_action(
659 remote_name,
660 to_json_binary(&IbcModuleToModuleMsg {
661 ibc_msg: "module_to_module:msg".to_string(),
662 })
663 .unwrap(),
664 target_module_info,
665 None,
666 )
667 .unwrap_err();
668
669 Ok(())
670 }
671 }
672}