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

update with duniter version of current gdev network

parent 7c9626b3
No related branches found
No related tags found
1 merge request!13update with duniter version of current gdev network
......@@ -23,6 +23,7 @@ sp-core = { git = "https://github.com/duniter/substrate.git", branch = "duniter-
sp-runtime = { git = "https://github.com/duniter/substrate", branch = "duniter-substrate-v0.9.42" }
subxt = { git = "https://github.com/duniter/subxt.git", branch = "subxt-v0.32.1-duniter-substrate-v0.9.42", features = ["substrate-compat"] }
# subxt-signer = { git = "https://github.com/duniter/subxt.git", branch = "subxt-v0.32.1-duniter-substrate-v0.9.42", features = ["subxt"] }
# sp-api = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.42'}
tokio = { version = "1.26.0", features = ["macros"] }
confy = "0.5.1"
scrypt = { version = "0.11", default-features = false } # for old-style key generation
......
# Resources
## Graphql schema and queries for Duniter indexer
...
## Metadata
To update the scale-encoded Duniter metadata, spawn a node and run the subxt command.
```sh
# spawn a node listening on localhost:9944
duniter --dev
# fetch the metadata with subxt
subxt metadata -f bytes > res/metadata.scale
```
\ No newline at end of file
query IdentityNameByPubkey($pubkey: String!) {
identity(where: { pubkey: { _eq: $pubkey } }) {
query IdentityByIndex($index: Int!) {
identity_by_pk(index: $index) {
index
name
pubkey
}
}
query IdentityPubkeyByName($name: String!) {
identity_by_pk(name: $name) {
query IdentityByName($name: String!) {
identity(where: { name: { _eq: $name } }) {
index
name
pubkey
}
}
query IdentityByPubkey($pubkey: String!) {
identity(where: { pubkey: { _eq: $pubkey } }) {
index
name
pubkey
}
}
......
This diff is collapsed.
No preview for this file type
......@@ -3,6 +3,7 @@ pub mod blockchain;
pub mod certification;
pub mod cesium;
pub mod collective;
pub mod distance;
pub mod expire;
pub mod identity;
pub mod net_test;
......@@ -13,4 +14,3 @@ pub mod smith;
pub mod sudo;
pub mod transfer;
pub mod ud;
pub mod distance;
......@@ -35,9 +35,7 @@ pub enum Subcommand {
pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliError> {
let data = data.build_client().await?.fetch_system_properties().await?;
match command {
Subcommand::Balance => {
get_balance(data).await?
}
Subcommand::Balance => get_balance(data).await?,
Subcommand::Transfer {
amount,
dest,
......
......@@ -20,17 +20,15 @@ pub async fn handle_command(_data: Data, command: Subcommand) -> Result<(), Gcli
Subcommand::Nothing => {}
Subcommand::Pubkey { id, pass } => {
let keypair = pair_from_cesium(id, pass);
println!(
"Pubkey: {}",
bs58::encode(keypair.pkey).into_string()
);
println!("Pubkey: {}", bs58::encode(keypair.pkey).into_string());
let address: AccountId = keypair.pkey.into();
println!("Address: {}", address.to_string());
}
Subcommand::Prompt => {
let keypair = prompt_secret_cesium();
println!(
"Pubkey: {}",
bs58::encode(keypair.pkey).into_string()
);
println!("Pubkey: {}", bs58::encode(keypair.pkey).into_string());
let address: AccountId = keypair.pkey.into();
println!("Address: {}", address.to_string());
}
}
Ok(())
......
......@@ -2,23 +2,36 @@ use crate::*;
/// request distance evaluation
pub async fn request_distance_evaluation(data: &Data) -> Result<(), subxt::Error> {
let progress = submit_call(data, &runtime::tx().distance().request_distance_evaluation())
let progress = submit_call(
data,
&runtime::tx().distance().request_distance_evaluation(),
)
.await?;
if data.args.no_wait {
return Ok(());
}
let _ = track_progress(progress).await?;
Ok(())
if data.args.no_wait {
return Ok(());
}
let _ = track_progress(progress).await?;
Ok(())
}
/// get identity distance status
pub async fn get_identity_distance_status(
data: &Data,
) -> Result<Option<(AccountId, runtime::runtime_types::pallet_distance::types::DistanceStatus)>, subxt::Error> {
) -> Result<
Option<(
AccountId,
runtime::runtime_types::pallet_distance::types::DistanceStatus,
)>,
subxt::Error,
> {
data.client()
.storage()
.at_latest()
.await?
.fetch(&runtime::storage().distance().identity_distance_status(data.idty_index()))
.fetch(
&runtime::storage()
.distance()
.identity_distance_status(data.idty_index()),
)
.await
}
\ No newline at end of file
}
......@@ -3,17 +3,15 @@ use crate::*;
use crate::{
commands::revocation::generate_revoc_doc,
runtime::runtime_types::{
common_runtime::entities::{IdtyData, NewOwnerKeySignature},
pallet_identity::types::*,
sp_runtime::MultiSignature,
common_runtime::entities::IdtyData, pallet_identity::types::*, sp_runtime::MultiSignature,
},
};
use std::str::FromStr;
/// define identity subcommands
#[derive(Clone, Default, Debug, clap::Parser)]
pub enum Subcommand {
/// show identity
/// Show identity
/// (same as get but without arg)
#[default]
Show,
/// Fetch identity
......@@ -62,6 +60,17 @@ pub enum Subcommand {
#[clap(short, long)]
secret: Option<String>,
},
/// Migrate identity to another account
/// Change Owner Key
ChangeOwnerKey {
/// Secret key format (seed, substrate)
#[clap(short = 'S', long, default_value = SecretFormat::Substrate)]
secret_format: SecretFormat,
/// Secret of account to link
/// most likely different from the one owning the identity
#[clap(short, long)]
secret: Option<String>,
},
}
/// handle identity commands
......@@ -69,7 +78,10 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
let mut data = data.build_client().await?;
match command {
// TODO remove indexer where not necessary when BlakeConcat will be there
Subcommand::Show => {}
Subcommand::Show => {
data = data.build_indexer().await?;
get_identity(&data, Some(data.address()), None, None).await?
}
Subcommand::Get {
ref account_id,
identity_id,
......@@ -132,6 +144,15 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
data = data.fetch_idty_index().await?; // idty index required for payload
link_account(&data, address, keypair).await?;
}
Subcommand::ChangeOwnerKey {
secret_format,
secret,
} => {
let keypair = get_keypair(secret_format, secret.as_deref())?;
let address = keypair.address();
data = data.fetch_idty_index().await?; // idty index required for payload
change_owner_key(&data, address, keypair).await?;
}
};
Ok(())
......@@ -149,26 +170,31 @@ pub async fn get_identity(
let client = data.client();
let indexer = data.indexer.clone();
// fetch missing information
// fetch reachable information using Duniter only (no indexer)
match (&account_id, identity_id, &username) {
// idty_id → account_id
(None, Some(identity_id), None) => {
account_id = get_identity_by_index(client, identity_id)
.await?
.map(|idty| idty.owner_key);
if account_id.is_none() {
return Err(anyhow!("no identity for this account id"));
}
}
// account_id → idty_id
(Some(account_id), None, None) => {
identity_id = get_idty_index_by_account_id(client, account_id).await?;
if identity_id.is_none() {
return Err(anyhow!("no identity for this identity index"));
}
}
// username → idty_id and account_id
(None, None, Some(username)) => {
let indexer = indexer.as_ref().ok_or(anyhow!(
"Cannot fetch identity from username without indexer."
))?;
if let Some(pubkey) = indexer.pubkey_by_username(username).await? {
// convert string to accountid
let fetched_account_id = AccountId::from_str(&pubkey).map_err(|e| anyhow!(e))?;
// in the future, also ask indexer the identity index
identity_id = get_idty_index_by_account_id(client, &fetched_account_id).await?;
account_id = Some(fetched_account_id);
identity_id = get_idty_index_by_name(client, username).await?;
if let Some(identity_id) = identity_id {
account_id = get_identity_by_index(client, identity_id)
.await?
.map(|idty| idty.owner_key);
} else {
return Err(anyhow!("no identity found for this username"));
}
......@@ -181,24 +207,26 @@ pub async fn get_identity(
};
// print result
// 1. identity index
println!(
"Account id: {}",
account_id
.as_ref()
.map_or(String::new(), AccountId::to_string)
);
println!(
"Identity id: {}",
"Identity index: {}",
identity_id.map_or(String::new(), |identity_id| format!("{identity_id}"))
);
if let (Some(indexer), Some(account_id), None) = (&indexer, &account_id, &username) {
username = indexer.username_by_pubkey(&account_id.to_string()).await?;
// 2. username (indexer needed if not provided)
if let (Some(indexer), Some(identity_id), None) = (&indexer, identity_id, &username) {
username = indexer.username_by_index(identity_id).await?;
}
println!(
"Username: {}",
"Username: {}",
username.unwrap_or("<no indexer>".to_string())
);
// 3. address
println!(
"Address: {}",
account_id
.as_ref()
.map_or(String::new(), AccountId::to_string)
);
Ok(())
}
......@@ -207,26 +235,39 @@ pub async fn get_identity(
pub async fn get_idty_index_by_account_id(
client: &Client,
account_id: &AccountId,
) -> Result<Option<IdtyId>, anyhow::Error> {
Ok(client
) -> Result<Option<IdtyId>, subxt::Error> {
client
.storage()
.at_latest()
.await?
.fetch(&runtime::storage().identity().identity_index_of(account_id))
.await?)
.await
}
/// get identity index by name
pub async fn get_idty_index_by_name(
client: &Client,
name: &str,
) -> Result<Option<IdtyId>, subxt::Error> {
client
.storage()
.at_latest()
.await?
.fetch(&runtime::storage().identity().identities_names(name))
.await
}
/// get identityt value by index
pub async fn get_identity_by_index(
client: &Client,
idty_index: IdtyId,
) -> Result<Option<IdtyValue<IdtyId, AccountId, IdtyData>>, anyhow::Error> {
Ok(client
) -> Result<Option<IdtyValue<IdtyId, AccountId, IdtyData>>, subxt::Error> {
client
.storage()
.at_latest()
.await?
.fetch(&runtime::storage().identity().identities(idty_index))
.await?)
.await
}
/// created identity
......@@ -292,13 +333,45 @@ pub fn generate_link_account(
data: &Data,
address: AccountId,
keypair: KeyPair,
) -> (LinkAccountPayload, sr25519::Signature) {
) -> (LinkAccountPayload, Signature) {
let payload = (b"link", data.genesis_hash, data.idty_index(), address).encode();
let KeyPair::Sr25519(keypair) = keypair else {
panic!("Cesium keys not implemented there")
};
let signature = keypair.sign(&payload);
(payload, signature)
match keypair {
KeyPair::Sr25519(keypair) => {
let signature = keypair.sign(&payload);
(payload, Signature::Sr25519(signature))
}
KeyPair::Nacl(keypair) => {
let signature = nacl::sign::signature(&payload, &keypair.skey).expect("could not sign");
(payload, Signature::Nacl(signature))
}
}
}
type ChOkPayload = Vec<u8>;
/// generate link account document
pub fn generate_chok_payload(
data: &Data,
_address: AccountId,
keypair: KeyPair,
) -> (ChOkPayload, Signature) {
let payload = (
b"icok",
data.genesis_hash,
data.idty_index(),
data.address(),
)
.encode();
match keypair {
KeyPair::Sr25519(keypair) => {
let signature = keypair.sign(&payload);
(payload, Signature::Sr25519(signature))
}
KeyPair::Nacl(keypair) => {
// should not migrate to Nacl
let signature = nacl::sign::signature(&payload, &keypair.skey).expect("could not sign");
(payload, Signature::Nacl(signature))
}
}
}
/// link an account to the identity
......@@ -311,16 +384,52 @@ pub async fn link_account(
// this is a hack, see
// https://substrate.stackexchange.com/questions/10309/how-to-use-core-crypto-types-instead-of-runtime-types
let signature = runtime::runtime_types::sp_core::sr25519::Signature(signature.0);
let signature = match signature {
Signature::Sr25519(signature) => MultiSignature::Sr25519(
runtime::runtime_types::sp_core::sr25519::Signature(signature.0),
),
Signature::Nacl(signature) => MultiSignature::Ed25519(
runtime::runtime_types::sp_core::ed25519::Signature(signature.try_into().unwrap()),
),
};
submit_call_and_look_event::<
runtime::account::events::AccountLinked,
Payload<runtime::identity::calls::types::LinkAccount>,
>(
data,
&runtime::tx().identity().link_account(address, signature),
)
.await
}
/// change owner key
pub async fn change_owner_key(
data: &Data,
address: AccountId,
keypair: KeyPair,
) -> Result<(), subxt::Error> {
let (_payload, signature) = generate_chok_payload(data, address.clone(), keypair);
// this is a hack, see
// https://substrate.stackexchange.com/questions/10309/how-to-use-core-crypto-types-instead-of-runtime-types
let signature = match signature {
Signature::Sr25519(signature) => MultiSignature::Sr25519(
runtime::runtime_types::sp_core::sr25519::Signature(signature.0),
),
Signature::Nacl(signature) => MultiSignature::Ed25519(
runtime::runtime_types::sp_core::ed25519::Signature(signature.try_into().unwrap()),
),
};
submit_call_and_look_event::<
runtime::identity::events::IdtyChangedOwnerKey,
Payload<runtime::identity::calls::types::ChangeOwnerKey>,
>(
data,
&runtime::tx()
.identity()
.link_account(address, NewOwnerKeySignature(signature)),
.change_owner_key(address, signature),
)
.await
}
use crate::*;
#[cfg(feature = "gdev")]
use runtime::runtime_types::gdev_runtime::opaque::SessionKeys as RuntimeSessionKeys;
use std::ops::Deref;
type SessionKeys = [u8; 128];
#[cfg(feature = "gdev")]
type SmithMembershipMetaData =
runtime::runtime_types::common_runtime::entities::SmithMembershipMetaData<SessionKeys>;
/// decode byte array into runtime session keys
// TODO find a way to avoid doing this manually by importing session keys trait implementation
fn session_keys_decode(session_keys: SessionKeys) -> RuntimeSessionKeys {
RuntimeSessionKeys {
grandpa: runtime::runtime_types::sp_consensus_grandpa::app::Public(
runtime::runtime_types::sp_core::ed25519::Public(
session_keys[0..32].try_into().unwrap(),
),
)
.into(),
babe: runtime::runtime_types::sp_consensus_babe::app::Public(
runtime::runtime_types::sp_core::sr25519::Public(
session_keys[32..64].try_into().unwrap(),
),
)
.into(),
im_online: runtime::runtime_types::pallet_im_online::sr25519::app_sr25519::Public(
runtime::runtime_types::sp_core::sr25519::Public(
session_keys[64..96].try_into().unwrap(),
),
)
.into(),
authority_discovery: runtime::runtime_types::sp_authority_discovery::app::Public(
runtime::runtime_types::sp_core::sr25519::Public(
session_keys[96..128].try_into().unwrap(),
),
)
.into(),
}
}
/// define smith subcommands
#[derive(Clone, Default, Debug, clap::Parser)]
pub enum Subcommand {
/// Request smith membership
Request { endpoint: String },
Request,
/// Emit a smith certification
Cert { to: IdtyId },
/// Claim smith membership
Claim,
/// Renew smith membership
Renew,
/// Revoke smith membership
Revoke,
/// go online
GoOnline,
/// go offline
......@@ -25,6 +57,8 @@ pub enum Subcommand {
GoOffline,
/// Rotate and set session keys
UpdateKeys,
/// Set session keys
SetSessionKeys { session_keys: String },
/// List upcoming expirations that require an action
ShowExpire {
/// Show certs that expire within less than this number of blocks
......@@ -44,8 +78,8 @@ pub enum Subcommand {
pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliError> {
let mut data = data.build_client().await?;
match command {
Subcommand::Request { endpoint } => {
request_smith_membership(&data, endpoint).await?;
Subcommand::Request => {
request_smith_membership(&data).await?;
}
Subcommand::Claim => {
claim_smith_membership(&data).await?;
......@@ -53,6 +87,9 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
Subcommand::Renew => {
renew_smith_membership(&data).await?;
}
Subcommand::Revoke => {
revoke_smith_membership(&data).await?;
}
Subcommand::GoOnline => {
go_online(&data).await?;
}
......@@ -66,6 +103,15 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
Subcommand::UpdateKeys => {
update_session_keys(&data).await?;
}
Subcommand::SetSessionKeys { session_keys } => {
let session_keys = session_keys_decode(
hex::decode(session_keys)
.expect("wrong hexadecimal")
.try_into()
.expect("wrong format"),
); // decode session keys from hex string
set_session_keys(&data, session_keys).await?;
}
Subcommand::ShowExpire { blocks, sessions } => {
data = data.build_client().await?.build_indexer().await?;
commands::expire::monitor_expirations(&data, blocks, sessions).await?
......@@ -113,30 +159,18 @@ pub async fn rotate_keys(data: &Data) -> Result<SessionKeys, anyhow::Error> {
}
/// request smith membership
pub async fn request_smith_membership(data: &Data, endpoint: String) -> Result<(), anyhow::Error> {
let session_keys = rotate_keys(data).await?;
let metadata = SmithMembershipMetaData {
session_keys,
owner_key: data.address(),
p2p_endpoint: endpoint,
};
pub async fn request_smith_membership(data: &Data) -> Result<(), subxt::Error> {
submit_call_and_look_event::<
runtime::smith_membership::events::MembershipRequested,
Payload<runtime::smith_membership::calls::types::RequestMembership>,
>(
data,
&runtime::tx()
.smith_membership()
.request_membership(metadata),
)
>(data, &runtime::tx().smith_membership().request_membership())
.await
.map_err(|e| anyhow!(e))
}
/// set session keys
pub async fn set_session_keys(
data: &Data,
session_keys: SessionKeys,
session_keys: RuntimeSessionKeys,
) -> Result<TxProgress, subxt::Error> {
submit_call::<Payload<runtime::authority_members::calls::types::SetSessionKeys>>(
data,
......@@ -147,9 +181,13 @@ pub async fn set_session_keys(
.await
}
// use runtime::runtime_types::sp_consensus_grandpa::app::Public
/// update session keys
pub async fn update_session_keys(data: &Data) -> Result<(), GcliError> {
let session_keys = rotate_keys(data).await?;
// manual session key conversion
let session_keys = session_keys_decode(session_keys);
let progress = set_session_keys(data, session_keys).await?;
if data.args.no_wait {
......@@ -201,6 +239,15 @@ pub async fn renew_smith_membership(data: &Data) -> Result<(), subxt::Error> {
.await
}
/// revoke smith membership
pub async fn revoke_smith_membership(data: &Data) -> Result<(), subxt::Error> {
submit_call_and_look_event::<
runtime::smith_membership::events::MembershipRevoked,
Payload<runtime::smith_membership::calls::types::RevokeMembership>,
>(data, &runtime::tx().smith_membership().revoke_membership())
.await
}
/// submit go_offline
pub async fn go_offline(data: &Data) -> Result<(), subxt::Error> {
submit_call_and_look_event::<
......
use crate::*;
/// define sudo subcommands
#[derive(Clone, Default, Debug, clap::Parser)]
pub enum Subcommand {
......@@ -30,7 +29,6 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
Ok(())
}
/// set sudo key
pub async fn set_key(data: &Data, new_key: AccountId) -> Result<(), subxt::Error> {
submit_call_and_look_event::<
......@@ -40,10 +38,15 @@ pub async fn set_key(data: &Data, new_key: AccountId) -> Result<(), subxt::Error
.await
}
/// set distance ok
pub async fn set_distance_ok(data: &Data, identity: IdtyId) -> Result<(), subxt::Error> {
let inner = runtime::distance::Call::force_set_distance_status { identity, status: Some((data.address(), runtime::runtime_types::pallet_distance::types::DistanceStatus::Valid)) };
let inner = runtime::distance::Call::force_set_distance_status {
identity,
status: Some((
data.address(),
runtime::runtime_types::pallet_distance::types::DistanceStatus::Valid,
)),
};
let inner = runtime::Call::Distance(inner);
submit_call_and_look_event::<
runtime::sudo::events::Sudid,
......
......@@ -11,7 +11,7 @@ pub enum Subcommand {
/// handle ud commands
pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliError> {
// build indexer because it is needed for all subcommands
let data = data.build_client().await?;
let data = data.build_client().await?.fetch_system_properties().await?;
// match subcommand
match command {
Subcommand::Claim => {
......
......@@ -144,14 +144,18 @@ impl Data {
if let Some(indexer_endpoint) = self.args.indexer.clone() {
self.cfg.indexer_endpoint = indexer_endpoint
}
// predefined secret format overwrites secret with mnemonic
// secret format and value
if self.args.secret_format == SecretFormat::Predefined {
// predefined secret format overwrites secret with mnemonic
match self.args.secret.clone() {
None => {}
Some(derivation) => {
self.cfg.secret = Some(predefined_mnemonic(&derivation));
}
};
} else if self.args.secret_format == SecretFormat::Cesium {
// cesium secret format also overwrites, to force valid prompt
self.cfg.secret = None
} else if let Some(secret) = self.args.secret.clone() {
// other secret type
self.cfg.secret = Some(secret);
......
......@@ -9,7 +9,8 @@ impl DisplayEvent for runtime::universal_dividend::events::UdsClaimed {
fn display(&self, data: &Data) -> String {
format!(
"claimed {} UD, for a total of {}",
self.count, data.format_balance(self.total)
self.count,
data.format_balance(self.total)
)
}
}
......@@ -45,12 +46,18 @@ impl DisplayEvent for runtime::technical_committee::events::Voted {
}
impl DisplayEvent for runtime::identity::events::IdtyCreated {
fn display(&self, _data: &Data) -> String {
format!("identity created for {} with index {}", self.owner_key, self.idty_index)
format!(
"identity created for {} with index {}",
self.owner_key, self.idty_index
)
}
}
impl DisplayEvent for runtime::identity::events::IdtyConfirmed {
fn display(&self, _data: &Data) -> String {
format!("identity confirmed with name \"{}\" (index {}, owner key {})", self.name, self.idty_index, self.owner_key)
format!(
"identity confirmed with name \"{}\" (index {}, owner key {})",
self.name, self.idty_index, self.owner_key
)
}
}
impl DisplayEvent for runtime::identity::events::IdtyValidated {
......@@ -58,6 +65,11 @@ impl DisplayEvent for runtime::identity::events::IdtyValidated {
format!("identity validated {:?}", self)
}
}
impl DisplayEvent for runtime::identity::events::IdtyChangedOwnerKey {
fn display(&self, _data: &Data) -> String {
format!("identity changed owner key {:?}", self)
}
}
impl DisplayEvent for runtime::membership::events::MembershipRenewed {
fn display(&self, _data: &Data) -> String {
format!("membership renewed {:?}", self)
......@@ -100,7 +112,12 @@ impl DisplayEvent for runtime::smith_membership::events::MembershipAcquired {
}
impl DisplayEvent for runtime::smith_membership::events::MembershipRenewed {
fn display(&self, _data: &Data) -> String {
format!("membership renewed {:?}", self)
format!("smith membership renewed {:?}", self)
}
}
impl DisplayEvent for runtime::smith_membership::events::MembershipRevoked {
fn display(&self, _data: &Data) -> String {
format!("smith membership revoked {:?}", self)
}
}
impl DisplayEvent for runtime::authority_members::events::MemberGoOffline {
......@@ -115,7 +132,12 @@ impl DisplayEvent for runtime::sudo::events::KeyChanged {
}
impl DisplayEvent for runtime::balances::events::Transfer {
fn display(&self, data: &Data) -> String {
format!("transfered {} ({} → {})", data.format_balance(self.amount), self.from, self.to)
format!(
"transfered {} ({} → {})",
data.format_balance(self.amount),
self.from,
self.to
)
}
}
impl DisplayEvent for runtime::utility::events::BatchCompleted {
......
......@@ -6,30 +6,40 @@ use crate::*;
#[allow(non_camel_case_types)]
type jsonb = serde_json::Value;
// index → identity
#[derive(GraphQLQuery)]
#[graphql(
schema_path = "res/indexer-schema.json",
schema_path = "res/indexer-schema.graphql",
query_path = "res/indexer-queries.graphql"
)]
pub struct IdentityNameByPubkey;
pub struct IdentityByIndex;
// // name → identity
// #[derive(GraphQLQuery)]
// #[graphql(
// schema_path = "res/indexer-schema.graphql",
// query_path = "res/indexer-queries.graphql"
// )]
// pub struct IdentityByName;
// pubkey → identity
#[derive(GraphQLQuery)]
#[graphql(
schema_path = "res/indexer-schema.json",
schema_path = "res/indexer-schema.graphql",
query_path = "res/indexer-queries.graphql"
)]
pub struct IdentityPubkeyByName;
pub struct IdentityByPubkey;
#[derive(GraphQLQuery)]
#[graphql(
schema_path = "res/indexer-schema.json",
schema_path = "res/indexer-schema.graphql",
query_path = "res/indexer-queries.graphql"
)]
pub struct LatestBlock;
#[derive(GraphQLQuery)]
#[graphql(
schema_path = "res/indexer-schema.json",
schema_path = "res/indexer-schema.graphql",
query_path = "res/indexer-queries.graphql"
)]
pub struct GenesisHash;
......@@ -41,32 +51,48 @@ pub struct Indexer {
}
impl Indexer {
pub async fn username_by_pubkey(&self, pubkey: &str) -> anyhow::Result<Option<String>> {
Ok(post_graphql::<IdentityNameByPubkey, _>(
pub async fn username_by_index(&self, index: u32) -> anyhow::Result<Option<String>> {
Ok(post_graphql::<IdentityByIndex, _>(
&self.gql_client,
&self.gql_url,
identity_name_by_pubkey::Variables {
pubkey: pubkey.to_string(),
identity_by_index::Variables {
index: index.into(),
},
)
.await?
.data
.and_then(|data| data.identity.into_iter().next().map(|idty| idty.name)))
.and_then(|data| data.identity_by_pk.map(|idty| idty.name))
.unwrap())
}
pub async fn pubkey_by_username(&self, username: &str) -> anyhow::Result<Option<String>> {
Ok(post_graphql::<IdentityPubkeyByName, _>(
pub async fn username_by_pubkey(&self, pubkey: &str) -> anyhow::Result<Option<String>> {
Ok(post_graphql::<IdentityByPubkey, _>(
&self.gql_client,
self.gql_url.clone(),
identity_pubkey_by_name::Variables {
name: username.to_string(),
&self.gql_url,
identity_by_pubkey::Variables {
pubkey: pubkey.to_string(),
},
)
.await?
.data
.and_then(|data| data.identity_by_pk.map(|idty| idty.pubkey)))
.and_then(|data| data.identity.into_iter().next().map(|idty| idty.name))
.unwrap())
}
// // not used anymore because available with Duniter
// pub async fn pubkey_by_username(&self, username: &str) -> anyhow::Result<Option<String>> {
// Ok(post_graphql::<IdentityByName, _>(
// &self.gql_client,
// self.gql_url.clone(),
// identity_by_name::Variables {
// name: username.to_string(),
// },
// )
// .await?
// .data
// .and_then(|data| data.identity.into_iter().next().map(|idty| idty.pubkey)))
// }
/// fetch latest block number
pub async fn fetch_latest_block(&self) -> Result<u64, anyhow::Error> {
Ok(post_graphql::<LatestBlock, _>(
......
......@@ -48,7 +48,7 @@ impl From<SecretFormat> for OsStr {
}
}
/// wrapper type for keys
/// wrapper type for keys + signature
pub enum KeyPair {
Sr25519(Sr25519Pair),
Nacl(nacl::sign::Keypair),
......@@ -83,6 +83,10 @@ impl From<nacl::sign::Keypair> for KeyPair {
KeyPair::Nacl(pair)
}
}
pub enum Signature {
Sr25519(sr25519::Signature),
Nacl(Vec<u8>),
}
/// get keypair in any possible way
/// at this point, if secret is predefined, it's not replaced yet
......
......@@ -12,10 +12,10 @@ use anyhow::anyhow;
use clap::Parser;
use codec::Encode;
use data::*;
use display::DisplayEvent;
use keys::*;
use runtime_config::*;
use serde::Deserialize;
use display::DisplayEvent;
use subxt::{
blocks::ExtrinsicEvents,
config::DefaultExtrinsicParamsBuilder,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment