Skip to content
Snippets Groups Projects
Commit 8c81a206 authored by Éloïs's avatar Éloïs
Browse files

Initial commit

parents
Branches
No related tags found
No related merge requests found
/target
This diff is collapsed.
[package]
authors = ['librelois <c@elo.tf>']
edition = "2021"
license = 'AGPL-3.0'
name = "gcli"
repository = 'https://git.duniter.org/clients/rust/gcli-v2s'
version = "0.1.0"
[dependencies]
anyhow = "1.0"
clap = { version = "3.0", features = ["derive"] }
env_logger = "0.9.0"
hex = "0.4.3"
logs = "0.5"
codec = { package = "parity-scale-codec", version = "2.3.1" }
serde_json = "1.0.64"
sp-core = { git = "https://github.com/librelois/substrate.git", branch = "duniter-monthly-2022-02" }
subxt = { git = 'https://github.com/librelois/subxt.git', branch = 'duniter-monthly-2022-02' }
tokio = { version = "1.15.0", features = ["macros"] }
This diff is collapsed.
gcli
File added
use anyhow::{anyhow, Context, Result};
use clap::Parser;
use codec::Encode;
use sp_core::{
crypto::{AccountId32, DeriveJunction, Pair as _},
sr25519::Pair,
};
use subxt::sp_runtime::MultiAddress;
use subxt::{ClientBuilder, DefaultConfig, DefaultExtra, PairSigner};
#[subxt::subxt(runtime_metadata_path = "res/metadata.scale")]
pub mod gdev_100 {}
pub type Api = gdev_100::RuntimeApi<DefaultConfig, DefaultExtra<DefaultConfig>>;
type Client = subxt::Client<DefaultConfig>;
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct Args {
#[clap(subcommand)]
pub subcommand: Subcommand,
/// Secret key or BIP39 mnemonic
/// (eventually followed by derivation path)
#[clap(short, long)]
secret: String,
/// Websocket RPC endpoint
#[clap(short, long, default_value = "ws://localhost:9945")]
url: String,
}
#[derive(Debug, clap::Subcommand)]
pub enum Subcommand {
/// Generate a revocation document for the provided account
GenRevocDoc,
#[clap(hide = true)]
Repart {
// Number of transactions per block to target
target: u32,
#[clap(short = 'o', long = "old-repart")]
// Old/actual repartition
actual_repart: Option<u32>,
},
#[clap(hide = true)]
SpamRoll { actual_repart: usize },
}
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<()> {
env_logger::init();
let args = Args::parse();
let pair = Pair::from_string(&args.secret, None)
.map_err(|_| anyhow!("Invalid secret {}", args.secret))?;
//let mut signer = PairSigner::new(pair.clone());
let client: Client = ClientBuilder::new()
.set_url(&args.url)
.build()
.await
.with_context(|| "fail to connect to node")?;
let api = client.clone().to_runtime_api::<Api>();
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);
match args.subcommand {
Subcommand::GenRevocDoc => gen_revoc_doc(&api, &pair).await?,
Subcommand::Repart {
target,
actual_repart,
} => {
let mut pairs = Vec::new();
for i in actual_repart.unwrap_or_default()..target {
let pair_i = pair
.derive(std::iter::once(DeriveJunction::hard::<u32>(i)), None)
.map_err(|_| anyhow!("Fail to derive //{}", i))?
.0;
pairs.push((i, pair_i));
}
for (i, pair_i) in &pairs {
/*let _ = api
.tx()
.balances()
.transfer(MultiAddress::Id(pair_i.public().into()), 501)
.sign_and_submit_then_watch(&signer)
.await?
.wait_for_in_block()
.await?;
signer.increment_nonce();*/
let pair_i_account = api
.storage()
.system()
.account(pair_i.public().into(), None)
.await?;
logs::info!("account //{} balance: {}", i, pair_i_account.data.free);
}
}
Subcommand::SpamRoll { actual_repart } => {
let mut pairs = Vec::<(
PairSigner<DefaultConfig, DefaultExtra<DefaultConfig>, Pair>,
AccountId32,
)>::with_capacity(actual_repart);
for i in 0..actual_repart {
let pair_i = pair
.derive(std::iter::once(DeriveJunction::hard::<u32>(i as u32)), None)
.map_err(|_| anyhow!("Fail to derive //{}", i))?
.0;
let account_id_i = pair_i.public().into();
pairs.push((PairSigner::new(pair_i), account_id_i));
}
loop {
let mut watchers = Vec::with_capacity(actual_repart);
for i in 0..(actual_repart - 1) {
let dest: AccountId32 = pairs[i + 1].1.clone();
let watcher = api
.tx()
.balances()
.transfer(MultiAddress::Id(dest), 1)
.sign_and_submit_then_watch(&pairs[i].0)
.await?;
pairs[i].0.increment_nonce();
logs::info!("send 1 cent from //{} to //{}", i, i + 1);
watchers.push(watcher);
}
let dest: AccountId32 = pairs[0].1.clone();
let watcher = api
.tx()
.balances()
.transfer(MultiAddress::Id(dest), 1)
.sign_and_submit_then_watch(&pairs[actual_repart - 1].0)
.await?;
pairs[actual_repart - 1].0.increment_nonce();
logs::info!("send 1 cent from //{} to //0", actual_repart - 1);
watchers.push(watcher);
// Wait all transactions
for watcher in watchers {
watcher.wait_for_in_block().await?;
}
}
}
}
Ok(())
}
async fn gen_revoc_doc(api: &Api, pair: &Pair) -> Result<()> {
let account_id: sp_core::crypto::AccountId32 = pair.public().into();
let genesis_hash = api.storage().system().block_hash(0, None).await?;
let payload = (account_id, genesis_hash).encode();
let signature = pair.sign(&payload);
println!("payload: 0x{}", hex::encode(payload));
println!("signature: 0x{}", hex::encode(signature));
Ok(())
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment