From 2976c20ee8364fe6a9f4de5e08efda076d7f12d1 Mon Sep 17 00:00:00 2001 From: Bruno Galvao Date: Thu, 7 Mar 2024 18:27:59 +0700 Subject: [PATCH 01/10] feat: add cargo contract e2e tests for Pop CLI (#22) * wrap cargo-contracts and generate new contract * feat: contracts engine * feat: build contracts * feat: tests contracts * test: unit test create contract * fix: run pop test contract inside smart contract directory * docs: add contract information in README * add e2e contract testing * add instructions on how to run it * Update README * update text * sync with `main` * not needed --------- Co-authored-by: AlexD10S --- README.md | 23 +++++++++++++++++++++-- src/commands/new/contract.rs | 4 ++-- src/commands/test/contract.rs | 26 ++++++++++++++++++-------- src/engines/contract_engine.rs | 30 ++++++++++++++++++++++-------- 4 files changed, 63 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 4cc73ec11..5e7179603 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,26 @@ Build the smart contract: pop build contract -p ./my_contract ``` -### Build locally +### E2E testing + +For e2e 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: +``` +cargo install contracts-node --git https://github.com/paritytech/substrate-contracts-node.git +``` +If you want to run any other node with `pallet-contracts` you need to change `CONTRACTS_NODE` environment variable: +``` +export CONTRACTS_NODE="YOUR_CONTRACTS_NODE_PATH" +``` + +Run e2e testing on the smart contract: +```sh +# Run e2e tests for an existing smart contract + pop test contract -p ./my_contract --features e2e-tests +``` + +## Building Pop CLI locally Build the tool locally with all the features: ```sh @@ -79,4 +98,4 @@ cargo build --features parachain Build the tool only for contracts functionality: ```sh cargo build --features contract -``` \ No newline at end of file +``` diff --git a/src/commands/new/contract.rs b/src/commands/new/contract.rs index 83a0bd65c..08aba690f 100644 --- a/src/commands/new/contract.rs +++ b/src/commands/new/contract.rs @@ -17,8 +17,8 @@ impl NewContractCommand { pub(crate) fn execute(&self) -> anyhow::Result<()> { create_smart_contract(self.name.clone(), &self.path)?; log::info(format!( - "Smart contract created. Move to the dir {:?}", - self.path.clone().unwrap_or(PathBuf::from(format!("{}", self.name))).display() + "Smart contract created! Located in the following directory {:?}", + self.path.clone().unwrap_or(PathBuf::from(format!("/{}", self.name))).display() ))?; Ok(()) } diff --git a/src/commands/test/contract.rs b/src/commands/test/contract.rs index 0419e8492..6db632cef 100644 --- a/src/commands/test/contract.rs +++ b/src/commands/test/contract.rs @@ -5,23 +5,33 @@ use cliclack::{clear_screen,intro}; use crate::style::style; use crate::engines::contract_engine::test_smart_contract; +use crate::engines::contract_engine::test_e2e_smart_contract; #[derive(Args)] pub(crate) struct TestContractCommand { #[arg(short = 'p', long = "path", help = "Path for the contract project [default: current directory]")] path: Option, + #[arg(short = 'f', long = "features", help = "Features for the contract project")] + features: Option, } impl TestContractCommand { pub(crate) fn execute(&self) -> anyhow::Result<()> { clear_screen()?; - intro(format!( - "{}: Starting unit tests", - style(" Pop CLI ").black().on_magenta() - ))?; - test_smart_contract(&self.path)?; - + if self.features.is_some() && self.features.clone().unwrap().contains("e2e-tests") { + intro(format!( + "{}: Starting e2e tests", + style(" Pop CLI ").black().on_magenta() + ))?; + test_e2e_smart_contract(&self.path)?; + } else { + intro(format!( + "{}: Starting unit tests", + style(" Pop CLI ").black().on_magenta() + ))?; + test_smart_contract(&self.path)?; + + } Ok(()) } -} - +} \ No newline at end of file diff --git a/src/engines/contract_engine.rs b/src/engines/contract_engine.rs index f01010fe7..309a6ed06 100644 --- a/src/engines/contract_engine.rs +++ b/src/engines/contract_engine.rs @@ -42,14 +42,28 @@ pub fn build_smart_contract(path: &Option) -> anyhow::Result<()> { pub fn test_smart_contract(path: &Option) -> anyhow::Result<()> { - cmd( - "cargo", - vec![ - "test", - ], - ) - .dir(path.clone().unwrap_or("./".into())) - .run()?; + cmd( + "cargo", + vec![ + "test", + ], + ) + .dir(path.clone().unwrap_or("./".into())) + .run()?; + + Ok(()) +} + +pub fn test_e2e_smart_contract(path: &Option) -> anyhow::Result<()> { + cmd( + "cargo", + vec![ + "test", + "--features=e2e-tests" + ], + ) + .dir(path.clone().unwrap_or("./".into())) + .run()?; Ok(()) } From 58346b863470b9bc6e005459e293a41341f571d1 Mon Sep 17 00:00:00 2001 From: Bruno Galvao Date: Thu, 7 Mar 2024 18:35:03 +0700 Subject: [PATCH 02/10] docs: update README.md (#24) * Update README.md * Update README.md --------- Co-authored-by: Alex Bean --- README.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5e7179603..2e9a16b46 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,13 @@ -# POP +# POP [WIP] -Your one-stop entry into the exciting world of Blockchain development with *Polkadot* +An all-in-one tool for Polkadot development. + +## Install +You can install Pop CLI as follows: +```shell +cargo install --git https://github.com/r0gue-io/pop-cli +``` ## Getting Started @@ -99,3 +105,12 @@ Build the tool only for contracts functionality: ```sh cargo build --features contract ``` + + +For running any parachain, we recommend using [zombienet](https://github.com/paritytech/zombienet). + +## Spawn Network using Zombienet +You can spawn a local network as follows: +```shell +pop up parachain -f ./tests/zombienet.toml -p https://github.com/r0gue-io/pop-node +``` From 301d9c5d5575a96131c3f4f0803235195747cb09 Mon Sep 17 00:00:00 2001 From: Alex Bean Date: Thu, 7 Mar 2024 12:53:19 +0100 Subject: [PATCH 03/10] feat: pop up contract (#27) * feat: command up contract * chore: install contract-extrinsics * feat: instantiate and upload smart contract * docs: added documentation on how to deploy the smart contract * chore: display messages for pop up contract * docs: improve docs * refactor: pr feedback and docs --- Cargo.lock | 2081 ++++++++++++++++++++++++++++++-- Cargo.toml | 16 +- README.md | 22 + src/commands/build/contract.rs | 2 +- src/commands/new/contract.rs | 2 +- src/commands/new/pallet.rs | 2 +- src/commands/test/contract.rs | 2 +- src/commands/up/contract.rs | 133 ++ src/commands/up/mod.rs | 6 + src/engines/contract_engine.rs | 55 +- src/helpers.rs | 2 + src/main.rs | 10 +- src/signer.rs | 19 + 13 files changed, 2234 insertions(+), 118 deletions(-) create mode 100644 src/commands/up/contract.rs create mode 100644 src/signer.rs diff --git a/Cargo.lock b/Cargo.lock index 1245ed39d..092e12049 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -212,6 +212,135 @@ version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +[[package]] +name = "ark-bls12-377" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb00293ba84f51ce3bd026bd0de55899c4e68f0a39a5728cebae3a73ffdc0a4f" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-bls12-381" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools 0.10.5", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.4.0", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + [[package]] name = "array-bytes" version = "6.2.2" @@ -366,6 +495,17 @@ dependencies = [ "futures-lite 1.13.0", ] +[[package]] +name = "async-fs" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc19683171f287921f2405677dd2ed2549c3b3bda697a563ebc3a121ace2aba1" +dependencies = [ + "async-lock 3.3.0", + "blocking", + "futures-lite 2.2.0", +] + [[package]] name = "async-io" version = "1.13.0" @@ -436,6 +576,17 @@ dependencies = [ "futures-lite 1.13.0", ] +[[package]] +name = "async-net" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" +dependencies = [ + "async-io 2.3.1", + "blocking", + "futures-lite 2.2.0", +] + [[package]] name = "async-process" version = "1.8.1" @@ -453,6 +604,24 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "async-process" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451e3cf68011bd56771c79db04a9e333095ab6349f7e47592b788e9b98720cc8" +dependencies = [ + "async-channel 2.2.0", + "async-io 2.3.1", + "async-lock 3.3.0", + "async-signal", + "blocking", + "cfg-if", + "event-listener 5.2.0", + "futures-lite 2.2.0", + "rustix 0.38.31", + "windows-sys 0.52.0", +] + [[package]] name = "async-signal" version = "0.2.5" @@ -621,6 +790,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f" dependencies = [ "bitcoin_hashes", + "rand 0.8.5", + "rand_core 0.6.4", "serde", "unicode-normalization", ] @@ -749,6 +920,70 @@ dependencies = [ "tracing", ] +[[package]] +name = "bollard" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f03db470b3c0213c47e978da93200259a1eb4dae2e5512cba9955e2b540a6fc6" +dependencies = [ + "base64 0.21.7", + "bollard-stubs", + "bytes", + "futures-core", + "futures-util", + "hex", + "http", + "hyper", + "hyperlocal", + "log", + "pin-project-lite", + "serde", + "serde_derive", + "serde_json", + "serde_repr", + "serde_urlencoded", + "thiserror", + "tokio", + "tokio-util", + "url", + "winapi", +] + +[[package]] +name = "bollard-stubs" +version = "1.43.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58071e8fd9ec1e930efd28e3a90c1251015872a2ce49f81f36421b86466932e" +dependencies = [ + "serde", + "serde_repr", + "serde_with", +] + +[[package]] +name = "borsh" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f58b559fd6448c6e2fd0adb5720cd98a2506594cafa4737ff98c396f3e82f667" +dependencies = [ + "borsh-derive", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aadb5b6ccbd078890f6d7003694e33816e6b784358f18e15e7e6d9f065a57cd" +dependencies = [ + "once_cell", + "proc-macro-crate 3.1.0", + "proc-macro2", + "quote", + "syn 2.0.52", + "syn_derive", +] + [[package]] name = "bounded-collections" version = "0.1.9" @@ -782,6 +1017,15 @@ dependencies = [ "alloc-stdlib", ] +[[package]] +name = "brownstone" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "030ea61398f34f1395ccbeb046fb68c87b631d1f34567fed0f0f11fa35d18d8d" +dependencies = [ + "arrayvec 0.7.4", +] + [[package]] name = "bs58" version = "0.4.0" @@ -815,6 +1059,28 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +[[package]] +name = "bytecheck" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "byteorder" version = "1.5.0" @@ -847,9 +1113,9 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.15.4" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" dependencies = [ "camino", "cargo-platform", @@ -883,6 +1149,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "chacha20" version = "0.9.1" @@ -1005,6 +1277,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "common-path" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101" + [[package]] name = "concurrent-queue" version = "2.4.0" @@ -1033,6 +1311,26 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const_env" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e9e4f72c6e3398ca6da372abd9affd8f89781fe728869bbf986206e9af9627e" +dependencies = [ + "const_env_impl", +] + +[[package]] +name = "const_env_impl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a4f51209740b5e1589e702b3044cdd4562cef41b6da404904192ffffb852d62" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -1045,63 +1343,137 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +[[package]] +name = "constcat" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd7e35aee659887cbfb97aaf227ac12cad1a9d7c71e55ff3376839ed4e282d08" + [[package]] name = "contract-build" -version = "3.2.0" +version = "4.0.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1c9e0b024481d35d46e1043323ec8c1dc8b57f4a08c4ee5392c2aefb75859b" +checksum = "77b539a7d2ae5b94b6ded984749f22882b38f0bc1558da0f5fdecb06fc56c75d" dependencies = [ "anyhow", "blake2", + "bollard", "cargo_metadata", "clap", "colored", "contract-metadata", + "crossterm", "duct", "heck", "hex", "impl-serde", "parity-scale-codec", "parity-wasm", + "regex", "rustc_version 0.4.0", "semver 1.0.22", "serde", "serde_json", - "strum 0.24.1", + "strum 0.26.1", "tempfile", "term_size", - "toml", + "tokio", + "tokio-stream", + "toml 0.8.10", "tracing", "url", + "uzers", "walkdir", "wasm-opt", - "which", + "which 6.0.0", "zip", ] [[package]] -name = "contract-metadata" -version = "3.2.0" +name = "contract-extrinsics" +version = "4.0.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39a88f62795e84270742796456086ddeebfa4cbd4e56f02777f792192d666725" +checksum = "2c7949acda7dedcdd865dcd8f87b20a45c0ee87743f6ca205a9619e12cf8a48a" dependencies = [ "anyhow", - "impl-serde", - "semver 1.0.22", + "blake2", + "clap", + "colored", + "contract-build", + "contract-metadata", + "contract-transcode", + "derivative", + "futures", + "hex", + "ink_env", + "ink_metadata", + "itertools 0.12.1", + "pallet-contracts-uapi", + "parity-scale-codec", + "rust_decimal", + "scale-info", "serde", "serde_json", + "sp-core 28.0.0", + "sp-runtime", + "sp-weights", + "subxt 0.34.0", + "tokio", + "tracing", "url", ] [[package]] -name = "convert_case" -version = "0.4.0" +name = "contract-metadata" +version = "4.0.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +checksum = "c7ded4f724afcfda2e39bda14c76ce502ba2e8c87bc49e77a98c20f61dba6043" +dependencies = [ + "anyhow", + "impl-serde", + "semver 1.0.22", + "serde", + "serde_json", + "url", +] [[package]] -name = "core-foundation" -version = "0.9.4" +name = "contract-transcode" +version = "4.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8bf87e763e9b67379c987c68749d55676a0e14878f38048c120165ecc3c4214" +dependencies = [ + "anyhow", + "base58", + "blake2", + "contract-metadata", + "escape8259", + "hex", + "indexmap 2.2.4", + "ink_env", + "ink_metadata", + "itertools 0.12.1", + "nom", + "nom-supreme", + "parity-scale-codec", + "primitive-types", + "scale-info", + "serde", + "serde_json", + "strsim 0.11.0", + "thiserror", + "tracing", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "core-foundation" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ @@ -1175,6 +1547,31 @@ version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +[[package]] +name = "crossterm" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" +dependencies = [ + "bitflags 2.4.2", + "crossterm_winapi", + "libc", + "mio", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + [[package]] name = "crunchy" version = "0.2.2" @@ -1216,9 +1613,9 @@ dependencies = [ [[package]] name = "crypto-mac" -version = "0.11.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e" dependencies = [ "generic-array 0.14.7", "subtle", @@ -1599,8 +1996,8 @@ dependencies = [ "dlopen2", "dlopen2_derive", "once_cell", - "rustls-native-certs", - "rustls-pemfile", + "rustls-native-certs 0.6.3", + "rustls-pemfile 1.0.4", ] [[package]] @@ -1645,9 +2042,9 @@ dependencies = [ "deno_core", "deno_native_certs", "once_cell", - "rustls", - "rustls-pemfile", - "rustls-webpki", + "rustls 0.21.10", + "rustls-pemfile 1.0.4", + "rustls-webpki 0.101.7", "serde", "webpki-roots", ] @@ -1731,6 +2128,16 @@ dependencies = [ "zeroize", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + [[package]] name = "derivative" version = "2.2.0" @@ -1742,6 +2149,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive-syn-parse" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79116f119dd1dba1abf1f3405f03b9b0e79a27a3883864bfebded8a3dc768cd" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -1829,6 +2247,33 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "docify" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cc4fd38aaa9fb98ac70794c82a00360d1e165a87fbf96a8a91f9dfc602aaee2" +dependencies = [ + "docify_macros", +] + +[[package]] +name = "docify_macros" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63fa215f3a0d40fb2a221b3aa90d8e1fbb8379785a990cb60d62ac71ebdc6460" +dependencies = [ + "common-path", + "derive-syn-parse", + "once_cell", + "proc-macro2", + "quote", + "regex", + "syn 2.0.52", + "termcolor", + "toml 0.8.10", + "walkdir", +] + [[package]] name = "downcast-rs" version = "1.2.0" @@ -2034,6 +2479,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "escape8259" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4f4911e3666fcd7826997b4745c8224295a6f3072f1418c3067b97a67557ee" +dependencies = [ + "rustversion", +] + [[package]] name = "event-listener" version = "2.5.3" @@ -2093,6 +2547,20 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "expander" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00e83c02035136f1592a47964ea60c05a50e4ed8b5892cfac197063850898d4d" +dependencies = [ + "blake2", + "fs-err", + "prettier-please", + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "fake-simd" version = "0.1.2" @@ -2253,6 +2721,15 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "fs-err" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" +dependencies = [ + "autocfg", +] + [[package]] name = "fslock" version = "0.1.8" @@ -2610,7 +3087,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" dependencies = [ - "crypto-mac 0.11.1", + "crypto-mac 0.11.0", "digest 0.9.0", ] @@ -2750,10 +3227,10 @@ dependencies = [ "http", "hyper", "log", - "rustls", - "rustls-native-certs", + "rustls 0.21.10", + "rustls-native-certs 0.6.3", "tokio", - "tokio-rustls", + "tokio-rustls 0.24.1", ] [[package]] @@ -2781,6 +3258,19 @@ dependencies = [ "tokio-native-tls", ] +[[package]] +name = "hyperlocal" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c" +dependencies = [ + "futures-util", + "hex", + "hyper", + "pin-project", + "tokio", +] + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -2866,6 +3356,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "indent_write" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cfe9645a18782869361d9c8732246be7b410ad4e919d3609ebabdac00ba12c3" + [[package]] name = "indexmap" version = "1.9.3" @@ -2885,6 +3381,7 @@ checksum = "967d6dd42f16dbf0eb8040cb9e477933562684d3918f7d253f2ff9087fb3e7a3" dependencies = [ "equivalent", "hashbrown 0.14.3", + "serde", ] [[package]] @@ -2906,6 +3403,115 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "ink_allocator" +version = "5.0.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1db87a731bd2534af4629d5bbf84b2fa659010f020f490abe996e5f76cfbcfd4" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_engine" +version = "5.0.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f2b07ba4113fa49d1d36771190a666b74cd5cff4840be572fb8194af9ca034f" +dependencies = [ + "blake2", + "derive_more", + "ink_primitives", + "pallet-contracts-uapi-next", + "parity-scale-codec", + "secp256k1 0.28.2", + "sha2 0.10.8", + "sha3", +] + +[[package]] +name = "ink_env" +version = "5.0.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abc1fd2c16521d8c585e7b0dbee65a9bbbb8d37cb78a57b57ca27a76bfc06266" +dependencies = [ + "blake2", + "cfg-if", + "const_env", + "derive_more", + "ink_allocator", + "ink_engine", + "ink_prelude", + "ink_primitives", + "ink_storage_traits", + "num-traits", + "pallet-contracts-uapi-next", + "parity-scale-codec", + "paste", + "rlibc", + "scale-decode", + "scale-encode", + "scale-info", + "schnorrkel 0.11.4", + "secp256k1 0.28.2", + "sha2 0.10.8", + "sha3", + "static_assertions", +] + +[[package]] +name = "ink_metadata" +version = "5.0.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "505fb52d8a5dccd6ca160d20aacb0f8d6f9e13f8a0f1f53bf05e8a4e083129ea" +dependencies = [ + "derive_more", + "impl-serde", + "ink_prelude", + "ink_primitives", + "linkme", + "parity-scale-codec", + "scale-info", + "schemars", + "serde", +] + +[[package]] +name = "ink_prelude" +version = "5.0.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a69a99f23d3a0a2d173f81a2c57a055d9e46acc530634c79c54548b5b9deb7b9" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_primitives" +version = "5.0.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be98091b19e2e7f6cdc128b405863fbb6c59ef8e361f3a60589ef029f69f6a8" +dependencies = [ + "derive_more", + "ink_prelude", + "parity-scale-codec", + "scale-decode", + "scale-encode", + "scale-info", + "xxhash-rust", +] + +[[package]] +name = "ink_storage_traits" +version = "5.0.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fbbf0e1933ba34732ad9ca35a3d0da48934068759e97dbb5d34762e3ab3d4" +dependencies = [ + "ink_metadata", + "ink_prelude", + "ink_primitives", + "parity-scale-codec", + "scale-info", +] + [[package]] name = "inout" version = "0.1.3" @@ -2925,6 +3531,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits", +] + [[package]] name = "io-lifetimes" version = "1.0.11" @@ -2966,6 +3581,15 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.11.0" @@ -2975,12 +3599,27 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +[[package]] +name = "joinery" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5" + [[package]] name = "js-sys" version = "0.3.68" @@ -3021,10 +3660,22 @@ version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "affdc52f7596ccb2d7645231fc6163bb314630c989b64998f3699a28b4d5d4dc" dependencies = [ - "jsonrpsee-client-transport", - "jsonrpsee-core", - "jsonrpsee-http-client", - "jsonrpsee-types", + "jsonrpsee-client-transport 0.20.3", + "jsonrpsee-core 0.20.3", + "jsonrpsee-http-client 0.20.3", + "jsonrpsee-types 0.20.3", +] + +[[package]] +name = "jsonrpsee" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9579d0ca9fb30da026bac2f0f7d9576ec93489aeb7cd4971dd5b4617d82c79b2" +dependencies = [ + "jsonrpsee-client-transport 0.21.0", + "jsonrpsee-core 0.21.0", + "jsonrpsee-http-client 0.21.0", + "jsonrpsee-types 0.21.0", ] [[package]] @@ -3035,13 +3686,34 @@ checksum = "b5b005c793122d03217da09af68ba9383363caa950b90d3436106df8cabce935" dependencies = [ "futures-util", "http", - "jsonrpsee-core", + "jsonrpsee-core 0.20.3", + "pin-project", + "rustls-native-certs 0.6.3", + "soketto", + "thiserror", + "tokio", + "tokio-rustls 0.24.1", + "tokio-util", + "tracing", + "url", +] + +[[package]] +name = "jsonrpsee-client-transport" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9f9ed46590a8d5681975f126e22531698211b926129a40a2db47cbca429220" +dependencies = [ + "futures-util", + "http", + "jsonrpsee-core 0.21.0", "pin-project", - "rustls-native-certs", + "rustls-native-certs 0.7.0", + "rustls-pki-types", "soketto", "thiserror", "tokio", - "tokio-rustls", + "tokio-rustls 0.25.0", "tokio-util", "tracing", "url", @@ -3060,7 +3732,7 @@ dependencies = [ "futures-timer", "futures-util", "hyper", - "jsonrpsee-types", + "jsonrpsee-types 0.20.3", "rustc-hash", "serde", "serde_json", @@ -3070,27 +3742,71 @@ dependencies = [ ] [[package]] -name = "jsonrpsee-http-client" -version = "0.20.3" +name = "jsonrpsee-core" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f80c17f62c7653ce767e3d7288b793dfec920f97067ceb189ebdd3570f2bc20" +checksum = "776d009e2f591b78c038e0d053a796f94575d66ca4e77dd84bfc5e81419e436c" dependencies = [ + "anyhow", + "async-lock 3.3.0", "async-trait", + "beef", + "futures-timer", + "futures-util", "hyper", - "hyper-rustls", - "jsonrpsee-core", - "jsonrpsee-types", + "jsonrpsee-types 0.21.0", + "pin-project", + "rustc-hash", "serde", "serde_json", "thiserror", "tokio", - "tower", + "tokio-stream", "tracing", - "url", ] [[package]] -name = "jsonrpsee-types" +name = "jsonrpsee-http-client" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f80c17f62c7653ce767e3d7288b793dfec920f97067ceb189ebdd3570f2bc20" +dependencies = [ + "async-trait", + "hyper", + "hyper-rustls", + "jsonrpsee-core 0.20.3", + "jsonrpsee-types 0.20.3", + "serde", + "serde_json", + "thiserror", + "tokio", + "tower", + "tracing", + "url", +] + +[[package]] +name = "jsonrpsee-http-client" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b7de9f3219d95985eb77fd03194d7c1b56c19bce1abfcc9d07462574b15572" +dependencies = [ + "async-trait", + "hyper", + "hyper-rustls", + "jsonrpsee-core 0.21.0", + "jsonrpsee-types 0.21.0", + "serde", + "serde_json", + "thiserror", + "tokio", + "tower", + "tracing", + "url", +] + +[[package]] +name = "jsonrpsee-types" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5be0be325642e850ed0bdff426674d2e66b2b7117c9be23a7caef68a2902b7d9" @@ -3103,6 +3819,19 @@ dependencies = [ "tracing", ] +[[package]] +name = "jsonrpsee-types" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3266dfb045c9174b24c77c2dfe0084914bb23a6b2597d70c9dc6018392e1cd1b" +dependencies = [ + "anyhow", + "beef", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "k8s-openapi" version = "0.20.0" @@ -3161,8 +3890,8 @@ dependencies = [ "pem", "pin-project", "rand 0.8.5", - "rustls", - "rustls-pemfile", + "rustls 0.21.10", + "rustls-pemfile 1.0.4", "secrecy", "serde", "serde_json", @@ -3478,6 +4207,26 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" +[[package]] +name = "linkme" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca16377a6dae364fb00769699ba440899f1a720d4f5abf2667d0a8a95f933dd" +dependencies = [ + "linkme-impl", +] + +[[package]] +name = "linkme-impl" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e5ac81de04bf8215501c50a436632c3789b22ef1625fe0bf8927dd4ba3696c5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "linux-raw-sys" version = "0.1.4" @@ -3584,6 +4333,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memory-db" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808b50db46293432a45e63bc15ea51e0ab4c0a1647b8eb114e31a3e698dd6fbe" +dependencies = [ + "hash-db", +] + [[package]] name = "merlin" version = "2.0.1" @@ -3646,6 +4404,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", + "log", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.48.0", ] @@ -3751,6 +4510,12 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + [[package]] name = "nom" version = "7.1.3" @@ -3761,6 +4526,19 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nom-supreme" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f909b25a8371ad5c054abc2c48205d677231e6a2dcbf83704ed57bb147f30e0" +dependencies = [ + "brownstone", + "indent_write", + "joinery", + "memchr", + "nom", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -3801,6 +4579,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-format" version = "0.4.4" @@ -4013,6 +4797,30 @@ dependencies = [ "sha2 0.10.8", ] +[[package]] +name = "pallet-contracts-uapi" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a992d0815b9dc36acbe0800b05b4f875398bb9d9b1aa15c8b1afdcb87f66df2a" +dependencies = [ + "bitflags 1.3.2", + "parity-scale-codec", + "paste", + "polkavm-derive 0.4.0", + "scale-info", +] + +[[package]] +name = "pallet-contracts-uapi-next" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e941fe56abf3b3d127c80d0a82989323f240ad81e6222421a56f1a3142db1e16" +dependencies = [ + "bitflags 1.3.2", + "paste", + "polkavm-derive 0.5.0", +] + [[package]] name = "parity-scale-codec" version = "3.6.9" @@ -4093,7 +4901,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" dependencies = [ - "crypto-mac 0.11.1", + "crypto-mac 0.11.0", ] [[package]] @@ -4333,6 +5141,62 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "polkavm-common" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fecd2caacfc4a7ee34243758dd7348859e6dec73f5e5df059890f5742ee46f0e" + +[[package]] +name = "polkavm-common" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b4e215c80fe876147f3d58158d5dfeae7dabdd6047e175af77095b78d0035c" + +[[package]] +name = "polkavm-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db65a500d4adf574893c726ae365e37e4fbb7f2cbd403f6eaa1b665457456adc" +dependencies = [ + "polkavm-derive-impl 0.4.0", + "syn 2.0.52", +] + +[[package]] +name = "polkavm-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6380dbe1fb03ecc74ad55d841cfc75480222d153ba69ddcb00977866cbdabdb8" +dependencies = [ + "polkavm-derive-impl 0.5.0", + "syn 2.0.52", +] + +[[package]] +name = "polkavm-derive-impl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c99f4e7a9ff434ef9c885b874c99d824c3a5693bf5e3e8569bb1d2245a8c1b7f" +dependencies = [ + "polkavm-common 0.4.0", + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "polkavm-derive-impl" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc8211b3365bbafb2fb32057d68b0e1ca55d079f5cf6f9da9b98079b94b3987d" +dependencies = [ + "polkavm-common 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "polling" version = "2.8.0" @@ -4396,16 +5260,22 @@ dependencies = [ "cliclack", "console", "contract-build", + "contract-extrinsics", "dirs", "duct", "git2", "indexmap 2.2.4", + "ink_env", "log", "reqwest", "serde", "serde_json", + "sp-core 28.0.0", + "sp-weights", "strum 0.26.1", "strum_macros 0.26.1", + "subxt 0.34.0", + "subxt-signer 0.34.0", "symlink", "tempdir", "tempfile", @@ -4424,12 +5294,28 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "prettier-please" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22020dfcf177fcc7bf5deaf7440af371400c67c0de14c399938d8ed4fb4645d3" +dependencies = [ + "proc-macro2", + "syn 2.0.52", +] + [[package]] name = "primeorder" version = "0.13.6" @@ -4471,6 +5357,15 @@ dependencies = [ "toml_edit 0.20.2", ] +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit 0.21.1", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -4536,6 +5431,26 @@ dependencies = [ "cc", ] +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -4767,6 +5682,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "rend" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" +dependencies = [ + "bytecheck", +] + [[package]] name = "reqwest" version = "0.11.24" @@ -4793,8 +5717,8 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls", - "rustls-pemfile", + "rustls 0.21.10", + "rustls-pemfile 1.0.4", "serde", "serde_json", "serde_urlencoded", @@ -4802,7 +5726,7 @@ dependencies = [ "system-configuration", "tokio", "tokio-native-tls", - "tokio-rustls", + "tokio-rustls 0.24.1", "tokio-socks", "tokio-util", "tower-service", @@ -4850,6 +5774,41 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rkyv" +version = "0.7.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0" +dependencies = [ + "bitvec", + "bytecheck", + "bytes", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rlibc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc874b127765f014d792f16763a81245ab80500e2ad921ed4ee9e82481ee08fe" + [[package]] name = "rsa" version = "0.9.6" @@ -4870,6 +5829,22 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rust_decimal" +version = "1.34.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39449a79f45e8da28c57c341891b69a183044b29518bb8f86dbac9df60bb7df" +dependencies = [ + "arrayvec 0.7.4", + "borsh", + "bytes", + "num-traits", + "rand 0.8.5", + "rkyv", + "serde", + "serde_json", +] + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -4955,10 +5930,24 @@ checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", "ring", - "rustls-webpki", + "rustls-webpki 0.101.7", "sct", ] +[[package]] +name = "rustls" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" +dependencies = [ + "log", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.2", + "subtle", + "zeroize", +] + [[package]] name = "rustls-native-certs" version = "0.6.3" @@ -4966,7 +5955,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ "openssl-probe", - "rustls-pemfile", + "rustls-pemfile 1.0.4", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" +dependencies = [ + "openssl-probe", + "rustls-pemfile 2.1.1", + "rustls-pki-types", "schannel", "security-framework", ] @@ -4980,6 +5982,22 @@ dependencies = [ "base64 0.21.7", ] +[[package]] +name = "rustls-pemfile" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f48172685e6ff52a556baa527774f61fcaa884f59daf3375c62a3f1cd2549dab" +dependencies = [ + "base64 0.21.7", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ede67b28608b4c60685c7d54122d4400d90f62b40caee7700e700380a390fa8" + [[package]] name = "rustls-tokio-stream" version = "0.2.9" @@ -4987,7 +6005,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55cae64d5219dfdd7f2d18dda421a2137ebdd63be6d0dc53d7836003f224f3d0" dependencies = [ "futures", - "rustls", + "rustls 0.21.10", "tokio", ] @@ -5001,6 +6019,17 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustls-webpki" +version = "0.102.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -5128,6 +6157,7 @@ dependencies = [ "derive_more", "parity-scale-codec", "scale-info-derive", + "schemars", "serde", ] @@ -5144,7 +6174,20 @@ dependencies = [ ] [[package]] -name = "scale-value" +name = "scale-typegen" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00860983481ac590ac87972062909bef0d6a658013b592ccc0f2feb272feab11" +dependencies = [ + "proc-macro2", + "quote", + "scale-info", + "syn 2.0.52", + "thiserror", +] + +[[package]] +name = "scale-value" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58223c7691bf0bd46b43c9aea6f0472d1067f378d574180232358d7c6e0a8089" @@ -5172,6 +6215,41 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "schemars" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 1.0.109", +] + +[[package]] +name = "schnellru" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "772575a524feeb803e5b0fcbc6dd9f367e579488197c94c6e4023aad2305774d" +dependencies = [ + "ahash 0.8.10", + "cfg-if", + "hashbrown 0.13.2", +] + [[package]] name = "schnorrkel" version = "0.9.1" @@ -5237,6 +6315,12 @@ dependencies = [ "untrusted", ] +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + [[package]] name = "sec1" version = "0.7.3" @@ -5383,6 +6467,17 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "serde_json" version = "1.0.114" @@ -5395,6 +6490,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "serde_spanned" version = "0.6.5" @@ -5431,6 +6537,23 @@ dependencies = [ "v8", ] +[[package]] +name = "serde_with" +version = "3.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15d167997bd841ec232f5b2b8e0e26606df2e7caa4c31b95ea9ca52b200bd270" +dependencies = [ + "base64 0.21.7", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.2.4", + "serde", + "serde_derive", + "serde_json", + "time", +] + [[package]] name = "serde_yaml" version = "0.9.32" @@ -5544,6 +6667,27 @@ dependencies = [ "winapi", ] +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -5569,6 +6713,12 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" +[[package]] +name = "simple-mermaid" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "620a1d43d70e142b1d46a929af51d44f383db9c7a2ec122de2cd992ccfcf3c18" + [[package]] name = "siphasher" version = "0.3.11" @@ -5621,15 +6771,32 @@ checksum = "13f2b548cd8447f8de0fdf1c592929f70f4fc7039a05e47404b0d096ec6987a1" dependencies = [ "async-channel 1.9.0", "async-executor", - "async-fs", + "async-fs 1.6.0", "async-io 1.13.0", "async-lock 2.8.0", - "async-net", - "async-process", + "async-net 1.8.0", + "async-process 1.8.1", "blocking", "futures-lite 1.13.0", ] +[[package]] +name = "smol" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e635339259e51ef85ac7aa29a1cd991b957047507288697a690e80ab97d07cad" +dependencies = [ + "async-channel 2.2.0", + "async-executor", + "async-fs 2.1.1", + "async-io 2.3.1", + "async-lock 3.3.0", + "async-net 2.0.0", + "async-process 2.1.0", + "blocking", + "futures-lite 2.2.0", +] + [[package]] name = "smoldot" version = "0.14.0" @@ -5655,7 +6822,62 @@ dependencies = [ "hashbrown 0.14.3", "hex", "hmac 0.12.1", - "itertools", + "itertools 0.11.0", + "libm", + "libsecp256k1", + "merlin 3.0.0", + "no-std-net", + "nom", + "num-bigint", + "num-rational", + "num-traits", + "pbkdf2 0.12.2", + "pin-project", + "poly1305", + "rand 0.8.5", + "rand_chacha 0.3.1", + "ruzstd", + "schnorrkel 0.11.4", + "serde", + "serde_json", + "sha2 0.10.8", + "sha3", + "siphasher 1.0.0", + "slab", + "smallvec", + "soketto", + "twox-hash", + "wasmi", + "x25519-dalek", + "zeroize", +] + +[[package]] +name = "smoldot" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d1eaa97d77be4d026a1e7ffad1bb3b78448763b357ea6f8188d3e6f736a9b9" +dependencies = [ + "arrayvec 0.7.4", + "async-lock 3.3.0", + "atomic-take", + "base64 0.21.7", + "bip39", + "blake2-rfc", + "bs58 0.5.0", + "chacha20", + "crossbeam-queue", + "derive_more", + "ed25519-zebra 4.0.3", + "either", + "event-listener 4.0.3", + "fnv", + "futures-lite 2.2.0", + "futures-util", + "hashbrown 0.14.3", + "hex", + "hmac 0.12.1", + "itertools 0.12.1", "libm", "libsecp256k1", "merlin 3.0.0", @@ -5704,7 +6926,7 @@ dependencies = [ "futures-util", "hashbrown 0.14.3", "hex", - "itertools", + "itertools 0.11.0", "log", "lru", "no-std-net", @@ -5716,8 +6938,44 @@ dependencies = [ "serde_json", "siphasher 1.0.0", "slab", - "smol", - "smoldot", + "smol 1.3.0", + "smoldot 0.14.0", + "zeroize", +] + +[[package]] +name = "smoldot-light" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5496f2d116b7019a526b1039ec2247dd172b8670633b1a64a614c9ea12c9d8c7" +dependencies = [ + "async-channel 2.2.0", + "async-lock 3.3.0", + "base64 0.21.7", + "blake2-rfc", + "derive_more", + "either", + "event-listener 4.0.3", + "fnv", + "futures-channel", + "futures-lite 2.2.0", + "futures-util", + "hashbrown 0.14.3", + "hex", + "itertools 0.12.1", + "log", + "lru", + "no-std-net", + "parking_lot", + "pin-project", + "rand 0.8.5", + "rand_chacha 0.3.1", + "serde", + "serde_json", + "siphasher 1.0.0", + "slab", + "smol 2.0.0", + "smoldot 0.16.0", "zeroize", ] @@ -5788,6 +7046,35 @@ dependencies = [ "url", ] +[[package]] +name = "sp-application-crypto" +version = "30.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e4fe7a9b7fa9da76272b201e2fb3c7900d97d32a46b66af9a04dad457f73c71" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "sp-core 28.0.0", + "sp-io", + "sp-std 14.0.0", +] + +[[package]] +name = "sp-arithmetic" +version = "23.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f42721f072b421f292a072e8f52a3b3c0fbc27428f0c9fe24067bc47046bad63" +dependencies = [ + "integer-sqrt", + "num-traits", + "parity-scale-codec", + "scale-info", + "serde", + "sp-std 14.0.0", + "static_assertions", +] + [[package]] name = "sp-core" version = "22.0.0" @@ -5821,11 +7108,11 @@ dependencies = [ "secrecy", "serde", "sp-core-hashing 10.0.0", - "sp-debug-derive", - "sp-externalities", - "sp-runtime-interface", - "sp-std", - "sp-storage", + "sp-debug-derive 9.0.0", + "sp-externalities 0.20.0", + "sp-runtime-interface 18.0.0", + "sp-std 9.0.0", + "sp-storage 14.0.0", "ss58-registry", "substrate-bip39", "thiserror", @@ -5834,6 +7121,52 @@ dependencies = [ "zeroize", ] +[[package]] +name = "sp-core" +version = "28.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f230cb12575455070da0fc174815958423a0b9a641d5e304a9457113c7cb4007" +dependencies = [ + "array-bytes", + "bip39", + "bitflags 1.3.2", + "blake2", + "bounded-collections", + "bs58 0.5.0", + "dyn-clonable", + "ed25519-zebra 3.1.0", + "futures", + "hash-db", + "hash256-std-hasher", + "impl-serde", + "itertools 0.10.5", + "libsecp256k1", + "log", + "merlin 3.0.0", + "parity-scale-codec", + "parking_lot", + "paste", + "primitive-types", + "rand 0.8.5", + "scale-info", + "schnorrkel 0.11.4", + "secp256k1 0.28.2", + "secrecy", + "serde", + "sp-core-hashing 15.0.0", + "sp-debug-derive 14.0.0", + "sp-externalities 0.25.0", + "sp-runtime-interface 24.0.0", + "sp-std 14.0.0", + "sp-storage 19.0.0", + "ss58-registry", + "substrate-bip39", + "thiserror", + "tracing", + "w3f-bls", + "zeroize", +] + [[package]] name = "sp-core-hashing" version = "10.0.0" @@ -5862,6 +7195,20 @@ dependencies = [ "twox-hash", ] +[[package]] +name = "sp-core-hashing" +version = "15.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0f4990add7b2cefdeca883c0efa99bb4d912cb2196120e1500c0cc099553b0" +dependencies = [ + "blake2b_simd", + "byteorder", + "digest 0.10.7", + "sha2 0.10.8", + "sha3", + "twox-hash", +] + [[package]] name = "sp-debug-derive" version = "9.0.0" @@ -5873,6 +7220,17 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "sp-debug-derive" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d09fa0a5f7299fb81ee25ae3853d26200f7a348148aed6de76be905c007dbe" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "sp-externalities" version = "0.20.0" @@ -5881,8 +7239,94 @@ checksum = "3313e2c5f2523b06062e541dff9961bde88ad5a28861621dc7b7b47a32bb0f7c" dependencies = [ "environmental", "parity-scale-codec", - "sp-std", - "sp-storage", + "sp-std 9.0.0", + "sp-storage 14.0.0", +] + +[[package]] +name = "sp-externalities" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63867ec85950ced90d4ab1bba902a47db1b1efdf2829f653945669b2bb470a9c" +dependencies = [ + "environmental", + "parity-scale-codec", + "sp-std 14.0.0", + "sp-storage 19.0.0", +] + +[[package]] +name = "sp-io" +version = "30.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c55f26d89feedaf0faf81688b6e1e1e81329cd8b4c6a4fd6c5b97ed9dd068b8a" +dependencies = [ + "bytes", + "ed25519-dalek", + "libsecp256k1", + "log", + "parity-scale-codec", + "rustversion", + "secp256k1 0.28.2", + "sp-core 28.0.0", + "sp-externalities 0.25.0", + "sp-keystore", + "sp-runtime-interface 24.0.0", + "sp-state-machine", + "sp-std 14.0.0", + "sp-tracing 16.0.0", + "sp-trie", + "tracing", + "tracing-core", +] + +[[package]] +name = "sp-keystore" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96806a28a62ed9ddecd0b28857b1344d029390f7c5c42a2ff9199cbf5638635c" +dependencies = [ + "parity-scale-codec", + "parking_lot", + "sp-core 28.0.0", + "sp-externalities 0.25.0", + "thiserror", +] + +[[package]] +name = "sp-panic-handler" +version = "13.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8f5a17a0a11de029a8b811cb6e8b32ce7e02183cc04a3e965c383246798c416" +dependencies = [ + "backtrace", + "lazy_static", + "regex", +] + +[[package]] +name = "sp-runtime" +version = "31.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3bb49a4475d390198dfd3d41bef4564ab569fbaf1b5e38ae69b35fc01199d91" +dependencies = [ + "docify", + "either", + "hash256-std-hasher", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "paste", + "rand 0.8.5", + "scale-info", + "serde", + "simple-mermaid", + "sp-application-crypto", + "sp-arithmetic", + "sp-core 28.0.0", + "sp-io", + "sp-std 14.0.0", + "sp-weights", ] [[package]] @@ -5895,12 +7339,31 @@ dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", "primitive-types", - "sp-externalities", - "sp-runtime-interface-proc-macro", - "sp-std", - "sp-storage", - "sp-tracing", - "sp-wasm-interface", + "sp-externalities 0.20.0", + "sp-runtime-interface-proc-macro 12.0.0", + "sp-std 9.0.0", + "sp-storage 14.0.0", + "sp-tracing 11.0.0", + "sp-wasm-interface 15.0.0", + "static_assertions", +] + +[[package]] +name = "sp-runtime-interface" +version = "24.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f66b66d8cec3d785fa6289336c1d9cbd4305d5d84f7134378c4d79ed7983e6fb" +dependencies = [ + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec", + "primitive-types", + "sp-externalities 0.25.0", + "sp-runtime-interface-proc-macro 17.0.0", + "sp-std 14.0.0", + "sp-storage 19.0.0", + "sp-tracing 16.0.0", + "sp-wasm-interface 20.0.0", "static_assertions", ] @@ -5917,12 +7380,54 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "sp-runtime-interface-proc-macro" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfaf6e85b2ec12a4b99cd6d8d57d083e30c94b7f1b0d8f93547121495aae6f0c" +dependencies = [ + "Inflector", + "expander", + "proc-macro-crate 3.1.0", + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "sp-state-machine" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "718c779ad1d6fcc0be64c7ce030b33fa44b5c8914b3a1319ef63bb5f27fb98df" +dependencies = [ + "hash-db", + "log", + "parity-scale-codec", + "parking_lot", + "rand 0.8.5", + "smallvec", + "sp-core 28.0.0", + "sp-externalities 0.25.0", + "sp-panic-handler", + "sp-std 14.0.0", + "sp-trie", + "thiserror", + "tracing", + "trie-db", +] + [[package]] name = "sp-std" version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d5bbc9339227d1b6a9b7ccd9b2920c818653d40eef1512f1e2e824d72e7a336" +[[package]] +name = "sp-std" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f8ee986414b0a9ad741776762f4083cd3a5128449b982a3919c4df36874834" + [[package]] name = "sp-storage" version = "14.0.0" @@ -5933,23 +7438,75 @@ dependencies = [ "parity-scale-codec", "ref-cast", "serde", - "sp-debug-derive", - "sp-std", + "sp-debug-derive 9.0.0", + "sp-std 9.0.0", +] + +[[package]] +name = "sp-storage" +version = "19.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fb92d7b24033a8a856d6e20dd980b653cbd7af7ec471cc988b1b7c1d2e3a32b" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "ref-cast", + "serde", + "sp-debug-derive 14.0.0", + "sp-std 14.0.0", +] + +[[package]] +name = "sp-tracing" +version = "11.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f5ba26db1f7513d5975970d1ba1f0580d7a1b8da8c86ea3f9f0f8dbe2cfa96e" +dependencies = [ + "parity-scale-codec", + "sp-std 9.0.0", + "tracing", + "tracing-core", + "tracing-subscriber 0.2.25", ] [[package]] name = "sp-tracing" -version = "11.0.0" +version = "16.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5ba26db1f7513d5975970d1ba1f0580d7a1b8da8c86ea3f9f0f8dbe2cfa96e" +checksum = "0351810b9d074df71c4514c5228ed05c250607cba131c1c9d1526760ab69c05c" dependencies = [ "parity-scale-codec", - "sp-std", + "sp-std 14.0.0", "tracing", "tracing-core", "tracing-subscriber 0.2.25", ] +[[package]] +name = "sp-trie" +version = "29.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e4d24d84a0beb44a71dcac1b41980e1edf7fb722c7f3046710136a283cd479b" +dependencies = [ + "ahash 0.8.10", + "hash-db", + "lazy_static", + "memory-db", + "nohash-hasher", + "parity-scale-codec", + "parking_lot", + "rand 0.8.5", + "scale-info", + "schnellru", + "sp-core 28.0.0", + "sp-externalities 0.25.0", + "sp-std 14.0.0", + "thiserror", + "tracing", + "trie-db", + "trie-root", +] + [[package]] name = "sp-wasm-interface" version = "15.0.0" @@ -5960,10 +7517,40 @@ dependencies = [ "impl-trait-for-tuples", "log", "parity-scale-codec", - "sp-std", + "sp-std 9.0.0", + "wasmtime", +] + +[[package]] +name = "sp-wasm-interface" +version = "20.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ef97172c42eb4c6c26506f325f48463e9bc29b2034a587f1b9e48c751229bee" +dependencies = [ + "anyhow", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "sp-std 14.0.0", "wasmtime", ] +[[package]] +name = "sp-weights" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e874bdf9dd3fd3242f5b7867a4eaedd545b02f29041a46d222a9d9d5caaaa5c" +dependencies = [ + "bounded-collections", + "parity-scale-codec", + "scale-info", + "serde", + "smallvec", + "sp-arithmetic", + "sp-debug-derive 14.0.0", + "sp-std 14.0.0", +] + [[package]] name = "spin" version = "0.5.2" @@ -6056,9 +7643,6 @@ name = "strum" version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" -dependencies = [ - "strum_macros 0.24.3", -] [[package]] name = "strum" @@ -6074,6 +7658,9 @@ name = "strum" version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "723b93e8addf9aa965ebe2d11da6d7540fa2283fcea14b3371ff055f7ba13f5f" +dependencies = [ + "strum_macros 0.26.1", +] [[package]] name = "strum_macros" @@ -6129,9 +7716,9 @@ dependencies = [ [[package]] name = "subtle" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "subxt" @@ -6148,7 +7735,7 @@ dependencies = [ "futures", "hex", "impl-serde", - "jsonrpsee", + "jsonrpsee 0.20.3", "parity-scale-codec", "primitive-types", "scale-bits", @@ -6159,11 +7746,47 @@ dependencies = [ "serde", "serde_json", "sp-core-hashing 13.0.0", - "subxt-lightclient", - "subxt-macro", - "subxt-metadata", + "subxt-lightclient 0.33.0", + "subxt-macro 0.33.0", + "subxt-metadata 0.33.0", + "thiserror", + "tracing", +] + +[[package]] +name = "subxt" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3323d5c27898b139d043dc1ee971f602f937b99354ee33ee933bd90e0009fbd" +dependencies = [ + "async-trait", + "base58", + "blake2", + "derivative", + "either", + "frame-metadata 16.0.0", + "futures", + "hex", + "impl-serde", + "instant", + "jsonrpsee 0.21.0", + "parity-scale-codec", + "primitive-types", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-info", + "scale-value", + "serde", + "serde_json", + "sp-core-hashing 15.0.0", + "subxt-lightclient 0.34.0", + "subxt-macro 0.34.0", + "subxt-metadata 0.34.0", "thiserror", + "tokio-util", "tracing", + "url", ] [[package]] @@ -6175,12 +7798,33 @@ dependencies = [ "frame-metadata 16.0.0", "heck", "hex", - "jsonrpsee", + "jsonrpsee 0.20.3", + "parity-scale-codec", + "proc-macro2", + "quote", + "scale-info", + "subxt-metadata 0.33.0", + "syn 2.0.52", + "thiserror", + "tokio", +] + +[[package]] +name = "subxt-codegen" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d0e58c3f88651cff26aa52bae0a0a85f806a2e923a20eb438c16474990743ea" +dependencies = [ + "frame-metadata 16.0.0", + "heck", + "hex", + "jsonrpsee 0.21.0", "parity-scale-codec", "proc-macro2", "quote", "scale-info", - "subxt-metadata", + "scale-typegen", + "subxt-metadata 0.34.0", "syn 2.0.52", "thiserror", "tokio", @@ -6196,7 +7840,24 @@ dependencies = [ "futures-util", "serde", "serde_json", - "smoldot-light", + "smoldot-light 0.12.0", + "thiserror", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "subxt-lightclient" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecec7066ba7bc0c3608fcd1d0c7d9584390990cd06095b6ae4f114f74c4b8550" +dependencies = [ + "futures", + "futures-util", + "serde", + "serde_json", + "smoldot-light 0.14.0", "thiserror", "tokio", "tokio-stream", @@ -6212,7 +7873,22 @@ dependencies = [ "darling 0.20.8", "parity-scale-codec", "proc-macro-error", - "subxt-codegen", + "subxt-codegen 0.33.0", + "syn 2.0.52", +] + +[[package]] +name = "subxt-macro" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "365251668613323064803427af8c7c7bc366cd8b28e33639640757669dafebd5" +dependencies = [ + "darling 0.20.8", + "parity-scale-codec", + "proc-macro-error", + "quote", + "scale-typegen", + "subxt-codegen 0.34.0", "syn 2.0.52", ] @@ -6229,6 +7905,19 @@ dependencies = [ "thiserror", ] +[[package]] +name = "subxt-metadata" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c02aca8d39a1f6c55fff3a8fd81557d30a610fedc1cef03f889a81bc0f8f0b52" +dependencies = [ + "frame-metadata 16.0.0", + "parity-scale-codec", + "scale-info", + "sp-core-hashing 15.0.0", + "thiserror", +] + [[package]] name = "subxt-signer" version = "0.33.0" @@ -6246,7 +7935,29 @@ dependencies = [ "secrecy", "sha2 0.10.8", "sp-core-hashing 13.0.0", - "subxt", + "subxt 0.33.0", + "thiserror", + "zeroize", +] + +[[package]] +name = "subxt-signer" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f88a76a5d114bfae2f6f9cc1491c46173ecc3fb2b9e53948eb3c8d43d4b43ab5" +dependencies = [ + "bip39", + "hex", + "hmac 0.12.1", + "parity-scale-codec", + "pbkdf2 0.12.2", + "regex", + "schnorrkel 0.11.4", + "secp256k1 0.28.2", + "secrecy", + "sha2 0.10.8", + "sp-core-hashing 15.0.0", + "subxt 0.34.0", "thiserror", "zeroize", ] @@ -6618,6 +8329,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "sync_wrapper" version = "0.1.2" @@ -6759,6 +8482,37 @@ dependencies = [ "once_cell", ] +[[package]] +name = "time" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tiny-bip39" version = "1.0.0" @@ -6849,7 +8603,18 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls", + "rustls 0.21.10", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +dependencies = [ + "rustls 0.22.2", + "rustls-pki-types", "tokio", ] @@ -6916,6 +8681,18 @@ dependencies = [ "toml_edit 0.19.15", ] +[[package]] +name = "toml" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.6", +] + [[package]] name = "toml_datetime" version = "0.6.5" @@ -6949,6 +8726,17 @@ dependencies = [ "winnow 0.5.40", ] +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap 2.2.4", + "toml_datetime", + "winnow 0.5.40", +] + [[package]] name = "toml_edit" version = "0.22.6" @@ -6956,6 +8744,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6" dependencies = [ "indexmap 2.2.4", + "serde", + "serde_spanned", "toml_datetime", "winnow 0.6.4", ] @@ -7120,6 +8910,28 @@ dependencies = [ "serde_json", ] +[[package]] +name = "trie-db" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff28e0f815c2fea41ebddf148e008b077d2faddb026c9555b29696114d602642" +dependencies = [ + "hash-db", + "hashbrown 0.13.2", + "log", + "rustc-hex", + "smallvec", +] + +[[package]] +name = "trie-root" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ed310ef5ab98f5fa467900ed906cb9232dd5376597e00fd4cba2a449d06c0b" +dependencies = [ + "hash-db", +] + [[package]] name = "trust-dns-proto" version = "0.22.0" @@ -7404,6 +9216,16 @@ dependencies = [ "serde", ] +[[package]] +name = "uzers" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d283dc7e8c901e79e32d077866eaf599156cbf427fffa8289aecc52c5c3f63" +dependencies = [ + "libc", + "log", +] + [[package]] name = "v8" version = "0.81.0" @@ -7413,7 +9235,7 @@ dependencies = [ "bitflags 1.3.2", "fslock", "once_cell", - "which", + "which 4.4.2", ] [[package]] @@ -7446,6 +9268,30 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" +[[package]] +name = "w3f-bls" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7335e4c132c28cc43caef6adb339789e599e39adbe78da0c4d547fad48cbc331" +dependencies = [ + "ark-bls12-377", + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-serialize-derive", + "arrayref", + "constcat", + "digest 0.10.7", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_core 0.6.4", + "sha2 0.10.8", + "sha3", + "thiserror", + "zeroize", +] + [[package]] name = "waker-fn" version = "1.1.1" @@ -7551,9 +9397,9 @@ checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" [[package]] name = "wasm-opt" -version = "0.113.0" +version = "0.116.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65a2799e08026234b07b44da6363703974e75be21430cef00756bbc438c8ff8a" +checksum = "fc942673e7684671f0c5708fc18993569d184265fd5223bb51fc8e5b9b6cfd52" dependencies = [ "anyhow", "libc", @@ -7567,9 +9413,9 @@ dependencies = [ [[package]] name = "wasm-opt-cxx-sys" -version = "0.113.0" +version = "0.116.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8d26f86d1132245e8bcea8fac7f02b10fb885b6696799969c94d7d3c14db5e1" +checksum = "8c57b28207aa724318fcec6575fe74803c23f6f266fce10cbc9f3f116762f12e" dependencies = [ "anyhow", "cxx", @@ -7579,9 +9425,9 @@ dependencies = [ [[package]] name = "wasm-opt-sys" -version = "0.113.0" +version = "0.116.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497d069cd3420cdd52154a320b901114a20946878e2de62c670f9d906e472370" +checksum = "8a1cce564dc768dacbdb718fc29df2dba80bd21cb47d8f77ae7e3d95ceb98cbe" dependencies = [ "anyhow", "cc", @@ -7812,6 +9658,19 @@ dependencies = [ "rustix 0.38.31", ] +[[package]] +name = "which" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fa5e0c10bf77f44aac573e498d1a82d5fbd5e91f6fc0a99e7be4b38e85e101c" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.31", + "windows-sys 0.52.0", +] + [[package]] name = "widestring" version = "1.0.2" @@ -8116,6 +9975,12 @@ dependencies = [ "rustix 0.38.31", ] +[[package]] +name = "xxhash-rust" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927da81e25be1e1a2901d59b81b37dd2efd1fc9c9345a55007f09bf5a2d3ee03" + [[package]] name = "yap" version = "0.11.0" @@ -8185,7 +10050,7 @@ dependencies = [ "serde", "serde_json", "thiserror", - "toml", + "toml 0.7.8", "url", ] @@ -8204,9 +10069,9 @@ dependencies = [ "reqwest", "serde_json", "sha2 0.10.8", - "sp-core", - "subxt", - "subxt-signer", + "sp-core 22.0.0", + "subxt 0.33.0", + "subxt-signer 0.33.0", "thiserror", "tokio", "tracing", @@ -8262,7 +10127,7 @@ source = "git+https://github.com/paritytech/zombienet-sdk#f78a5e95327f2fde514800 dependencies = [ "async-trait", "futures", - "subxt", + "subxt 0.33.0", "tokio", "zombienet-configuration", "zombienet-orchestrator", diff --git a/Cargo.toml b/Cargo.toml index ff75d5697..f45dfc930 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,13 @@ tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } walkdir = "2.4" # contracts -contract-build = { version = "3.2.0", optional = true } +contract-build = { version = "4.0.0-rc.3", optional = true } +contract-extrinsics = { version = "4.0.0-rc.3", optional = true } +sp-core = { version = "28.0.0", optional = true } +subxt-signer = { version = "0.34.0", features = ["subxt", "sr25519"], optional = true } +subxt = { version = "0.34.0", optional = true } +ink_env = { version = "5.0.0-rc.2", optional = true } +sp-weights = { version ="27.0.0", optional = true } # parachains dirs = { version = "5.0", optional = true } @@ -47,7 +53,13 @@ zombienet-support = { git = "https://github.com/paritytech/zombienet-sdk", optio [features] default = ["contract", "parachain"] contract = [ - "dep:contract-build" + "dep:contract-build", + "dep:contract-extrinsics", + "dep:sp-core", + "dep:subxt-signer", + "dep:subxt", + "dep:ink_env", + "dep:sp-weights", ] parachain = [ "dep:dirs", diff --git a/README.md b/README.md index 2e9a16b46..b292aadbd 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,28 @@ Build the smart contract: pop build contract -p ./my_contract ``` +To deploy a contract you need your chain running. For testing purposes one option is to run [substrate-contracts-node](https://github.com/paritytech/substrate-contracts-node): + +```sh +cargo install contracts-node +substrate-contracts-node +``` + +Deploy and instantiate the smart contract: +```sh +pop up contract -p ./my_contract --constructor new --args "false" --suri //Alice +``` +Some of the options available are: +- Specify the contract `constructor `to use, which in this example is new(). +- Specify the argument (`args`) to the constructor, which in this example is false +- Specify the account uploading and instantiating the contract with `--suri`, which in this example is the default development account of //Alice +For other accounts, the actual secret key must be provided e.g. an 0x prefixed 64 bit hex string, or the seed phrase. +> :warning: **Use only for development**: Use a safer method of signing here before using this tool with production projects. + +- You also can specify the url of your network with `--url ws://your-endpoint`, by default is using `ws://localhost:9944` + +For more information about the options, check [cargo-contract documentation](https://github.com/paritytech/cargo-contract/blob/master/crates/extrinsics/README.md#instantiate) + ### E2E testing For e2e testing you will need to have a Substrate node with `pallet contracts`. diff --git a/src/commands/build/contract.rs b/src/commands/build/contract.rs index f1e56be96..cae6055f5 100644 --- a/src/commands/build/contract.rs +++ b/src/commands/build/contract.rs @@ -7,7 +7,7 @@ use crate::engines::contract_engine::build_smart_contract; #[derive(Args)] pub struct BuildContractCommand { - #[arg(short = 'p', long = "path", help = "Path for the contract project, [default: current directory]")] + #[arg(short = 'p', long, help = "Path for the contract project, [default: current directory]")] pub(crate) path: Option, } diff --git a/src/commands/new/contract.rs b/src/commands/new/contract.rs index 08aba690f..b69489f81 100644 --- a/src/commands/new/contract.rs +++ b/src/commands/new/contract.rs @@ -9,7 +9,7 @@ use crate::engines::contract_engine::create_smart_contract; pub struct NewContractCommand { #[arg(help = "Name of the contract")] pub(crate) name: String, - #[arg(short = 'p', long = "path", help = "Path for the contract project, [default: current directory]")] + #[arg(short = 'p', long, help = "Path for the contract project, [default: current directory]")] pub(crate) path: Option, } diff --git a/src/commands/new/pallet.rs b/src/commands/new/pallet.rs index 1c318d8c0..ef0bfa2a3 100644 --- a/src/commands/new/pallet.rs +++ b/src/commands/new/pallet.rs @@ -14,7 +14,7 @@ pub struct NewPalletCommand { default_value = "Frame Pallet" )] pub(crate) description: Option, - #[arg(short = 'p', long = "path", help = "Path to the pallet, [default: current directory]")] + #[arg(short = 'p', long, help = "Path to the pallet, [default: current directory]")] pub(crate) path: Option, } diff --git a/src/commands/test/contract.rs b/src/commands/test/contract.rs index 6db632cef..67087438b 100644 --- a/src/commands/test/contract.rs +++ b/src/commands/test/contract.rs @@ -9,7 +9,7 @@ use crate::engines::contract_engine::test_e2e_smart_contract; #[derive(Args)] pub(crate) struct TestContractCommand { - #[arg(short = 'p', long = "path", help = "Path for the contract project [default: current directory]")] + #[arg(short = 'p', long, help = "Path for the contract project [default: current directory]")] path: Option, #[arg(short = 'f', long = "features", help = "Features for the contract project")] features: Option, diff --git a/src/commands/up/contract.rs b/src/commands/up/contract.rs new file mode 100644 index 000000000..c83cfff81 --- /dev/null +++ b/src/commands/up/contract.rs @@ -0,0 +1,133 @@ +use std::path::PathBuf; +use sp_core::Bytes; +use clap::Args; +use cliclack::{intro, log}; +use anyhow::anyhow; + +use crate::{ + style::style, signer::{parse_hex_bytes, create_signer}, + engines::contract_engine::{instantiate_smart_contract,dry_run_gas_estimate_instantiate} +}; + +use sp_weights::Weight; +use contract_extrinsics::{BalanceVariant, ExtrinsicOptsBuilder, InstantiateExec, InstantiateCommandBuilder, TokenMetadata}; +use contract_build::ManifestPath; +use subxt::PolkadotConfig as DefaultConfig; +use subxt_signer::sr25519::Keypair; +use ink_env::{DefaultEnvironment, Environment}; + + +#[derive(Args)] +pub struct UpContractCommand { + /// Path to a contract build folder + #[arg(short = 'p', long)] + path: Option, + /// The name of the contract constructor to call + #[clap(name = "constructor", long, default_value = "new")] + constructor: String, + /// The constructor arguments, encoded as strings + #[clap(long, num_args = 0..)] + args: Vec, + /// Transfers an initial balance to the instantiated contract + #[clap(name = "value", long, default_value = "0")] + value: BalanceVariant<::Balance>, + /// Maximum amount of gas to be used for this command. + /// If not specified will perform a dry-run to estimate the gas consumed for the + /// instantiation. + #[clap(name = "gas", long)] + gas_limit: Option, + /// Maximum proof size for this instantiation. + /// If not specified will perform a dry-run to estimate the proof size required. + #[clap(long)] + proof_size: Option, + /// 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. + #[clap(long, value_parser = parse_hex_bytes)] + salt: Option, + /// Websockets url of a substrate node. + #[clap( + name = "url", + long, + value_parser, + default_value = "ws://localhost:9944" + )] + url: url::Url, + /// Secret key URI for the account deploying the contract. + /// + /// e.g. + /// - for a dev account "//Alice" + /// - with a password "//Alice///SECRET_PASSWORD" + #[clap(name = "suri", long, short)] + suri: String, +} + +impl UpContractCommand { + pub(crate) async fn execute(&self) -> anyhow::Result<()> { + intro(format!( + "{}: Deploy a smart contract", + style(" Pop CLI ").black().on_magenta() + ))?; + let instantiate_exec = + self.set_up_deployment().await?; + + let weight_limit; + if self.gas_limit.is_some() && self.proof_size.is_some() { + weight_limit = Weight::from_parts(self.gas_limit.unwrap(), self.proof_size.unwrap()); + } + else { + log::info("Doing a dry run to estimate the gas...")?; + weight_limit = dry_run_gas_estimate_instantiate(&instantiate_exec).await?; + log::info(format!( + "Gas limit {:?}", + weight_limit + ))?; + } + log::info("Uploading and instantiating the contract...")?; + instantiate_smart_contract(instantiate_exec, weight_limit).await.map_err(|err| anyhow!( + "{} {}", + "ERROR:", + format!("{err:?}") + ))?; + Ok(()) + } + + async fn set_up_deployment(&self) -> anyhow::Result> { + // If the user specify a path (not current directory) have to manually add Cargo.toml here or ask to the user the specific path + let manifest_path ; + if self.path.is_some(){ + let full_path: PathBuf = PathBuf::from(self.path.as_ref().unwrap().to_string_lossy().to_string() + "/Cargo.toml"); + manifest_path = ManifestPath::try_from(Some(full_path))?; + } + else { + manifest_path = ManifestPath::try_from(self.path.as_ref())?; + } + + let token_metadata = + TokenMetadata::query::(&self.url).await?; + + let signer = create_signer(&self.suri)?; + let extrinsic_opts = ExtrinsicOptsBuilder::new(signer) + .manifest_path(Some(manifest_path)) + .url(self.url.clone()) + .done(); + + let instantiate_exec: InstantiateExec< + DefaultConfig, + DefaultEnvironment, + Keypair, + > = InstantiateCommandBuilder::new(extrinsic_opts) + .constructor(self.constructor.clone()) + .args(self.args.clone()) + .value(self.value.denominate_balance(&token_metadata)?) + .gas_limit(self.gas_limit) + .proof_size(self.proof_size) + .salt(self.salt.clone()) + .done() + .await?; + return Ok(instantiate_exec); + } +} diff --git a/src/commands/up/mod.rs b/src/commands/up/mod.rs index 086a7d41b..038ff7b90 100644 --- a/src/commands/up/mod.rs +++ b/src/commands/up/mod.rs @@ -1,5 +1,7 @@ #[cfg(feature = "parachain")] mod parachain; +#[cfg(feature = "contract")] +mod contract; use clap::{Args, Subcommand}; @@ -16,4 +18,8 @@ pub(crate) enum UpCommands { /// Deploy a parachain to a network. #[clap(alias = "p")] Parachain(parachain::ZombienetCommand), + #[cfg(feature = "contract")] + /// Deploy a smart contract to a network. + #[clap(alias = "c")] + Contract(contract::UpContractCommand), } diff --git a/src/engines/contract_engine.rs b/src/engines/contract_engine.rs index 309a6ed06..0b1b333a4 100644 --- a/src/engines/contract_engine.rs +++ b/src/engines/contract_engine.rs @@ -1,17 +1,26 @@ use std::path::PathBuf; use duct::cmd; +use cliclack::outro; use contract_build::{ new_contract_project, execute, ExecuteArgs, ManifestPath,Verbosity, BuildMode,Features,Network,BuildArtifacts, UnstableFlags, OptimizationPasses, OutputType, Target, + DEFAULT_MAX_MEMORY_PAGES }; +use sp_weights::Weight; +use contract_extrinsics::{InstantiateExec, ErrorVariant}; +use subxt::PolkadotConfig as DefaultConfig; +use subxt_signer::sr25519::Keypair; +use ink_env::DefaultEnvironment; + pub fn create_smart_contract(name: String, target: &Option) -> anyhow::Result<()> { new_contract_project(&name, target.as_ref()) } pub fn build_smart_contract(path: &Option) -> anyhow::Result<()> { - // If the user specify a path (not current directory) have to manually add Cargo.toml here or ask to the user the specific path + // If the user specify a path (not current directory) have to manually add Cargo.toml here or ask to the user the specific path + // (Like cargo-contract does) let manifest_path ; if path.is_some(){ let full_path: PathBuf = PathBuf::from(path.as_ref().unwrap().to_string_lossy().to_string() + "/Cargo.toml"); @@ -31,10 +40,12 @@ pub fn build_smart_contract(path: &Option) -> anyhow::Result<()> { unstable_flags: UnstableFlags::default(), optimization_passes: Some(OptimizationPasses::default()), keep_debug_symbols: false, - lint: false, + extra_lints: false, output_type: OutputType::Json, skip_wasm_validation: false, target: Target::Wasm, + max_memory_pages: DEFAULT_MAX_MEMORY_PAGES, + image: Default::default(), }; execute(args)?; Ok(()) @@ -68,6 +79,46 @@ pub fn test_e2e_smart_contract(path: &Option) -> anyhow::Result<()> { Ok(()) } + + +pub async fn instantiate_smart_contract(instantiate_exec: InstantiateExec< + DefaultConfig, + DefaultEnvironment, + Keypair, +>, gas_limit: Weight) -> anyhow::Result<(), ErrorVariant> { + let instantiate_result = instantiate_exec.instantiate(Some(gas_limit)).await?; + outro( + format!("Contract deployed and instantiate: The Contract Address is {:?}", instantiate_result.contract_address.to_string()) + )?; + Ok(()) +} + +pub async fn dry_run_gas_estimate_instantiate( + instantiate_exec: &InstantiateExec, +) -> anyhow::Result { + let instantiate_result = instantiate_exec.instantiate_dry_run().await?; + match instantiate_result.result { + Ok(_) => { + // use user specified values where provided, otherwise use the estimates + let ref_time = instantiate_exec + .args() + .gas_limit() + .unwrap_or_else(|| instantiate_result.gas_required.ref_time()); + let proof_size = instantiate_exec + .args() + .proof_size() + .unwrap_or_else(|| instantiate_result.gas_required.proof_size()); + Ok(Weight::from_parts(ref_time, proof_size)) + } + Err(ref _err) => { + Err(anyhow::anyhow!( + "Pre-submission dry-run failed. Add gas_limit and proof_size manually to skip this step." + )) + } + } + +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/helpers.rs b/src/helpers.rs index dc971c4ef..20db473a8 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -5,6 +5,8 @@ use std::{ fs::{self, OpenOptions}, path::{Path, PathBuf}, }; + + pub(crate) fn sanitize(target: &Path) -> Result<()> { use std::io::{stdin, stdout, Write}; if target.exists() { diff --git a/src/main.rs b/src/main.rs index a04408f72..90df3c435 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,12 +5,16 @@ mod engines; #[cfg(any(feature = "parachain", feature = "contract"))] mod style; + #[cfg(feature = "parachain")] mod git; #[cfg(feature = "parachain")] -mod helpers; -#[cfg(feature = "parachain")] mod parachains; +#[cfg(feature = "parachain")] +mod helpers; + +#[cfg(feature = "contract")] +mod signer; use anyhow::{anyhow, Result}; use clap::{Parser, Subcommand}; @@ -59,6 +63,8 @@ async fn main() -> Result<()> { Commands::Up(args) => Ok(match &args.command { #[cfg(feature = "parachain")] commands::up::UpCommands::Parachain(cmd) => cmd.execute().await?, + #[cfg(feature = "contract")] + commands::up::UpCommands::Contract(cmd) => cmd.execute().await?, }), Commands::Test(args) => match &args.command { #[cfg(feature = "contract")] diff --git a/src/signer.rs b/src/signer.rs new file mode 100644 index 000000000..10ca29d42 --- /dev/null +++ b/src/signer.rs @@ -0,0 +1,19 @@ +use sp_core::Bytes; +use contract_build::util::decode_hex; +use subxt_signer::{ + sr25519::Keypair, + SecretUri, +}; +use anyhow::Result; + +/// Create a Signer from a secret URI. +pub fn create_signer(suri: &str) -> Result { + let uri = ::from_str(suri)?; + let keypair = Keypair::from_uri(&uri)?; + Ok(keypair) +} +/// Parse hex encoded bytes. +pub(crate) fn parse_hex_bytes(input: &str) -> Result { + let bytes = decode_hex(input)?; + Ok(bytes.into()) +} From 7737357d7bb6e71689389d45d903b580c1a35845 Mon Sep 17 00:00:00 2001 From: Alex Bean Date: Thu, 7 Mar 2024 12:56:05 +0100 Subject: [PATCH 04/10] feat: pop build parachain (#30) * feat: pop build parachain * fix: feedback on wording --- README.md | 11 +++++++++++ src/commands/build/mod.rs | 9 +++++++-- src/commands/build/parachain.rs | 28 ++++++++++++++++++++++++++++ src/engines/parachain_engine.rs | 17 ++++++++++++++++- src/main.rs | 2 ++ 5 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 src/commands/build/parachain.rs diff --git a/README.md b/README.md index b292aadbd..17e10e84a 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,17 @@ pop new parachain my-app cpt pop new parachain my-app fpt ``` +Use `pop` to build your just created parachain. +```sh +# Build your parachain +pop build parachain -p ./my-app +``` +or +```sh +cd my-app +pop build parachain +``` + You can also customize a template by providing config options for token symbol (as it appears on polkadot-js apps UI), token decimals, and the initial endowment for substrate developer accounts. Here's how: ```sh diff --git a/src/commands/build/mod.rs b/src/commands/build/mod.rs index b758fc7d5..b2d0a00f3 100644 --- a/src/commands/build/mod.rs +++ b/src/commands/build/mod.rs @@ -1,6 +1,7 @@ use clap::{Args, Subcommand}; -pub mod contract; +pub(crate) mod contract; +pub(crate) mod parachain; #[derive(Args)] #[command(args_conflicts_with_subcommands = true)] @@ -11,8 +12,12 @@ pub(crate) struct BuildArgs { #[derive(Subcommand)] pub(crate) enum BuildCommands { + /// Build a parachain template + #[cfg(feature = "parachain")] + #[clap(alias = "p")] + Parachain(parachain::BuildParachainCommand), /// Compiles the contract, generates metadata, bundles both together in a - /// `.contract` file + /// `.contract` file #[cfg(feature = "contract")] #[clap(alias = "c")] Contract(contract::BuildContractCommand), diff --git a/src/commands/build/parachain.rs b/src/commands/build/parachain.rs new file mode 100644 index 000000000..510f88083 --- /dev/null +++ b/src/commands/build/parachain.rs @@ -0,0 +1,28 @@ +use clap::Args; +use std::path::PathBuf; +use cliclack::{clear_screen,intro, set_theme, outro}; +use crate::style::{style, Theme}; + +use crate::engines::parachain_engine::build_parachain; + + +#[derive(Args)] +pub struct BuildParachainCommand { + #[arg(short = 'p', long = "path", help = "Directory path for your project, [default: current directory]")] + pub(crate) path: Option, +} + +impl BuildParachainCommand { + pub(crate) fn execute(&self) -> anyhow::Result<()> { + clear_screen()?; + intro(format!( + "{}: Building a parachain", + style(" Pop CLI ").black().on_magenta() + ))?; + set_theme(Theme); + build_parachain(&self.path)?; + + outro("Build Completed Successfully!")?; + Ok(()) + } +} \ No newline at end of file diff --git a/src/engines/parachain_engine.rs b/src/engines/parachain_engine.rs index 2bda53a27..29d054ece 100644 --- a/src/engines/parachain_engine.rs +++ b/src/engines/parachain_engine.rs @@ -5,8 +5,9 @@ use crate::{ }; use anyhow::Result; use git2::Repository; -use std::{fs, path::Path}; +use std::{fs, path::{Path, PathBuf}}; use walkdir::WalkDir; +use duct::cmd; #[derive(Debug, Clone)] pub struct Config { @@ -64,6 +65,20 @@ pub fn instantiate_vanilla_template(target: &Path, config: Config) -> Result<()> Ok(()) } +pub fn build_parachain(path: &Option) -> anyhow::Result<()> { + cmd( + "cargo", + vec![ + "build", + "--release", + ], + ) + .dir(path.clone().unwrap_or("./".into())) + .run()?; + + Ok(()) +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/main.rs b/src/main.rs index 90df3c435..a9a6b565b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -57,6 +57,8 @@ async fn main() -> Result<()> { commands::new::NewCommands::Contract(cmd) => cmd.execute(), }, Commands::Build(args) => match &args.command { + #[cfg(feature = "parachain")] + commands::build::BuildCommands::Parachain(cmd) => cmd.execute(), #[cfg(feature = "contract")] commands::build::BuildCommands::Contract(cmd) => cmd.execute(), }, From 37c849107f88bb6e3212debcfa8d5a69d709278c Mon Sep 17 00:00:00 2001 From: Alex Bean Date: Thu, 7 Mar 2024 19:23:35 +0100 Subject: [PATCH 05/10] refactor: renaming, removing unused features and styling (#33) * docs: remove todo comments * style: add rustfmt.toml file * remove ept parachain * refactor: rename vanilla per base parachain * refactor: replace println per log * style: cargo fmt --- .gitmodules | 10 +- .rustfmt.toml | 24 + README.md | 2 - src/commands/build/contract.rs | 14 +- src/commands/build/mod.rs | 22 +- src/commands/build/parachain.rs | 34 +- src/commands/mod.rs | 4 +- src/commands/new/contract.rs | 56 +- src/commands/new/mod.rs | 28 +- src/commands/new/pallet.rs | 44 +- src/commands/new/parachain.rs | 139 +-- src/commands/test/contract.rs | 48 +- src/commands/test/mod.rs | 12 +- src/commands/up/contract.rs | 215 +++-- src/commands/up/mod.rs | 24 +- src/commands/up/parachain.rs | 138 ++- src/engines/contract_engine.rs | 170 ++-- src/engines/generator.rs | 59 +- src/engines/mod.rs | 6 +- src/engines/pallet_engine.rs | 110 ++- src/engines/parachain_engine.rs | 155 ++-- src/git.rs | 110 ++- src/helpers.rs | 100 +-- src/main.rs | 99 ++- src/parachains/zombienet.rs | 830 +++++++++--------- src/signer.rs | 19 +- src/style.rs | 70 +- templates/{vanilla => base}/chain_spec.templ | 0 .../{vanilla => base}/runtime-cargo.templ | 0 templates/{vanilla => base}/runtime.templ | 0 templates/ept | 1 - 31 files changed, 1213 insertions(+), 1330 deletions(-) create mode 100644 .rustfmt.toml rename templates/{vanilla => base}/chain_spec.templ (100%) rename templates/{vanilla => base}/runtime-cargo.templ (100%) rename templates/{vanilla => base}/runtime.templ (100%) delete mode 160000 templates/ept diff --git a/.gitmodules b/.gitmodules index 7c74b3fd8..1c48a6d02 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,8 +1,4 @@ -[submodule "templates/ept"] - path = templates/ept - url = git@github.com:paritytech/extended-parachain-template.git - -[submodule "templates/vanilla-parachain"] - path = templates/vanilla-parachain - url = git@github.com:r0guelabs/vanilla-parachain.git +[submodule "templates/base-parachain"] + path = templates/base-parachain + url = git@github.com:r0gue-io/base-parachain.git diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 000000000..7a037ea5d --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,24 @@ +# Basic +edition = "2021" +hard_tabs = true +max_width = 100 +use_small_heuristics = "Max" +# Imports +imports_granularity = "Crate" +reorder_imports = true +# Consistency +newline_style = "Unix" +# Misc +chain_width = 80 +spaces_around_ranges = false +binop_separator = "Back" +reorder_impl_items = false +match_arm_leading_pipes = "Preserve" +match_arm_blocks = false +match_block_trailing_comma = true +trailing_comma = "Vertical" +trailing_semicolon = false +use_field_init_shorthand = true +# Format comments +comment_width = 100 +wrap_comments = true \ No newline at end of file diff --git a/README.md b/README.md index 17e10e84a..12465a025 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,6 @@ Use `pop` to either clone of your existing templates or instantiate a new parach ```sh # Create a minimal parachain template pop new parachain my-app -# Get the extended-parachain-template -pop new parachain my-app ept # Get a pallet-contracts enabled template pop new parachain my-app cpt # Get a evm compatible parachain template diff --git a/src/commands/build/contract.rs b/src/commands/build/contract.rs index cae6055f5..d08e7187c 100644 --- a/src/commands/build/contract.rs +++ b/src/commands/build/contract.rs @@ -7,14 +7,14 @@ use crate::engines::contract_engine::build_smart_contract; #[derive(Args)] pub struct BuildContractCommand { - #[arg(short = 'p', long, help = "Path for the contract project, [default: current directory]")] - pub(crate) path: Option, + #[arg(short = 'p', long, help = "Path for the contract project, [default: current directory]")] + pub(crate) path: Option, } impl BuildContractCommand { - pub(crate) fn execute(&self) -> anyhow::Result<()> { - build_smart_contract(&self.path)?; - log::info("The smart contract has been successfully built.")?; - Ok(()) - } + pub(crate) fn execute(&self) -> anyhow::Result<()> { + build_smart_contract(&self.path)?; + log::info("The smart contract has been successfully built.")?; + Ok(()) + } } diff --git a/src/commands/build/mod.rs b/src/commands/build/mod.rs index b2d0a00f3..1dd430157 100644 --- a/src/commands/build/mod.rs +++ b/src/commands/build/mod.rs @@ -6,19 +6,19 @@ pub(crate) mod parachain; #[derive(Args)] #[command(args_conflicts_with_subcommands = true)] pub(crate) struct BuildArgs { - #[command(subcommand)] - pub command: BuildCommands, + #[command(subcommand)] + pub command: BuildCommands, } #[derive(Subcommand)] pub(crate) enum BuildCommands { - /// Build a parachain template - #[cfg(feature = "parachain")] - #[clap(alias = "p")] - Parachain(parachain::BuildParachainCommand), - /// Compiles the contract, generates metadata, bundles both together in a - /// `.contract` file - #[cfg(feature = "contract")] - #[clap(alias = "c")] - Contract(contract::BuildContractCommand), + /// Build a parachain template + #[cfg(feature = "parachain")] + #[clap(alias = "p")] + Parachain(parachain::BuildParachainCommand), + /// Compiles the contract, generates metadata, bundles both together in a + /// `.contract` file + #[cfg(feature = "contract")] + #[clap(alias = "c")] + Contract(contract::BuildContractCommand), } diff --git a/src/commands/build/parachain.rs b/src/commands/build/parachain.rs index 510f88083..20485f563 100644 --- a/src/commands/build/parachain.rs +++ b/src/commands/build/parachain.rs @@ -1,28 +1,28 @@ +use crate::style::{style, Theme}; use clap::Args; +use cliclack::{clear_screen, intro, outro, set_theme}; use std::path::PathBuf; -use cliclack::{clear_screen,intro, set_theme, outro}; -use crate::style::{style, Theme}; use crate::engines::parachain_engine::build_parachain; - #[derive(Args)] pub struct BuildParachainCommand { - #[arg(short = 'p', long = "path", help = "Directory path for your project, [default: current directory]")] - pub(crate) path: Option, + #[arg( + short = 'p', + long = "path", + help = "Directory path for your project, [default: current directory]" + )] + pub(crate) path: Option, } impl BuildParachainCommand { - pub(crate) fn execute(&self) -> anyhow::Result<()> { - clear_screen()?; - intro(format!( - "{}: Building a parachain", - style(" Pop CLI ").black().on_magenta() - ))?; - set_theme(Theme); - build_parachain(&self.path)?; + pub(crate) fn execute(&self) -> anyhow::Result<()> { + clear_screen()?; + intro(format!("{}: Building a parachain", style(" Pop CLI ").black().on_magenta()))?; + set_theme(Theme); + build_parachain(&self.path)?; - outro("Build Completed Successfully!")?; - Ok(()) - } -} \ No newline at end of file + outro("Build Completed Successfully!")?; + Ok(()) + } +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 1bc59b6c6..17f1ca138 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,4 +1,4 @@ -pub(crate) mod new; pub(crate) mod build; -pub(crate) mod up; +pub(crate) mod new; pub(crate) mod test; +pub(crate) mod up; diff --git a/src/commands/new/contract.rs b/src/commands/new/contract.rs index b69489f81..0c52e8bca 100644 --- a/src/commands/new/contract.rs +++ b/src/commands/new/contract.rs @@ -7,41 +7,39 @@ use crate::engines::contract_engine::create_smart_contract; #[derive(Args)] pub struct NewContractCommand { - #[arg(help = "Name of the contract")] - pub(crate) name: String, - #[arg(short = 'p', long, help = "Path for the contract project, [default: current directory]")] - pub(crate) path: Option, + #[arg(help = "Name of the contract")] + pub(crate) name: String, + #[arg(short = 'p', long, help = "Path for the contract project, [default: current directory]")] + pub(crate) path: Option, } impl NewContractCommand { - pub(crate) fn execute(&self) -> anyhow::Result<()> { - create_smart_contract(self.name.clone(), &self.path)?; - log::info(format!( - "Smart contract created! Located in the following directory {:?}", - self.path.clone().unwrap_or(PathBuf::from(format!("/{}", self.name))).display() - ))?; - Ok(()) - } + pub(crate) fn execute(&self) -> anyhow::Result<()> { + create_smart_contract(self.name.clone(), &self.path)?; + log::info(format!( + "Smart contract created! Located in the following directory {:?}", + self.path.clone().unwrap_or(PathBuf::from(format!("/{}", self.name))).display() + ))?; + Ok(()) + } } #[cfg(test)] mod tests { - use super::*; - use std::fs; + use super::*; + use std::fs; - #[test] - fn test_new_contract_command_execute() -> anyhow::Result<()> { - let command = NewContractCommand { - name: "test_contract".to_string(), - path: Some(PathBuf::new()) - }; - let result = command.execute(); - assert!(result.is_ok()); - - // Clean up - if let Err(err) = fs::remove_dir_all("test_contract") { - eprintln!("Failed to delete directory: {}", err); - } - Ok(()) - } + #[test] + fn test_new_contract_command_execute() -> anyhow::Result<()> { + let command = + NewContractCommand { name: "test_contract".to_string(), path: Some(PathBuf::new()) }; + let result = command.execute(); + assert!(result.is_ok()); + + // Clean up + if let Err(err) = fs::remove_dir_all("test_contract") { + eprintln!("Failed to delete directory: {}", err); + } + Ok(()) + } } diff --git a/src/commands/new/mod.rs b/src/commands/new/mod.rs index f6ee1a503..aa66f024a 100644 --- a/src/commands/new/mod.rs +++ b/src/commands/new/mod.rs @@ -10,22 +10,22 @@ pub mod parachain; #[derive(Args)] #[command(args_conflicts_with_subcommands = true)] pub struct NewArgs { - #[command(subcommand)] - pub command: NewCommands, + #[command(subcommand)] + pub command: NewCommands, } #[derive(Subcommand)] pub enum NewCommands { - /// Generate a new parachain template - #[cfg(feature = "parachain")] - #[clap(alias = "p")] - Parachain(parachain::NewParachainCommand), - /// Generate a new pallet template - #[cfg(feature = "parachain")] - #[clap(alias = "m")] // (m)odule, as p used above - Pallet(pallet::NewPalletCommand), - /// Generate a new smart contract template - #[cfg(feature = "contract")] - #[clap(alias = "c")] - Contract(contract::NewContractCommand), + /// Generate a new parachain template + #[cfg(feature = "parachain")] + #[clap(alias = "p")] + Parachain(parachain::NewParachainCommand), + /// Generate a new pallet template + #[cfg(feature = "parachain")] + #[clap(alias = "m")] // (m)odule, as p used above + Pallet(pallet::NewPalletCommand), + /// Generate a new smart contract template + #[cfg(feature = "contract")] + #[clap(alias = "c")] + Contract(contract::NewContractCommand), } diff --git a/src/commands/new/pallet.rs b/src/commands/new/pallet.rs index ef0bfa2a3..f63889ed0 100644 --- a/src/commands/new/pallet.rs +++ b/src/commands/new/pallet.rs @@ -1,30 +1,28 @@ +use crate::engines::pallet_engine::{create_pallet_template, TemplatePalletConfig}; use clap::Args; -use crate::engines::pallet_engine::{TemplatePalletConfig, create_pallet_template}; #[derive(Args)] pub struct NewPalletCommand { - #[arg(help = "Name of the pallet", default_value = "pallet-template")] - pub(crate) name: String, - #[arg(short, long, help = "Name of authors", default_value = "Anonymous")] - pub(crate) authors: Option, - #[arg( - short, - long, - help = "Pallet description", - default_value = "Frame Pallet" - )] - pub(crate) description: Option, - #[arg(short = 'p', long, help = "Path to the pallet, [default: current directory]")] - pub(crate) path: Option, + #[arg(help = "Name of the pallet", default_value = "pallet-template")] + pub(crate) name: String, + #[arg(short, long, help = "Name of authors", default_value = "Anonymous")] + pub(crate) authors: Option, + #[arg(short, long, help = "Pallet description", default_value = "Frame Pallet")] + pub(crate) description: Option, + #[arg(short = 'p', long, help = "Path to the pallet, [default: current directory]")] + pub(crate) path: Option, } impl NewPalletCommand { - pub(crate) fn execute(&self) -> anyhow::Result<()> { - create_pallet_template(self.path.clone(), TemplatePalletConfig { - name: self.name.clone(), - authors: self.authors.clone().expect("default values"), - description: self.description.clone().expect("default values"), - })?; - Ok(()) - } -} \ No newline at end of file + pub(crate) fn execute(&self) -> anyhow::Result<()> { + create_pallet_template( + self.path.clone(), + TemplatePalletConfig { + name: self.name.clone(), + authors: self.authors.clone().expect("default values"), + description: self.description.clone().expect("default values"), + }, + )?; + Ok(()) + } +} diff --git a/src/commands/new/parachain.rs b/src/commands/new/parachain.rs index d2c04fdf5..22abf79e8 100644 --- a/src/commands/new/parachain.rs +++ b/src/commands/new/parachain.rs @@ -1,86 +1,91 @@ -use crate::engines::parachain_engine::{instantiate_template_dir, Config}; +use crate::{ + engines::parachain_engine::{instantiate_template_dir, Config}, + style::{style, Theme}, +}; use clap::{Args, Parser}; use std::path::Path; use strum_macros::{Display, EnumString}; +use cliclack::{clear_screen, intro, outro, set_theme}; + #[derive(Clone, Parser, Debug, Display, EnumString, PartialEq)] pub enum Template { - #[strum(serialize = "Extended Parachain Template", serialize = "ept")] - EPT, - #[strum(serialize = "Frontier Parachain Template", serialize = "fpt")] - FPT, - #[strum(serialize = "Contracts Node Template", serialize = "cpt")] - Contracts, - #[strum(serialize = "Vanilla Parachain Template", serialize = "vanilla")] - Vanilla, - // Kitchensink, + #[strum(serialize = "Frontier Parachain Template", serialize = "fpt")] + FPT, + #[strum(serialize = "Contracts Node Template", serialize = "cpt")] + Contracts, + #[strum(serialize = "Base Parachain Template", serialize = "base")] + Base, } #[derive(Args)] pub struct NewParachainCommand { - #[arg(help = "Name of the app. Also works as a directory path for your project")] - pub(crate) name: String, - #[arg( - help = "Template to create; Options are 'ept', 'fpt', 'cpt'. Leave empty for default parachain template" - )] - #[arg(default_value = "vanilla")] - pub(crate) template: Template, - #[arg(long, short, help = "Token Symbol", default_value = "UNIT")] - pub(crate) symbol: Option, - #[arg(long, short, help = "Token Decimals", default_value = "12")] - pub(crate) decimals: Option, - #[arg( - long = "endowment", - short, - help = "Token Endowment for dev accounts", - default_value = "1u64 << 60" - )] - pub(crate) initial_endowment: Option, + #[arg(help = "Name of the app. Also works as a directory path for your project")] + pub(crate) name: String, + #[arg( + help = "Template to create; Options are 'fpt', 'cpt'. Leave empty for default parachain template" + )] + #[arg(default_value = "base")] + pub(crate) template: Template, + #[arg(long, short, help = "Token Symbol", default_value = "UNIT")] + pub(crate) symbol: Option, + #[arg(long, short, help = "Token Decimals", default_value = "12")] + pub(crate) decimals: Option, + #[arg( + long = "endowment", + short, + help = "Token Endowment for dev accounts", + default_value = "1u64 << 60" + )] + pub(crate) initial_endowment: Option, } impl NewParachainCommand { - pub(crate) fn execute(&self) -> anyhow::Result<()> { - println!("Starting {} on `{}`!", &self.template, &self.name); - let destination_path = Path::new(&self.name); - instantiate_template_dir( - &self.template, - destination_path, - Config { - symbol: self.symbol.clone().expect("default values"), - decimals: self - .decimals - .clone() - .expect("default values") - .parse::()?, - initial_endowment: self.initial_endowment.clone().expect("default values"), - }, - )?; - println!("cd into {} and enjoy hacking! 🚀", &self.name); - Ok(()) - } + pub(crate) fn execute(&self) -> anyhow::Result<()> { + clear_screen()?; + intro(format!( + "{}: Starting {} on {}!", + style(" Pop CLI ").black().on_magenta(), + &self.template, + &self.name + ))?; + set_theme(Theme); + let destination_path = Path::new(&self.name); + instantiate_template_dir( + &self.template, + destination_path, + Config { + symbol: self.symbol.clone().expect("default values"), + decimals: self.decimals.clone().expect("default values").parse::()?, + initial_endowment: self.initial_endowment.clone().expect("default values"), + }, + )?; + outro(format!("cd into {} and enjoy hacking! 🚀", &self.name))?; + Ok(()) + } } #[cfg(test)] mod tests { - use super::*; - use std::fs; + use super::*; + use std::fs; + + #[test] + fn test_new_parachain_command_execute() -> anyhow::Result<()> { + let command = NewParachainCommand { + name: "test_parachain".to_string(), + template: Template::Base, + symbol: Some("UNIT".to_string()), + decimals: Some("12".to_string()), + initial_endowment: Some("1u64 << 60".to_string()), + }; + let result = command.execute(); + assert!(result.is_ok()); - #[test] - fn test_new_parachain_command_execute() -> anyhow::Result<()> { - let command = NewParachainCommand { - name: "test_parachain".to_string(), - template: Template::Vanilla, - symbol: Some("UNIT".to_string()), - decimals: Some("12".to_string()), - initial_endowment: Some("1u64 << 60".to_string()), - }; - let result = command.execute(); - assert!(result.is_ok()); - - // Clean up - if let Err(err) = fs::remove_dir_all("test_parachain") { - eprintln!("Failed to delete directory: {}", err); - } - Ok(()) - } + // Clean up + if let Err(err) = fs::remove_dir_all("test_parachain") { + eprintln!("Failed to delete directory: {}", err); + } + Ok(()) + } } diff --git a/src/commands/test/contract.rs b/src/commands/test/contract.rs index 67087438b..2fb6ab1e4 100644 --- a/src/commands/test/contract.rs +++ b/src/commands/test/contract.rs @@ -1,37 +1,31 @@ use std::path::PathBuf; use clap::Args; -use cliclack::{clear_screen,intro}; +use cliclack::{clear_screen, intro}; -use crate::style::style; -use crate::engines::contract_engine::test_smart_contract; -use crate::engines::contract_engine::test_e2e_smart_contract; +use crate::{ + engines::contract_engine::{test_e2e_smart_contract, test_smart_contract}, + style::style, +}; #[derive(Args)] pub(crate) struct TestContractCommand { - #[arg(short = 'p', long, help = "Path for the contract project [default: current directory]")] - path: Option, - #[arg(short = 'f', long = "features", help = "Features for the contract project")] - features: Option, + #[arg(short = 'p', long, help = "Path for the contract project [default: current directory]")] + path: Option, + #[arg(short = 'f', long = "features", help = "Features for the contract project")] + features: Option, } impl TestContractCommand { - pub(crate) fn execute(&self) -> anyhow::Result<()> { - clear_screen()?; - if self.features.is_some() && self.features.clone().unwrap().contains("e2e-tests") { - intro(format!( - "{}: Starting e2e tests", - style(" Pop CLI ").black().on_magenta() - ))?; - test_e2e_smart_contract(&self.path)?; - } else { - intro(format!( - "{}: Starting unit tests", - style(" Pop CLI ").black().on_magenta() - ))?; - test_smart_contract(&self.path)?; - - } - Ok(()) - } -} \ No newline at end of file + pub(crate) fn execute(&self) -> anyhow::Result<()> { + clear_screen()?; + if self.features.is_some() && self.features.clone().unwrap().contains("e2e-tests") { + intro(format!("{}: Starting e2e tests", style(" Pop CLI ").black().on_magenta()))?; + test_e2e_smart_contract(&self.path)?; + } else { + intro(format!("{}: Starting unit tests", style(" Pop CLI ").black().on_magenta()))?; + test_smart_contract(&self.path)?; + } + Ok(()) + } +} diff --git a/src/commands/test/mod.rs b/src/commands/test/mod.rs index 49309cf34..ee2481b18 100644 --- a/src/commands/test/mod.rs +++ b/src/commands/test/mod.rs @@ -5,14 +5,14 @@ pub mod contract; #[derive(Args)] #[command(args_conflicts_with_subcommands = true)] pub(crate) struct TestArgs { - #[command(subcommand)] - pub command: TestCommands, + #[command(subcommand)] + pub command: TestCommands, } #[derive(Subcommand)] pub(crate) enum TestCommands { - /// Test the contract - #[cfg(feature = "contract")] - #[clap(alias = "c")] - Contract(contract::TestContractCommand), + /// Test the contract + #[cfg(feature = "contract")] + #[clap(alias = "c")] + Contract(contract::TestContractCommand), } diff --git a/src/commands/up/contract.rs b/src/commands/up/contract.rs index c83cfff81..7b91e8f22 100644 --- a/src/commands/up/contract.rs +++ b/src/commands/up/contract.rs @@ -1,133 +1,116 @@ -use std::path::PathBuf; -use sp_core::Bytes; +use anyhow::anyhow; use clap::Args; use cliclack::{intro, log}; -use anyhow::anyhow; +use sp_core::Bytes; +use std::path::PathBuf; use crate::{ - style::style, signer::{parse_hex_bytes, create_signer}, - engines::contract_engine::{instantiate_smart_contract,dry_run_gas_estimate_instantiate} + engines::contract_engine::{dry_run_gas_estimate_instantiate, instantiate_smart_contract}, + signer::{create_signer, parse_hex_bytes}, + style::style, }; -use sp_weights::Weight; -use contract_extrinsics::{BalanceVariant, ExtrinsicOptsBuilder, InstantiateExec, InstantiateCommandBuilder, TokenMetadata}; use contract_build::ManifestPath; +use contract_extrinsics::{ + BalanceVariant, ExtrinsicOptsBuilder, InstantiateCommandBuilder, InstantiateExec, TokenMetadata, +}; +use ink_env::{DefaultEnvironment, Environment}; +use sp_weights::Weight; use subxt::PolkadotConfig as DefaultConfig; use subxt_signer::sr25519::Keypair; -use ink_env::{DefaultEnvironment, Environment}; - #[derive(Args)] pub struct UpContractCommand { - /// Path to a contract build folder - #[arg(short = 'p', long)] - path: Option, - /// The name of the contract constructor to call - #[clap(name = "constructor", long, default_value = "new")] - constructor: String, - /// The constructor arguments, encoded as strings - #[clap(long, num_args = 0..)] - args: Vec, - /// Transfers an initial balance to the instantiated contract - #[clap(name = "value", long, default_value = "0")] - value: BalanceVariant<::Balance>, - /// Maximum amount of gas to be used for this command. - /// If not specified will perform a dry-run to estimate the gas consumed for the - /// instantiation. - #[clap(name = "gas", long)] - gas_limit: Option, - /// Maximum proof size for this instantiation. - /// If not specified will perform a dry-run to estimate the proof size required. - #[clap(long)] - proof_size: Option, - /// 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. - #[clap(long, value_parser = parse_hex_bytes)] - salt: Option, - /// Websockets url of a substrate node. - #[clap( - name = "url", - long, - value_parser, - default_value = "ws://localhost:9944" - )] - url: url::Url, - /// Secret key URI for the account deploying the contract. - /// - /// e.g. - /// - for a dev account "//Alice" - /// - with a password "//Alice///SECRET_PASSWORD" - #[clap(name = "suri", long, short)] - suri: String, + /// Path to a contract build folder + #[arg(short = 'p', long)] + path: Option, + /// The name of the contract constructor to call + #[clap(name = "constructor", long, default_value = "new")] + constructor: String, + /// The constructor arguments, encoded as strings + #[clap(long, num_args = 0..)] + args: Vec, + /// Transfers an initial balance to the instantiated contract + #[clap(name = "value", long, default_value = "0")] + value: BalanceVariant<::Balance>, + /// Maximum amount of gas to be used for this command. + /// If not specified will perform a dry-run to estimate the gas consumed for the + /// instantiation. + #[clap(name = "gas", long)] + gas_limit: Option, + /// Maximum proof size for this instantiation. + /// If not specified will perform a dry-run to estimate the proof size required. + #[clap(long)] + proof_size: Option, + /// 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. + #[clap(long, value_parser = parse_hex_bytes)] + salt: Option, + /// Websockets url of a substrate node. + #[clap(name = "url", long, value_parser, default_value = "ws://localhost:9944")] + url: url::Url, + /// Secret key URI for the account deploying the contract. + /// + /// e.g. + /// - for a dev account "//Alice" + /// - with a password "//Alice///SECRET_PASSWORD" + #[clap(name = "suri", long, short)] + suri: String, } impl UpContractCommand { - pub(crate) async fn execute(&self) -> anyhow::Result<()> { - intro(format!( - "{}: Deploy a smart contract", - style(" Pop CLI ").black().on_magenta() - ))?; - let instantiate_exec = - self.set_up_deployment().await?; - - let weight_limit; - if self.gas_limit.is_some() && self.proof_size.is_some() { - weight_limit = Weight::from_parts(self.gas_limit.unwrap(), self.proof_size.unwrap()); - } - else { - log::info("Doing a dry run to estimate the gas...")?; - weight_limit = dry_run_gas_estimate_instantiate(&instantiate_exec).await?; - log::info(format!( - "Gas limit {:?}", - weight_limit - ))?; - } - log::info("Uploading and instantiating the contract...")?; - instantiate_smart_contract(instantiate_exec, weight_limit).await.map_err(|err| anyhow!( - "{} {}", - "ERROR:", - format!("{err:?}") - ))?; - Ok(()) - } + pub(crate) async fn execute(&self) -> anyhow::Result<()> { + intro(format!("{}: Deploy a smart contract", style(" Pop CLI ").black().on_magenta()))?; + let instantiate_exec = self.set_up_deployment().await?; + + let weight_limit; + if self.gas_limit.is_some() && self.proof_size.is_some() { + weight_limit = Weight::from_parts(self.gas_limit.unwrap(), self.proof_size.unwrap()); + } else { + log::info("Doing a dry run to estimate the gas...")?; + weight_limit = dry_run_gas_estimate_instantiate(&instantiate_exec).await?; + log::info(format!("Gas limit {:?}", weight_limit))?; + } + log::info("Uploading and instantiating the contract...")?; + instantiate_smart_contract(instantiate_exec, weight_limit) + .await + .map_err(|err| anyhow!("{} {}", "ERROR:", format!("{err:?}")))?; + Ok(()) + } + + async fn set_up_deployment( + &self, + ) -> anyhow::Result> { + // If the user specify a path (not current directory) have to manually add Cargo.toml here + // or ask to the user the specific path + let manifest_path; + if self.path.is_some() { + let full_path: PathBuf = PathBuf::from( + self.path.as_ref().unwrap().to_string_lossy().to_string() + "/Cargo.toml", + ); + manifest_path = ManifestPath::try_from(Some(full_path))?; + } else { + manifest_path = ManifestPath::try_from(self.path.as_ref())?; + } + + let token_metadata = TokenMetadata::query::(&self.url).await?; + + let signer = create_signer(&self.suri)?; + let extrinsic_opts = ExtrinsicOptsBuilder::new(signer) + .manifest_path(Some(manifest_path)) + .url(self.url.clone()) + .done(); - async fn set_up_deployment(&self) -> anyhow::Result> { - // If the user specify a path (not current directory) have to manually add Cargo.toml here or ask to the user the specific path - let manifest_path ; - if self.path.is_some(){ - let full_path: PathBuf = PathBuf::from(self.path.as_ref().unwrap().to_string_lossy().to_string() + "/Cargo.toml"); - manifest_path = ManifestPath::try_from(Some(full_path))?; - } - else { - manifest_path = ManifestPath::try_from(self.path.as_ref())?; - } - - let token_metadata = - TokenMetadata::query::(&self.url).await?; - - let signer = create_signer(&self.suri)?; - let extrinsic_opts = ExtrinsicOptsBuilder::new(signer) - .manifest_path(Some(manifest_path)) - .url(self.url.clone()) - .done(); - - let instantiate_exec: InstantiateExec< - DefaultConfig, - DefaultEnvironment, - Keypair, - > = InstantiateCommandBuilder::new(extrinsic_opts) - .constructor(self.constructor.clone()) - .args(self.args.clone()) - .value(self.value.denominate_balance(&token_metadata)?) - .gas_limit(self.gas_limit) - .proof_size(self.proof_size) - .salt(self.salt.clone()) - .done() - .await?; - return Ok(instantiate_exec); - } + let instantiate_exec: InstantiateExec = + InstantiateCommandBuilder::new(extrinsic_opts) + .constructor(self.constructor.clone()) + .args(self.args.clone()) + .value(self.value.denominate_balance(&token_metadata)?) + .gas_limit(self.gas_limit) + .proof_size(self.proof_size) + .salt(self.salt.clone()) + .done() + .await?; + return Ok(instantiate_exec); + } } diff --git a/src/commands/up/mod.rs b/src/commands/up/mod.rs index 038ff7b90..d0ea1c051 100644 --- a/src/commands/up/mod.rs +++ b/src/commands/up/mod.rs @@ -1,25 +1,25 @@ -#[cfg(feature = "parachain")] -mod parachain; #[cfg(feature = "contract")] mod contract; +#[cfg(feature = "parachain")] +mod parachain; use clap::{Args, Subcommand}; #[derive(Args)] #[command(args_conflicts_with_subcommands = true)] pub(crate) struct UpArgs { - #[command(subcommand)] - pub(crate) command: UpCommands, + #[command(subcommand)] + pub(crate) command: UpCommands, } #[derive(Subcommand)] pub(crate) enum UpCommands { - #[cfg(feature = "parachain")] - /// Deploy a parachain to a network. - #[clap(alias = "p")] - Parachain(parachain::ZombienetCommand), - #[cfg(feature = "contract")] - /// Deploy a smart contract to a network. - #[clap(alias = "c")] - Contract(contract::UpContractCommand), + #[cfg(feature = "parachain")] + /// Deploy a parachain to a network. + #[clap(alias = "p")] + Parachain(parachain::ZombienetCommand), + #[cfg(feature = "contract")] + /// Deploy a smart contract to a network. + #[clap(alias = "c")] + Contract(contract::UpContractCommand), } diff --git a/src/commands/up/parachain.rs b/src/commands/up/parachain.rs index 202e317b6..b70fd3e2e 100644 --- a/src/commands/up/parachain.rs +++ b/src/commands/up/parachain.rs @@ -4,80 +4,72 @@ use cliclack::{clear_screen, confirm, intro, log, outro, outro_cancel, set_theme #[derive(Args)] pub(crate) struct ZombienetCommand { - /// The configuration file to be used. Only Zombienet configuration files are currently supported. - #[arg(short, long)] - file: String, - /// The version of Polkadot to be used for the relay chain, as per the release tag (e.g. "v1.7.0"). - #[arg(short, long)] - relay_chain: Option, - /// The version of Polkadot to be used for a system parachain, as per the release tag (e.g. "v1.7.0"). - #[arg(short, long)] - system_parachain: Option, - /// The url of the git repository of a parachain to be used, with branch/release tag specified as #fragment (e.g. 'https://github.com/org/repository#tag'). A specific binary name can also be optionally specified via query string parameter (e.g. 'https://github.com/org/repository?binaryname#tag'), defaulting to the name of the repository when not specified. - #[arg(short, long)] - parachain: Option>, + /// The configuration file to be used. Only Zombienet configuration files are currently + /// supported. + #[arg(short, long)] + file: String, + /// The version of Polkadot to be used for the relay chain, as per the release tag (e.g. + /// "v1.7.0"). + #[arg(short, long)] + relay_chain: Option, + /// The version of Polkadot to be used for a system parachain, as per the release tag (e.g. + /// "v1.7.0"). + #[arg(short, long)] + system_parachain: Option, + /// The url of the git repository of a parachain to be used, with branch/release tag specified as #fragment (e.g. 'https://github.com/org/repository#tag'). A specific binary name can also be optionally specified via query string parameter (e.g. 'https://github.com/org/repository?binaryname#tag'), defaulting to the name of the repository when not specified. + #[arg(short, long)] + parachain: Option>, } impl ZombienetCommand { - pub(crate) async fn execute(&self) -> anyhow::Result<()> { - clear_screen()?; - intro(format!( - "{}: Deploy a parachain", - style(" Pop CLI ").black().on_magenta() - ))?; - set_theme(Theme); - // Parse arguments - let cache = crate::cache()?; - let mut zombienet = crate::parachains::zombienet::Zombienet::new( - cache.clone(), - &self.file, - self.relay_chain.as_ref(), - self.system_parachain.as_ref(), - self.parachain.as_ref(), - ) - .await?; - // Check if any binaries need to be sourced - let missing = zombienet.missing_binaries(); - if missing.len() > 0 { - log::warning(format!( - "The following missing binaries are required: {}", - missing - .iter() - .map(|b| b.name.as_str()) - .collect::>() - .join(", ") - ))?; - if !confirm("Would you like to source them automatically now?").interact()? { - outro_cancel("Cannot deploy parachain to local network until all required binaries are available.")?; - return Ok(()); - } - log::info(format!( - "They will be cached at {}", - &cache.to_str().unwrap() - ))?; - // Source binaries - for binary in missing { - let mut spinner = cliclack::spinner(); - spinner.start(format!("Sourcing {}...", binary.name)); - // todo: improve progress - binary.source(&cache).await?; - spinner.stop("Sourcing complete"); - } - } - // Finally spawn network and wait for signal to terminate - log::info("Launching local network...")?; - tracing_subscriber::fmt().init(); - match zombienet.spawn().await { - Ok(_network) => { - let mut spinner = cliclack::spinner(); - spinner.start("Local network launched - ctrl-c to terminate."); - tokio::signal::ctrl_c().await?; - outro("Done")?; - } - Err(e) => { - outro_cancel(format!("Could not spawn network: {e}"))?; - } - } + pub(crate) async fn execute(&self) -> anyhow::Result<()> { + clear_screen()?; + intro(format!("{}: Deploy a parachain", style(" Pop CLI ").black().on_magenta()))?; + set_theme(Theme); + // Parse arguments + let cache = crate::cache()?; + let mut zombienet = crate::parachains::zombienet::Zombienet::new( + cache.clone(), + &self.file, + self.relay_chain.as_ref(), + self.system_parachain.as_ref(), + self.parachain.as_ref(), + ) + .await?; + // Check if any binaries need to be sourced + let missing = zombienet.missing_binaries(); + if missing.len() > 0 { + log::warning(format!( + "The following missing binaries are required: {}", + missing.iter().map(|b| b.name.as_str()).collect::>().join(", ") + ))?; + if !confirm("Would you like to source them automatically now?").interact()? { + outro_cancel("Cannot deploy parachain to local network until all required binaries are available.")?; + return Ok(()); + } + log::info(format!("They will be cached at {}", &cache.to_str().unwrap()))?; + // Source binaries + for binary in missing { + let mut spinner = cliclack::spinner(); + spinner.start(format!("Sourcing {}...", binary.name)); + binary.source(&cache).await?; + spinner.stop("Sourcing complete"); + } + } + // Finally spawn network and wait for signal to terminate + log::info("Launching local network...")?; + tracing_subscriber::fmt().init(); + match zombienet.spawn().await { + Ok(_network) => { + let mut spinner = cliclack::spinner(); + spinner.start("Local network launched - ctrl-c to terminate."); + tokio::signal::ctrl_c().await?; + outro("Done")?; + }, + Err(e) => { + outro_cancel(format!("Could not spawn network: {e}"))?; + }, + } - Ok(()) - } + Ok(()) + } } diff --git a/src/engines/contract_engine.rs b/src/engines/contract_engine.rs index 0b1b333a4..158f4b4a4 100644 --- a/src/engines/contract_engine.rs +++ b/src/engines/contract_engine.rs @@ -1,103 +1,86 @@ -use std::path::PathBuf; -use duct::cmd; use cliclack::outro; +use duct::cmd; +use std::path::PathBuf; use contract_build::{ - new_contract_project, execute, - ExecuteArgs, ManifestPath,Verbosity, BuildMode,Features,Network,BuildArtifacts, UnstableFlags, OptimizationPasses, OutputType, Target, - DEFAULT_MAX_MEMORY_PAGES + execute, new_contract_project, BuildArtifacts, BuildMode, ExecuteArgs, Features, ManifestPath, + Network, OptimizationPasses, OutputType, Target, UnstableFlags, Verbosity, + DEFAULT_MAX_MEMORY_PAGES, }; +use contract_extrinsics::{ErrorVariant, InstantiateExec}; +use ink_env::DefaultEnvironment; use sp_weights::Weight; -use contract_extrinsics::{InstantiateExec, ErrorVariant}; use subxt::PolkadotConfig as DefaultConfig; use subxt_signer::sr25519::Keypair; -use ink_env::DefaultEnvironment; - pub fn create_smart_contract(name: String, target: &Option) -> anyhow::Result<()> { - new_contract_project(&name, target.as_ref()) + new_contract_project(&name, target.as_ref()) } pub fn build_smart_contract(path: &Option) -> anyhow::Result<()> { - // If the user specify a path (not current directory) have to manually add Cargo.toml here or ask to the user the specific path - // (Like cargo-contract does) - let manifest_path ; - if path.is_some(){ - let full_path: PathBuf = PathBuf::from(path.as_ref().unwrap().to_string_lossy().to_string() + "/Cargo.toml"); - manifest_path = ManifestPath::try_from(Some(full_path))?; - } - else { - manifest_path = ManifestPath::try_from(path.as_ref())?; - } - - let args = ExecuteArgs { - manifest_path, - verbosity: Verbosity::Default, - build_mode: BuildMode::Release, - features: Features::default(), - network: Network::Online, - build_artifact: BuildArtifacts::All, - unstable_flags: UnstableFlags::default(), - optimization_passes: Some(OptimizationPasses::default()), - keep_debug_symbols: false, - extra_lints: false, - output_type: OutputType::Json, - skip_wasm_validation: false, - target: Target::Wasm, - max_memory_pages: DEFAULT_MAX_MEMORY_PAGES, - image: Default::default(), - }; - execute(args)?; - Ok(()) + // If the user specify a path (not current directory) have to manually add Cargo.toml here or + // ask to the user the specific path (Like cargo-contract does) + let manifest_path; + if path.is_some() { + let full_path: PathBuf = + PathBuf::from(path.as_ref().unwrap().to_string_lossy().to_string() + "/Cargo.toml"); + manifest_path = ManifestPath::try_from(Some(full_path))?; + } else { + manifest_path = ManifestPath::try_from(path.as_ref())?; + } + + let args = ExecuteArgs { + manifest_path, + verbosity: Verbosity::Default, + build_mode: BuildMode::Release, + features: Features::default(), + network: Network::Online, + build_artifact: BuildArtifacts::All, + unstable_flags: UnstableFlags::default(), + optimization_passes: Some(OptimizationPasses::default()), + keep_debug_symbols: false, + extra_lints: false, + output_type: OutputType::Json, + skip_wasm_validation: false, + target: Target::Wasm, + max_memory_pages: DEFAULT_MAX_MEMORY_PAGES, + image: Default::default(), + }; + execute(args)?; + Ok(()) } - pub fn test_smart_contract(path: &Option) -> anyhow::Result<()> { - cmd( - "cargo", - vec![ - "test", - ], - ) - .dir(path.clone().unwrap_or("./".into())) - .run()?; + cmd("cargo", vec!["test"]).dir(path.clone().unwrap_or("./".into())).run()?; - Ok(()) + Ok(()) } pub fn test_e2e_smart_contract(path: &Option) -> anyhow::Result<()> { - cmd( - "cargo", - vec![ - "test", - "--features=e2e-tests" - ], - ) - .dir(path.clone().unwrap_or("./".into())) - .run()?; + cmd("cargo", vec!["test", "--features=e2e-tests"]) + .dir(path.clone().unwrap_or("./".into())) + .run()?; - Ok(()) + Ok(()) } - - -pub async fn instantiate_smart_contract(instantiate_exec: InstantiateExec< - DefaultConfig, - DefaultEnvironment, - Keypair, ->, gas_limit: Weight) -> anyhow::Result<(), ErrorVariant> { - let instantiate_result = instantiate_exec.instantiate(Some(gas_limit)).await?; - outro( - format!("Contract deployed and instantiate: The Contract Address is {:?}", instantiate_result.contract_address.to_string()) - )?; - Ok(()) +pub async fn instantiate_smart_contract( + instantiate_exec: InstantiateExec, + gas_limit: Weight, +) -> anyhow::Result<(), ErrorVariant> { + let instantiate_result = instantiate_exec.instantiate(Some(gas_limit)).await?; + outro(format!( + "Contract deployed and instantiate: The Contract Address is {:?}", + instantiate_result.contract_address.to_string() + ))?; + Ok(()) } pub async fn dry_run_gas_estimate_instantiate( - instantiate_exec: &InstantiateExec, -) -> anyhow::Result { - let instantiate_result = instantiate_exec.instantiate_dry_run().await?; - match instantiate_result.result { + instantiate_exec: &InstantiateExec, +) -> anyhow::Result { + let instantiate_result = instantiate_exec.instantiate_dry_run().await?; + match instantiate_result.result { Ok(_) => { // use user specified values where provided, otherwise use the estimates let ref_time = instantiate_exec @@ -116,28 +99,27 @@ pub async fn dry_run_gas_estimate_instantiate( )) } } - } #[cfg(test)] mod tests { - use super::*; - use tempdir; - use std::fs; + use super::*; + use std::fs; + use tempdir; - #[test] - fn test_create_smart_contract() -> Result<(), Box> { - let temp_dir = tempdir::TempDir::new("test_folder")?; - let result: anyhow::Result<()> = create_smart_contract("test".to_string(),&Some(PathBuf::from(temp_dir.path()))); - assert!(result.is_ok()); + #[test] + fn test_create_smart_contract() -> Result<(), Box> { + let temp_dir = tempdir::TempDir::new("test_folder")?; + let result: anyhow::Result<()> = + create_smart_contract("test".to_string(), &Some(PathBuf::from(temp_dir.path()))); + assert!(result.is_ok()); - // Verify that the generated smart contract contains the expected content - let generated_file_content = - fs::read_to_string(temp_dir.path().join("test/lib.rs"))?; - - assert!(generated_file_content.contains("#[ink::contract]")); - assert!(generated_file_content.contains("mod test {")); - - Ok(()) - } -} \ No newline at end of file + // Verify that the generated smart contract contains the expected content + let generated_file_content = fs::read_to_string(temp_dir.path().join("test/lib.rs"))?; + + assert!(generated_file_content.contains("#[ink::contract]")); + assert!(generated_file_content.contains("mod test {")); + + Ok(()) + } +} diff --git a/src/engines/generator.rs b/src/engines/generator.rs index 21b269c42..dad6dbec0 100644 --- a/src/engines/generator.rs +++ b/src/engines/generator.rs @@ -1,26 +1,23 @@ -//! TODO: Generators should reference files that live in the repository - use std::path::{Path, PathBuf}; use askama::Template; use crate::helpers::write_to_file; -// TODO: This should be coupled with Runtime in the sense that pallets part of a Runtime may need a default genesis config #[derive(Template)] -#[template(path = "vanilla/chain_spec.templ", escape = "none")] +#[template(path = "base/chain_spec.templ", escape = "none")] pub(crate) struct ChainSpec { - pub(crate) token_symbol: String, - pub(crate) decimals: u8, - pub(crate) initial_endowment: String, + pub(crate) token_symbol: String, + pub(crate) decimals: u8, + pub(crate) initial_endowment: String, } #[derive(Template)] #[template(path = "pallet/Cargo.templ", escape = "none")] pub(crate) struct PalletCargoToml { - pub(crate) name: String, - pub(crate) authors: String, - pub(crate) description: String, + pub(crate) name: String, + pub(crate) authors: String, + pub(crate) description: String, } #[derive(Template)] #[template(path = "pallet/src/benchmarking.rs.templ", escape = "none")] @@ -31,46 +28,46 @@ pub(crate) struct PalletLib {} #[derive(Template)] #[template(path = "pallet/src/mock.rs.templ", escape = "none")] pub(crate) struct PalletMock { - pub(crate) module: String, + pub(crate) module: String, } #[derive(Template)] #[template(path = "pallet/src/tests.rs.templ", escape = "none")] pub(crate) struct PalletTests { - pub(crate) module: String, + pub(crate) module: String, } // todo : generate directory structure // todo : This is only for development #[allow(unused)] pub fn generate() { - let cs = ChainSpec { - token_symbol: "DOT".to_owned(), - decimals: 10, - initial_endowment: "1u64 << 15".to_owned(), - }; - let rendered = cs.render().unwrap(); - write_to_file(Path::new("src/x.rs"), &rendered); + let cs = ChainSpec { + token_symbol: "DOT".to_owned(), + decimals: 10, + initial_endowment: "1u64 << 15".to_owned(), + }; + let rendered = cs.render().unwrap(); + write_to_file(Path::new("src/x.rs"), &rendered); } pub trait PalletItem { - /// Render and Write to file, root is the path to the pallet - fn execute(&self, root: &PathBuf) -> anyhow::Result<()>; + /// Render and Write to file, root is the path to the pallet + fn execute(&self, root: &PathBuf) -> anyhow::Result<()>; } macro_rules! generate_pallet_item { - ($item:ty, $filename:expr) => { - impl PalletItem for $item { - fn execute(&self, root: &PathBuf) -> anyhow::Result<()> { - let rendered = self.render()?; - write_to_file(&root.join($filename), &rendered); - Ok(()) - } - } - }; + ($item:ty, $filename:expr) => { + impl PalletItem for $item { + fn execute(&self, root: &PathBuf) -> anyhow::Result<()> { + let rendered = self.render()?; + write_to_file(&root.join($filename), &rendered); + Ok(()) + } + } + }; } generate_pallet_item!(PalletTests, "src/tests.rs"); generate_pallet_item!(PalletMock, "src/mock.rs"); generate_pallet_item!(PalletLib, "src/lib.rs"); generate_pallet_item!(PalletBenchmarking, "src/benchmarking.rs"); -generate_pallet_item!(PalletCargoToml, "Cargo.toml"); \ No newline at end of file +generate_pallet_item!(PalletCargoToml, "Cargo.toml"); diff --git a/src/engines/mod.rs b/src/engines/mod.rs index 0b9df1fc8..a8484b610 100644 --- a/src/engines/mod.rs +++ b/src/engines/mod.rs @@ -1,4 +1,4 @@ -pub mod parachain_engine; -pub mod pallet_engine; pub mod contract_engine; -pub mod generator; \ No newline at end of file +pub mod generator; +pub mod pallet_engine; +pub mod parachain_engine; diff --git a/src/engines/pallet_engine.rs b/src/engines/pallet_engine.rs index e1ceead02..7a7e3e5e3 100644 --- a/src/engines/pallet_engine.rs +++ b/src/engines/pallet_engine.rs @@ -1,72 +1,64 @@ use crate::{ - engines::generator::PalletItem, - helpers::{resolve_pallet_path, sanitize}, + engines::generator::PalletItem, + helpers::{resolve_pallet_path, sanitize}, }; use std::{fs, path::PathBuf}; -pub fn create_pallet_template(path: Option, config: TemplatePalletConfig) -> anyhow::Result<()> { - let target = resolve_pallet_path(path); - // TODO : config.name might use `-` or use snake_case. We want to use pallet_template for the pallet dirs - // and PalletTemplate for the runtime macro - // TODO: this can be further polished (edge cases: no pallet prefix.) - let pallet_name = config.name.clone(); - let pallet_path = target.join(pallet_name.clone()); - sanitize(&pallet_path)?; - generate_pallet_structure(&target, &pallet_name)?; - // todo let pallet_module_name = ... ; - render_pallet(pallet_name, config, &pallet_path)?; - Ok(()) +pub fn create_pallet_template( + path: Option, + config: TemplatePalletConfig, +) -> anyhow::Result<()> { + let target = resolve_pallet_path(path); + let pallet_name = config.name.clone(); + let pallet_path = target.join(pallet_name.clone()); + sanitize(&pallet_path)?; + generate_pallet_structure(&target, &pallet_name)?; + + render_pallet(pallet_name, config, &pallet_path)?; + Ok(()) } pub struct TemplatePalletConfig { - pub(crate) name: String, - pub(crate) authors: String, - pub(crate) description: String, + pub(crate) name: String, + pub(crate) authors: String, + pub(crate) description: String, } -/// Generate a pallet folder and file structure +/// Generate a pallet folder and file structure fn generate_pallet_structure(target: &PathBuf, pallet_name: &str) -> anyhow::Result<()> { - use fs::{create_dir, File}; - let (pallet, src) = ( - target.join(pallet_name), - target.join(pallet_name.to_string() + "/src"), - ); - // println!("source = > {}", src.display()); - create_dir(&pallet)?; - create_dir(&src)?; - File::create(format!("{}/Cargo.toml", pallet.display()))?; - File::create(format!("{}/lib.rs", src.display()))?; - File::create(format!("{}/benchmarking.rs", src.display()))?; - File::create(format!("{}/tests.rs", src.display()))?; - File::create(format!("{}/mock.rs", src.display()))?; - Ok(()) + use fs::{create_dir, File}; + let (pallet, src) = (target.join(pallet_name), target.join(pallet_name.to_string() + "/src")); + create_dir(&pallet)?; + create_dir(&src)?; + File::create(format!("{}/Cargo.toml", pallet.display()))?; + File::create(format!("{}/lib.rs", src.display()))?; + File::create(format!("{}/benchmarking.rs", src.display()))?; + File::create(format!("{}/tests.rs", src.display()))?; + File::create(format!("{}/mock.rs", src.display()))?; + Ok(()) } fn render_pallet( - pallet_name: String, - config: TemplatePalletConfig, - pallet_path: &PathBuf, + pallet_name: String, + config: TemplatePalletConfig, + pallet_path: &PathBuf, ) -> anyhow::Result<()> { - let pallet_name = pallet_name.replace('-', "_"); - use crate::engines::generator::{ - PalletBenchmarking, PalletCargoToml, PalletLib, PalletMock, PalletTests, - }; - // Todo `module` must be of the form Template if pallet_name : `pallet_template` - let pallet: Vec> = vec![ - Box::new(PalletCargoToml { - name: pallet_name.clone(), - authors: config.authors, - description: config.description, - }), - Box::new(PalletLib {}), - Box::new(PalletBenchmarking {}), - Box::new(PalletMock { - module: pallet_name.clone(), - }), - Box::new(PalletTests { - module: pallet_name, - }), - ]; - for item in pallet { - item.execute(pallet_path)?; - } - Ok(()) + let pallet_name = pallet_name.replace('-', "_"); + use crate::engines::generator::{ + PalletBenchmarking, PalletCargoToml, PalletLib, PalletMock, PalletTests, + }; + // Todo `module` must be of the form Template if pallet_name : `pallet_template` + let pallet: Vec> = vec![ + Box::new(PalletCargoToml { + name: pallet_name.clone(), + authors: config.authors, + description: config.description, + }), + Box::new(PalletLib {}), + Box::new(PalletBenchmarking {}), + Box::new(PalletMock { module: pallet_name.clone() }), + Box::new(PalletTests { module: pallet_name }), + ]; + for item in pallet { + item.execute(pallet_path)?; + } + Ok(()) } diff --git a/src/engines/parachain_engine.rs b/src/engines/parachain_engine.rs index 29d054ece..420a8788a 100644 --- a/src/engines/parachain_engine.rs +++ b/src/engines/parachain_engine.rs @@ -1,108 +1,103 @@ use crate::{ - commands::new::parachain::Template, - engines::generator::ChainSpec, - helpers::{clone_and_degit, sanitize, write_to_file}, + commands::new::parachain::Template, + engines::generator::ChainSpec, + helpers::{clone_and_degit, sanitize, write_to_file}, }; use anyhow::Result; +use duct::cmd; use git2::Repository; -use std::{fs, path::{Path, PathBuf}}; +use std::{ + fs, + path::{Path, PathBuf}, +}; use walkdir::WalkDir; -use duct::cmd; #[derive(Debug, Clone)] pub struct Config { - pub(crate) symbol: String, - pub(crate) decimals: u8, - pub(crate) initial_endowment: String, + pub(crate) symbol: String, + pub(crate) decimals: u8, + pub(crate) initial_endowment: String, } /// Creates a new template at `target` dir pub fn instantiate_template_dir(template: &Template, target: &Path, config: Config) -> Result<()> { - sanitize(target)?; - use Template::*; - let url = match template { - EPT => "https://github.com/paritytech/extended-parachain-template.git", - FPT => "https://github.com/paritytech/frontier-parachain-template.git", - Contracts => "https://github.com/paritytech/substrate-contracts-node.git", - Vanilla => { - return instantiate_vanilla_template(target, config); - } - }; - clone_and_degit(url, target)?; - Repository::init(target)?; - Ok(()) + sanitize(target)?; + use Template::*; + let url = match template { + FPT => "https://github.com/paritytech/frontier-parachain-template.git", + Contracts => "https://github.com/paritytech/substrate-contracts-node.git", + Base => { + return instantiate_base_template(target, config); + }, + }; + clone_and_degit(url, target)?; + Repository::init(target)?; + Ok(()) } -// TODO: The config will shape the emitted template -pub fn instantiate_vanilla_template(target: &Path, config: Config) -> Result<()> { - let temp_dir = ::tempfile::TempDir::new_in(std::env::temp_dir())?; - let source = temp_dir.path(); - // println!("Temporary directory created at {:?}", temp_path); - clone_and_degit("https://github.com/r0guelabs/vanilla-parachain.git", source)?; - for entry in WalkDir::new(&source) { - let entry = entry?; +pub fn instantiate_base_template(target: &Path, config: Config) -> Result<()> { + let temp_dir = ::tempfile::TempDir::new_in(std::env::temp_dir())?; + let source = temp_dir.path(); + clone_and_degit("https://github.com/r0gue-io/base-parachain", source)?; + + for entry in WalkDir::new(&source) { + let entry = entry?; - let source_path = entry.path(); - let destination_path = target.join(source_path.strip_prefix(&source)?); + let source_path = entry.path(); + let destination_path = target.join(source_path.strip_prefix(&source)?); - if entry.file_type().is_dir() { - fs::create_dir_all(&destination_path)?; - } else { - fs::copy(source_path, &destination_path)?; - } - } - let chainspec = ChainSpec { - token_symbol: config.symbol, - decimals: config.decimals, - initial_endowment: config.initial_endowment, - }; - use askama::Template; - write_to_file( - &target.join("node/src/chain_spec.rs"), - chainspec.render().expect("infallible").as_ref(), - ); - Repository::init(target)?; - Ok(()) + if entry.file_type().is_dir() { + fs::create_dir_all(&destination_path)?; + } else { + fs::copy(source_path, &destination_path)?; + } + } + let chainspec = ChainSpec { + token_symbol: config.symbol, + decimals: config.decimals, + initial_endowment: config.initial_endowment, + }; + use askama::Template; + write_to_file( + &target.join("node/src/chain_spec.rs"), + chainspec.render().expect("infallible").as_ref(), + ); + Repository::init(target)?; + Ok(()) } pub fn build_parachain(path: &Option) -> anyhow::Result<()> { - cmd( - "cargo", - vec![ - "build", - "--release", - ], - ) - .dir(path.clone().unwrap_or("./".into())) - .run()?; + cmd("cargo", vec!["build", "--release"]) + .dir(path.clone().unwrap_or("./".into())) + .run()?; - Ok(()) + Ok(()) } #[cfg(test)] mod tests { - use super::*; - use tempdir; - use std::fs; + use super::*; + use std::fs; + use tempdir; - #[test] - fn test_instantiate_template_dir_vanilla() -> Result<(), Box> { - let temp_dir = tempdir::TempDir::new("vanilla_template")?; - let config = Config { - symbol: "DOT".to_string(), - decimals: 18, - initial_endowment: "1000000000000000000000000".to_string(), - }; - let result: Result<()> = instantiate_vanilla_template(temp_dir.path(), config); - assert!(result.is_ok()); + #[test] + fn test_instantiate_template_dir_base() -> Result<(), Box> { + let temp_dir = tempdir::TempDir::new("base_template")?; + let config = Config { + symbol: "DOT".to_string(), + decimals: 18, + initial_endowment: "1000000000000000000000000".to_string(), + }; + let result: Result<()> = instantiate_base_template(temp_dir.path(), config); + assert!(result.is_ok()); - // Verify that the generated chain_spec.rs file contains the expected content - let generated_file_content = - fs::read_to_string(temp_dir.path().join("node/src/chain_spec.rs"))?; - assert!(generated_file_content.contains("DOT")); - assert!(generated_file_content.contains("18")); - assert!(generated_file_content.contains("1000000000000000000000000")); + // Verify that the generated chain_spec.rs file contains the expected content + let generated_file_content = + fs::read_to_string(temp_dir.path().join("node/src/chain_spec.rs"))?; + assert!(generated_file_content.contains("DOT")); + assert!(generated_file_content.contains("18")); + assert!(generated_file_content.contains("1000000000000000000000000")); - Ok(()) - } + Ok(()) + } } diff --git a/src/git.rs b/src/git.rs index 03f33b395..0156bccd1 100644 --- a/src/git.rs +++ b/src/git.rs @@ -7,69 +7,67 @@ use url::Url; pub(crate) struct Git; impl Git { - pub(crate) fn clone(url: &Url, working_dir: &Path, branch: Option<&str>) -> Result<()> { - if !working_dir.exists() { - trace!("cloning {url}..."); - let mut fo = FetchOptions::new(); - fo.depth(1); - let mut repo = RepoBuilder::new(); - repo.fetch_options(fo); - if let Some(branch) = branch { - repo.branch(branch); - } - repo.clone(url.as_str(), working_dir)?; - } - Ok(()) - } + pub(crate) fn clone(url: &Url, working_dir: &Path, branch: Option<&str>) -> Result<()> { + if !working_dir.exists() { + trace!("cloning {url}..."); + let mut fo = FetchOptions::new(); + fo.depth(1); + let mut repo = RepoBuilder::new(); + repo.fetch_options(fo); + if let Some(branch) = branch { + repo.branch(branch); + } + repo.clone(url.as_str(), working_dir)?; + } + Ok(()) + } } pub struct GitHub; type Tag = String; impl GitHub { - pub async fn get_latest_release(repo: &Url) -> Result { - static APP_USER_AGENT: &str = - concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION")); + pub async fn get_latest_release(repo: &Url) -> Result { + static APP_USER_AGENT: &str = + concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION")); - let client = reqwest::ClientBuilder::new() - .user_agent(APP_USER_AGENT) - .build()?; - let response = client - .get(format!( - "https://api.github.com/repos/{}/{}/releases/latest", - Self::org(repo)?, - Self::name(repo)? - )) - .send() - .await?; - let value = response.json::().await?; - value - .get("tag_name") - .and_then(|v| v.as_str()) - .map(|v| v.to_owned()) - .ok_or(anyhow!("the github release tag was not found")) - } + let client = reqwest::ClientBuilder::new().user_agent(APP_USER_AGENT).build()?; + let response = client + .get(format!( + "https://api.github.com/repos/{}/{}/releases/latest", + Self::org(repo)?, + Self::name(repo)? + )) + .send() + .await?; + let value = response.json::().await?; + value + .get("tag_name") + .and_then(|v| v.as_str()) + .map(|v| v.to_owned()) + .ok_or(anyhow!("the github release tag was not found")) + } - fn org(repo: &Url) -> Result<&str> { - let path_segments = repo - .path_segments() - .map(|c| c.collect::>()) - .expect("repository must have path segments"); - Ok(path_segments.get(0).ok_or(anyhow!( - "the organization (or user) is missing from the github url" - ))?) - } + fn org(repo: &Url) -> Result<&str> { + let path_segments = repo + .path_segments() + .map(|c| c.collect::>()) + .expect("repository must have path segments"); + Ok(path_segments + .get(0) + .ok_or(anyhow!("the organization (or user) is missing from the github url"))?) + } - pub(crate) fn name(repo: &Url) -> Result<&str> { - let path_segments = repo - .path_segments() - .map(|c| c.collect::>()) - .expect("repository must have path segments"); - Ok(path_segments.get(1).ok_or(anyhow!( - "the repository name is missing from the github url" - ))?) - } + pub(crate) fn name(repo: &Url) -> Result<&str> { + let path_segments = repo + .path_segments() + .map(|c| c.collect::>()) + .expect("repository must have path segments"); + Ok(path_segments + .get(1) + .ok_or(anyhow!("the repository name is missing from the github url"))?) + } - pub(crate) fn release(repo: &Url, tag: &str, artifact: &str) -> String { - format!("{}/releases/download/{tag}/{artifact}", repo.as_str()) - } + pub(crate) fn release(repo: &Url, tag: &str, artifact: &str) -> String { + format!("{}/releases/download/{tag}/{artifact}", repo.as_str()) + } } diff --git a/src/helpers.rs b/src/helpers.rs index 20db473a8..da3a61570 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -1,77 +1,67 @@ use anyhow::Result; +use cliclack::{log, outro_cancel}; use git2::Repository; use std::{ - env::current_dir, - fs::{self, OpenOptions}, - path::{Path, PathBuf}, + env::current_dir, + fs::{self, OpenOptions}, + path::{Path, PathBuf}, }; - pub(crate) fn sanitize(target: &Path) -> Result<()> { - use std::io::{stdin, stdout, Write}; - if target.exists() { - print!( - "\"{}\" folder exists. Do you want to clean it? [y/n]: ", - target.display() - ); - stdout().flush()?; + use std::io::{stdin, stdout, Write}; + if target.exists() { + print!("\"{}\" folder exists. Do you want to clean it? [y/n]: ", target.display()); + stdout().flush()?; - let mut input = String::new(); - stdin().read_line(&mut input)?; + let mut input = String::new(); + stdin().read_line(&mut input)?; - if input.trim().to_lowercase() == "y" { - fs::remove_dir_all(target)?; - } else { - return Err(anyhow::anyhow!( - "User aborted due to existing target folder." - )); - } - } - Ok(()) + if input.trim().to_lowercase() == "y" { + fs::remove_dir_all(target)?; + } else { + return Err(anyhow::anyhow!("User aborted due to existing target folder.")); + } + } + Ok(()) } -// TODO: Check the usage of `expect`. We don't want to leave the outdir in a unhygenic state pub(crate) fn write_to_file<'a>(path: &Path, contents: &'a str) { - println!("Writing to {}", path.display()); - use std::io::Write; - let mut file = OpenOptions::new() - .write(true) - .truncate(true) - .open(path) - .unwrap(); - file.write_all(contents.as_bytes()).unwrap(); - if path.extension().map_or(false, |ext| ext == "rs") { - let output = std::process::Command::new("rustfmt") - .arg(path.to_str().unwrap()) - .output() - .expect("failed to execute rustfmt"); - - if !output.status.success() { - eprintln!("rustfmt exited with non-zero status code."); - } - } + log::info(format!("Writing to {}", path.display())).ok(); + use std::io::Write; + let mut file = OpenOptions::new().write(true).truncate(true).open(path).unwrap(); + file.write_all(contents.as_bytes()).unwrap(); + if path.extension().map_or(false, |ext| ext == "rs") { + let output = std::process::Command::new("rustfmt") + .arg(path.to_str().unwrap()) + .output() + .expect("failed to execute rustfmt"); + + if !output.status.success() { + outro_cancel("rustfmt exited with non-zero status code.").ok(); + } + } } /// Clone `url` into `target` and degit it pub(crate) fn clone_and_degit(url: &str, target: &Path) -> Result<()> { - let repo = Repository::clone(url, target)?; - let git_dir = repo.path(); - fs::remove_dir_all(&git_dir)?; - Ok(()) + let repo = Repository::clone(url, target)?; + let git_dir = repo.path(); + fs::remove_dir_all(&git_dir)?; + Ok(()) } /// Resolve pallet path /// For a template it should be `