diff --git a/CHANGELOG.md b/CHANGELOG.md index 51debc367..14c868d15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add `verify` command - [#1306](https://github.com/paritytech/cargo-contract/pull/1306) - Add `--binary` flag for `info` command - [#1311](https://github.com/paritytech/cargo-contract/pull/1311/) - Add `--all` flag for `info` command - [#1319](https://github.com/paritytech/cargo-contract/pull/1319) +- Fix for a Url to String conversion in `info` command - [#1330](https://github.com/paritytech/cargo-contract/pull/1330) ## [4.0.0-alpha] diff --git a/crates/cargo-contract/src/cmd/info.rs b/crates/cargo-contract/src/cmd/info.rs index a5d5b393c..9bdfa2d87 100644 --- a/crates/cargo-contract/src/cmd/info.rs +++ b/crates/cargo-contract/src/cmd/info.rs @@ -27,6 +27,7 @@ use contract_extrinsics::{ fetch_all_contracts, fetch_contract_info, fetch_wasm_code, + url_to_string, ErrorVariant, }; use std::{ @@ -70,7 +71,8 @@ pub struct InfoCommand { impl InfoCommand { pub async fn run(&self) -> Result<(), ErrorVariant> { - let client = OnlineClient::::from_url(&self.url).await?; + let client = + OnlineClient::::from_url(url_to_string(&self.url)).await?; // All flag applied if self.all { diff --git a/crates/extrinsics/src/call.rs b/crates/extrinsics/src/call.rs index e29fbece3..3b614883f 100644 --- a/crates/extrinsics/src/call.rs +++ b/crates/extrinsics/src/call.rs @@ -178,8 +178,8 @@ impl CallCommandBuilder { let signer = self.opts.extrinsic_opts.signer()?; - let url = self.opts.extrinsic_opts.url_to_string(); - let client = OnlineClient::from_url(url.clone()).await?; + let url = self.opts.extrinsic_opts.url(); + let client = OnlineClient::from_url(url).await?; Ok(CallExec { contract: self.opts.contract.clone(), message: self.opts.message.clone(), @@ -221,7 +221,7 @@ impl CallExec { /// Returns the dry run simulation result of type [`ContractExecResult`], which /// includes information about the simulated call, or an error in case of failure. pub async fn call_dry_run(&self) -> Result> { - let url = self.opts.url_to_string(); + let url = self.opts.url(); let token_metadata = TokenMetadata::query(&self.client).await?; let storage_deposit_limit = self .opts diff --git a/crates/extrinsics/src/extrinsic_opts.rs b/crates/extrinsics/src/extrinsic_opts.rs index 7bcb3f5a9..7f4096fc9 100644 --- a/crates/extrinsics/src/extrinsic_opts.rs +++ b/crates/extrinsics/src/extrinsic_opts.rs @@ -28,6 +28,7 @@ use anyhow::{ }; use crate::{ + url_to_string, Balance, BalanceVariant, ContractArtifacts, @@ -169,18 +170,6 @@ impl ExtrinsicOpts { Ok(keypair) } - /// Convert URL to String without omitting the default port - pub fn url_to_string(&self) -> String { - let mut res = self.url.to_string(); - match (self.url.port(), self.url.port_or_known_default()) { - (None, Some(port)) => { - res.insert_str(res.len() - 1, &format!(":{port}")); - res - } - _ => res, - } - } - /// Return the file path of the contract artifact. pub fn file(&self) -> Option<&PathBuf> { self.file.as_ref() @@ -192,8 +181,8 @@ impl ExtrinsicOpts { } /// Return the URL of the substrate node. - pub fn url(&self) -> &Url { - &self.url + pub fn url(&self) -> String { + url_to_string(&self.url) } /// Return the secret URI of the signer. diff --git a/crates/extrinsics/src/instantiate.rs b/crates/extrinsics/src/instantiate.rs index 178f9e087..b0a92c73b 100644 --- a/crates/extrinsics/src/instantiate.rs +++ b/crates/extrinsics/src/instantiate.rs @@ -165,7 +165,7 @@ impl InstantiateCommandBuilder { let transcoder = artifacts.contract_transcoder()?; let data = transcoder.encode(&self.opts.constructor, &self.opts.args)?; let signer = self.opts.extrinsic_opts.signer()?; - let url = self.opts.extrinsic_opts.url_to_string(); + let url = self.opts.extrinsic_opts.url(); let code = if let Some(code) = artifacts.code { Code::Upload(code.0) } else { @@ -174,7 +174,7 @@ impl InstantiateCommandBuilder { }; let salt = self.opts.salt.clone().map(|s| s.0).unwrap_or_default(); - let client = OnlineClient::from_url(url.clone()).await?; + let client = OnlineClient::from_url(&url).await?; let token_metadata = TokenMetadata::query(&client).await?; diff --git a/crates/extrinsics/src/lib.rs b/crates/extrinsics/src/lib.rs index c8c3d3f56..ca91641a8 100644 --- a/crates/extrinsics/src/lib.rs +++ b/crates/extrinsics/src/lib.rs @@ -427,6 +427,21 @@ pub async fn fetch_all_contracts( Ok(contracts) } +// Converts a Url into a String representation without excluding the default port. +pub fn url_to_string(url: &url::Url) -> String { + match (url.port(), url.port_or_known_default()) { + (None, Some(port)) => { + format!( + "{}:{port}{}", + &url[..url::Position::AfterHost], + &url[url::Position::BeforePath..] + ) + .to_string() + } + _ => url.to_string(), + } +} + /// Copy of `pallet_contracts_primitives::StorageDeposit` which implements `Serialize`, /// required for json output. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, serde::Serialize)] @@ -473,4 +488,27 @@ mod tests { ) .is_ok()) } + + #[test] + fn url_to_string_works() { + // with custom port + let url = url::Url::parse("ws://127.0.0.1:9944").unwrap(); + assert_eq!(url_to_string(&url), "ws://127.0.0.1:9944/"); + + // with default port + let url = url::Url::parse("wss://127.0.0.1:443").unwrap(); + assert_eq!(url_to_string(&url), "wss://127.0.0.1:443/"); + + // with default port and path + let url = url::Url::parse("wss://127.0.0.1:443/test/1").unwrap(); + assert_eq!(url_to_string(&url), "wss://127.0.0.1:443/test/1"); + + // with default port and domain + let url = url::Url::parse("wss://test.io:443").unwrap(); + assert_eq!(url_to_string(&url), "wss://test.io:443/"); + + // with default port, domain and path + let url = url::Url::parse("wss://test.io/test/1").unwrap(); + assert_eq!(url_to_string(&url), "wss://test.io:443/test/1"); + } } diff --git a/crates/extrinsics/src/remove.rs b/crates/extrinsics/src/remove.rs index 47ebf14fb..46efd23cc 100644 --- a/crates/extrinsics/src/remove.rs +++ b/crates/extrinsics/src/remove.rs @@ -118,8 +118,8 @@ impl RemoveCommandBuilder { artifacts_path.display() )), }?; - let url = self.opts.extrinsic_opts.url_to_string(); - let client = OnlineClient::from_url(url.clone()).await?; + let url = self.opts.extrinsic_opts.url(); + let client = OnlineClient::from_url(url).await?; Ok(RemoveExec { final_code_hash, diff --git a/crates/extrinsics/src/upload.rs b/crates/extrinsics/src/upload.rs index 70fb66cc1..55c0e9702 100644 --- a/crates/extrinsics/src/upload.rs +++ b/crates/extrinsics/src/upload.rs @@ -105,8 +105,8 @@ impl UploadCommandBuilder { artifacts_path.display() ) })?; - let url = self.opts.extrinsic_opts.url_to_string(); - let client = OnlineClient::from_url(url.clone()).await?; + let url = self.opts.extrinsic_opts.url(); + let client = OnlineClient::from_url(url).await?; Ok(UploadExec { opts: self.opts.extrinsic_opts.clone(), client, @@ -131,7 +131,7 @@ impl UploadExec { /// then sends the request using the provided URL. This operation does not modify /// the state of the blockchain. pub async fn upload_code_rpc(&self) -> Result> { - let url = self.opts.url_to_string(); + let url = self.opts.url(); let token_metadata = TokenMetadata::query(&self.client).await?; let storage_deposit_limit = self .opts