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/). ...@@ -4,14 +4,14 @@ CLI client for [Duniter-V2S](https://git.duniter.org/nodes/rust/duniter-v2s/).
## Usage ## 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: If using a different runtime, update the metadata for the client to compile:
subxt metadata -f bytes > res/metadata.scale 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: 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}; ...@@ -5,10 +5,11 @@ use anyhow::{anyhow, Context, Result};
use clap::Parser; use clap::Parser;
use codec::Encode; use codec::Encode;
use sp_core::{ use sp_core::{
crypto::{AccountId32, DeriveJunction, Pair as _}, crypto::{AccountId32, DeriveJunction, Pair as _, Ss58Codec},
sr25519::Pair, sr25519::Pair,
}; };
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::str::FromStr;
use subxt::sp_runtime::MultiAddress; use subxt::sp_runtime::MultiAddress;
use subxt::{ use subxt::{
extrinsic::{BaseExtrinsicParams, BaseExtrinsicParamsBuilder}, extrinsic::{BaseExtrinsicParams, BaseExtrinsicParamsBuilder},
...@@ -54,7 +55,10 @@ struct Args { ...@@ -54,7 +55,10 @@ struct Args {
/// Secret key or BIP39 mnemonic /// Secret key or BIP39 mnemonic
/// (eventually followed by derivation path) /// (eventually followed by derivation path)
#[clap(short, long)] #[clap(short, long)]
secret: String, secret: Option<String>,
/// Address
#[clap(short, long)]
address: Option<String>,
/// Websocket RPC endpoint /// Websocket RPC endpoint
#[clap(short, long, default_value = "ws://localhost:9944")] #[clap(short, long, default_value = "ws://localhost:9944")]
url: String, url: String,
...@@ -118,8 +122,33 @@ async fn main() -> Result<()> { ...@@ -118,8 +122,33 @@ async fn main() -> Result<()> {
let args = Args::parse(); let args = Args::parse();
let pair = Pair::from_string(&args.secret, None) let (account_id, pair) = match (&args.address, &args.secret) {
.map_err(|_| anyhow!("Invalid secret {}", 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() let client: Client = ClientBuilder::new()
.set_url(&args.url) .set_url(&args.url)
...@@ -132,12 +161,15 @@ async fn main() -> Result<()> { ...@@ -132,12 +161,15 @@ async fn main() -> Result<()> {
.user_agent("gcli/0.1.0") .user_agent("gcli/0.1.0")
.build()?; .build()?;
let account_id: sp_core::crypto::AccountId32 = pair.public().into(); if let Some(account_id) = &account_id {
let account = api.storage().system().account(&account_id, None).await?; let account = api.storage().system().account(account_id, None).await?;
logs::info!("Account free balance: {}", account.data.free); logs::info!("Account free balance: {}", account.data.free);
}
match args.subcommand { match args.subcommand {
Subcommand::CreateOneshot { balance, dest } => { Subcommand::CreateOneshot { balance, dest } => {
let pair = pair.expect("This subcommand needs a secret.");
api.tx() api.tx()
.oneshot_account() .oneshot_account()
.create_oneshot_account(dest.into(), balance)? .create_oneshot_account(dest.into(), balance)?
...@@ -148,6 +180,8 @@ async fn main() -> Result<()> { ...@@ -148,6 +180,8 @@ async fn main() -> Result<()> {
.await?; .await?;
} }
Subcommand::ConsumeOneshot { dest, dest_oneshot } => { Subcommand::ConsumeOneshot { dest, dest_oneshot } => {
let pair = pair.expect("This subcommand needs a secret.");
let number = api.storage().system().number(None).await?; let number = api.storage().system().number(None).await?;
api.tx() api.tx()
.oneshot_account() .oneshot_account()
...@@ -176,6 +210,8 @@ async fn main() -> Result<()> { ...@@ -176,6 +210,8 @@ async fn main() -> Result<()> {
remaining_to, remaining_to,
remaining_to_oneshot, remaining_to_oneshot,
} => { } => {
let pair = pair.expect("This subcommand needs a secret.");
let number = api.storage().system().number(None).await?; let number = api.storage().system().number(None).await?;
api.tx() api.tx()
.oneshot_account() .oneshot_account()
...@@ -354,7 +390,9 @@ async fn main() -> Result<()> { ...@@ -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 } => { Subcommand::OneshotBalance { account } => {
logs::info!( logs::info!(
"{}", "{}",
...@@ -369,6 +407,8 @@ async fn main() -> Result<()> { ...@@ -369,6 +407,8 @@ async fn main() -> Result<()> {
target, target,
actual_repart, actual_repart,
} => { } => {
let pair = pair.expect("This subcommand needs a secret.");
let mut pairs = Vec::new(); let mut pairs = Vec::new();
for i in actual_repart.unwrap_or_default()..target { for i in actual_repart.unwrap_or_default()..target {
let pair_i = pair let pair_i = pair
...@@ -398,6 +438,8 @@ async fn main() -> Result<()> { ...@@ -398,6 +438,8 @@ async fn main() -> Result<()> {
} }
} }
Subcommand::SpamRoll { actual_repart } => { Subcommand::SpamRoll { actual_repart } => {
let pair = pair.expect("This subcommand needs a secret.");
let mut pairs = let mut pairs =
Vec::<(PairSigner<DefaultConfig, Pair>, AccountId32)>::with_capacity(actual_repart); Vec::<(PairSigner<DefaultConfig, Pair>, AccountId32)>::with_capacity(actual_repart);
for i in 0..actual_repart { for i in 0..actual_repart {
...@@ -448,6 +490,8 @@ async fn main() -> Result<()> { ...@@ -448,6 +490,8 @@ async fn main() -> Result<()> {
dest, dest,
keep_alive, keep_alive,
} => { } => {
let pair = pair.expect("This subcommand needs a secret.");
if keep_alive { if keep_alive {
api.tx() api.tx()
.balances() .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