Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into nitro
Browse files Browse the repository at this point in the history
  • Loading branch information
jwiegley committed Feb 5, 2022
2 parents ecce0dc + 310d7d6 commit be2fa53
Show file tree
Hide file tree
Showing 20 changed files with 1,752 additions and 97 deletions.
52 changes: 46 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "quill"
version = "0.2.13"
version = "0.2.14"
authors = ["DFINITY Team"]
edition = "2018"

Expand All @@ -10,9 +10,11 @@ path = "src/main.rs"

[dependencies]
anyhow = "1.0.34"
base64 = "0.13.0"
bip39 = "1.0.1"
candid = "0.7.8"
clap = "3.0.0-beta.5"
flate2 = "1.0.22"
hex = {version = "0.4.2", features = ["serde"] }
ic-agent = "0.10.0"
ic-base-types = { git = "https://github.com/dfinity/ic", rev = "bd3b73e075aea1cc81b23b38ccfb138ca4ab17ab" }
Expand All @@ -36,5 +38,8 @@ pkcs11 = "0.5.0"
thiserror = "1.0.20"
rpassword = "4.0.0"

[dev-dependencies]
tempfile = "3.3.0"

[features]
static-ssl = ["openssl/vendored"]
5 changes: 5 additions & 0 deletions candid/governance.did
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type Command = variant {
ClaimOrRefresh : ClaimOrRefresh;
Configure : Configure;
RegisterVote : RegisterVote;
Merge : Merge;
DisburseToNeuron : DisburseToNeuron;
MakeProposal : Proposal;
MergeMaturity : MergeMaturity;
Expand All @@ -49,6 +50,7 @@ type Command_1 = variant {
ClaimOrRefresh : ClaimOrRefreshResponse;
Configure : record {};
RegisterVote : record {};
Merge : record {};
DisburseToNeuron : SpawnResponse;
MakeProposal : MakeProposalResponse;
MergeMaturity : MergeMaturityResponse;
Expand All @@ -57,6 +59,7 @@ type Command_1 = variant {
type Command_2 = variant {
Spawn : Spawn;
Split : Split;
Merge : Merge;
DisburseToNeuron : DisburseToNeuron;
ClaimOrRefreshNeuron : ClaimOrRefresh;
MergeMaturity : MergeMaturity;
Expand Down Expand Up @@ -123,6 +126,7 @@ type ManageNeuron = record {
neuron_id_or_subaccount : opt NeuronIdOrSubaccount;
};
type ManageNeuronResponse = record { command : opt Command_1 };
type Merge = record { source_neuron_id : opt NeuronId };
type MergeMaturity = record { percentage_to_merge : nat32 };
type MergeMaturityResponse = record {
merged_maturity_e8s : nat64;
Expand Down Expand Up @@ -170,6 +174,7 @@ type NeuronInfo = record {
recent_ballots : vec BallotInfo;
created_timestamp_seconds : nat64;
state : int32;
stake_e8s : nat64;
retrieved_at_timestamp_seconds : nat64;
voting_power : nat64;
age_seconds : nat64;
Expand Down
4 changes: 2 additions & 2 deletions default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@

with pkgs; rustPlatform.buildRustPackage rec {
pname = "quill";
version = "0.2.9";
version = "0.2.14";

src = ./.;

cargoSha256 = "1x0gsg62nmf5l9avfd18qzdc9i9lm2y62qgkj9iwshgdfjqzavvy";
cargoSha256 = "sha256-t+N0UoVOJIxi1q0SBfCqxNIcmXVBo44hhKE0SllJ63M=";

cargoBuildFlags = [];

Expand Down
6 changes: 3 additions & 3 deletions src/commands/generate.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::lib::{mnemonic_to_pem, AnyhowResult, AuthInfo};
use anyhow::anyhow;
use anyhow::{anyhow, Context};
use bip39::{Language, Mnemonic};
use clap::Parser;
use rand::{rngs::OsRng, RngCore};
Expand Down Expand Up @@ -49,14 +49,14 @@ pub fn exec(opts: GenerateOpts) -> AnyhowResult {
_ => return Err(anyhow!("Words must be 12 or 24.")),
};
let mnemonic = match opts.phrase {
Some(phrase) => Mnemonic::parse(phrase).unwrap(),
Some(phrase) => Mnemonic::parse(phrase).context("Failed to parse mnemonic")?,
None => {
let mut key = vec![0u8; bytes];
OsRng.fill_bytes(&mut key);
Mnemonic::from_entropy_in(Language::English, &key).unwrap()
}
};
let pem = mnemonic_to_pem(&mnemonic);
let pem = mnemonic_to_pem(&mnemonic).context("Failed to convert mnemonic to PEM")?;
let mut phrase = mnemonic
.word_iter()
.collect::<Vec<&'static str>>()
Expand Down
27 changes: 27 additions & 0 deletions src/commands/get_neuron_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use crate::{
commands::send::submit_unsigned_ingress,
lib::{governance_canister_id, AnyhowResult},
};
use candid::Encode;
use clap::Parser;

#[derive(Parser)]
pub struct GetNeuronInfoOpts {
pub ident: u64,

/// Will display the query, but not send it.
#[clap(long)]
dry_run: bool,
}

// We currently only support a subset of the functionality.
pub async fn exec(opts: GetNeuronInfoOpts) -> AnyhowResult {
let args = Encode!(&opts.ident)?;
submit_unsigned_ingress(
governance_canister_id(),
"get_neuron_info",
args,
opts.dry_run,
)
.await
}
91 changes: 84 additions & 7 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
//! This module implements the command-line API.
use crate::lib::{AnyhowResult, AuthInfo};
use crate::lib::{qr, AnyhowResult, AuthInfo};
use anyhow::Context;
use clap::Parser;
use std::io::{self, Write};
use tokio::runtime::Runtime;

mod account_balance;
mod claim_neurons;
mod generate;
mod get_neuron_info;
mod get_proposal_info;
mod list_neurons;
mod list_proposals;
mod neuron_manage;
mod neuron_stake;
mod public;
mod qrcode;
mod request_status;
mod send;
mod transfer;
Expand All @@ -35,29 +38,43 @@ pub enum Command {
ListNeurons(list_neurons::ListNeuronsOpts),
ListProposals(list_proposals::ListProposalsOpts),
GetProposalInfo(get_proposal_info::GetProposalInfoOpts),
GetNeuronInfo(get_neuron_info::GetNeuronInfoOpts),
/// Queries a ledger account balance.
AccountBalance(account_balance::AccountBalanceOpts),
/// Update node provider details
UpdateNodeProvider(update_node_provider::UpdateNodeProviderOpts),
/// Generate a mnemonic seed phrase and generate or recover PEM.
Generate(generate::GenerateOpts),
/// Print QR Scanner dapp QR code: scan to start dapp to submit QR results.
ScannerQRCode,
/// Print QR code for data e.g. principal id.
QRCode(qrcode::QRCodeOpts),
}

pub fn exec(auth: &AuthInfo, cmd: Command) -> AnyhowResult {
pub fn exec(auth: &AuthInfo, qr: bool, cmd: Command) -> AnyhowResult {
let runtime = Runtime::new().expect("Unable to create a runtime");
match cmd {
Command::PublicIds(opts) => public::exec(auth, opts),
Command::Transfer(opts) => transfer::exec(auth, opts).and_then(|out| print(&out)),
Command::NeuronStake(opts) => neuron_stake::exec(auth, opts).and_then(|out| print(&out)),
Command::NeuronManage(opts) => neuron_manage::exec(auth, opts).and_then(|out| print(&out)),
Command::ListNeurons(opts) => list_neurons::exec(auth, opts).and_then(|out| print(&out)),
Command::ClaimNeurons => claim_neurons::exec(auth).and_then(|out| print(&out)),
Command::Transfer(opts) => transfer::exec(auth, opts).and_then(|out| print_vec(qr, &out)),
Command::NeuronStake(opts) => {
neuron_stake::exec(auth, opts).and_then(|out| print_vec(qr, &out))
}
Command::NeuronManage(opts) => {
neuron_manage::exec(auth, opts).and_then(|out| print_vec(qr, &out))
}
Command::ListNeurons(opts) => {
list_neurons::exec(auth, opts).and_then(|out| print_vec(qr, &out))
}
Command::ClaimNeurons => claim_neurons::exec(auth).and_then(|out| print_vec(qr, &out)),
Command::ListProposals(opts) => {
runtime.block_on(async { list_proposals::exec(opts).await })
}
Command::GetProposalInfo(opts) => {
runtime.block_on(async { get_proposal_info::exec(opts).await })
}
Command::GetNeuronInfo(opts) => {
runtime.block_on(async { get_neuron_info::exec(opts).await })
}
Command::AccountBalance(opts) => {
runtime.block_on(async { account_balance::exec(opts).await })
}
Expand All @@ -66,6 +83,33 @@ pub fn exec(auth: &AuthInfo, cmd: Command) -> AnyhowResult {
}
Command::Send(opts) => runtime.block_on(async { send::exec(opts).await }),
Command::Generate(opts) => generate::exec(opts),
// QR code for URL: https://p5deo-6aaaa-aaaab-aaaxq-cai.raw.ic0.app/
// Source code: https://github.com/ninegua/ic-qr-scanner
Command::ScannerQRCode => {
println!(
"█████████████████████████████████████
█████████████████████████████████████
████ ▄▄▄▄▄ █▀█ █▄▀▄▀▄█ ▄ █ ▄▄▄▄▄ ████
████ █ █ █▀▀▀█ ▀▀█▄▀████ █ █ ████
████ █▄▄▄█ █▀ █▀▀██▀▀█ ▄ █ █▄▄▄█ ████
████▄▄▄▄▄▄▄█▄▀ ▀▄█ ▀▄█▄█▄█▄▄▄▄▄▄▄████
████▄▄▄▄ ▀▄ ▄▀▄ ▄ █▀▄▀▀▀ ▀ ▀▄█▄▀████
████▄█ █ ▄█▀█▄▀█▄ ▄▄ █ █ ▀█▀█████
████▄▀ ▀ █▄▄▄ ▄ █▄▀ █ ▀▀▀▄▄█▀████
████▄██▀▄▀▄▄ █▀█ ▄▄▄▄███▄█▄▀ ▄▄▀█████
████ ▀▄▀▄█▄▀▄▄▄▀█ ▄▄▀▄▀▀▀▄▀▀▀▄ █▀████
████ █▀██▀▄██▀▄█ █▀ █▄█▄▀▀ █▄▀█████
████▄████▄▄▄ ▀▀█▄▄██▄▀█ ▄▄▄ ▀ ████
████ ▄▄▄▄▄ █▄▄██▀▄▀ ▄█▄ █▄█ ▄▄▀█████
████ █ █ █ █▀▄▄▀▄ ▄▀▀▄▄▄ ▄▀ ▄▀████
████ █▄▄▄█ █ █▄▀▄██ ██▄█▀ ▄█ ▄ █████
████▄▄▄▄▄▄▄█▄▄▄▄▄▄██▄▄█▄████▄▄▄██████
█████████████████████████████████████
█████████████████████████████████████"
);
Ok(())
}
Command::QRCode(opts) => qrcode::exec(opts),
}
}

Expand All @@ -85,3 +129,36 @@ where
}
Ok(())
}

fn print_qr<T>(arg: &T, pause: bool) -> AnyhowResult
where
T: serde::ser::Serialize,
{
let json = serde_json::to_string(&arg)?;
let mut e = flate2::write::GzEncoder::new(Vec::new(), flate2::Compression::default());
e.write_all(json.as_bytes()).unwrap();
let json = e.finish().unwrap();
let json = base64::encode(json);
qr::print_qr(json.as_str());
if pause {
let mut input_string = String::new();
std::io::stdin()
.read_line(&mut input_string)
.expect("Failed to read line");
}
Ok(())
}

fn print_vec<T>(qr: bool, arg: &[T]) -> AnyhowResult
where
T: serde::ser::Serialize,
{
if !qr {
print(arg)
} else {
for (i, a) in arg.iter().enumerate() {
print_qr(&a, i != arg.len() - 1).context("Failed to print QR code")?;
}
Ok(())
}
}
Loading

0 comments on commit be2fa53

Please sign in to comment.