diff --git a/res/indexer-queries.graphql b/res/indexer-queries.graphql index 8d4272d2ce60aab55235430ca1262db8a784e906..edf068eef96c3167710a4a597a068cb072bd3099 100644 --- a/res/indexer-queries.graphql +++ b/res/indexer-queries.graphql @@ -1,11 +1,17 @@ query IdentityNameByPubkey($pubkey: String!) { - identity(where: {pubkey: {_eq: $pubkey}}) { - name - } + identity(where: { pubkey: { _eq: $pubkey } }) { + name + } } query IdentityPubkeyByName($name: String!) { - identity_by_pk(name: $name) { - pubkey - } + identity_by_pk(name: $name) { + pubkey + } +} + +query LatestBlock { + parameters(where: { key: { _eq: "last_indexed_block_number" } }) { + value + } } diff --git a/src/indexer.rs b/src/indexer.rs index a10f6051bbd64c2feaf03a9f6c6bbd8226794c8a..d02b1d9a064b272fe8dddbb1340634be4079b161 100644 --- a/src/indexer.rs +++ b/src/indexer.rs @@ -1,6 +1,11 @@ -pub use graphql_client::{reqwest::post_graphql, GraphQLQuery}; +use graphql_client::reqwest::post_graphql; +use graphql_client::GraphQLQuery; -use anyhow::Result; +use crate::*; + +// type used in parameters query +#[allow(non_camel_case_types)] +type jsonb = serde_json::Value; #[derive(GraphQLQuery)] #[graphql( @@ -16,14 +21,21 @@ pub struct IdentityNameByPubkey; )] pub struct IdentityPubkeyByName; -#[derive(Clone)] +#[derive(GraphQLQuery)] +#[graphql( + schema_path = "res/indexer-schema.json", + query_path = "res/indexer-queries.graphql" +)] +pub struct LatestBlock; + +#[derive(Clone, Debug)] pub struct Indexer { pub gql_client: reqwest::Client, pub gql_url: String, } impl Indexer { - pub async fn username_by_pubkey(&self, pubkey: &str) -> Result<Option<String>> { + pub async fn username_by_pubkey(&self, pubkey: &str) -> anyhow::Result<Option<String>> { Ok(post_graphql::<IdentityNameByPubkey, _>( &self.gql_client, &self.gql_url, @@ -36,7 +48,7 @@ impl Indexer { .and_then(|data| data.identity.into_iter().next().map(|idty| idty.name))) } - pub async fn pubkey_by_username(&self, username: &str) -> Result<Option<String>> { + pub async fn pubkey_by_username(&self, username: &str) -> anyhow::Result<Option<String>> { Ok(post_graphql::<IdentityPubkeyByName, _>( &self.gql_client, self.gql_url.clone(), @@ -48,4 +60,50 @@ impl Indexer { .data .and_then(|data| data.identity_by_pk.map(|idty| idty.pubkey))) } + + /// fetch latest block + pub async fn fetch_latest_block(&self) -> Result<u64, anyhow::Error> { + Ok(post_graphql::<LatestBlock, _>( + &self.gql_client, + self.gql_url.clone(), + latest_block::Variables {}, + ) + .await? + .data + .unwrap() // must have a data field + .parameters + .first() + .unwrap() // must have one and only one parameter matching request + .value + .clone() + .unwrap() // must have a value field + .as_u64() + .unwrap()) // must be a Number of blocks + } +} + +#[derive(Clone, Default, Debug, clap::Parser)] +pub enum IndexerSubcommand { + #[default] + /// Show indexer endpoint + ShowEndpoint, + /// Fetch latest indexed block + LatestBlock, +} + +pub async fn handle_command(data: Data, command: IndexerSubcommand) -> anyhow::Result<()> { + let data = data.build_indexer()?; + match command { + IndexerSubcommand::ShowEndpoint => { + println!("indexer endpoint: {}", data.indexer().gql_url); + } + IndexerSubcommand::LatestBlock => { + println!( + "latest indexed block is: {}", + data.indexer().fetch_latest_block().await? + ); + } + }; + + Ok(()) } diff --git a/src/main.rs b/src/main.rs index ed9bb2f81ca42887746b19f0b34589b87e899158..e4697349a6a7bc9527cac075fa2090769dda02ce 100644 --- a/src/main.rs +++ b/src/main.rs @@ -564,7 +564,7 @@ async fn main() -> Result<(), GcliError> { .await .unwrap(), Subcommand::RuntimeInfo => commands::runtime::runtime_info(data).await, - Subcommand::Indexer(subcommand) => indexer::handle_command(data, subcommand)?, + Subcommand::Indexer(subcommand) => indexer::handle_command(data, subcommand).await?, } Ok(())