Skip to content
Snippets Groups Projects
identity.rs 3.24 KiB
Newer Older
use crate::{gdev, indexer::*, Args, Client};

use crate::gdev::runtime_types::common_runtime::entities::IdtyData;
use crate::gdev::runtime_types::pallet_identity::types::*;
use anyhow::{anyhow, Result};
use sp_core::{crypto::AccountId32, sr25519::Pair};
use std::str::FromStr;
use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner};

pub async fn get_identity(
	client: Client,
	mut account_id: Option<AccountId32>,
	mut identity_id: Option<u32>,
	mut username: Option<String>,
	args: &Args,
) -> Result<()> {
	// build indexer if not disabled
	let indexer = if args.no_indexer {
		None
	} else {
		Some(Indexer {
			gql_client: reqwest::Client::builder()
				.user_agent("gcli/0.1.0")
				.build()?,
			gql_url: &args.indexer,
		})
	};
	// fetch missing information
	match (&account_id, identity_id, &username) {
		(None, Some(identity_id), None) => {
			account_id = get_identity_by_index(client, identity_id)
				.await?
				.map(|idty| idty.owner_key);
		(Some(account_id), None, None) => {
			identity_id = get_idty_index_by_account_id(client, account_id).await?;
		}
		(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 = AccountId32::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);
			} else {
				return Err(anyhow!("no identity found for this username"));
			}
		}
		_ => {
			return Err(anyhow!(
				"One and only one argument is needed to fetch the identity."
			));
		}
	};
	// print result
	println!(
		"Account id:  {}",
		account_id
			.as_ref()
			.map_or(String::new(), AccountId32::to_string)
	);
	println!(
		"Identity id: {}",
		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?;
	}
	println!("Username:    {}", username.unwrap_or_default());
	Ok(())
pub async fn get_idty_index_by_account_id(
	client: Client,
	account_id: &AccountId32,
) -> Result<Option<u32>> {
	Ok(client
		.storage()
		.fetch(
			&gdev::storage().identity().identity_index_of(account_id),
			None,
		)
		.await?)
}

pub async fn get_identity_by_index(
	client: Client,
	idty_index: u32,
) -> Result<Option<IdtyValue<u32, AccountId32, IdtyData>>> {
	Ok(client
		.storage()
		.fetch(&gdev::storage().identity().identities(idty_index), None)
		.await?)
}

pub async fn create_identity(pair: Pair, client: Client, target: AccountId32) -> Result<()> {
	client
		.tx()
		.sign_and_submit_then_watch(
			&gdev::tx().identity().create_identity(target),
			&PairSigner::new(pair),
			BaseExtrinsicParamsBuilder::new(),
		)
		.await?;

	Ok(())
}

pub async fn confirm_identity(pair: Pair, client: Client, name: String) -> Result<()> {
	client
		.tx()
		.sign_and_submit_then_watch(
			&gdev::tx().identity().confirm_identity(name),
			&PairSigner::new(pair),
			BaseExtrinsicParamsBuilder::new(),
		)
		.await?;

	Ok(())
}