partner_chains_data_sources_cli/
main.rs

1#![deny(missing_docs)]
2//! This crate provides CLI allowing usage of db-sync data sources.
3//! It can be extended with more data sources.
4//!
5//! `follower_commands` macro is used to generate [clap] commands.
6//! Command level doc comments are supported, but parameter level doc comments are not supported.
7
8use authority_selection_inherents::AuthoritySelectionDataSource;
9use clap::Parser;
10use partner_chains_db_sync_data_sources::{BlockDataSourceImpl, CandidatesDataSourceImpl, PgPool};
11use sidechain_domain::*;
12use sp_timestamp::Timestamp;
13use std::error::Error;
14
15type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>;
16
17#[tokio::main]
18async fn main() {
19	env_logger::builder().filter_level(log::LevelFilter::Info).init();
20	match Command::parse().run().await {
21		Ok(resp) => println!("{resp}"),
22		Err(err) => log::error!("{}", err.to_string()),
23	}
24}
25
26macro_rules! follower_commands {
27	(
28		$(
29			$ds:ident {
30				$(
31					$(#[$cmd_comment:meta])*
32					async fn $method:ident($($i:literal $arg:ident : $arg_ty:ty),*);
33				)+
34			}
35		)*
36	) => {
37		#[derive(Debug, clap::Parser)]
38		#[allow(non_camel_case_types)]
39		enum Command {
40			$(
41				$(
42					$(#[$cmd_comment])*
43					$method {
44						$(
45							#[clap(index = $i)]
46							$arg: $arg_ty
47						),*
48					}
49				),*
50			),*
51		}
52		impl Command {
53			async fn run(self) -> Result<String> {
54				match self {
55					$(
56						$(
57							Command::$method { $($arg),* } => {
58								let data_source = crate::data_source::$ds().await.expect("Failed to create data source");
59								let result = data_source.$method($($arg),*).await?;
60								let result = serde_json::to_string_pretty(&result)?;
61								Ok(result)
62							}
63						),*
64					),*
65				}
66			}
67		}
68    };
69}
70
71follower_commands! {
72	block {
73		/// Returns the latest block recorded by DB-Sync
74		async fn get_latest_block_info();
75		/// Returns data of block that was the latest stable block at given timestamp
76		async fn get_latest_stable_block_for(1 reference_timestamp_millis: u64);
77		/// Returns data of the block identified by given hash, but only if the block can be considered stable in relation to reference timestamp
78		async fn get_stable_block_for(1 hash: McBlockHash, 2 reference_timestamp_millis: u64);
79	}
80	candidate {
81		/// Returns values of D-parameter and Permissioned Candidates effective at given epoch. Policy IDs should be hex encoded.
82		async fn get_ariadne_parameters(1 epoch_number: McEpochNumber, 2 d_parameter_policy_id: PolicyId, 3 permissioned_candidates_policy_id: PolicyId);
83		/// Returns registered candidates data effective at given Cardano epoch.
84		async fn get_candidates(1 epoch_number: McEpochNumber, 2 committee_candidate_validator_address: MainchainAddress);
85		/// Returns Cardano epoch nonce used by committee selection during given Cardano epoch. It is not nonce of the given epoch.
86		async fn get_epoch_nonce(1 epoch_number: McEpochNumber);
87	}
88}
89
90mod data_source {
91
92	use super::*;
93
94	async fn pool() -> Result<PgPool> {
95		partner_chains_db_sync_data_sources::get_connection_from_env().await
96	}
97
98	pub(crate) struct BlockDataSourceWrapper {
99		inner: BlockDataSourceImpl,
100	}
101
102	impl BlockDataSourceWrapper {
103		pub(crate) async fn get_latest_block_info(&self) -> Result<MainchainBlock> {
104			self.inner.get_latest_block_info().await
105		}
106
107		pub(crate) async fn get_latest_stable_block_for(
108			&self,
109			reference_timestamp: u64,
110		) -> Result<Option<MainchainBlock>> {
111			self.inner
112				.get_latest_stable_block_for(Timestamp::new(reference_timestamp))
113				.await
114		}
115
116		pub(crate) async fn get_stable_block_for(
117			&self,
118			hash: McBlockHash,
119			reference_timestamp: u64,
120		) -> Result<Option<MainchainBlock>> {
121			self.inner.get_stable_block_for(hash, Timestamp::new(reference_timestamp)).await
122		}
123	}
124
125	pub(crate) async fn block() -> Result<BlockDataSourceWrapper> {
126		Ok(BlockDataSourceWrapper {
127			inner: BlockDataSourceImpl::new_from_env(pool().await?).await?,
128		})
129	}
130
131	pub(crate) async fn candidate() -> Result<CandidatesDataSourceImpl> {
132		CandidatesDataSourceImpl::new(pool().await?, None).await
133	}
134}