From fecd24a35a721c75be71da6e10a0d7b80bfa5346 Mon Sep 17 00:00:00 2001 From: tuxmain <tuxmain@zettascript.org> Date: Thu, 1 Sep 2022 12:07:58 +0200 Subject: [PATCH] feat: optional secret --- README.md | 10 ++++----- src/main.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 8bf013f..640f0fd 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,14 @@ CLI client for [Duniter-V2S](https://git.duniter.org/nodes/rust/duniter-v2s/). ## Usage -Send 10 ÄžD from Alice to Ferdie: - - cargo run -- --url ws://localhost:9944 --secret //Alice transfer 1000 5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL - If using a different runtime, update the metadata for the client to compile: subxt metadata -f bytes > res/metadata.scale +Send 10 ÄžD from Alice to Ferdie: + + cargo run -- --url ws://localhost:9944 --secret //Alice transfer 1000 5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL + List certifications and session keys that will expire within one month: - cargo run -- --url wss://gdev.librelois.fr:443/ws --secret //Alice expire --blocks 432000 + cargo run -- --url wss://gdev.librelois.fr:443/ws expire --blocks 432000 diff --git a/src/main.rs b/src/main.rs index f7ca9b0..d5ca0e3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,10 +5,11 @@ use anyhow::{anyhow, Context, Result}; use clap::Parser; use codec::Encode; use sp_core::{ - crypto::{AccountId32, DeriveJunction, Pair as _}, + crypto::{AccountId32, DeriveJunction, Pair as _, Ss58Codec}, sr25519::Pair, }; use std::collections::BTreeMap; +use std::str::FromStr; use subxt::sp_runtime::MultiAddress; use subxt::{ extrinsic::{BaseExtrinsicParams, BaseExtrinsicParamsBuilder}, @@ -54,7 +55,10 @@ struct Args { /// Secret key or BIP39 mnemonic /// (eventually followed by derivation path) #[clap(short, long)] - secret: String, + secret: Option<String>, + /// Address + #[clap(short, long)] + address: Option<String>, /// Websocket RPC endpoint #[clap(short, long, default_value = "ws://localhost:9944")] url: String, @@ -118,8 +122,33 @@ async fn main() -> Result<()> { let args = Args::parse(); - let pair = Pair::from_string(&args.secret, None) - .map_err(|_| anyhow!("Invalid secret {}", args.secret))?; + let (account_id, pair) = match (&args.address, &args.secret) { + (Some(address), Some(secret)) => { + let pair = Pair::from_string(secret, None) + .map_err(|_| anyhow!("Invalid secret {}", secret))?; + let address = sp_core::crypto::AccountId32::from_string(address) + .map_err(|_| anyhow!("Invalid address {}", address))?; + assert_eq!( + address, + pair.public().into(), + "Secret and address do not match." + ); + (Some(pair.public().into()), Some(pair)) + } + (None, Some(secret)) => { + let pair = Pair::from_string(secret, None) + .map_err(|_| anyhow!("Invalid secret {}", secret))?; + (Some(pair.public().into()), Some(pair)) + } + (Some(address), None) => ( + Some( + sp_core::crypto::AccountId32::from_str(address) + .map_err(|_| anyhow!("Invalid address {}", address))?, + ), + None, + ), + (None, None) => (None, None), + }; let client: Client = ClientBuilder::new() .set_url(&args.url) @@ -132,12 +161,15 @@ async fn main() -> Result<()> { .user_agent("gcli/0.1.0") .build()?; - let account_id: sp_core::crypto::AccountId32 = pair.public().into(); - let account = api.storage().system().account(&account_id, None).await?; - logs::info!("Account free balance: {}", account.data.free); + if let Some(account_id) = &account_id { + let account = api.storage().system().account(account_id, None).await?; + logs::info!("Account free balance: {}", account.data.free); + } match args.subcommand { Subcommand::CreateOneshot { balance, dest } => { + let pair = pair.expect("This subcommand needs a secret."); + api.tx() .oneshot_account() .create_oneshot_account(dest.into(), balance)? @@ -148,6 +180,8 @@ async fn main() -> Result<()> { .await?; } Subcommand::ConsumeOneshot { dest, dest_oneshot } => { + let pair = pair.expect("This subcommand needs a secret."); + let number = api.storage().system().number(None).await?; api.tx() .oneshot_account() @@ -176,6 +210,8 @@ async fn main() -> Result<()> { remaining_to, remaining_to_oneshot, } => { + let pair = pair.expect("This subcommand needs a secret."); + let number = api.storage().system().number(None).await?; api.tx() .oneshot_account() @@ -354,7 +390,9 @@ async fn main() -> Result<()> { } } } - Subcommand::GenRevocDoc => gen_revoc_doc(&api, &pair).await?, + Subcommand::GenRevocDoc => { + gen_revoc_doc(&api, &pair.expect("This subcommand needs a secret.")).await? + } Subcommand::OneshotBalance { account } => { logs::info!( "{}", @@ -369,6 +407,8 @@ async fn main() -> Result<()> { target, actual_repart, } => { + let pair = pair.expect("This subcommand needs a secret."); + let mut pairs = Vec::new(); for i in actual_repart.unwrap_or_default()..target { let pair_i = pair @@ -398,6 +438,8 @@ async fn main() -> Result<()> { } } Subcommand::SpamRoll { actual_repart } => { + let pair = pair.expect("This subcommand needs a secret."); + let mut pairs = Vec::<(PairSigner<DefaultConfig, Pair>, AccountId32)>::with_capacity(actual_repart); for i in 0..actual_repart { @@ -448,6 +490,8 @@ async fn main() -> Result<()> { dest, keep_alive, } => { + let pair = pair.expect("This subcommand needs a secret."); + if keep_alive { api.tx() .balances() -- GitLab