Skip to content
Snippets Groups Projects
Commit 17795da1 authored by Flojito Stillnet's avatar Flojito Stillnet :blush: Committed by Hugo Trentesaux
Browse files

GetBalance + RevokeIdentity

- Add GetBalance + Revoke Identity
- Refactor revocation

refac get balance

get token decimals and symbol

fmt + clippy
parent 84043f18
No related branches found
No related tags found
1 merge request!5add features and refac data
pub mod account;
pub mod collective; pub mod collective;
pub mod expire; pub mod expire;
pub mod identity; pub mod identity;
......
use crate::*;
use anyhow::Result;
use sp_core::crypto::AccountId32;
pub async fn get_balance(data: Data) -> Result<()> {
let account_id = data.address();
let account_info = get_account_info(data.client(), &account_id).await?;
if let Some(account_info) = account_info {
println!(
"{account_id} has {}",
data.format_balance(account_info.data.free)
);
} else {
println!("account {account_id} does not exist")
}
Ok(())
}
pub async fn get_account_info(
client: Client,
account_id: &AccountId32,
) -> Result<Option<AccountInfo>> {
Ok(client
.storage()
.fetch(&runtime::storage().system().account(account_id), None)
.await?)
}
use crate::indexer::*; use crate::indexer::*;
use crate::*; use crate::*;
use crate::commands::revocation::get_revoc_doc;
use crate::runtime::runtime_types::common_runtime::entities::IdtyData; use crate::runtime::runtime_types::common_runtime::entities::IdtyData;
use crate::runtime::runtime_types::pallet_identity::types::*; 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;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use sp_core::{crypto::AccountId32, sr25519::Pair}; use sp_core::{crypto::AccountId32, sr25519::Pair};
use std::str::FromStr; use std::str::FromStr;
...@@ -106,14 +109,14 @@ pub async fn create_identity( ...@@ -106,14 +109,14 @@ pub async fn create_identity(
client: Client, client: Client,
target: AccountId32, target: AccountId32,
) -> Result<TxProgress, subxt::Error> { ) -> Result<TxProgress, subxt::Error> {
Ok(client client
.tx() .tx()
.sign_and_submit_then_watch( .sign_and_submit_then_watch(
&runtime::tx().identity().create_identity(target), &runtime::tx().identity().create_identity(target),
&PairSigner::new(pair), &PairSigner::new(pair),
BaseExtrinsicParamsBuilder::new(), BaseExtrinsicParamsBuilder::new(),
) )
.await?) .await
} }
pub async fn confirm_identity( pub async fn confirm_identity(
...@@ -121,12 +124,39 @@ pub async fn confirm_identity( ...@@ -121,12 +124,39 @@ pub async fn confirm_identity(
client: Client, client: Client,
name: String, name: String,
) -> Result<TxProgress, subxt::Error> { ) -> Result<TxProgress, subxt::Error> {
Ok(client client
.tx() .tx()
.sign_and_submit_then_watch( .sign_and_submit_then_watch(
&runtime::tx().identity().confirm_identity(name), &runtime::tx().identity().confirm_identity(name),
&PairSigner::new(pair), &PairSigner::new(pair),
BaseExtrinsicParamsBuilder::new(), BaseExtrinsicParamsBuilder::new(),
) )
.await?) .await
}
// TODO : use Result<TxProgress, subxt::Error> instead of Result<()>
pub async fn revoke_identity(pair: Pair, client: Client, account_id: AccountId32) -> Result<()> {
let (idty_index, signature) = get_revoc_doc(&client, &pair).await?;
// 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);
client
.tx()
.sign_and_submit_then_watch(
&runtime::tx()
.identity()
.revoke_identity(idty_index, account_id, multisign),
&PairSigner::new(pair),
BaseExtrinsicParamsBuilder::new(),
)
.await?
.wait_for_in_block()
.await?
.wait_for_success()
.await?;
Ok(())
} }
...@@ -2,12 +2,22 @@ use crate::*; ...@@ -2,12 +2,22 @@ use crate::*;
use anyhow::Result; use anyhow::Result;
use futures::join; use futures::join;
use sp_core::sr25519::Signature;
use sp_core::{sr25519::Pair, Encode, Pair as _}; use sp_core::{sr25519::Pair, Encode, Pair as _};
pub async fn gen_revoc_doc(api: &Client, pair: &Pair) -> Result<()> { pub async fn generate_revoc_doc(api: &Client, pair: &Pair) -> Result<()> {
let signature = get_revoc_doc(api, pair).await?.1;
println!("0x{}", hex::encode(signature));
Ok(())
}
pub async fn get_revoc_doc(api: &Client, pair: &Pair) -> Result<(u32, Signature)> {
let account_id: sp_core::crypto::AccountId32 = pair.public().into(); let account_id: sp_core::crypto::AccountId32 = pair.public().into();
let addr_idty_index = runtime::storage().identity().identity_index_of(&account_id); let addr_idty_index = runtime::storage().identity().identity_index_of(&account_id);
let addr_block_hash = runtime::storage().system().block_hash(0); let addr_block_hash = runtime::storage().system().block_hash(0);
// Multiple fetches can be done in a single request.
let (idty_index, genesis_hash) = join!( let (idty_index, genesis_hash) = join!(
api.storage().fetch(&addr_idty_index, None,), api.storage().fetch(&addr_idty_index, None,),
api.storage().fetch(&addr_block_hash, None) api.storage().fetch(&addr_block_hash, None)
...@@ -17,7 +27,5 @@ pub async fn gen_revoc_doc(api: &Client, pair: &Pair) -> Result<()> { ...@@ -17,7 +27,5 @@ pub async fn gen_revoc_doc(api: &Client, pair: &Pair) -> Result<()> {
let payload = (b"revo", genesis_hash, idty_index).encode(); let payload = (b"revo", genesis_hash, idty_index).encode();
let signature = pair.sign(&payload); let signature = pair.sign(&payload);
println!("0x{}", hex::encode(signature)); Ok((idty_index, signature))
Ok(())
} }
...@@ -6,17 +6,28 @@ mod keys; ...@@ -6,17 +6,28 @@ mod keys;
use clap::Parser; use clap::Parser;
use codec::Encode; use codec::Encode;
use keys::*; use keys::*;
use serde::Deserialize;
use sp_core::sr25519::Pair; use sp_core::sr25519::Pair;
use sp_core::H256; use sp_core::H256;
#[cfg(feature = "dev")] #[cfg(feature = "dev")]
#[subxt::subxt(runtime_metadata_path = "res/metadata.scale")] #[subxt::subxt(
pub mod runtime {} runtime_metadata_path = "res/metadata.scale",
derive_for_all_types = "Debug"
)]
pub mod runtime {
// IF NEEDED
// #[subxt(substitute_type = "spcore::sr25519::Signature")]
// use crate::gdev::runtime_types::sp_core::sr25519::Signature;
}
pub type Client = subxt::OnlineClient<Runtime>; pub type Client = subxt::OnlineClient<Runtime>;
pub type AccountId = subxt::ext::sp_runtime::AccountId32; pub type AccountId = subxt::ext::sp_runtime::AccountId32;
pub type TxInBlock = subxt::tx::TxInBlock<Runtime, Client>; pub type TxInBlock = subxt::tx::TxInBlock<Runtime, Client>;
pub type TxProgress = subxt::tx::TxProgress<Runtime, Client>; pub type TxProgress = subxt::tx::TxProgress<Runtime, Client>;
pub type Balance = u64;
pub type AccountData = runtime::runtime_types::pallet_duniter_account::types::AccountData<Balance>;
pub type AccountInfo = runtime::runtime_types::frame_system::AccountInfo<u32, AccountData>;
pub enum Runtime {} pub enum Runtime {}
impl subxt::config::Config for Runtime { impl subxt::config::Config for Runtime {
...@@ -88,14 +99,25 @@ pub struct Data { ...@@ -88,14 +99,25 @@ pub struct Data {
pub address: Option<AccountId>, pub address: Option<AccountId>,
pub keypair: Option<Pair>, pub keypair: Option<Pair>,
pub idty_index: Option<u32>, pub idty_index: Option<u32>,
pub token_decimals: u32,
pub token_symbol: String,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct SystemProperties {
token_decimals: u32,
token_symbol: String,
} }
// implement helper functions for Data // implement helper functions for Data
impl Data { impl Data {
/// constructor /// --- constructor ---
pub fn new(args: Args) -> Self { pub fn new(args: Args) -> Self {
Self { Self {
args, args,
token_decimals: 0,
token_symbol: "tokens".into(),
..Default::default() ..Default::default()
} }
} }
...@@ -111,7 +133,16 @@ impl Data { ...@@ -111,7 +133,16 @@ impl Data {
self.keypair.clone().unwrap() self.keypair.clone().unwrap()
} }
pub fn idty_index(&self) -> u32 { pub fn idty_index(&self) -> u32 {
self.idty_index.clone().unwrap() self.idty_index.unwrap()
}
// --- methods ---
pub fn format_balance(&self, amount: Balance) -> String {
let base: u32 = 10;
format!(
"{} {}",
(amount as f32) / (base.pow(self.token_decimals) as f32),
self.token_symbol
)
} }
// --- mutators --- // --- mutators ---
/// force an address if needed /// force an address if needed
...@@ -161,6 +192,16 @@ impl Data { ...@@ -161,6 +192,16 @@ impl Data {
); );
Ok(self) Ok(self)
} }
/// get properties
pub async fn fetch_system_properties(mut self) -> Result<Self, anyhow::Error> {
let system_properties = self.client().clone().rpc().system_properties().await?;
let system_properties = serde_json::from_value::<SystemProperties>(
serde_json::Value::Object(system_properties),
)?;
self.token_decimals = system_properties.token_decimals;
self.token_symbol = system_properties.token_symbol;
Ok(self)
}
} }
/// track progress of transaction on the network /// track progress of transaction on the network
...@@ -202,7 +243,7 @@ impl From<anyhow::Error> for GcliError { ...@@ -202,7 +243,7 @@ impl From<anyhow::Error> for GcliError {
#[derive(Clone, Debug, clap::Subcommand, Default)] #[derive(Clone, Debug, clap::Subcommand, Default)]
pub enum Subcommand { pub enum Subcommand {
// TODO flodef /// Fetch account balance
#[default] #[default]
GetBalance, GetBalance,
/// Create and certify an identity /// Create and certify an identity
...@@ -313,6 +354,8 @@ pub enum Subcommand { ...@@ -313,6 +354,8 @@ pub enum Subcommand {
}, },
/// Rotate and set session keys /// Rotate and set session keys
UpdateKeys, UpdateKeys,
/// Revoke an identity
RevokeIdentity,
} }
#[tokio::main(flavor = "current_thread")] #[tokio::main(flavor = "current_thread")]
...@@ -323,7 +366,15 @@ async fn main() -> Result<(), GcliError> { ...@@ -323,7 +366,15 @@ async fn main() -> Result<(), GcliError> {
let mut data = Data::new(args.clone()); let mut data = Data::new(args.clone());
match args.subcommand { match args.subcommand {
Subcommand::GetBalance => {} Subcommand::GetBalance => {
data = data
.build_keypair()
.build_client()
.await
.fetch_system_properties()
.await?;
commands::account::get_balance(data).await?
}
Subcommand::CreateIdentity { target } => { Subcommand::CreateIdentity { target } => {
data = data.build_client().await.build_keypair(); data = data.build_client().await.build_keypair();
let progress = let progress =
...@@ -417,7 +468,7 @@ async fn main() -> Result<(), GcliError> { ...@@ -417,7 +468,7 @@ async fn main() -> Result<(), GcliError> {
.await? .await?
} }
Subcommand::GenRevocDoc => { Subcommand::GenRevocDoc => {
commands::revocation::gen_revoc_doc( commands::revocation::generate_revoc_doc(
&Client::from_url(&args.url).await.unwrap(), &Client::from_url(&args.url).await.unwrap(),
&get_keys( &get_keys(
args.secret_format, args.secret_format,
...@@ -611,6 +662,21 @@ async fn main() -> Result<(), GcliError> { ...@@ -611,6 +662,21 @@ async fn main() -> Result<(), GcliError> {
) )
.await .await
.unwrap(), .unwrap(),
Subcommand::RevokeIdentity => {
let (address, pair) = get_keys(
args.secret_format,
&args.address,
&args.secret,
NeededKeys::Secret,
)?;
commands::identity::revoke_identity(
pair.unwrap(),
Client::from_url(&args.url).await.unwrap(),
address.unwrap(),
)
.await?
}
} }
Ok(()) Ok(())
......
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