hermes_relayer_components/relay/impls/channel/
open_try.rs1use core::fmt::Debug;
2
3use cgp::core::error::CanRaiseError;
4
5use crate::chain::traits::message_builders::channel_handshake::CanBuildChannelOpenTryMessage;
6use crate::chain::traits::payload_builders::channel_handshake::CanBuildChannelOpenTryPayload;
7use crate::chain::traits::queries::chain_status::CanQueryChainHeight;
8use crate::chain::traits::queries::client_state::CanQueryClientStateWithLatestHeight;
9use crate::chain::traits::types::ibc_events::channel::HasChannelOpenTryEvent;
10use crate::chain::types::aliases::ChannelIdOf;
11use crate::relay::traits::chains::{CanRaiseRelayChainErrors, HasRelayChains};
12use crate::relay::traits::channel::open_try::ChannelOpenTryRelayer;
13use crate::relay::traits::ibc_message_sender::{CanSendSingleIbcMessage, MainSink};
14use crate::relay::traits::target::DestinationTarget;
15use crate::relay::types::aliases::{DstChannelId, DstPortId, SrcChannelId, SrcPortId};
16
17pub struct RelayChannelOpenTry;
31
32pub struct MissingChannelTryEventError<'a, Relay>
33where
34 Relay: HasRelayChains,
35{
36 pub relay: &'a Relay,
37 pub src_channel_id: &'a ChannelIdOf<Relay::SrcChain, Relay::DstChain>,
38}
39
40impl<Relay, SrcChain, DstChain> ChannelOpenTryRelayer<Relay> for RelayChannelOpenTry
41where
42 Relay: HasRelayChains<SrcChain = SrcChain, DstChain = DstChain>
43 + CanSendSingleIbcMessage<MainSink, DestinationTarget>
44 + for<'a> CanRaiseError<MissingChannelTryEventError<'a, Relay>>
45 + CanRaiseRelayChainErrors,
46 SrcChain: CanQueryChainHeight + CanBuildChannelOpenTryPayload<DstChain>,
47 DstChain: CanQueryClientStateWithLatestHeight<SrcChain>
48 + CanBuildChannelOpenTryMessage<SrcChain>
49 + HasChannelOpenTryEvent<SrcChain>,
50 DstChain::ChannelId: Clone,
51{
52 async fn relay_channel_open_try(
53 relay: &Relay,
54 dst_port: &DstPortId<Relay>,
55 src_port_id: &SrcPortId<Relay>,
56 src_channel_id: &SrcChannelId<Relay>,
57 ) -> Result<DstChannelId<Relay>, Relay::Error> {
58 let src_chain = relay.src_chain();
59 let dst_chain = relay.dst_chain();
60
61 let src_proof_height = src_chain
62 .query_chain_height()
63 .await
64 .map_err(Relay::raise_error)?;
65
66 let src_client_state = dst_chain
67 .query_client_state_with_latest_height(relay.dst_client_id())
68 .await
69 .map_err(Relay::raise_error)?;
70
71 let open_try_payload = src_chain
72 .build_channel_open_try_payload(
73 &src_client_state,
74 &src_proof_height,
75 src_port_id,
76 src_channel_id,
77 )
78 .await
79 .map_err(Relay::raise_error)?;
80
81 let open_try_message = dst_chain
82 .build_channel_open_try_message(dst_port, src_port_id, src_channel_id, open_try_payload)
83 .await
84 .map_err(Relay::raise_error)?;
85
86 let events = relay
87 .send_message(DestinationTarget, open_try_message)
88 .await?;
89
90 let open_try_event = events
91 .into_iter()
92 .find_map(|event| DstChain::try_extract_channel_open_try_event(event))
93 .ok_or_else(|| {
94 Relay::raise_error(MissingChannelTryEventError {
95 relay,
96 src_channel_id,
97 })
98 })?;
99
100 let dst_channel_id = DstChain::channel_open_try_event_channel_id(&open_try_event);
101
102 Ok(dst_channel_id.clone())
103 }
104}
105
106impl<'a, Relay> Debug for MissingChannelTryEventError<'a, Relay>
107where
108 Relay: HasRelayChains,
109{
110 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
111 f.debug_struct("MissingChannelTryEventError")
112 .field("src_channel_id", &self.src_channel_id)
113 .finish()
114 }
115}