use ibc_relayer::chain::handle::ChainHandle;
use tracing::info;
use super::foreign_client::ForeignClientPair;
use crate::types::env::{prefix_writer, EnvWriter, ExportEnv};
use crate::types::id::{TaggedChainIdRef, TaggedClientIdRef};
use crate::types::single::node::{FullNode, TaggedFullNodeExt};
use crate::types::tagged::*;
#[derive(Clone)]
pub struct ConnectedChains<ChainA: ChainHandle, ChainB: ChainHandle> {
pub handle_a: ChainA,
pub handle_b: ChainB,
pub node_a: MonoTagged<ChainA, FullNode>,
pub node_b: MonoTagged<ChainB, FullNode>,
pub foreign_clients: ForeignClientPair<ChainA, ChainB>,
}
impl<ChainA: ChainHandle, ChainB: ChainHandle> ConnectedChains<ChainA, ChainB> {
pub fn new(
handle_a: ChainA,
handle_b: ChainB,
node_a: MonoTagged<ChainA, FullNode>,
node_b: MonoTagged<ChainB, FullNode>,
foreign_clients: ForeignClientPair<ChainA, ChainB>,
) -> Self {
Self {
handle_a,
handle_b,
node_a,
node_b,
foreign_clients,
}
}
pub fn handle_a(&self) -> &ChainA {
&self.handle_a
}
pub fn handle_b(&self) -> &ChainB {
&self.handle_b
}
pub fn chain_id_a(&self) -> TaggedChainIdRef<ChainA> {
self.node_a.chain_id()
}
pub fn client_id_a(&self) -> TaggedClientIdRef<ChainA, ChainB> {
self.foreign_clients.client_id_a()
}
pub fn client_id_b(&self) -> TaggedClientIdRef<ChainB, ChainA> {
self.foreign_clients.client_id_b()
}
pub fn chain_id_b(&self) -> TaggedChainIdRef<ChainB> {
self.node_b.chain_id()
}
pub fn flip(self) -> ConnectedChains<ChainB, ChainA> {
ConnectedChains {
handle_a: self.handle_b,
handle_b: self.handle_a,
node_a: self.node_b,
node_b: self.node_a,
foreign_clients: self.foreign_clients.flip(),
}
}
pub fn map_chain<ChainC: ChainHandle, ChainD: ChainHandle>(
self,
map_a: &impl Fn(ChainA) -> ChainC,
map_b: &impl Fn(ChainB) -> ChainD,
) -> ConnectedChains<ChainC, ChainD> {
ConnectedChains {
handle_a: map_a(self.handle_a),
handle_b: map_b(self.handle_b),
node_a: self.node_a.retag(),
node_b: self.node_b.retag(),
foreign_clients: self.foreign_clients.map_chain(map_a, map_b),
}
}
}
impl<ChainA: ChainHandle, ChainB: ChainHandle> ExportEnv for ConnectedChains<ChainA, ChainB> {
fn export_env(&self, writer: &mut impl EnvWriter) {
writer.write_env("CHAIN_ID_A", &format!("{}", self.node_a.chain_id()));
writer.write_env("CHAIN_ID_B", &format!("{}", self.node_b.chain_id()));
writer.write_env(
"CLIENT_ID_B",
&format!("{}", self.foreign_clients.client_a_to_b.id()),
);
writer.write_env(
"CLIENT_ID_A",
&format!("{}", self.foreign_clients.client_b_to_a.id()),
);
self.node_a.export_env(&mut prefix_writer("NODE_A", writer));
self.node_b.export_env(&mut prefix_writer("NODE_B", writer));
}
}
pub struct DropChainHandle<Chain: ChainHandle>(pub Chain);
impl<Chain: ChainHandle> Drop for DropChainHandle<Chain> {
fn drop(&mut self) {
info!("stopping chain handle {}", self.0.id());
let _ = self.0.shutdown();
}
}