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

refac

parent 17795da1
Branches
Tags
1 merge request!5add features and refac data
......@@ -4,14 +4,14 @@ use crate::*;
use anyhow::{anyhow, Result};
use std::collections::{hash_map, HashMap};
pub struct IdentityCache<'a> {
client: &'a Client,
pub struct IdentityCache {
client: Client,
identities: HashMap<u32, String>,
indexer: Option<Indexer<'a>>,
indexer: Option<Indexer>,
}
impl<'a> IdentityCache<'a> {
pub fn new(client: &'a Client, indexer: Option<Indexer<'a>>) -> Self {
impl IdentityCache {
pub fn new(client: Client, indexer: Option<Indexer>) -> Self {
Self {
client,
identities: HashMap::new(),
......
......@@ -5,6 +5,7 @@ pub mod identity;
pub mod net_test;
pub mod oneshot;
pub mod revocation;
pub mod runtime;
pub mod smith;
pub mod sudo;
pub mod transfer;
use crate::*;
use anyhow::Result;
use sp_core::crypto::AccountId32;
pub async fn get_balance(data: Data) -> Result<()> {
let account_id = data.address();
......@@ -18,8 +17,8 @@ pub async fn get_balance(data: Data) -> Result<()> {
}
pub async fn get_account_info(
client: Client,
account_id: &AccountId32,
client: &Client,
account_id: &AccountId,
) -> Result<Option<AccountInfo>> {
Ok(client
.storage()
......
......@@ -21,7 +21,7 @@ pub async fn technical_committee_members(client: Client, args: &Args) -> Result<
} else {
Some(Indexer {
gql_client,
gql_url: &args.indexer,
gql_url: args.indexer.clone(),
})
};
......
......@@ -37,13 +37,13 @@ pub async fn monitor_expirations(
let end_session = current_session + sessions;
let mut identity_cache = cache::IdentityCache::new(
&client,
client.clone(),
if args.no_indexer {
None
} else {
Some(Indexer {
gql_client,
gql_url: &args.indexer,
gql_url: args.indexer.clone(),
})
},
);
......
use crate::indexer::*;
use crate::*;
use crate::commands::revocation::get_revoc_doc;
use crate::commands::revocation::generate_revoc_doc;
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;
......@@ -12,7 +12,7 @@ use std::str::FromStr;
use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner};
pub async fn get_identity(
client: Client,
client: &Client,
mut account_id: Option<AccountId32>,
mut identity_id: Option<u32>,
mut username: Option<String>,
......@@ -26,7 +26,7 @@ pub async fn get_identity(
gql_client: reqwest::Client::builder()
.user_agent("gcli/0.1.0")
.build()?,
gql_url: &args.indexer,
gql_url: args.indexer.clone(),
})
};
......@@ -82,7 +82,7 @@ pub async fn get_identity(
}
pub async fn get_idty_index_by_account_id(
client: Client,
client: &Client,
account_id: &AccountId32,
) -> Result<Option<u32>> {
Ok(client
......@@ -95,7 +95,7 @@ pub async fn get_idty_index_by_account_id(
}
pub async fn get_identity_by_index(
client: Client,
client: &Client,
idty_index: u32,
) -> Result<Option<IdtyValue<u32, AccountId32, IdtyData>>> {
Ok(client
......@@ -106,7 +106,7 @@ pub async fn get_identity_by_index(
pub async fn create_identity(
pair: Pair,
client: Client,
client: &Client,
target: AccountId32,
) -> Result<TxProgress, subxt::Error> {
client
......@@ -121,7 +121,7 @@ pub async fn create_identity(
pub async fn confirm_identity(
pair: Pair,
client: Client,
client: &Client,
name: String,
) -> Result<TxProgress, subxt::Error> {
client
......@@ -134,29 +134,23 @@ pub async fn confirm_identity(
.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?;
/// generate revokation document and submit it immediately
pub async fn revoke_identity(data: Data) -> Result<TxProgress, subxt::Error> {
let (_payload, signature) = generate_revoc_doc(&data);
// 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
data.client()
.tx()
.sign_and_submit_then_watch(
&runtime::tx()
.identity()
.revoke_identity(idty_index, account_id, multisign),
&PairSigner::new(pair),
.revoke_identity(data.idty_index(), data.address(), multisign),
&PairSigner::new(data.keypair()),
BaseExtrinsicParamsBuilder::new(),
)
.await?
.wait_for_in_block()
.await?
.wait_for_success()
.await?;
Ok(())
.await
}
use crate::*;
use anyhow::Result;
use futures::join;
use sp_core::sr25519::Signature;
use sp_core::{sr25519::Pair, Encode, Pair as _};
pub async fn generate_revoc_doc(api: &Client, pair: &Pair) -> Result<()> {
let signature = get_revoc_doc(api, pair).await?.1;
// TODO include prefix in RevocationPayload and use below
// use crate::runtime::runtime_types::pallet_identity::types::RevocationPayload;
type EncodedRevocationPayload = Vec<u8>;
pub fn print_revoc_sig(data: &Data) -> () {
let (_, signature) = generate_revoc_doc(data);
println!("revocation payload signature");
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 addr_idty_index = runtime::storage().identity().identity_index_of(&account_id);
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!(
api.storage().fetch(&addr_idty_index, None,),
api.storage().fetch(&addr_block_hash, None)
);
let idty_index = idty_index?.unwrap();
let genesis_hash = genesis_hash?.unwrap();
let payload = (b"revo", genesis_hash, idty_index).encode();
let signature = pair.sign(&payload);
pub fn generate_revoc_doc(data: &Data) -> (EncodedRevocationPayload, Signature) {
let payload = (b"revo", data.genesis_hash, data.idty_index()).encode();
let signature = data.keypair().sign(&payload);
Ok((idty_index, signature))
(payload, signature)
}
use crate::*;
pub async fn runtime_info(_data: Data) -> () {
// TODO get information from runtime
// certification duration for example
println!("TODO");
()
}
......@@ -80,6 +80,7 @@ pub async fn go_offline(pair: Pair, client: Client) -> Result<()> {
pub async fn online(client: Client, args: &Args) -> Result<()> {
let parent_hash = client
.clone()
.storage()
.fetch(&runtime::storage().system().parent_hash(), None)
.await?
......@@ -90,13 +91,13 @@ pub async fn online(client: Client, args: &Args) -> Result<()> {
.build()?;
let mut identity_cache = cache::IdentityCache::new(
&client,
client.clone(),
if args.no_indexer {
None
} else {
Some(Indexer {
gql_client,
gql_url: &args.indexer,
gql_url: args.indexer.clone(),
})
},
);
......@@ -169,7 +170,7 @@ pub async fn online(client: Client, args: &Args) -> Result<()> {
}
/// submit a certification and track progress
pub async fn cert(client: Client, pair: Pair, issuer: u32, receiver: u32) -> Result<()> {
pub async fn cert(client: &Client, pair: Pair, issuer: u32, receiver: u32) -> Result<()> {
let mut progress = client
.tx()
.sign_and_submit_then_watch(
......
......@@ -4,7 +4,7 @@ use anyhow::Result;
use sp_core::{crypto::AccountId32, sr25519::Pair};
use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner};
pub async fn set_key(pair: Pair, client: Client, new_key: AccountId32) -> Result<()> {
pub async fn set_key(pair: Pair, client: &Client, new_key: AccountId32) -> Result<()> {
client
.tx()
.sign_and_submit_then_watch(
......
use crate::*;
// data derived from command arguments
/// Data of current command
/// can also include fetched information
#[derive(Default)]
pub struct Data {
// command line arguments
pub args: Args,
// rpc to substrate client
pub client: Option<Client>,
// graphql to duniter-indexer
pub indexer: Option<Indexer>,
// user address
pub address: Option<AccountId>,
// user keypair
pub keypair: Option<Pair>,
// user identity index
pub idty_index: Option<u32>,
// token decimals
pub token_decimals: u32,
// token symbol
pub token_symbol: String,
// genesis hash
pub genesis_hash: Hash,
}
/// system properties defined in client specs
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct SystemProperties {
token_decimals: u32,
token_symbol: String,
}
// implement helper functions for Data
impl Data {
/// --- constructor ---
pub fn new(args: Args) -> Self {
Self {
args,
token_decimals: 0,
token_symbol: "tokens".into(),
..Default::default()
}
}
// --- getters ---
// the "unwrap" should not fail if data is well prepared
pub fn client(&self) -> &Client {
self.client.as_ref().expect("must build client first")
}
pub fn indexer(&self) -> &Indexer {
self.indexer.as_ref().expect("indexer is not set up")
}
pub fn address(&self) -> AccountId {
self.address.clone().expect("an address is needed")
}
pub fn keypair(&self) -> Pair {
self.keypair.clone().expect("a keypair is needed")
}
pub fn idty_index(&self) -> u32 {
self.idty_index.expect("must fetch idty index first")
}
// --- 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 ---
/// force an address if needed
pub fn build_address(mut self) -> Self {
self.address = Some(
get_keys(
self.args.secret_format,
&self.args.address,
&self.args.secret,
NeededKeys::Public,
)
.expect("needed")
.0
.expect("needed"),
);
self
}
/// force a keypair if needed
pub fn build_keypair(mut self) -> Self {
let (address, keypair) = get_keys(
self.args.secret_format,
&self.args.address,
&self.args.secret,
NeededKeys::Secret,
)
.expect("needed");
self.address = address;
self.keypair = keypair;
self
}
/// build a client from url
// TODO get client from a pre-defined list
pub async fn build_client(mut self) -> Self {
self.client = Some(Client::from_url(&self.args.url).await.expect("needed"));
self
}
/// build an indexer if not disabled
// TODO check that indexer matches client
pub fn build_indexer(mut self) -> Result<Self, anyhow::Error> {
self.indexer = if self.args.no_indexer {
None
} else {
Some(Indexer {
gql_client: reqwest::Client::builder()
.user_agent("gcli/0.1.0")
.build()?,
gql_url: self.args.indexer.clone(),
})
};
Ok(self)
}
/// get issuer index
/// needs address and client first
pub async fn fetch_idty_index(mut self) -> Result<Self, anyhow::Error> {
self.idty_index = Some(
commands::identity::get_idty_index_by_account_id(self.client(), &self.address())
.await?
.ok_or(anyhow::anyhow!("needs to be member to use this command"))?,
);
Ok(self)
}
/// get genesis hash
pub async fn fetch_genesis_hash(mut self) -> Result<Self, anyhow::Error> {
self.genesis_hash = self
.client()
.storage()
.fetch(&runtime::storage().system().block_hash(0), None)
.await?
.unwrap();
Ok(self)
}
/// get properties
pub async fn fetch_system_properties(mut self) -> Result<Self, anyhow::Error> {
let system_properties = self.client().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)
}
// TODO prevent awaits in async methods, prefer register requests and execute them all at once with a join
// example below
// example!(
// use futures::join;
// let addr_idty_index = runtime::storage().identity().identity_index_of(&account_id);
// let addr_block_hash = runtime::storage().system().block_hash(0);
// // Multiple fetches can be done in parallel.
// let (idty_index, genesis_hash) = join!(
// api.storage().fetch(&addr_idty_index, None),
// api.storage().fetch(&addr_block_hash, None)
// );
// );
}
......@@ -16,16 +16,17 @@ pub struct IdentityNameByPubkey;
)]
pub struct IdentityPubkeyByName;
pub struct Indexer<'a> {
#[derive(Clone)]
pub struct Indexer {
pub gql_client: reqwest::Client,
pub gql_url: &'a str,
pub gql_url: String,
}
impl<'a> Indexer<'a> {
impl Indexer {
pub async fn username_by_pubkey(&self, pubkey: &str) -> Result<Option<String>> {
Ok(post_graphql::<IdentityNameByPubkey, _>(
&self.gql_client,
self.gql_url,
&self.gql_url,
identity_name_by_pubkey::Variables {
pubkey: pubkey.to_string(),
},
......@@ -38,7 +39,7 @@ impl<'a> Indexer<'a> {
pub async fn pubkey_by_username(&self, username: &str) -> Result<Option<String>> {
Ok(post_graphql::<IdentityPubkeyByName, _>(
&self.gql_client,
self.gql_url,
self.gql_url.clone(),
identity_pubkey_by_name::Variables {
name: username.to_string(),
},
......
mod cache;
mod commands;
mod data;
mod indexer;
mod keys;
use clap::Parser;
use codec::Encode;
use data::*;
use indexer::*;
use keys::*;
use serde::Deserialize;
use sp_core::sr25519::Pair;
use sp_core::H256;
use sp_core::{sr25519::Pair, Pair as _, H256};
#[cfg(feature = "dev")]
#[subxt::subxt(
......@@ -21,6 +23,7 @@ pub mod runtime {
// use crate::gdev::runtime_types::sp_core::sr25519::Signature;
}
// declare custom types
pub type Client = subxt::OnlineClient<Runtime>;
pub type AccountId = subxt::ext::sp_runtime::AccountId32;
pub type TxInBlock = subxt::tx::TxInBlock<Runtime, Client>;
......@@ -28,12 +31,14 @@ 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 type Hash = sp_core::H256;
// declare runtime types
pub enum Runtime {}
impl subxt::config::Config for Runtime {
type Index = u32;
type BlockNumber = u32;
type Hash = sp_core::H256;
type Hash = Hash;
type Hashing = subxt::ext::sp_runtime::traits::BlakeTwo256;
type AccountId = AccountId;
type Address = subxt::ext::sp_runtime::MultiAddress<Self::AccountId, u32>;
......@@ -45,30 +50,30 @@ impl subxt::config::Config for Runtime {
type ExtrinsicParams = subxt::tx::BaseExtrinsicParams<Self, Tip>;
}
#[derive(Copy, Clone, Debug, Default, Encode)]
// Tip for transaction fee
#[derive(Copy, Clone, Debug, Default, codec::Encode)]
pub struct Tip {
#[codec(compact)]
tip: u64,
}
impl Tip {
pub fn new(amount: u64) -> Self {
Tip { tip: amount }
}
}
impl From<u64> for Tip {
fn from(n: u64) -> Self {
Self::new(n)
}
}
#[derive(Clone, Parser, Debug, Default)]
// define command line arguments
#[derive(Clone, clap::Parser, Debug, Default)]
#[clap(author, version, about, long_about = None)]
pub struct Args {
/// Subcommands
#[clap(subcommand)]
pub subcommand: Subcommand,
/// Indexer URL
#[clap(short, long, default_value = "http://localhost:8080/v1/graphql")]
indexer: String,
......@@ -90,120 +95,6 @@ pub struct Args {
url: String,
}
/// Data of current command
/// can also include fetched information
#[derive(Default)]
pub struct Data {
pub args: Args,
pub client: Option<Client>,
pub address: Option<AccountId>,
pub keypair: Option<Pair>,
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
impl Data {
/// --- constructor ---
pub fn new(args: Args) -> Self {
Self {
args,
token_decimals: 0,
token_symbol: "tokens".into(),
..Default::default()
}
}
// --- getters ---
// the "unwrap" should not fail if data is well prepared
pub fn client(&self) -> Client {
self.client.clone().unwrap()
}
pub fn address(&self) -> AccountId {
self.address.clone().unwrap()
}
pub fn keypair(&self) -> Pair {
self.keypair.clone().unwrap()
}
pub fn idty_index(&self) -> u32 {
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 ---
/// force an address if needed
pub fn build_address(mut self) -> Self {
self.address = Some(
get_keys(
self.args.secret_format,
&self.args.address,
&self.args.secret,
NeededKeys::Public,
)
.expect("needed")
.0
.expect("needed"),
);
self
}
/// force a keypair if needed
pub fn build_keypair(mut self) -> Self {
let (address, keypair) = get_keys(
self.args.secret_format,
&self.args.address,
&self.args.secret,
NeededKeys::Secret,
)
.expect("needed");
self.address = address;
self.keypair = keypair;
self
}
/// build a client from url
// TODO get client from a pre-defined list
pub async fn build_client(mut self) -> Self {
self.client = Some(Client::from_url(&self.args.url).await.expect("needed"));
self
}
/// get issuer index
/// needs address and client first
pub async fn fetch_idty_index(mut self) -> Result<Self, anyhow::Error> {
self.idty_index = Some(
commands::identity::get_idty_index_by_account_id(
self.client().clone(),
&self.address(),
)
.await?
.ok_or(anyhow::anyhow!("needs to be member to use this command"))?,
);
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
/// until it is in block with success or failure
pub async fn track_progress(progress: TxProgress) -> anyhow::Result<()> {
......@@ -246,11 +137,22 @@ pub enum Subcommand {
/// Fetch account balance
#[default]
GetBalance,
/// Show address corresponding to given arguments
ShowAddress,
/// Fetch identity
Identity {
#[clap(short = 'p', long = "pubkey")]
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.
CreateIdentity {
target: sp_core::crypto::AccountId32,
target: AccountId,
},
/// Confirm an identity
///
......@@ -258,24 +160,31 @@ pub enum Subcommand {
ConfirmIdentity {
name: String,
},
/// Generate a revocation document for the provided account
GenRevocDoc,
/// Revoke an identity immediately
RevokeIdentity,
CreateOneshot {
balance: u64,
dest: sp_core::crypto::AccountId32,
dest: AccountId,
},
ConsumeOneshot {
dest: sp_core::crypto::AccountId32,
dest: AccountId,
#[clap(long = "oneshot")]
dest_oneshot: bool,
},
ConsumeOneshotWithRemaining {
balance: u64,
dest: sp_core::crypto::AccountId32,
dest: AccountId,
#[clap(long = "one")]
dest_oneshot: bool,
remaining_to: sp_core::crypto::AccountId32,
remaining_to: AccountId,
#[clap(long = "rem-one")]
remaining_to_oneshot: bool,
},
OneshotBalance {
account: AccountId,
},
/// List upcoming expirations that require an action
Expire {
/// Show certs that expire within less than this number of blocks
......@@ -285,22 +194,8 @@ pub enum Subcommand {
#[clap(short, long, default_value_t = 100)]
sessions: u32,
},
/// Fetch identity
Identity {
#[clap(short = 'p', long = "pubkey")]
account_id: Option<sp_core::crypto::AccountId32>,
#[clap(short = 'i', long = "identity")]
identity_id: Option<u32>,
#[clap(short = 'u', long = "username")]
username: Option<String>,
},
/// Generate a revocation document for the provided account
GenRevocDoc,
GoOffline,
GoOnline,
OneshotBalance {
account: sp_core::crypto::AccountId32,
},
/// List online authorities
Online,
#[clap(hide = true)]
......@@ -316,7 +211,7 @@ pub enum Subcommand {
actual_repart: usize,
},
SudoSetKey {
new_key: sp_core::crypto::AccountId32,
new_key: AccountId,
},
/// Emit a smith certification
SmithCert {
......@@ -339,7 +234,7 @@ pub enum Subcommand {
/// Amount to transfer
amount: u64,
/// Destination address
dest: sp_core::crypto::AccountId32,
dest: AccountId,
/// Prevent from going below account existential deposit
#[clap(short = 'k', long = "keep-alive")]
keep_alive: bool,
......@@ -350,12 +245,15 @@ pub enum Subcommand {
/// Amount given to each destination address
amount: u64,
/// List of target addresses
dests: Vec<sp_core::crypto::AccountId32>,
dests: Vec<AccountId>,
},
/// Rotate and set session keys
UpdateKeys,
/// Revoke an identity
RevokeIdentity,
/// Get information about runtime
RuntimeInfo,
/// Indexer subcommands
#[clap(subcommand)]
Indexer(IndexerSubcommand),
}
#[tokio::main(flavor = "current_thread")]
......@@ -375,6 +273,10 @@ async fn main() -> Result<(), GcliError> {
.await?;
commands::account::get_balance(data).await?
}
Subcommand::ShowAddress => {
data = data.build_address();
println!("address is: {}", data.address());
}
Subcommand::CreateIdentity { target } => {
data = data.build_client().await.build_keypair();
let progress =
......@@ -387,6 +289,18 @@ async fn main() -> Result<(), GcliError> {
commands::identity::confirm_identity(data.keypair(), data.client(), name).await?;
track_progress(progress).await?
}
Subcommand::RevokeIdentity => {
data = data
.build_client()
.await
.build_keypair()
.fetch_idty_index()
.await?
.fetch_genesis_hash()
.await?;
let progress = commands::identity::revoke_identity(data).await?;
track_progress(progress).await?
}
Subcommand::CreateOneshot { balance, dest } => {
commands::oneshot::create_oneshot_account(
get_keys(
......@@ -458,8 +372,9 @@ async fn main() -> Result<(), GcliError> {
identity_id,
ref username,
} => {
data = data.build_client().await;
commands::identity::get_identity(
Client::from_url(&args.url).await.unwrap(),
data.client(),
account_id.clone(),
identity_id,
username.clone(),
......@@ -468,18 +383,15 @@ async fn main() -> Result<(), GcliError> {
.await?
}
Subcommand::GenRevocDoc => {
commands::revocation::generate_revoc_doc(
&Client::from_url(&args.url).await.unwrap(),
&get_keys(
args.secret_format,
&args.address,
&args.secret,
NeededKeys::Secret,
)?
.1
.unwrap(),
)
data = data
.build_client()
.await
.build_keypair()
.fetch_idty_index()
.await?
.fetch_genesis_hash()
.await?;
commands::revocation::print_revoc_sig(&data)
}
Subcommand::GoOffline => {
commands::smith::go_offline(
......@@ -554,19 +466,8 @@ async fn main() -> Result<(), GcliError> {
.await?
}
Subcommand::SudoSetKey { new_key } => {
commands::sudo::set_key(
get_keys(
args.secret_format,
&args.address,
&args.secret,
NeededKeys::Secret,
)?
.1
.unwrap(),
Client::from_url(&args.url).await.unwrap(),
new_key,
)
.await?
data = data.build_keypair().build_client().await;
commands::sudo::set_key(data.keypair(), data.client(), new_key).await?
}
Subcommand::SmithCert { to } => {
data = data
......@@ -662,21 +563,8 @@ async fn main() -> Result<(), GcliError> {
)
.await
.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?
}
Subcommand::RuntimeInfo => commands::runtime::runtime_info(data).await,
Subcommand::Indexer(subcommand) => indexer::handle_command(data, subcommand)?,
}
Ok(())
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment