Skip to content
Snippets Groups Projects
Commit fecd24a3 authored by Pascal Engélibert's avatar Pascal Engélibert :bicyclist:
Browse files

feat: optional secret

parent 0385a423
No related branches found
No related tags found
No related merge requests found
......@@ -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
......@@ -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()
......
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