Newer
Older
use crate::runtime::runtime_types::common_runtime::entities::IdtyData;
use crate::runtime::runtime_types::pallet_identity::types::*;
use crate::runtime::runtime_types::sp_core::sr25519::Signature;
use crate::runtime::runtime_types::sp_runtime::MultiSignature;
/// define identity subcommands
#[derive(Clone, Default, Debug, clap::Parser)]
pub enum Subcommand {
/// show identity
#[default]
Show,
/// Fetch identity
Get {
#[clap(short = 'a', long = "address")]
account_id: Option<AccountId>,
#[clap(short = 'i', long = "identity")]
identity_id: Option<u32>,
#[clap(short = 'u', long = "username")]
username: Option<String>,
},
/// Create and certify an identity
///
/// Caller must be member, and the target account must exist.
Create { target: AccountId },
/// Confirm an identity
///
/// To be called by the certified not-yet-member account, to become member.
Confirm { name: String },
/// Revoke an identity immediately
Revoke,
/// Generate a revocation document for the provided account
GenRevocDoc,
}
/// handle identity commands
pub async fn handle_command(data: Data, command: Subcommand) -> anyhow::Result<()> {
match command {
Subcommand::Show => {}
Subcommand::Get {
ref account_id,
identity_id,
ref username,
} => {
commands::identity::get_identity(
&data,
account_id.clone(),
identity_id,
username.clone(),
)
.await?
}
Subcommand::Create { target } => {
commands::identity::create_identity(data.keypair(), data.client(), target).await?;
}
Subcommand::Confirm { name } => {
commands::identity::confirm_identity(data.keypair(), data.client(), name).await?;
}
Subcommand::Revoke => {
data = data.fetch_idty_index().await?;
commands::identity::revoke_identity(data).await?;
}
data = data.fetch_idty_index().await?;
commands::revocation::print_revoc_sig(&data)
}
};
Ok(())
}
// ======================
/// get identity
mut identity_id: Option<u32>,
mut username: Option<String>,
let client = data.client();
let indexer = data.indexer.clone();
// 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 = 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);
} else {
return Err(anyhow!("no identity found for this username"));
}
}
_ => {
return Err(anyhow!(
"One and only one argument is needed to fetch the identity."
));
}
};
println!(
"Account id: {}",
account_id
.as_ref()
.map_or(String::new(), AccountId::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("<no indexer>".to_string())
);
/// get identity index by account id
) -> Result<Option<u32>, anyhow::Error> {
) -> Result<Option<IdtyValue<u32, AccountId, IdtyData>>, anyhow::Error> {
.fetch(&runtime::storage().identity().identities(idty_index), None)
) -> Result<(), subxt::Error> {
let progress = client
.tx()
.sign_and_submit_then_watch(
&PairSigner::new(pair),
BaseExtrinsicParamsBuilder::new(),
)
.await?;
let events = track_progress(progress).await?;
if let Some(e) = events.find_first::<runtime::identity::events::IdtyCreated>()? {
println!("{e:?}");
}
Ok(())
) -> Result<(), subxt::Error> {
let progress = client
.tx()
.sign_and_submit_then_watch(
&PairSigner::new(pair),
BaseExtrinsicParamsBuilder::new(),
)
.await?;
let events = track_progress(progress).await?;
if let Some(e) = events.find_first::<runtime::identity::events::IdtyConfirmed>()? {
println!("{e:?}");
}
Ok(())
pub async fn revoke_identity(data: Data) -> Result<(), subxt::Error> {
// Transform signature to MultiSignature
// TODO: this is a hack, we should be able to use the signature directly
let signature = Signature(signature.0);
let multisign = MultiSignature::Sr25519(signature);
.tx()
.sign_and_submit_then_watch(
&runtime::tx()
.identity()
.revoke_identity(data.idty_index(), data.address(), multisign),
&PairSigner::new(data.keypair()),
.await?;
let events = track_progress(progress).await?;
if let Some(e) = events.find_first::<runtime::identity::events::IdtyRemoved>()? {
println!("{e:?}");
}
Ok(())