Skip to content
Snippets Groups Projects
Commit 76a19ff9 authored by Hugo Trentesaux's avatar Hugo Trentesaux
Browse files

add info on idty view (clients/rust/gcli-v2s!18)

* add info on identity command

* cli schema update
parent fbf95014
No related branches found
No related tags found
1 merge request!18add info on idty view
Pipeline #35752 passed
...@@ -74,13 +74,14 @@ Secret key format can be changed using `--secret-format` with the following valu ...@@ -74,13 +74,14 @@ Secret key format can be changed using `--secret-format` with the following valu
- [x] migrate all xt to submit_call_and_look_event - [x] migrate all xt to submit_call_and_look_event
- [x] add transfer with unit (ĞD, UD...) - [x] add transfer with unit (ĞD, UD...)
- [x] add more runtime-info like cert count, wot and smith params... - [x] add more runtime-info like cert count, wot and smith params...
- [x] add more info on identity view like status, number certs emitted, received
- [x] implement squid indexer to get cert list
- [ ] implement indexer tx history...
- [ ] add more info like sudo key, block interval - [ ] add more info like sudo key, block interval
- [ ] better format runtime info block number (duration in days...) and perbill (%) - [ ] better format runtime info block number (duration in days...) and perbill (%)
- [ ] add proper tabulation for runtime info - [ ] add proper tabulation for runtime info
- [ ] add clap complete for autocompletion - [ ] add clap complete for autocompletion
- [ ] allow to listen to multiple events (like CertAdded and CertRenewed) - [ ] allow to listen to multiple events (like SmithCertAdded and SmithMembershipAdded)
- [ ] add more info on identity view like status, number certs emitted, received
- [ ] implement squid indexer to get cert list + tx history...
- [ ] - [ ]
- [ ] - [ ]
- [ ] - [ ]
......
...@@ -2,6 +2,15 @@ ...@@ -2,6 +2,15 @@
## Graphql schema and queries for Duniter indexer ## Graphql schema and queries for Duniter indexer
Update the schema with:
```sh
# install graphql client cli
cargo install graphql_client_cli
# download schema from node
graphql-client introspect-schema https://subsquid.gdev.coinduf.eu/graphql --output ./res/indexer-schema.json
```
... ...
## Metadata ## Metadata
...@@ -9,6 +18,8 @@ ...@@ -9,6 +18,8 @@
To update the scale-encoded Duniter metadata, spawn a node and run the subxt command. To update the scale-encoded Duniter metadata, spawn a node and run the subxt command.
```sh ```sh
# install subxt
cargo install subxt
# spawn a node listening on localhost:9944 # spawn a node listening on localhost:9944
duniter --dev duniter --dev
# fetch the metadata with subxt # fetch the metadata with subxt
......
query IdentityByIndex($index: Int!) { query IdentityNameByIndex($index: Int!) {
identities(where: {index_eq: $index}) { identities(where: {index_eq: $index}) {
index
name name
account {
id
}
} }
} }
query IdentityByName($name: String!) { query IdentityInfo($index: Int!) {
identities(where: {name_eq: $name}) { identities(where: {index_eq: $index}) {
index
name name
account { certIssued(where: {active_eq: true}) {
receiver {
name
}
}
certReceived(where: {active_eq: true}) {
issuer {
name
}
}
linkedAccount {
id id
} }
} }
} }
query IdentityByPubkey($pubkey: String!) { query IdentityNameByPubkey($pubkey: String!) {
identities(where: {account: {id_eq: $pubkey}}) { identities(where: {account: {id_eq: $pubkey}}) {
index
name name
account {
id
}
} }
} }
......
Source diff could not be displayed: it is too large. Options to address this: view the blob.
...@@ -152,37 +152,35 @@ pub async fn get_identity( ...@@ -152,37 +152,35 @@ pub async fn get_identity(
account_id: Option<AccountId>, account_id: Option<AccountId>,
identity_id: Option<IdtyId>, identity_id: Option<IdtyId>,
username: Option<String>, username: Option<String>,
) -> Result<(), anyhow::Error> { ) -> Result<(), GcliError> {
let client = data.client(); let client = data.client();
let indexer = data.indexer.clone(); let indexer = data.indexer.clone();
// fetch reachable information using Duniter only (no indexer) // get idty_id
let (idty, value) = match (&account_id, identity_id, &username) { let idty =
// idty_id → account_id match (identity_id, &account_id, &username) {
(None, Some(idty), None) => (idty, get_identity_by_index(client, idty).await?), // idty_id
(Some(idty), None, None) => idty,
// account_id → idty_id // account_id → idty_id
(Some(account_id), None, None) => { (None, Some(account_id), None) => get_idty_index_by_account_id(client, account_id)
let idty = get_idty_index_by_account_id(client, account_id)
.await? .await?
.ok_or_else(|| anyhow!("no identity for this account id"))?; .ok_or_else(|| anyhow!("no identity for account '{account_id}'"))?,
(idty, get_identity_by_index(client, idty).await?) // username → idty_id
} (None, None, Some(username)) => get_idty_index_by_name(client, username)
// username → idty_id and account_id
(None, None, Some(username)) => {
let idty = get_idty_index_by_name(client, username)
.await? .await?
.ok_or_else(|| anyhow!("no identity found for this username"))?; .ok_or_else(|| anyhow!("no identity for name '{username}'"))?,
(idty, get_identity_by_index(client, idty).await?)
}
_ => { _ => {
return Err(anyhow!( return Err(GcliError::Logic(
"One and only one argument is needed to fetch the identity." "One and only one argument is needed to fetch the identity.".to_string(),
)); ));
} }
}; };
let value = value.ok_or_else(|| anyhow!("no identity value"))?; // idty_id → value
let value = get_identity_by_index(client, idty)
.await?
.ok_or_else(|| anyhow!("no identity value for index {idty}"))?;
// print result // --- print result ---
// 1. identity index // 1. identity index
println!("Identity index: {idty}",); println!("Identity index: {idty}",);
// 2. username (indexer needed if not provided) // 2. username (indexer needed if not provided)
...@@ -190,7 +188,7 @@ pub async fn get_identity( ...@@ -190,7 +188,7 @@ pub async fn get_identity(
indexer indexer
.username_by_index(idty) .username_by_index(idty)
.await? .await?
.ok_or_else(|| anyhow!("indexer does not have username for this index"))? .ok_or_else(|| anyhow!("indexer does not have username for this index {idty}"))?
} else { } else {
"<no indexer>".to_string() "<no indexer>".to_string()
}); });
...@@ -200,6 +198,20 @@ pub async fn get_identity( ...@@ -200,6 +198,20 @@ pub async fn get_identity(
// 4. status // 4. status
println!("Status: {:?}", value.status); println!("Status: {:?}", value.status);
// get more info
if let Some(indexer) = &indexer {
let info = indexer.identity_info(idty).await.expect("no info");
println!(
"Certifications: issued {}, received {}",
info.cert_issued.len(),
info.cert_received.len()
);
let a = info.linked_account.len();
if a > 1 {
println!("Linked accounts: {a}");
}
}
Ok(()) Ok(())
} }
......
...@@ -281,18 +281,9 @@ pub async fn accept_invitation(data: &Data) -> Result<(), subxt::Error> { ...@@ -281,18 +281,9 @@ pub async fn accept_invitation(data: &Data) -> Result<(), subxt::Error> {
/// invite identity to join smith /// invite identity to join smith
pub async fn certify_smith(data: &Data, target: IdtyId) -> Result<(), subxt::Error> { pub async fn certify_smith(data: &Data, target: IdtyId) -> Result<(), subxt::Error> {
// submit_call_and_look_event::< submit_call_and_look_event::<
// runtime::smith_members::events::CertificationReceived, runtime::smith_members::events::SmithCertAdded,
// Payload<runtime::smith_members::calls::types::CertifySmith>, Payload<runtime::smith_members::calls::types::CertifySmith>,
// >(data, &runtime::tx().smith_members().certify_smith(target)) >(data, &runtime::tx().smith_members().certify_smith(target))
// .await .await
let progress = submit_call(data, &runtime::tx().smith_members().certify_smith(target)).await?;
if data.args.no_wait {
return Ok(());
}
let events = track_progress(progress).await?;
// look for the expected event
look_event::<runtime::smith_members::events::SmithCertAdded>(data, &events)?;
look_event::<runtime::smith_members::events::SmithMembershipAdded>(data, &events)?;
Ok(())
} }
...@@ -2,6 +2,7 @@ use graphql_client::{reqwest::post_graphql, GraphQLQuery}; ...@@ -2,6 +2,7 @@ use graphql_client::{reqwest::post_graphql, GraphQLQuery};
use sp_core::Bytes; use sp_core::Bytes;
use crate::*; use crate::*;
use identity_info::*;
// type used in parameters query // type used in parameters query
// #[allow(non_camel_case_types)] // #[allow(non_camel_case_types)]
...@@ -10,37 +11,37 @@ use crate::*; ...@@ -10,37 +11,37 @@ use crate::*;
// index → identity // index → identity
#[derive(GraphQLQuery)] #[derive(GraphQLQuery)]
#[graphql( #[graphql(
schema_path = "res/indexer-schema.graphql", schema_path = "res/indexer-schema.json",
query_path = "res/indexer-queries.graphql" query_path = "res/indexer-queries.graphql"
)] )]
pub struct IdentityByIndex; pub struct IdentityNameByIndex;
// // name → identity // index → identity info
// #[derive(GraphQLQuery)] #[derive(GraphQLQuery)]
// #[graphql( #[graphql(
// schema_path = "res/indexer-schema.graphql", schema_path = "res/indexer-schema.json",
// query_path = "res/indexer-queries.graphql" query_path = "res/indexer-queries.graphql"
// )] )]
// pub struct IdentityByName; pub struct IdentityInfo;
// pubkey → identity // pubkey → identity
#[derive(GraphQLQuery)] #[derive(GraphQLQuery)]
#[graphql( #[graphql(
schema_path = "res/indexer-schema.graphql", schema_path = "res/indexer-schema.json",
query_path = "res/indexer-queries.graphql" query_path = "res/indexer-queries.graphql"
)] )]
pub struct IdentityByPubkey; pub struct IdentityNameByPubkey;
#[derive(GraphQLQuery)] #[derive(GraphQLQuery)]
#[graphql( #[graphql(
schema_path = "res/indexer-schema.graphql", schema_path = "res/indexer-schema.json",
query_path = "res/indexer-queries.graphql" query_path = "res/indexer-queries.graphql"
)] )]
pub struct LatestBlock; pub struct LatestBlock;
#[derive(GraphQLQuery)] #[derive(GraphQLQuery)]
#[graphql( #[graphql(
schema_path = "res/indexer-schema.graphql", schema_path = "res/indexer-schema.json",
query_path = "res/indexer-queries.graphql" query_path = "res/indexer-queries.graphql"
)] )]
pub struct GenesisHash; pub struct GenesisHash;
...@@ -52,45 +53,48 @@ pub struct Indexer { ...@@ -52,45 +53,48 @@ pub struct Indexer {
} }
impl Indexer { impl Indexer {
/// index → name
pub async fn username_by_index(&self, index: u32) -> anyhow::Result<Option<String>> { pub async fn username_by_index(&self, index: u32) -> anyhow::Result<Option<String>> {
Ok(post_graphql::<IdentityByIndex, _>( Ok(post_graphql::<IdentityNameByIndex, _>(
&self.gql_client, &self.gql_client,
&self.gql_url, &self.gql_url,
identity_by_index::Variables { identity_name_by_index::Variables {
index: index.into(), index: index.into(),
}, },
) )
.await? .await?
.data .data
.and_then(|data| data.identities.first().map(|idty| idty.name.clone()))) .and_then(move |mut data| data.identities.pop().map(|idty| idty.name)))
} }
/// pubkey → name
pub async fn username_by_pubkey(&self, pubkey: &str) -> anyhow::Result<Option<String>> { pub async fn username_by_pubkey(&self, pubkey: &str) -> anyhow::Result<Option<String>> {
Ok(post_graphql::<IdentityByPubkey, _>( Ok(post_graphql::<IdentityNameByPubkey, _>(
&self.gql_client, &self.gql_client,
&self.gql_url, &self.gql_url,
identity_by_pubkey::Variables { identity_name_by_pubkey::Variables {
pubkey: pubkey.to_string(), pubkey: pubkey.to_string(),
}, },
) )
.await? .await?
.data .data
.and_then(|data| data.identities.first().map(|idty| idty.name.clone()))) .and_then(move |mut data| data.identities.pop().map(|idty| idty.name)))
} }
// // not used anymore because available with Duniter /// index → info
// pub async fn pubkey_by_username(&self, username: &str) -> anyhow::Result<Option<String>> { pub async fn identity_info(&self, index: u32) -> Option<IdentityInfoIdentities> {
// Ok(post_graphql::<IdentityByName, _>( post_graphql::<IdentityInfo, _>(
// &self.gql_client, &self.gql_client,
// self.gql_url.clone(), &self.gql_url,
// identity_by_name::Variables { identity_info::Variables {
// name: username.to_string(), index: index.into(),
// }, },
// ) )
// .await? .await
// .data .expect("problem")
// .and_then(|data| data.identity.into_iter().next().map(|idty| idty.pubkey))) .data
// } .and_then(move |mut data| data.identities.pop())
}
/// fetch latest block number /// fetch latest block number
pub async fn fetch_latest_block(&self) -> Result<u64, anyhow::Error> { pub async fn fetch_latest_block(&self) -> Result<u64, anyhow::Error> {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment