Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor into jcli-lib crate #3216

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a28223f
Add new jcli-lib crate to workspace
filip-dulic-bloxico Apr 13, 2021
d002b33
transfer the same dependencies from jcli to jcli-lib
filip-dulic-bloxico Apr 13, 2021
232d99f
bulk transfer of jcli_lib code into jcli-lib crate
filip-dulic-bloxico Apr 13, 2021
e445722
refactor main library modules, transfer to new crate
filip-dulic-bloxico Apr 13, 2021
07fbb0c
set jcli-lib as a dependency of jcli
filip-dulic-bloxico Apr 13, 2021
502f473
correct imports in new jcli-lib
filip-dulic-bloxico Apr 13, 2021
be60ecb
copy build.rs from jcli crate
filip-dulic-bloxico Apr 13, 2021
b5235e9
remove unused dependencies from jcli
filip-dulic-bloxico Apr 13, 2021
92f5a70
make structopt an optional feature, add to default features in Cargo …
filip-dulic-bloxico Apr 14, 2021
49c52d8
feature gate structopt attributes for jcli_lib::address
filip-dulic-bloxico Apr 14, 2021
fbc507d
feature gate structopt attributes for jcli_lib::auto_complete
filip-dulic-bloxico Apr 14, 2021
422f282
feature gate structopt attributes for jcli_lib::block
filip-dulic-bloxico Apr 14, 2021
30fdb1f
feature gate structopt attributes for jcli_lib::certificate::*
filip-dulic-bloxico Apr 14, 2021
4f21efd
feature gate structopt attributes for jcli_lib::debug::*
filip-dulic-bloxico Apr 14, 2021
6525177
feature gate structopt attributes for jcli_lib::key
filip-dulic-bloxico Apr 14, 2021
6584dd4
feature gate structopt attributes for jcli_lib::rest::*
filip-dulic-bloxico Apr 14, 2021
a0bce01
feature gate structopt attributes for jcli_lib::transaction::*
filip-dulic-bloxico Apr 14, 2021
5d2f1b4
feature gate structopt attributes for jcli_lib::utils::*
filip-dulic-bloxico Apr 14, 2021
1fdb6b7
feature gate structopt attributes for jcli_lib::vote::*
filip-dulic-bloxico Apr 14, 2021
48ad2d8
feature gate structopt attributes for top-level lib.rs
filip-dulic-bloxico Apr 14, 2021
0c0a6bb
feature gate auto_complete module
filip-dulic-bloxico Apr 15, 2021
247030b
add top-level docstrings to modules in crate
filip-dulic-bloxico Apr 15, 2021
004405f
more doc strings for modules and public types
filip-dulic-bloxico Apr 16, 2021
192d45f
make crate::rest::v0 module public
filip-dulic-bloxico Apr 16, 2021
d57f892
remove duplicate Seed structs, make Seed public for library
filip-dulic-bloxico Apr 19, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ members = [
"jormungandr-lib",
"jormungandr",
"jcli",
"jcli-lib",
"modules/settings",
"modules/blockchain",
"testing/jormungandr-testing-utils",
Expand Down
62 changes: 62 additions & 0 deletions jcli-lib/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
[package]
name = "jcli-lib"
version = "0.11.1"
authors = [ "[email protected]" ]
license = "MIT OR Apache-2.0"
repository = "https://github.com/input-output-hk/jormungandr"
homepage = "https://github.com/input-output-hk/jormungandr#README.md"
documentation = "https://github.com/input-output-hk/jormungandr#USAGE.md"
description = """
Midgard Serpent
"""
edition = "2018"

[dependencies]
rand = "0.8"
rand_chacha = "0.3"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0.59"
serde_yaml = "0.8"
bincode = "1.3.3"
mime = "^0.3.7"
bech32 = "0.7"
hex = "0.4.2"
rayon = "1.5"
base64 = "0.13.0"
chain-core = { git = "https://github.com/input-output-hk/chain-libs.git", branch = "master" }
chain-impl-mockchain = { git = "https://github.com/input-output-hk/chain-libs.git", branch = "master" }
chain-addr = { git = "https://github.com/input-output-hk/chain-libs.git", branch = "master" }
chain-crypto = { git = "https://github.com/input-output-hk/chain-libs.git", branch = "master" }
chain-time = { git = "https://github.com/input-output-hk/chain-libs.git", branch = "master" }
chain-vote = { git = "https://github.com/input-output-hk/chain-libs.git", branch = "master", features = ["p256k1"] }
jormungandr-lib = { path = "../jormungandr-lib" }
gtmpl = "0.6.0"
valico = "3.5.0"
ed25519-bip32 = "0.3"
thiserror = "1.0"
bytes = "1.0"

[dependencies.structopt]
version = "^0.3"
optional = true

[dependencies.clap]
version = "2.33"
default-features = false
features = [ "suggestions", "color", "wrap_help" ]

[dependencies.reqwest]
version = "0.11"
default-features = false
features = ["blocking", "rustls-tls", "json"]

[dev-dependencies]
assert_fs = "1.0"
predicates = "1.0"

[build-dependencies]
versionisator = "1.0.2"

[features]
default = ["structopt"]
19 changes: 19 additions & 0 deletions jcli-lib/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
fn main() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not needed for the library actually. We should be pretty much happy with what Cargo.toml provides.

let pkg_version = if let Ok(date) = std::env::var("DATE") {
format!("{}.{}", env!("CARGO_PKG_VERSION"), date)
} else {
env!("CARGO_PKG_VERSION").to_string()
};

println!("cargo:rustc-env=CARGO_PKG_VERSION={}", pkg_version);

let version = versionisator::Version::new(
env!("CARGO_MANIFEST_DIR"),
env!("CARGO_PKG_NAME").to_string(),
pkg_version,
);

println!("cargo:rustc-env=FULL_VERSION={}", version.full());
println!("cargo:rustc-env=SIMPLE_VERSION={}", version.simple());
println!("cargo:rustc-env=SOURCE_VERSION={}", version.hash());
}
37 changes: 22 additions & 15 deletions jcli/src/jcli_lib/address.rs → jcli-lib/src/address.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
use crate::jcli_lib::utils::key_parser::parse_pub_key;
use crate::utils::key_parser::parse_pub_key;
use chain_addr::{AddressReadable, Discrimination, Kind};
use chain_crypto::{bech32::Bech32 as _, AsymmetricPublicKey, Ed25519, PublicKey};
#[cfg(feature = "structopt")]
use structopt::StructOpt;
use thiserror::Error;

#[derive(StructOpt)]
#[structopt(name = "address", rename_all = "kebab-case")]
#[cfg_attr(
filip-dulic-bloxico marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would oppose that. Instead just "move the functionality to the library and optional command parser" we should implement an API that is intended for library users. By this I mean that the current approach, that is initially intended for "parse arguments and run a command" is not suitable here. Most commands could (and should) be made into functions receiving several arguments.

Let's reserve argument parsing for the actual CLI binary and think of a better approach here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, argument parsing could be reused too. Even inside jcli itself we have some duplicated code. Also some tools could reuse some of that code (it is being used for a tool now on catalyst-toolbox).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even inside jcli itself we have some duplicated code

This is the problem of a client, not the problem of a library. ;)

Also some tools could reuse some of that code

Need to look at the amount.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the problem of a client, not the problem of a library

In this case, it is both.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The library could implement things like parsing common argument formats. Probably not the options and subcommand structures though, these should be defined in the CLI tool.

feature = "structopt",
derive(StructOpt),
structopt(name = "address", rename_all = "kebab-case")
)]
pub enum Address {
/// Display the content and info of a bech32 formatted address.
Info(InfoArgs),
Expand All @@ -18,48 +22,51 @@ pub enum Address {
Account(AccountArgs),
}

#[derive(StructOpt)]
#[cfg_attr(feature = "structopt", derive(StructOpt))]
pub struct InfoArgs {
/// An address, in bech32 format, to display the content
/// and info that can be extracted from.
#[structopt(name = "ADDRESS")]
#[cfg_attr(feature = "structopt", structopt(name = "ADDRESS"))]
address: AddressReadable,
}

#[derive(StructOpt)]
#[cfg_attr(feature = "structopt", derive(StructOpt))]
pub struct DiscriminationData {
/// Set the discrimination type to testing (default is production).
#[structopt(long = "testing")]
#[cfg_attr(feature = "structopt", structopt(long = "testing"))]
testing: bool,

/// Set the prefix to use to describe the address. This is only available
/// on the human readable representation of the address and will not be
/// used or checked by the node.
#[structopt(long = "prefix", default_value = "ca")]
#[cfg_attr(
feature = "structopt",
structopt(long = "prefix", default_value = "ca")
)]
prefix: String,
}

#[derive(StructOpt)]
#[cfg_attr(feature = "structopt", derive(StructOpt))]
pub struct SingleArgs {
/// A public key in bech32 encoding with the key type prefix.
#[structopt(name = "PUBLIC_KEY", parse(try_from_str = parse_pub_key))]
#[cfg_attr(feature = "structopt", structopt(name = "PUBLIC_KEY", parse(try_from_str = parse_pub_key)))]
key: PublicKey<Ed25519>,

/// A public key in bech32 encoding with the key type prefix.
#[structopt(name = "DELEGATION_KEY", parse(try_from_str = parse_pub_key))]
#[cfg_attr(feature = "structopt", structopt(name = "DELEGATION_KEY", parse(try_from_str = parse_pub_key)))]
delegation: Option<PublicKey<Ed25519>>,

#[structopt(flatten)]
#[cfg_attr(feature = "structopt", structopt(flatten))]
discrimination_data: DiscriminationData,
}

#[derive(StructOpt)]
#[cfg_attr(feature = "structopt", derive(StructOpt))]
pub struct AccountArgs {
/// A public key in bech32 encoding with the key type prefix.
#[structopt(name = "PUBLIC_KEY", parse(try_from_str = parse_pub_key))]
#[cfg_attr(feature = "structopt", structopt(name = "PUBLIC_KEY", parse(try_from_str = parse_pub_key)))]
key: PublicKey<Ed25519>,

#[structopt(flatten)]
#[cfg_attr(feature = "structopt", structopt(flatten))]
discrimination_data: DiscriminationData,
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
//! Generated auto-completions for supported shells supported by `structopt` via `clap`.
use std::path::{Path, PathBuf};
#[cfg(feature = "structopt")]
use structopt::{clap::Shell, StructOpt};
use thiserror::Error;

#[derive(StructOpt)]
#[structopt(rename_all = "kebab-case")]
#[cfg_attr(
feature = "structopt",
derive(StructOpt),
structopt(rename_all = "kebab-case")
)]
pub struct AutoCompletion {
#[cfg(feature = "structopt")]
/// set the type shell for the auto completion output (bash, zsh...)
shell: Shell,

/// path to the directory to write the generated auto completion files
output: PathBuf,
}

#[cfg(feature = "structopt")]
impl AutoCompletion {
pub fn exec<S: StructOpt>(self) -> Result<(), Error> {
validate_output(&self.output)?;
Expand Down
26 changes: 18 additions & 8 deletions jcli/src/jcli_lib/block/mod.rs → jcli-lib/src/block/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::jcli_lib::utils::io;
use crate::utils::io;
use chain_core::property::{Block as _, Deserialize, Serialize};
use chain_impl_mockchain::{
block::Block,
Expand All @@ -11,6 +11,7 @@ use std::{
io::{BufRead, Write},
path::PathBuf,
};
#[cfg(feature = "structopt")]
use structopt::StructOpt;
use thiserror::Error;

Expand Down Expand Up @@ -85,8 +86,11 @@ fn print_hash(input: Input) -> Result<(), Error> {
}

/// create block 0 of the blockchain (i.e. the genesis block)
#[derive(StructOpt)]
#[structopt(name = "genesis", rename_all = "kebab-case")]
#[cfg_attr(
feature = "structopt",
derive(StructOpt),
structopt(name = "genesis", rename_all = "kebab-case")
)]
pub enum Genesis {
/// Create a default Genesis file with appropriate documentation
/// to help creating the YAML file
Expand All @@ -104,13 +108,16 @@ pub enum Genesis {
Hash(Input),
}

#[derive(StructOpt)]
#[cfg_attr(feature = "structopt", derive(StructOpt))]
pub struct Input {
/// the file path to the genesis file defining the block 0
///
/// If not available the command will expect to read the configuration from
/// the standard input.
#[structopt(long = "input", parse(from_os_str), name = "FILE_INPUT")]
#[cfg_attr(
feature = "structopt",
structopt(long = "input", parse(from_os_str), name = "FILE_INPUT")
)]
input_file: Option<std::path::PathBuf>,
}

Expand All @@ -128,16 +135,19 @@ impl Input {
}
}

#[derive(StructOpt)]
#[cfg_attr(feature = "structopt", derive(StructOpt))]
pub struct Common {
#[structopt(flatten)]
#[cfg_attr(feature = "structopt", structopt(flatten))]
pub input: Input,

/// the file path to the block to create
///
/// If not available the command will expect to write the block to
/// to the standard output
#[structopt(long = "output", parse(from_os_str), name = "FILE_OUTPUT")]
#[cfg_attr(
feature = "structopt",
structopt(long = "output", parse(from_os_str), name = "FILE_OUTPUT")
)]
pub output_file: Option<std::path::PathBuf>,
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub(crate) use self::sign::{
pool_owner_sign, stake_delegation_account_binding_sign,
};

use crate::jcli_lib::utils::{
use crate::utils::{
io, key_parser,
vote::{SharesError, VotePlanError},
};
Expand All @@ -26,6 +26,7 @@ use std::{
io::{BufRead, BufReader, Write},
path::{Path, PathBuf},
};
#[cfg(feature = "structopt")]
use structopt::StructOpt;
use thiserror::Error;

Expand Down Expand Up @@ -114,8 +115,11 @@ pub enum Error {
}

#[allow(clippy::large_enum_variant)]
#[derive(StructOpt)]
#[structopt(rename_all = "kebab-case")]
#[cfg_attr(
feature = "structopt",
derive(StructOpt),
structopt(rename_all = "kebab-case")
)]
pub enum Certificate {
/// Build certificate
New(NewArgs),
Expand All @@ -129,8 +133,11 @@ pub enum Certificate {
}

#[allow(clippy::large_enum_variant)]
#[derive(StructOpt)]
#[structopt(rename_all = "kebab-case")]
#[cfg_attr(
feature = "structopt",
derive(StructOpt),
structopt(rename_all = "kebab-case")
)]
pub enum NewArgs {
/// create the stake pool registration certificate.
///
Expand Down Expand Up @@ -167,21 +174,24 @@ pub enum NewArgs {
VoteCast(new_vote_cast::VoteCastCmd),
}

#[derive(StructOpt)]
#[structopt(rename_all = "kebab-case")]
#[cfg_attr(
feature = "structopt",
derive(StructOpt),
structopt(rename_all = "kebab-case")
)]
pub struct PrintArgs {
/// get the certificate to sign from the given file. If no file
/// provided, it will be read from the standard input
pub input: Option<PathBuf>,
}

#[derive(StructOpt)]
#[cfg_attr(feature = "structopt", derive(StructOpt))]
pub struct StakeDelegationArgs {
#[structopt(name = "PUBLIC_KEY")]
#[cfg_attr(feature = "structopt", structopt(name = "PUBLIC_KEY"))]
pub key: String,
#[structopt(name = "POOL_ID")]
#[cfg_attr(feature = "structopt", structopt(name = "POOL_ID"))]
pub pool_id: String,
#[structopt(name = "SIGNING_KEY")]
#[cfg_attr(feature = "structopt", structopt(name = "SIGNING_KEY"))]
pub private_key: PathBuf,
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
use crate::jcli_lib::certificate::{write_cert, Error};
use crate::certificate::{write_cert, Error};
use chain_impl_mockchain::certificate;
use chain_impl_mockchain::certificate::{Certificate, VotePlanId};
use std::path::PathBuf;
#[cfg(feature = "structopt")]
use structopt::StructOpt;

/// create an encrypted vote tally certificate
///
/// voteplan id needs to be provided
#[derive(StructOpt)]
#[structopt(rename_all = "kebab-case")]
#[cfg_attr(
feature = "structopt",
derive(StructOpt),
structopt(rename_all = "kebab-case")
)]
pub struct EncryptedVoteTally {
/// vote plan id
///
/// the vote plan identifier on the blockchain
#[structopt(long = "vote-plan-id")]
#[cfg_attr(feature = "structopt", structopt(long = "vote-plan-id"))]
pub id: VotePlanId,

/// write the output to the given file or print it to the standard output if not defined
#[structopt(long = "output")]
#[cfg_attr(feature = "structopt", structopt(long = "output"))]
pub output: Option<PathBuf>,
}

Expand Down
Loading