From c2aaa08c0db4e1b9d42a5d5595163bba592d1293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Molina=20Colmenero?= Date: Wed, 22 May 2024 19:23:01 +0200 Subject: [PATCH] feat: add the "pop up contracts-node" command (#185) * Add the "pop up contracts-node" command * Adapt wording * Restore README paragraph --- README.md | 15 ++++----- crates/pop-cli/Cargo.toml | 1 + .../pop-cli/src/commands/up/contracts_node.rs | 31 +++++++++++++++++++ crates/pop-cli/src/commands/up/mod.rs | 6 ++++ crates/pop-cli/src/main.rs | 11 ++++--- 5 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 crates/pop-cli/src/commands/up/contracts_node.rs diff --git a/README.md b/README.md index 2c6f5f9c..ea933512 100644 --- a/README.md +++ b/README.md @@ -137,12 +137,10 @@ Build the Smart Contract: pop build contract -p ./my_contract ``` -To deploy a Smart Contract you need a chain running. For testing purposes one option is to -run [substrate-contracts-node](https://github.com/paritytech/substrate-contracts-node): +To deploy a Smart Contract you need a chain running. For testing purposes you can simply spawn a contract node: ```sh -cargo install contracts-node -substrate-contracts-node +pop up contracts-node ``` > :information_source: We plan to automate this in the future. @@ -192,16 +190,15 @@ pop call contract -p ./my_contract --contract $INSTANTIATED_CONTRACT_ADDRESS --m ## E2E testing For end-to-end testing you will need to have a Substrate node with `pallet contracts`. -You do not need to run it in the background since the node is started for each test independently. -To install the latest version: +Pop provides the latest version out-of-the-box by running: -``` -cargo install contracts-node --git https://github.com/paritytech/substrate-contracts-node.git +```sh +pop up contracts-node ``` If you want to run any other node with `pallet-contracts` you need to change `CONTRACTS_NODE` environment variable: -``` +```sh export CONTRACTS_NODE="YOUR_CONTRACTS_NODE_PATH" ``` diff --git a/crates/pop-cli/Cargo.toml b/crates/pop-cli/Cargo.toml index cb942624..e106a18a 100644 --- a/crates/pop-cli/Cargo.toml +++ b/crates/pop-cli/Cargo.toml @@ -51,6 +51,7 @@ contract = [ "dep:pop-contracts", "dep:sp-core", "dep:sp-weights", + "dep:dirs", ] parachain = [ "dep:pop-parachains", diff --git a/crates/pop-cli/src/commands/up/contracts_node.rs b/crates/pop-cli/src/commands/up/contracts_node.rs new file mode 100644 index 00000000..074ff470 --- /dev/null +++ b/crates/pop-cli/src/commands/up/contracts_node.rs @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-3.0 + +use clap::Args; +use cliclack::{clear_screen, intro, set_theme}; +use duct::cmd; + +use crate::style::{style, Theme}; + +const BIN_NAME: &str = "substrate-contracts-node"; + +#[derive(Args)] +pub(crate) struct ContractsNodeCommand; +impl ContractsNodeCommand { + pub(crate) async fn execute(&self) -> anyhow::Result<()> { + clear_screen()?; + intro(format!("{}: Launch a contracts node", style(" Pop CLI ").black().on_magenta()))?; + set_theme(Theme); + + let cache = crate::cache()?; + let cached_file = cache.join("bin").join(BIN_NAME); + if !cached_file.exists() { + cmd( + "cargo", + vec!["install", "--root", cache.display().to_string().as_str(), "contracts-node"], + ) + .run()?; + } + cmd(cached_file.display().to_string().as_str(), Vec::<&str>::new()).run()?; + Ok(()) + } +} diff --git a/crates/pop-cli/src/commands/up/mod.rs b/crates/pop-cli/src/commands/up/mod.rs index 125b2bb9..c7a2bde8 100644 --- a/crates/pop-cli/src/commands/up/mod.rs +++ b/crates/pop-cli/src/commands/up/mod.rs @@ -2,6 +2,8 @@ #[cfg(feature = "contract")] mod contract; +#[cfg(feature = "contract")] +mod contracts_node; #[cfg(feature = "parachain")] mod parachain; @@ -24,4 +26,8 @@ pub(crate) enum UpCommands { /// Deploy a smart contract to a node. #[clap(alias = "c")] Contract(contract::UpContractCommand), + #[cfg(feature = "contract")] + /// Deploy a contracts node. + #[clap(alias = "n")] + ContractsNode(contracts_node::ContractsNodeCommand), } diff --git a/crates/pop-cli/src/main.rs b/crates/pop-cli/src/main.rs index da8e0495..6544907e 100644 --- a/crates/pop-cli/src/main.rs +++ b/crates/pop-cli/src/main.rs @@ -7,7 +7,6 @@ compile_error!("feature \"contract\" or feature \"parachain\" must be enabled"); mod commands; mod style; -#[cfg(feature = "parachain")] use anyhow::anyhow; use anyhow::Result; use clap::{Parser, Subcommand}; @@ -15,8 +14,9 @@ use commands::*; #[cfg(feature = "telemetry")] use pop_telemetry::{config_file_path, record_cli_command, record_cli_used, Telemetry}; use serde_json::{json, Value}; -#[cfg(feature = "parachain")] -use std::{env::args, fs::create_dir_all, path::PathBuf}; +#[cfg(feature = "telemetry")] +use std::env::args; +use std::{fs::create_dir_all, path::PathBuf}; #[derive(Parser)] #[command(author, version, about, styles=style::get_styles())] @@ -98,6 +98,8 @@ async fn main() -> Result<()> { up::UpCommands::Parachain(cmd) => cmd.execute().await.map(|_| Value::Null), #[cfg(feature = "contract")] up::UpCommands::Contract(cmd) => cmd.execute().await.map(|_| Value::Null), + #[cfg(feature = "contract")] + up::UpCommands::ContractsNode(cmd) => cmd.execute().await.map(|_| Value::Null), }, #[cfg(feature = "contract")] Commands::Test(args) => match &args.command { @@ -131,7 +133,7 @@ async fn main() -> Result<()> { // map result from Result to Result<()> res.map(|_| ()) } -#[cfg(feature = "parachain")] + fn cache() -> Result { let cache_path = dirs::cache_dir() .ok_or(anyhow!("the cache directory could not be determined"))? @@ -158,6 +160,7 @@ fn init() -> Result> { Ok(maybe_tel) } +#[cfg(feature = "telemetry")] fn parse_args(args: Vec) -> (String, String) { // command is always present as clap will print help if not set let command = args.get(1).expect("expected command missing").to_string();