diff --git a/Cargo.lock b/Cargo.lock index 81ccaef1d62a60c633e10a8d0716054bc4e1786f..0f5873ae7cc0bcf7e7ceec5b20f6949f1c013f73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -482,12 +482,13 @@ dependencies = [ "async-std", "blake2", "cargo_metadata", + "clap", "colored", "contract-metadata", "env_logger", "escape8259", "futures", - "heck 0.4.0", + "heck", "hex", "impl-serde", "indexmap", @@ -516,7 +517,6 @@ dependencies = [ "serde_json", "sp-core", "sp-runtime", - "structopt", "substrate-build-script-utils", "subxt", "tempfile", @@ -583,17 +583,32 @@ dependencies = [ [[package]] name = "clap" -version = "2.34.0" +version = "3.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "d8c93436c21e4698bacadf42917db28b23017027a4deccb35dbe47a7e7840123" dependencies = [ - "ansi_term", "atty", "bitflags", - "strsim 0.8.0", + "clap_derive", + "indexmap", + "lazy_static", + "os_str_bytes", + "strsim", + "termcolor", "textwrap", - "unicode-width", - "vec_map", +] + +[[package]] +name = "clap_derive" +version = "3.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da95d038ede1a964ce99f49cbe27a7fb538d1da595e4b4f70b8c8f338d17bf16" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -788,7 +803,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", + "strsim", "syn", ] @@ -1246,15 +1261,6 @@ dependencies = [ "ahash", ] -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "heck" version = "0.4.0" @@ -1502,7 +1508,7 @@ dependencies = [ "blake2", "derive_more", "either", - "heck 0.4.0", + "heck", "impl-serde", "ink_lang_ir", "itertools", @@ -2113,6 +2119,15 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +[[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +dependencies = [ + "memchr", +] + [[package]] name = "output_vt100" version = "0.1.3" @@ -3419,42 +3434,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -[[package]] -name = "structopt" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" -dependencies = [ - "clap", - "lazy_static", - "structopt-derive", -] - -[[package]] -name = "structopt-derive" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" -dependencies = [ - "heck 0.3.3", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "substrate-bip39" version = "0.4.4" @@ -3518,7 +3503,7 @@ dependencies = [ "async-trait", "darling", "frame-metadata", - "heck 0.4.0", + "heck", "parity-scale-codec", "proc-macro-crate 0.1.5", "proc-macro-error", @@ -3537,7 +3522,7 @@ dependencies = [ "async-trait", "darling", "frame-metadata", - "heck 0.4.0", + "heck", "parity-scale-codec", "proc-macro-crate 0.1.5", "proc-macro-error", @@ -3608,12 +3593,9 @@ checksum = "507e9898683b6c43a9aa55b64259b721b52ba226e0f3779137e50ad114a4c90b" [[package]] name = "textwrap" -version = "0.11.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "thiserror" @@ -3902,18 +3884,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-segmentation" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" - -[[package]] -name = "unicode-width" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" - [[package]] name = "unicode-xid" version = "0.2.2" @@ -3955,12 +3925,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "version_check" version = "0.9.4" diff --git a/Cargo.toml b/Cargo.toml index cf210e1c33b2071de922670b348e83118604ec13..7a6e0777cc76a5fa3f1d802c8d1f50e54880d5b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE", "build.rs", "tem [dependencies] env_logger = "0.9.0" anyhow = "1.0.56" -structopt = "0.3.26" +clap = { version = "3.1.6", features = ["derive", "env"] } log = "0.4.14" heck = "0.4.0" zip = { version = "0.5.13", default-features = false } diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 99faf9566fd6b10e710942881a6ea15079ce65ed..3541952ebdab7b8066e9e116cb9a1803add84171 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -34,7 +34,6 @@ use std::{ process::Command, str, }; -use structopt::StructOpt; /// This is the maximum number of pages available for a contract to allocate. const MAX_MEMORY_PAGES: u32 = 16; @@ -57,11 +56,11 @@ pub(crate) struct ExecuteArgs { /// Executes build of the smart contract which produces a Wasm binary that is ready for deploying. /// /// It does so by invoking `cargo build` and then post processing the final binary. -#[derive(Debug, StructOpt)] -#[structopt(name = "build")] +#[derive(Debug, clap::Args)] +#[clap(name = "build")] pub struct BuildCommand { /// Path to the `Cargo.toml` of the contract to build - #[structopt(long, parse(from_os_str))] + #[clap(long, parse(from_os_str))] manifest_path: Option, /// By default the contract is compiled with debug functionality /// included. This enables the contract to output debug messages, @@ -69,10 +68,10 @@ pub struct BuildCommand { /// /// A production contract should always be build in `release` mode! /// Then no debug functionality is compiled into the contract. - #[structopt(long = "--release")] + #[clap(long = "--release")] build_release: bool, /// Build offline - #[structopt(long = "--offline")] + #[clap(long = "--offline")] build_offline: bool, /// Which build artifacts to generate. /// @@ -80,16 +79,16 @@ pub struct BuildCommand { /// /// - `code-only`: Only the Wasm is created, generation of metadata and a bundled /// `.contract` file is skipped. - #[structopt( + #[clap( long = "generate", default_value = "all", value_name = "all | code-only", verbatim_doc_comment )] build_artifact: BuildArtifacts, - #[structopt(flatten)] + #[clap(flatten)] verbosity: VerbosityFlags, - #[structopt(flatten)] + #[clap(flatten)] unstable_options: UnstableOptions, /// Number of optimization passes, passed as an argument to `wasm-opt`. /// @@ -113,16 +112,16 @@ pub struct BuildCommand { /// - It is possible to define the number of optimization passes in the /// `[package.metadata.contract]` of your `Cargo.toml` as e.g. `optimization-passes = "3"`. /// The CLI argument always takes precedence over the profile value. - #[structopt(long)] + #[clap(long)] optimization_passes: Option, /// Do not remove symbols (Wasm name section) when optimizing. /// /// This is useful if one wants to analyze or debug the optimized binary. - #[structopt(long)] + #[clap(long)] keep_debug_symbols: bool, /// Export the build output in JSON format. - #[structopt(long, conflicts_with = "verbose")] + #[clap(long, conflicts_with = "verbose")] output_json: bool, } @@ -184,15 +183,15 @@ impl BuildCommand { } } -#[derive(Debug, StructOpt)] -#[structopt(name = "check")] +#[derive(Debug, clap::Args)] +#[clap(name = "check")] pub struct CheckCommand { /// Path to the `Cargo.toml` of the contract to build - #[structopt(long, parse(from_os_str))] + #[clap(long, parse(from_os_str))] manifest_path: Option, - #[structopt(flatten)] + #[clap(flatten)] verbosity: VerbosityFlags, - #[structopt(flatten)] + #[clap(flatten)] unstable_options: UnstableOptions, } diff --git a/src/cmd/extrinsics/call.rs b/src/cmd/extrinsics/call.rs index 59291544f92d63f9e9b6222d02e98359477222a0..ff95e4adcf200062735e34fcc3f99f5b94f2b4a9 100644 --- a/src/cmd/extrinsics/call.rs +++ b/src/cmd/extrinsics/call.rs @@ -25,30 +25,29 @@ use jsonrpsee::{core::client::ClientT, rpc_params, ws_client::WsClientBuilder}; use serde::Serialize; use sp_core::Bytes; use std::fmt::Debug; -use structopt::StructOpt; use subxt::{rpc::NumberOrHex, ClientBuilder, Config, DefaultConfig, Signer}; type ContractExecResult = pallet_contracts_primitives::ContractExecResult; -#[derive(Debug, StructOpt)] -#[structopt(name = "call", about = "Call a contract")] +#[derive(Debug, clap::Args)] +#[clap(name = "call", about = "Call a contract")] pub struct CallCommand { /// The address of the the contract to call. - #[structopt(name = "contract", long, env = "CONTRACT")] + #[clap(name = "contract", long, env = "CONTRACT")] contract: ::AccountId, /// The name of the contract message to call. - #[structopt(long, short)] + #[clap(long, short)] message: String, /// The arguments of the contract message to call. - #[structopt(long)] + #[clap(long)] args: Vec, - #[structopt(flatten)] + #[clap(flatten)] extrinsic_opts: ExtrinsicOpts, /// Maximum amount of gas to be used for this command. - #[structopt(name = "gas", long, default_value = "50000000000")] + #[clap(name = "gas", long, default_value = "50000000000")] gas_limit: u64, /// The value to be transferred as part of the call. - #[structopt(name = "value", long, parse(try_from_str = parse_balance), default_value = "0")] + #[clap(name = "value", long, parse(try_from_str = parse_balance), default_value = "0")] value: Balance, } diff --git a/src/cmd/extrinsics/instantiate.rs b/src/cmd/extrinsics/instantiate.rs index e670a1e694b46d3b6dd4e2573b6c5e3634c52f50..57a984ed6c5c5e48075cdcd6829ed5704b47a549 100644 --- a/src/cmd/extrinsics/instantiate.rs +++ b/src/cmd/extrinsics/instantiate.rs @@ -29,41 +29,40 @@ use std::{ fs, path::{Path, PathBuf}, }; -use structopt::StructOpt; use subxt::{rpc::NumberOrHex, ClientBuilder, Config, DefaultConfig, Signer}; type ContractInstantiateResult = pallet_contracts_primitives::ContractInstantiateResult; -#[derive(Debug, StructOpt)] +#[derive(Debug, clap::Args)] pub struct InstantiateCommand { /// Path to Wasm contract code, defaults to `./target/ink/.wasm`. /// Use to instantiate contracts which have not yet been uploaded. /// If the contract has already been uploaded use `--code-hash` instead. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] wasm_path: Option, /// The hash of the smart contract code already uploaded to the chain. /// If the contract has not already been uploaded use `--wasm-path` or run the `upload` command /// first. - #[structopt(long, parse(try_from_str = parse_code_hash))] + #[clap(long, parse(try_from_str = parse_code_hash))] code_hash: Option<::Hash>, /// The name of the contract constructor to call - #[structopt(name = "constructor", long, default_value = "new")] + #[clap(name = "constructor", long, default_value = "new")] constructor: String, /// The constructor arguments, encoded as strings - #[structopt(long)] + #[clap(long)] args: Vec, - #[structopt(flatten)] + #[clap(flatten)] extrinsic_opts: ExtrinsicOpts, /// Transfers an initial balance to the instantiated contract - #[structopt(name = "value", long, default_value = "0", parse(try_from_str = parse_balance))] + #[clap(name = "value", long, default_value = "0", parse(try_from_str = parse_balance))] value: Balance, /// Maximum amount of gas to be used for this command - #[structopt(name = "gas", long, default_value = "50000000000")] + #[clap(name = "gas", long, default_value = "50000000000")] gas_limit: u64, /// A salt used in the address derivation of the new contract. Use to create multiple instances /// of the same contract code from the same account. - #[structopt(long, parse(try_from_str = parse_hex_bytes))] + #[clap(long, parse(try_from_str = parse_hex_bytes))] salt: Option, } diff --git a/src/cmd/extrinsics/mod.rs b/src/cmd/extrinsics/mod.rs index 03aa522a9e5f00edaa63ca9f037c0e170efb6e78..4a5185a9f1b115fba7ba640baf6483000ff0af88 100644 --- a/src/cmd/extrinsics/mod.rs +++ b/src/cmd/extrinsics/mod.rs @@ -35,7 +35,6 @@ use crate::{ }; use pallet_contracts_primitives::ContractResult; use sp_core::{crypto::Pair, sr25519}; -use structopt::StructOpt; use subxt::{Config, DefaultConfig}; pub use call::CallCommand; @@ -51,13 +50,13 @@ type SignedExtra = subxt::DefaultExtra; type RuntimeApi = runtime_api::api::RuntimeApi; /// Arguments required for creating and sending an extrinsic to a substrate node. -#[derive(Clone, Debug, StructOpt)] +#[derive(Clone, Debug, clap::Args)] pub struct ExtrinsicOpts { /// Path to the `Cargo.toml` of the contract. - #[structopt(long, parse(from_os_str))] + #[clap(long, parse(from_os_str))] manifest_path: Option, /// Websockets url of a substrate node. - #[structopt( + #[clap( name = "url", long, parse(try_from_str), @@ -65,19 +64,19 @@ pub struct ExtrinsicOpts { )] url: url::Url, /// Secret key URI for the account deploying the contract. - #[structopt(name = "suri", long, short)] + #[clap(name = "suri", long, short)] suri: String, /// Password for the secret key. - #[structopt(name = "password", long, short)] + #[clap(name = "password", long, short)] password: Option, - #[structopt(flatten)] + #[clap(flatten)] verbosity: VerbosityFlags, /// Dry-run the extrinsic via rpc, instead of as an extrinsic. Chain state will not be mutated. - #[structopt(long, short = "rpc")] + #[clap(long)] dry_run: bool, /// The maximum amount of balance that can be charged from the caller to pay for the storage /// consumed. - #[structopt(long, parse(try_from_str = parse_balance))] + #[clap(long, parse(try_from_str = parse_balance))] storage_deposit_limit: Option, } diff --git a/src/cmd/extrinsics/upload.rs b/src/cmd/extrinsics/upload.rs index 5bef240ccafa68e901958092bc64a68ec3b4da3b..fa2d2dd8c9594b250a084f016ab8950b8f6382e4 100644 --- a/src/cmd/extrinsics/upload.rs +++ b/src/cmd/extrinsics/upload.rs @@ -24,19 +24,18 @@ use jsonrpsee::{core::client::ClientT, rpc_params, ws_client::WsClientBuilder}; use serde::Serialize; use sp_core::Bytes; use std::{fmt::Debug, path::PathBuf}; -use structopt::StructOpt; use subxt::{rpc::NumberOrHex, ClientBuilder, Config, DefaultConfig, Signer}; type CodeUploadResult = pallet_contracts_primitives::CodeUploadResult; type CodeUploadReturnValue = pallet_contracts_primitives::CodeUploadReturnValue; -#[derive(Debug, StructOpt)] -#[structopt(name = "upload", about = "Upload a contract's code")] +#[derive(Debug, clap::Args)] +#[clap(name = "upload", about = "Upload a contract's code")] pub struct UploadCommand { /// Path to Wasm contract code, defaults to `./target/ink/.wasm`. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] wasm_path: Option, - #[structopt(flatten)] + #[clap(flatten)] extrinsic_opts: ExtrinsicOpts, } diff --git a/src/cmd/test.rs b/src/cmd/test.rs index bf624e4132f9349557bd883e4c6fecd97f4d7461..2d3d28869c0e3563e7f8b252ad77e53d7f93d2a1 100644 --- a/src/cmd/test.rs +++ b/src/cmd/test.rs @@ -18,16 +18,15 @@ use crate::{maybe_println, util, workspace::ManifestPath, Verbosity, VerbosityFl use anyhow::Result; use colored::Colorize; use std::{convert::TryFrom, path::PathBuf}; -use structopt::StructOpt; /// Executes smart contract tests off-chain by delegating to `cargo test`. -#[derive(Debug, StructOpt)] -#[structopt(name = "test")] +#[derive(Debug, clap::Args)] +#[clap(name = "test")] pub struct TestCommand { /// Path to the `Cargo.toml` of the contract to test. - #[structopt(long, parse(from_os_str))] + #[clap(long, parse(from_os_str))] manifest_path: Option, - #[structopt(flatten)] + #[clap(flatten)] verbosity: VerbosityFlags, } diff --git a/src/main.rs b/src/main.rs index eb7adacf36d8e0ce1d951d08d84f07b593418eb2..0bc942036dda1876a4b08bd6b78d969876fa5832 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,25 +37,23 @@ use std::{ }; use anyhow::{Error, Result}; +use clap::{AppSettings, Args, Parser, Subcommand}; use colored::Colorize; -use structopt::{clap, StructOpt}; -#[derive(Debug, StructOpt)] -#[structopt(bin_name = "cargo")] -#[structopt(version = env!("CARGO_CONTRACT_CLI_IMPL_VERSION"))] +#[derive(Debug, Parser)] +#[clap(bin_name = "cargo")] +#[clap(version = env!("CARGO_CONTRACT_CLI_IMPL_VERSION"))] pub(crate) enum Opts { /// Utilities to develop Wasm smart contracts. - #[structopt(name = "contract")] - #[structopt(version = env!("CARGO_CONTRACT_CLI_IMPL_VERSION"))] - #[structopt(setting = clap::AppSettings::UnifiedHelpMessage)] - #[structopt(setting = clap::AppSettings::DeriveDisplayOrder)] - #[structopt(setting = clap::AppSettings::DontCollapseArgsInUsage)] + #[clap(name = "contract")] + #[clap(version = env!("CARGO_CONTRACT_CLI_IMPL_VERSION"))] + #[clap(setting = AppSettings::DeriveDisplayOrder)] Contract(ContractArgs), } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub(crate) struct ContractArgs { - #[structopt(subcommand)] + #[clap(subcommand)] cmd: Command, } @@ -129,13 +127,13 @@ impl From for OptimizationPasses { } } -#[derive(Default, Clone, Debug, StructOpt)] +#[derive(Default, Clone, Debug, Args)] pub struct VerbosityFlags { /// No output printed to stdout - #[structopt(long)] + #[clap(long)] quiet: bool, /// Use verbose output - #[structopt(long)] + #[clap(long)] verbose: bool, } @@ -179,10 +177,10 @@ impl TryFrom<&VerbosityFlags> for Verbosity { } } -#[derive(Default, Clone, Debug, StructOpt)] +#[derive(Default, Clone, Debug, Args)] struct UnstableOptions { /// Use the original manifest (Cargo.toml), do not modify for build optimizations - #[structopt(long = "unstable-options", short = "Z", number_of_values = 1)] + #[clap(long = "unstable-options", short = 'Z', number_of_values = 1)] options: Vec, } @@ -211,14 +209,14 @@ impl TryFrom<&UnstableOptions> for UnstableFlags { } /// Describes which artifacts to generate -#[derive(Copy, Clone, Eq, PartialEq, Debug, StructOpt, serde::Serialize)] -#[structopt(name = "build-artifacts")] +#[derive(Copy, Clone, Eq, PartialEq, Debug, Subcommand, serde::Serialize)] +#[clap(name = "build-artifacts")] pub enum BuildArtifacts { /// Generate the Wasm, the metadata and a bundled `.contract` file - #[structopt(name = "all")] + #[clap(name = "all")] All, /// Only the Wasm is created, generation of metadata and a bundled `.contract` file is skipped - #[structopt(name = "code-only")] + #[clap(name = "code-only")] CodeOnly, CheckOnly, } @@ -427,41 +425,41 @@ impl BuildResult { } } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] enum Command { /// Setup and create a new smart contract project - #[structopt(name = "new")] + #[clap(name = "new")] New { /// The name of the newly created smart contract name: String, /// The optional target directory for the contract project - #[structopt(short, long, parse(from_os_str))] + #[clap(short, long, parse(from_os_str))] target_dir: Option, }, /// Compiles the contract, generates metadata, bundles both together in a `.contract` file - #[structopt(name = "build")] + #[clap(name = "build")] Build(BuildCommand), /// Check that the code builds as Wasm; does not output any `.contract` artifact to the `target/` directory - #[structopt(name = "check")] + #[clap(name = "check")] Check(CheckCommand), /// Test the smart contract off-chain - #[structopt(name = "test")] + #[clap(name = "test")] Test(TestCommand), /// Upload contract code - #[structopt(name = "upload")] + #[clap(name = "upload")] Upload(UploadCommand), /// Instantiate a contract - #[structopt(name = "instantiate")] + #[clap(name = "instantiate")] Instantiate(InstantiateCommand), /// Call a contract - #[structopt(name = "call")] + #[clap(name = "call")] Call(CallCommand), } fn main() { env_logger::init(); - let Opts::Contract(args) = Opts::from_args(); + let Opts::Contract(args) = Opts::parse(); match exec(args.cmd) { Ok(()) => {} Err(err) => {