From 9f7f430d33ee762a67cae08410d165741c1b0b87 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Wed, 11 Dec 2024 12:52:22 +0100 Subject: [PATCH 01/27] chore: get_payload_works --- crates/pop-contracts/src/up.rs | 59 ++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/crates/pop-contracts/src/up.rs b/crates/pop-contracts/src/up.rs index dd186395..216b833b 100644 --- a/crates/pop-contracts/src/up.rs +++ b/crates/pop-contracts/src/up.rs @@ -384,6 +384,12 @@ mod tests { run_contracts_node, }; use anyhow::Result; + use reqwest::get; + use std::{env, fs, process::Command}; + use subxt::{ + config::{substrate::BlakeTwo256, Hasher}, + utils::to_hex, + }; use pop_common::{find_free_port, set_executable_permission}; use std::{env, process::Command, time::Duration}; use tokio::time::sleep; @@ -439,30 +445,35 @@ mod tests { Ok(()) } - // #[tokio::test] - // async fn get_payload_works() -> Result<()> { - // let temp_dir = new_environment("testing")?; - // let current_dir = env::current_dir().expect("Failed to get current directory"); - // mock_build_process( - // temp_dir.path().join("testing"), - // current_dir.join("./tests/files/testing.contract"), - // current_dir.join("./tests/files/testing.json"), - // )?; - // let up_opts = UpOpts { - // path: Some(temp_dir.path().join("testing")), - // constructor: "new".to_string(), - // args: ["false".to_string()].to_vec(), - // value: "1000".to_string(), - // gas_limit: None, - // proof_size: None, - // salt: None, - // url: Url::parse(CONTRACTS_NETWORK_URL)?, - // suri: "//Alice".to_string(), - // }; - // let call_data = get_upload_payload(up_opts, CONTRACTS_NETWORK_URL).await?; - // // println!("{:?}", call_data); - // Ok(()) - // } + #[tokio::test] + async fn get_payload_works() -> Result<()> { + let temp_dir = new_environment("testing")?; + let current_dir = env::current_dir().expect("Failed to get current directory"); + mock_build_process( + temp_dir.path().join("testing"), + current_dir.join("./tests/files/testing.contract"), + current_dir.join("./tests/files/testing.json"), + )?; + let up_opts = UpOpts { + path: Some(temp_dir.path().join("testing")), + constructor: "new".to_string(), + args: ["false".to_string()].to_vec(), + value: "1000".to_string(), + gas_limit: None, + proof_size: None, + salt: None, + url: Url::parse(CONTRACTS_NETWORK_URL)?, + suri: "//Alice".to_string(), + }; + let contract_code = get_contract_code(up_opts.path.as_ref()).await?; + let call_data = get_upload_payload(contract_code, CONTRACTS_NETWORK_URL).await?; + let payload_hash = BlakeTwo256::hash(&call_data).to_string(); + // We know that for the above opts the payload hash should be: + // 0x4e4ff6ad411346d4cd6cf9bcc9101360e4657f776b0af3b46bfe780b0413e819 + assert!(payload_hash.starts_with("0x4e4f")); + assert!(payload_hash.ends_with("e819")); + Ok(()) + } #[tokio::test] async fn dry_run_gas_estimate_instantiate_works() -> Result<()> { From 1485dfa5f0ffbcd99418aaa34c57c03f96c0aa02 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Thu, 12 Dec 2024 10:45:45 +0100 Subject: [PATCH 02/27] test(wallet-integration): up contract get payload works --- crates/pop-contracts/Cargo.toml | 3 ++- crates/pop-contracts/src/up.rs | 22 +++++++++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/crates/pop-contracts/Cargo.toml b/crates/pop-contracts/Cargo.toml index 3d4f15fb..5a8f8180 100644 --- a/crates/pop-contracts/Cargo.toml +++ b/crates/pop-contracts/Cargo.toml @@ -33,7 +33,7 @@ subxt.workspace = true # cargo-contracts contract-build.workspace = true contract-extrinsics.workspace = true -contract-transcode.workspace = true +contract-transcode.workspace = true scale-info.workspace = true # pop pop-common = { path = "../pop-common", version = "0.5.0" } @@ -42,3 +42,4 @@ pop-common = { path = "../pop-common", version = "0.5.0" } dirs.workspace = true mockito.workspace = true tokio-test.workspace = true +hex.workspace = true diff --git a/crates/pop-contracts/src/up.rs b/crates/pop-contracts/src/up.rs index 216b833b..3344c5da 100644 --- a/crates/pop-contracts/src/up.rs +++ b/crates/pop-contracts/src/up.rs @@ -384,14 +384,13 @@ mod tests { run_contracts_node, }; use anyhow::Result; - use reqwest::get; - use std::{env, fs, process::Command}; + use hex::FromHex; + use pop_common::{find_free_port, set_executable_permission}; + use std::{env, process::Command, time::Duration}; use subxt::{ config::{substrate::BlakeTwo256, Hasher}, - utils::to_hex, + utils::{to_hex, H256}, }; - use pop_common::{find_free_port, set_executable_permission}; - use std::{env, process::Command, time::Duration}; use tokio::time::sleep; use url::Url; @@ -467,11 +466,16 @@ mod tests { }; let contract_code = get_contract_code(up_opts.path.as_ref()).await?; let call_data = get_upload_payload(contract_code, CONTRACTS_NETWORK_URL).await?; - let payload_hash = BlakeTwo256::hash(&call_data).to_string(); + let payload_hash = BlakeTwo256::hash(&call_data); // We know that for the above opts the payload hash should be: - // 0x4e4ff6ad411346d4cd6cf9bcc9101360e4657f776b0af3b46bfe780b0413e819 - assert!(payload_hash.starts_with("0x4e4f")); - assert!(payload_hash.ends_with("e819")); + // 0x98c24584107b3a01d12e8e02c0bb634d15dc86123c44d186206813ede42f478d + let expected_hash: H256 = H256::from( + <[u8; 32]>::from_hex( + "98c24584107b3a01d12e8e02c0bb634d15dc86123c44d186206813ede42f478d", + ) + .expect("Invalid hex string"), + ); + assert_eq!(expected_hash, payload_hash); Ok(()) } From 55addf5bb35ccf53e4c2380a6e6016b0a6fed1d4 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Thu, 12 Dec 2024 13:25:51 +0100 Subject: [PATCH 03/27] get paylaod from server works --- crates/pop-cli/src/commands/up/contract.rs | 144 +++++++++++++++++- crates/pop-contracts/tests/files/testing.wasm | Bin 3710 -> 0 bytes 2 files changed, 143 insertions(+), 1 deletion(-) diff --git a/crates/pop-cli/src/commands/up/contract.rs b/crates/pop-cli/src/commands/up/contract.rs index 14eed8dc..22813c25 100644 --- a/crates/pop-cli/src/commands/up/contract.rs +++ b/crates/pop-cli/src/commands/up/contract.rs @@ -397,8 +397,31 @@ fn display_contract_info(spinner: &ProgressBar, address: String, code_hash: Opti #[cfg(test)] mod tests { use super::*; + use crate::wallet_integration::TransactionData; + use pop_common::{find_free_port, set_executable_permission}; + use pop_contracts::{contracts_node_generator, mock_build_process, new_environment}; + use std::{env, process::Command, time::Duration}; + use subxt::utils::to_hex; + use subxt_signer::sr25519::dev; + use tokio::time::sleep; use url::Url; + use subxt::{config::DefaultExtrinsicParamsBuilder as Params, tx::Payload}; + // This struct implements the [`Payload`] trait and is used to submit + // pre-encoded SCALE call data directly, without the dynamic construction of transactions. + struct CallData(Vec); + + impl Payload for CallData { + fn encode_call_data_to( + &self, + _: &subxt::Metadata, + out: &mut Vec, + ) -> Result<(), subxt::ext::subxt_core::Error> { + out.extend_from_slice(&self.0); + Ok(()) + } + } + fn default_up_contract_command() -> UpContractCommand { UpContractCommand { path: None, @@ -417,6 +440,53 @@ mod tests { } } + // This is a helper function to test the waller integration server. + // Given some preconfigured UpContractCommand, the command is executed and the payload is + // requested to the wallet integration http server. + // After retrievign the payload will sign and send it back to the server in order to kill the + // process. + async fn run_server_and_retrive_payload( + up_config: UpContractCommand, + ) -> anyhow::Result { + const WALLET_INT_URI: &str = "http://127.0.0.1:9090"; + + let task_handle = tokio::spawn(up_config.clone().execute()); + + // Wait a moment for the server to start + sleep(Duration::from_millis(10000)).await; + + let pre_sign_payload = reqwest::get(&format!("{}/payload", WALLET_INT_URI)) + .await + .expect("Failed to get payload") + .json::() + .await + .expect("Failed to parse payload"); + + // Submit signed payload to kill the process. + + let rpc_client = subxt::backend::rpc::RpcClient::from_url(up_config.url).await?; + let client = + subxt::OnlineClient::::from_rpc_client(rpc_client).await?; + + let signer = dev::alice(); + + let payload = CallData(pre_sign_payload.call_data()); + let ext_params = Params::new().build(); + let signed = client.tx().create_signed(&payload, &signer, ext_params).await?; + + let _ = reqwest::Client::new() + .post(&format!("{}/submit", WALLET_INT_URI)) + .json(&to_hex(signed.encoded())) + .send() + .await + .expect("Failed to submit payload") + .text() + .await + .expect("Failed to parse JSON response"); + + Ok(pre_sign_payload) + } + #[test] fn conversion_up_contract_command_to_up_opts_works() -> anyhow::Result<()> { let command = default_up_contract_command(); @@ -438,8 +508,80 @@ mod tests { Ok(()) } + #[tokio::test] async fn get_upload_call_data_works() -> anyhow::Result<()> { - todo!() + let random_port = find_free_port(); + let localhost_url = format!("ws://127.0.0.1:{}", random_port); + let temp_dir = new_environment("testing")?; + let current_dir = env::current_dir().expect("Failed to get current directory"); + mock_build_process( + temp_dir.path().join("testing"), + current_dir.join("../pop-contracts/tests/files/testing.contract"), + current_dir.join("../pop-contracts/tests/files/testing.json"), + )?; + + const WALLET_INT_URI: &str = "http://127.0.0.1:9090"; + + let up_contract_opts = UpContractCommand { + path: Some(temp_dir.path().join("testing")), + constructor: "new".to_string(), + args: vec![], + value: "0".to_string(), + gas_limit: None, + proof_size: None, + salt: None, + url: Url::parse(&localhost_url).expect("default url is valid"), + suri: "//Alice".to_string(), + dry_run: false, + upload_only: true, + skip_confirm: true, + use_wallet: true, + }; + + let task_handle = tokio::spawn(up_contract_opts.clone().execute()); + + // Wait a moment for the server to start + sleep(Duration::from_millis(10000)).await; + + // Calculate the expected call data based on the above command options. + let (expected_call_data, _) = match up_contract_opts.get_contract_data().await { + Ok(data) => data, + Err(e) => { + error(format!("An error occurred getting the call data: {e}"))?; + return Err(e); + }, + }; + + let pre_sign_payload = reqwest::get(&format!("{}/payload", WALLET_INT_URI)) + .await + .expect("Failed to get payload") + .json::() + .await + .expect("Failed to parse payload"); + + let rpc_client = subxt::backend::rpc::RpcClient::from_url(&up_contract_opts.url).await?; + let client = + subxt::OnlineClient::::from_rpc_client(rpc_client).await?; + + let signer = dev::alice(); + + let payload = CallData(pre_sign_payload.call_data()); + let ext_params = Params::new().build(); + let signed = client.tx().create_signed(&payload, &signer, ext_params).await?; + + let _ = reqwest::Client::new() + .post(&format!("{}/submit", WALLET_INT_URI)) + .json(&to_hex(signed.encoded())) + .send() + .await + .expect("Failed to submit payload") + .text() + .await + .expect("Failed to parse JSON response"); + + assert_eq!(expected_call_data, pre_sign_payload.call_data()); + + Ok(()) } async fn get_instantiate_call_data_works() -> anyhow::Result<()> { diff --git a/crates/pop-contracts/tests/files/testing.wasm b/crates/pop-contracts/tests/files/testing.wasm index 430888669464e770d310139f29e8af1ebf865ba4..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 GIT binary patch literal 0 HcmV?d00001 literal 3710 zcmb_fO>ZPu6}|7Hx~pC8aXC1S84uE{iiI30?T;bxhzSyYkzz9%A+uqL>>j(uxZBen zSNAv>DN1{y2#GCQ#0H5i8-4|1#S$U0VGA2J2nk5ed9T|aN+LFl<*Daa@1A?_x#!;3 zE#2WWB_isb)`1?6<-m-`V>LbyIj~r9$(_kxa-hOX?BcK*>ro>aR^8Lh?6?~34@YNp z_qY-h_BN7}!Sfd*k?`03Z2099*z2C|*VX7nJrEnM<}bRZFRJ}f-5m^{R&`w+iI{3| z(RfxpJF8!6rE~MfVxsU*8i-r0G*gWXMC-<)87qHzX|u8Tf4@rjxcoH9n)BKoc27^` zn~kID`RUn9xjXaUrN!69DQ9-iF>FHZX2 zoR>+jFisVgZwwAP!(-anj>tn1XT9p-t>%NKnKQ28l0E=GJ}*;j0$#bKS0;e_0Jce? zBG3=pKyzwU%a%rT-u4QF$cLE~1m_Y$*tietQQ7oM=S2&#HTzsOorQ5>r*N=#*0nAI zW@%k>RDTU}1F;kc(;+~lt6c+01Q;9BQP zJgAPeA85lN+6ms3h;YK42}eV!npF4877Hr2Db zo1sVqd%(S+6dZ{Xi7JaWKpB-nVI%>cE9+891aw{lswp5C9Yw7emt0J>a*ge>9z@cj zRuWVRe?gRi06;+FfnDStV+^_9(9IMFNhU!hR7ew%LA;<2+=j*qX$FO$nQk`~_=L+q zAOduHLf{NG0m>?slmMGb2c>}f|JhX3Rhh-6g7pXu2A)#HWkXXXE}J%0fQwC)UNu$n zwM}(J6awT7LDNqe+G~@s8|1L5Ch3J%Z)RTUu^yXk1foA^tGm!0l!j3SPS{I)U*7pqR3A@Pcalxt>?~of6Z>3xev%T=q~D zUvjcc{Quy}|HOVv&+6@9Ka1wd?*zH5>e(nGAUK)9ct_o%b`_XbX5B9xmfqyPQZ}u9mW9#KT5f2sSZ%Fn% zW{TMk3i+;ps?gQoUWcPBpZ`zT*BPgR(<~@br|~at$=d1nFE7;toq|O`fqOO#+PSp( zyxyi%)3U+GY#G=L+J#yWBq+iFN3VcH#*YSN?Ub`QB?f?K2SA{(00|3>VnD*09Z7|g ze%6NW(I`f;G$fxdX20fj0=74%Y$Mbyy%J7}U%_X9TE;Wxrm8s z#1kk+nYtwZ29+1i8^3f>pzVErftnbfUK9=XI1HD1_&8ufn;XBr3k&1_D)IR@*+p&s zsdj5jZwvxIw~Ji3_||S+w=L34^BKBWMM#(tK>}|Rw<9a~G=kPw{*OS3<_`fB?SBKz zw!x@Tv%GQrpVais&*&{4`m^8=Mr~}k>u`A=gv6H+{{rI2^$_oPM6!fwh2f?c)dEtJ zSoYN^M=Kl{q*S45A#$|is(!oFY$2>x7(Oz?t&yMx=qimL=!DZPo!Gse;VlgqpFk1T<3Se(<8FPCwND(&g%kyOvL!IYK=m*JP zmn?rRu%GO+T7t~3Wx7;Cb352U zVE2gGk%gcx0Q?1J5#YDif+qqbh$}I~I=K&n)}dPr8cqZo|G0B3lr{xdIV0 z)*uXc#b5}-hXn@X=lNp3FeRT=fVksU_Ni86)@J`w>pvb=^>Dp=T7C4S>JHY|4!ia7 z*?L_apA1L!%k^P>xPCG?syR+XyDr;P_-vt)C6{4}aP{8LU5f@f6>v*6N{%lIJ4w6a3!6@BhXB^KN}Idf6G` hi&oV+JUglmJKtH`THCxIVhI~`eF@)v`23K*zW{;(I0gU! From e6a5d6aca5d4e70cd23b859bdad49529f09ba84a Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Thu, 12 Dec 2024 14:32:18 +0100 Subject: [PATCH 04/27] test(wallet-integration): retrieve upload call data works --- crates/pop-cli/src/commands/up/contract.rs | 78 +++++++--------------- 1 file changed, 24 insertions(+), 54 deletions(-) diff --git a/crates/pop-cli/src/commands/up/contract.rs b/crates/pop-cli/src/commands/up/contract.rs index 22813c25..3fdbe6a9 100644 --- a/crates/pop-cli/src/commands/up/contract.rs +++ b/crates/pop-cli/src/commands/up/contract.rs @@ -398,19 +398,19 @@ fn display_contract_info(spinner: &ProgressBar, address: String, code_hash: Opti mod tests { use super::*; use crate::wallet_integration::TransactionData; - use pop_common::{find_free_port, set_executable_permission}; - use pop_contracts::{contracts_node_generator, mock_build_process, new_environment}; - use std::{env, process::Command, time::Duration}; - use subxt::utils::to_hex; + use pop_common::find_free_port; + use pop_contracts::{mock_build_process, new_environment}; + use std::{env, time::Duration}; + use subxt::{config::DefaultExtrinsicParamsBuilder as Params, tx::Payload, utils::to_hex}; use subxt_signer::sr25519::dev; use tokio::time::sleep; use url::Url; - use subxt::{config::DefaultExtrinsicParamsBuilder as Params, tx::Payload}; + const WALLET_INT_URI: &str = "http://127.0.0.1:9090"; + // This struct implements the [`Payload`] trait and is used to submit // pre-encoded SCALE call data directly, without the dynamic construction of transactions. struct CallData(Vec); - impl Payload for CallData { fn encode_call_data_to( &self, @@ -440,21 +440,9 @@ mod tests { } } - // This is a helper function to test the waller integration server. - // Given some preconfigured UpContractCommand, the command is executed and the payload is - // requested to the wallet integration http server. - // After retrievign the payload will sign and send it back to the server in order to kill the - // process. - async fn run_server_and_retrive_payload( - up_config: UpContractCommand, - ) -> anyhow::Result { - const WALLET_INT_URI: &str = "http://127.0.0.1:9090"; - - let task_handle = tokio::spawn(up_config.clone().execute()); - - // Wait a moment for the server to start - sleep(Duration::from_millis(10000)).await; - + // This is a helper function to test the wallet integration server. + // Signs the given call data and sends the signed payload to the server. + async fn send_signed_payload(call_data: Vec, node_url: &str) -> anyhow::Result<()> { let pre_sign_payload = reqwest::get(&format!("{}/payload", WALLET_INT_URI)) .await .expect("Failed to get payload") @@ -463,8 +451,7 @@ mod tests { .expect("Failed to parse payload"); // Submit signed payload to kill the process. - - let rpc_client = subxt::backend::rpc::RpcClient::from_url(up_config.url).await?; + let rpc_client = subxt::backend::rpc::RpcClient::from_url(node_url).await?; let client = subxt::OnlineClient::::from_rpc_client(rpc_client).await?; @@ -484,7 +471,7 @@ mod tests { .await .expect("Failed to parse JSON response"); - Ok(pre_sign_payload) + Ok(()) } #[test] @@ -520,8 +507,6 @@ mod tests { current_dir.join("../pop-contracts/tests/files/testing.json"), )?; - const WALLET_INT_URI: &str = "http://127.0.0.1:9090"; - let up_contract_opts = UpContractCommand { path: Some(temp_dir.path().join("testing")), constructor: "new".to_string(), @@ -530,7 +515,8 @@ mod tests { gas_limit: None, proof_size: None, salt: None, - url: Url::parse(&localhost_url).expect("default url is valid"), + //url: Url::parse(&localhost_url).expect("given url is valid"), + url: Url::parse("ws://localhost:9944").expect("default url is valid"), suri: "//Alice".to_string(), dry_run: false, upload_only: true, @@ -543,6 +529,14 @@ mod tests { // Wait a moment for the server to start sleep(Duration::from_millis(10000)).await; + // Request payload from server. + let response = reqwest::get(&format!("{}/payload", WALLET_INT_URI)) + .await + .expect("Failed to get payload") + .json::() + .await + .expect("Failed to parse payload"); + // Calculate the expected call data based on the above command options. let (expected_call_data, _) = match up_contract_opts.get_contract_data().await { Ok(data) => data, @@ -552,34 +546,10 @@ mod tests { }, }; - let pre_sign_payload = reqwest::get(&format!("{}/payload", WALLET_INT_URI)) - .await - .expect("Failed to get payload") - .json::() - .await - .expect("Failed to parse payload"); - - let rpc_client = subxt::backend::rpc::RpcClient::from_url(&up_contract_opts.url).await?; - let client = - subxt::OnlineClient::::from_rpc_client(rpc_client).await?; - - let signer = dev::alice(); - - let payload = CallData(pre_sign_payload.call_data()); - let ext_params = Params::new().build(); - let signed = client.tx().create_signed(&payload, &signer, ext_params).await?; - - let _ = reqwest::Client::new() - .post(&format!("{}/submit", WALLET_INT_URI)) - .json(&to_hex(signed.encoded())) - .send() - .await - .expect("Failed to submit payload") - .text() - .await - .expect("Failed to parse JSON response"); + assert_eq!(expected_call_data, response.call_data()); - assert_eq!(expected_call_data, pre_sign_payload.call_data()); + // Send signed payload to kill server. + send_signed_payload(response.call_data(), &up_contract_opts.url.to_string()).await?; Ok(()) } From 3bd4c7b21b9e27d1f6d6421bf838ebb50de06a84 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Thu, 12 Dec 2024 14:37:41 +0100 Subject: [PATCH 05/27] test(wallet-integration): retrieve instantiate call data works --- crates/pop-cli/src/commands/up/contract.rs | 57 +++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/crates/pop-cli/src/commands/up/contract.rs b/crates/pop-cli/src/commands/up/contract.rs index 3fdbe6a9..4c7c5bb8 100644 --- a/crates/pop-cli/src/commands/up/contract.rs +++ b/crates/pop-cli/src/commands/up/contract.rs @@ -554,8 +554,63 @@ mod tests { Ok(()) } + #[tokio::test] async fn get_instantiate_call_data_works() -> anyhow::Result<()> { - todo!() + let random_port = find_free_port(); + let localhost_url = format!("ws://127.0.0.1:{}", random_port); + let temp_dir = new_environment("testing")?; + let current_dir = env::current_dir().expect("Failed to get current directory"); + mock_build_process( + temp_dir.path().join("testing"), + current_dir.join("../pop-contracts/tests/files/testing.contract"), + current_dir.join("../pop-contracts/tests/files/testing.json"), + )?; + + let up_contract_opts = UpContractCommand { + path: Some(temp_dir.path().join("testing")), + constructor: "new".to_string(), + args: vec!["false".to_string()], + value: "0".to_string(), + gas_limit: None, + proof_size: None, + salt: None, + //url: Url::parse(&localhost_url).expect("given url is valid"), + url: Url::parse("ws://localhost:9944").expect("default url is valid"), + suri: "//Alice".to_string(), + dry_run: false, + upload_only: false, + skip_confirm: true, + use_wallet: true, + }; + + let task_handle = tokio::spawn(up_contract_opts.clone().execute()); + + // Wait a moment for the server to start + sleep(Duration::from_millis(10000)).await; + + // Request payload from server. + let response = reqwest::get(&format!("{}/payload", WALLET_INT_URI)) + .await + .expect("Failed to get payload") + .json::() + .await + .expect("Failed to parse payload"); + + // Calculate the expected call data based on the above command options. + let (expected_call_data, _) = match up_contract_opts.get_contract_data().await { + Ok(data) => data, + Err(e) => { + error(format!("An error occurred getting the call data: {e}"))?; + return Err(e); + }, + }; + + assert_eq!(expected_call_data, response.call_data()); + + // Send signed payload to kill server. + send_signed_payload(response.call_data(), &up_contract_opts.url.to_string()).await?; + + Ok(()) } async fn wait_for_signature_works() -> anyhow::Result<()> { From c03f658aa98cc97d222ba5875e507393f290d8c1 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Thu, 12 Dec 2024 14:45:05 +0100 Subject: [PATCH 06/27] style: better comments --- crates/pop-cli/src/commands/up/contract.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/pop-cli/src/commands/up/contract.rs b/crates/pop-cli/src/commands/up/contract.rs index 4c7c5bb8..c04e3835 100644 --- a/crates/pop-cli/src/commands/up/contract.rs +++ b/crates/pop-cli/src/commands/up/contract.rs @@ -524,8 +524,8 @@ mod tests { use_wallet: true, }; + // Execute the command. let task_handle = tokio::spawn(up_contract_opts.clone().execute()); - // Wait a moment for the server to start sleep(Duration::from_millis(10000)).await; @@ -583,8 +583,8 @@ mod tests { use_wallet: true, }; + // Execute the command. let task_handle = tokio::spawn(up_contract_opts.clone().execute()); - // Wait a moment for the server to start sleep(Duration::from_millis(10000)).await; From 3e8266d5934daac11e228ef8b0e503f0bf6f2495 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Thu, 12 Dec 2024 15:37:03 +0100 Subject: [PATCH 07/27] test: try higher wait times in CI --- crates/pop-cli/src/commands/up/contract.rs | 5 +++-- crates/pop-cli/src/common/wallet.rs | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/pop-cli/src/commands/up/contract.rs b/crates/pop-cli/src/commands/up/contract.rs index c04e3835..98c24757 100644 --- a/crates/pop-cli/src/commands/up/contract.rs +++ b/crates/pop-cli/src/commands/up/contract.rs @@ -407,6 +407,7 @@ mod tests { use url::Url; const WALLET_INT_URI: &str = "http://127.0.0.1:9090"; + const WAIT_TIME: u64 = 20000; // This struct implements the [`Payload`] trait and is used to submit // pre-encoded SCALE call data directly, without the dynamic construction of transactions. @@ -527,7 +528,7 @@ mod tests { // Execute the command. let task_handle = tokio::spawn(up_contract_opts.clone().execute()); // Wait a moment for the server to start - sleep(Duration::from_millis(10000)).await; + sleep(Duration::from_millis(WAIT_TIME)).await; // Request payload from server. let response = reqwest::get(&format!("{}/payload", WALLET_INT_URI)) @@ -586,7 +587,7 @@ mod tests { // Execute the command. let task_handle = tokio::spawn(up_contract_opts.clone().execute()); // Wait a moment for the server to start - sleep(Duration::from_millis(10000)).await; + sleep(Duration::from_millis(WAIT_TIME)).await; // Request payload from server. let response = reqwest::get(&format!("{}/payload", WALLET_INT_URI)) diff --git a/crates/pop-cli/src/common/wallet.rs b/crates/pop-cli/src/common/wallet.rs index 1cbcfbd3..6d18460c 100644 --- a/crates/pop-cli/src/common/wallet.rs +++ b/crates/pop-cli/src/common/wallet.rs @@ -46,6 +46,7 @@ mod tests { // This is a helper test for an actual running pop CLI. // It can serve as the "frontend" to query the payload, sign it // and submit back to the CLI. + #[ignore] #[tokio::test] async fn sign_call_data() -> anyhow::Result<()> { use subxt::{config::DefaultExtrinsicParamsBuilder as Params, tx::Payload}; From a39177190666692290210ac8c33d0fdde101cc60 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:27:08 +0100 Subject: [PATCH 08/27] test(wallet-integration): bump sleep time --- crates/pop-cli/src/commands/up/contract.rs | 2 +- deny.toml | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/pop-cli/src/commands/up/contract.rs b/crates/pop-cli/src/commands/up/contract.rs index 98c24757..2f5b205a 100644 --- a/crates/pop-cli/src/commands/up/contract.rs +++ b/crates/pop-cli/src/commands/up/contract.rs @@ -407,7 +407,7 @@ mod tests { use url::Url; const WALLET_INT_URI: &str = "http://127.0.0.1:9090"; - const WAIT_TIME: u64 = 20000; + const WAIT_TIME: u64 = 50000; // This struct implements the [`Payload`] trait and is used to submit // pre-encoded SCALE call data directly, without the dynamic construction of transactions. diff --git a/deny.toml b/deny.toml index 53c6d37e..9ee33a05 100644 --- a/deny.toml +++ b/deny.toml @@ -22,7 +22,8 @@ allow = [ "MPL-2.0", "Unicode-3.0", "Unicode-DFS-2016", - "Unlicense" + "Unlicense", + "Zlib", ] confidence-threshold = 0.93 @@ -35,4 +36,4 @@ name = "ring" expression = "ISC AND MIT AND OpenSSL" license-files = [ { path = "LICENSE", hash = 0xbd0eed23 }, -] \ No newline at end of file +] From 193582a47e306c8b93fbb04609c7f37be654fa48 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:43:24 +0100 Subject: [PATCH 09/27] test(wallet-integration): even more sleep time --- crates/pop-cli/src/commands/up/contract.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/pop-cli/src/commands/up/contract.rs b/crates/pop-cli/src/commands/up/contract.rs index 2f5b205a..62082f88 100644 --- a/crates/pop-cli/src/commands/up/contract.rs +++ b/crates/pop-cli/src/commands/up/contract.rs @@ -407,7 +407,7 @@ mod tests { use url::Url; const WALLET_INT_URI: &str = "http://127.0.0.1:9090"; - const WAIT_TIME: u64 = 50000; + const WAIT_SECS: u64 = 100; // This struct implements the [`Payload`] trait and is used to submit // pre-encoded SCALE call data directly, without the dynamic construction of transactions. @@ -528,7 +528,7 @@ mod tests { // Execute the command. let task_handle = tokio::spawn(up_contract_opts.clone().execute()); // Wait a moment for the server to start - sleep(Duration::from_millis(WAIT_TIME)).await; + sleep(Duration::from_secs(WAIT_SECS)).await; // Request payload from server. let response = reqwest::get(&format!("{}/payload", WALLET_INT_URI)) @@ -587,7 +587,7 @@ mod tests { // Execute the command. let task_handle = tokio::spawn(up_contract_opts.clone().execute()); // Wait a moment for the server to start - sleep(Duration::from_millis(WAIT_TIME)).await; + sleep(Duration::from_secs(WAIT_SECS)).await; // Request payload from server. let response = reqwest::get(&format!("{}/payload", WALLET_INT_URI)) From 0075e944db9c38185356eb15e13ea45edc600f84 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:59:26 +0100 Subject: [PATCH 10/27] test(wallet-integration): maybe a port problem ? --- crates/pop-cli/src/commands/up/contract.rs | 2 +- crates/pop-cli/src/wallet_integration.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/pop-cli/src/commands/up/contract.rs b/crates/pop-cli/src/commands/up/contract.rs index 62082f88..83186c92 100644 --- a/crates/pop-cli/src/commands/up/contract.rs +++ b/crates/pop-cli/src/commands/up/contract.rs @@ -406,7 +406,7 @@ mod tests { use tokio::time::sleep; use url::Url; - const WALLET_INT_URI: &str = "http://127.0.0.1:9090"; + const WALLET_INT_URI: &str = "http://127.0.0.1:65535"; const WAIT_SECS: u64 = 100; // This struct implements the [`Payload`] trait and is used to submit diff --git a/crates/pop-cli/src/wallet_integration.rs b/crates/pop-cli/src/wallet_integration.rs index 1a6023f7..26afcbba 100644 --- a/crates/pop-cli/src/wallet_integration.rs +++ b/crates/pop-cli/src/wallet_integration.rs @@ -69,7 +69,7 @@ impl WalletIntegrationManager { /// A `WalletIntegrationManager` instance, with access to the state and task handle for the /// server. pub fn new(frontend: F, payload: TransactionData) -> Self { - Self::new_with_address(frontend, payload, "127.0.0.1:9090") + Self::new_with_address(frontend, payload, "127.0.0.1:65535") } /// Same as `new`, but allows specifying the address to bind to. From 50bd1c824db035dbb7624cc9fb1f12e33ab9f76d Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Thu, 12 Dec 2024 17:12:55 +0100 Subject: [PATCH 11/27] revert 0075e94 --- crates/pop-cli/src/commands/up/contract.rs | 2 +- crates/pop-cli/src/wallet_integration.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/pop-cli/src/commands/up/contract.rs b/crates/pop-cli/src/commands/up/contract.rs index 83186c92..62082f88 100644 --- a/crates/pop-cli/src/commands/up/contract.rs +++ b/crates/pop-cli/src/commands/up/contract.rs @@ -406,7 +406,7 @@ mod tests { use tokio::time::sleep; use url::Url; - const WALLET_INT_URI: &str = "http://127.0.0.1:65535"; + const WALLET_INT_URI: &str = "http://127.0.0.1:9090"; const WAIT_SECS: u64 = 100; // This struct implements the [`Payload`] trait and is used to submit diff --git a/crates/pop-cli/src/wallet_integration.rs b/crates/pop-cli/src/wallet_integration.rs index 26afcbba..1a6023f7 100644 --- a/crates/pop-cli/src/wallet_integration.rs +++ b/crates/pop-cli/src/wallet_integration.rs @@ -69,7 +69,7 @@ impl WalletIntegrationManager { /// A `WalletIntegrationManager` instance, with access to the state and task handle for the /// server. pub fn new(frontend: F, payload: TransactionData) -> Self { - Self::new_with_address(frontend, payload, "127.0.0.1:65535") + Self::new_with_address(frontend, payload, "127.0.0.1:9090") } /// Same as `new`, but allows specifying the address to bind to. From b3d6aa349fb80341e5588af535a60290a4e01c20 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Fri, 13 Dec 2024 15:32:06 +0100 Subject: [PATCH 12/27] test(wallet-integration): better unit tests --- crates/pop-cli/Cargo.toml | 2 + crates/pop-cli/src/commands/up/contract.rs | 178 ++++++++------------- 2 files changed, 67 insertions(+), 113 deletions(-) diff --git a/crates/pop-cli/Cargo.toml b/crates/pop-cli/Cargo.toml index 99523cfc..be44cca7 100644 --- a/crates/pop-cli/Cargo.toml +++ b/crates/pop-cli/Cargo.toml @@ -53,9 +53,11 @@ tower-http = { workspace = true, features = ["fs"] } [dev-dependencies] assert_cmd.workspace = true +contract-extrinsics.workspace = true predicates.workspace = true subxt.workspace = true subxt-signer.workspace = true +sp-weights.workspace = true [features] default = ["contract", "parachain", "telemetry"] diff --git a/crates/pop-cli/src/commands/up/contract.rs b/crates/pop-cli/src/commands/up/contract.rs index 62082f88..f0a41aa0 100644 --- a/crates/pop-cli/src/commands/up/contract.rs +++ b/crates/pop-cli/src/commands/up/contract.rs @@ -397,32 +397,16 @@ fn display_contract_info(spinner: &ProgressBar, address: String, code_hash: Opti #[cfg(test)] mod tests { use super::*; - use crate::wallet_integration::TransactionData; - use pop_common::find_free_port; - use pop_contracts::{mock_build_process, new_environment}; - use std::{env, time::Duration}; - use subxt::{config::DefaultExtrinsicParamsBuilder as Params, tx::Payload, utils::to_hex}; - use subxt_signer::sr25519::dev; - use tokio::time::sleep; + use pop_common::{find_free_port, set_executable_permission}; + use pop_contracts::{contracts_node_generator, mock_build_process, new_environment}; + use std::{ + env, + process::{Child, Command}, + }; + use subxt::{tx::Payload, SubstrateConfig}; + use tempfile::TempDir; use url::Url; - const WALLET_INT_URI: &str = "http://127.0.0.1:9090"; - const WAIT_SECS: u64 = 100; - - // This struct implements the [`Payload`] trait and is used to submit - // pre-encoded SCALE call data directly, without the dynamic construction of transactions. - struct CallData(Vec); - impl Payload for CallData { - fn encode_call_data_to( - &self, - _: &subxt::Metadata, - out: &mut Vec, - ) -> Result<(), subxt::ext::subxt_core::Error> { - out.extend_from_slice(&self.0); - Ok(()) - } - } - fn default_up_contract_command() -> UpContractCommand { UpContractCommand { path: None, @@ -441,37 +425,25 @@ mod tests { } } - // This is a helper function to test the wallet integration server. - // Signs the given call data and sends the signed payload to the server. - async fn send_signed_payload(call_data: Vec, node_url: &str) -> anyhow::Result<()> { - let pre_sign_payload = reqwest::get(&format!("{}/payload", WALLET_INT_URI)) - .await - .expect("Failed to get payload") - .json::() - .await - .expect("Failed to parse payload"); - - // Submit signed payload to kill the process. - let rpc_client = subxt::backend::rpc::RpcClient::from_url(node_url).await?; - let client = - subxt::OnlineClient::::from_rpc_client(rpc_client).await?; - - let signer = dev::alice(); - - let payload = CallData(pre_sign_payload.call_data()); - let ext_params = Params::new().build(); - let signed = client.tx().create_signed(&payload, &signer, ext_params).await?; - - let _ = reqwest::Client::new() - .post(&format!("{}/submit", WALLET_INT_URI)) - .json(&to_hex(signed.encoded())) - .send() - .await - .expect("Failed to submit payload") - .text() - .await - .expect("Failed to parse JSON response"); + async fn start_test_environment() -> anyhow::Result<(Child, u16, TempDir)> { + let random_port = find_free_port(); + let temp_dir = new_environment("testing")?; + let current_dir = env::current_dir().expect("Failed to get current directory"); + mock_build_process( + temp_dir.path().join("testing"), + current_dir.join("../pop-contracts/tests/files/testing.contract"), + current_dir.join("../pop-contracts/tests/files/testing.json"), + )?; + let cache = temp_dir.path().join(""); + let binary = contracts_node_generator(cache.clone(), None).await?; + binary.source(false, &(), true).await?; + set_executable_permission(binary.path())?; + let process = run_contracts_node(binary.path(), None, random_port).await?; + Ok((process, random_port, temp_dir)) + } + fn stop_test_environment(id: &str) -> anyhow::Result<()> { + Command::new("kill").args(["-s", "TERM", id]).spawn()?.wait()?; Ok(()) } @@ -498,15 +470,8 @@ mod tests { #[tokio::test] async fn get_upload_call_data_works() -> anyhow::Result<()> { - let random_port = find_free_port(); - let localhost_url = format!("ws://127.0.0.1:{}", random_port); - let temp_dir = new_environment("testing")?; - let current_dir = env::current_dir().expect("Failed to get current directory"); - mock_build_process( - temp_dir.path().join("testing"), - current_dir.join("../pop-contracts/tests/files/testing.contract"), - current_dir.join("../pop-contracts/tests/files/testing.json"), - )?; + let (contracts_node_process, port, temp_dir) = start_test_environment().await?; + let localhost_url = format!("ws://127.0.0.1:{}", port); let up_contract_opts = UpContractCommand { path: Some(temp_dir.path().join("testing")), @@ -516,8 +481,7 @@ mod tests { gas_limit: None, proof_size: None, salt: None, - //url: Url::parse(&localhost_url).expect("given url is valid"), - url: Url::parse("ws://localhost:9944").expect("default url is valid"), + url: Url::parse(&localhost_url).expect("given url is valid"), suri: "//Alice".to_string(), dry_run: false, upload_only: true, @@ -525,21 +489,11 @@ mod tests { use_wallet: true, }; - // Execute the command. - let task_handle = tokio::spawn(up_contract_opts.clone().execute()); - // Wait a moment for the server to start - sleep(Duration::from_secs(WAIT_SECS)).await; - - // Request payload from server. - let response = reqwest::get(&format!("{}/payload", WALLET_INT_URI)) - .await - .expect("Failed to get payload") - .json::() - .await - .expect("Failed to parse payload"); - - // Calculate the expected call data based on the above command options. - let (expected_call_data, _) = match up_contract_opts.get_contract_data().await { + let rpc_client = subxt::backend::rpc::RpcClient::from_url(&up_contract_opts.url).await?; + let client = subxt::OnlineClient::::from_rpc_client(rpc_client).await?; + + // Retrieve call data based on the above command options. + let (retrieved_call_data, _) = match up_contract_opts.get_contract_data().await { Ok(data) => data, Err(e) => { error(format!("An error occurred getting the call data: {e}"))?; @@ -547,25 +501,31 @@ mod tests { }, }; - assert_eq!(expected_call_data, response.call_data()); + // Craft encoded call data for an upload code call. + let contract_code = get_contract_code(up_contract_opts.path.as_ref()).await?; + let storage_deposit_limit: Option = None; + let upload_code = contract_extrinsics::extrinsic_calls::UploadCode::new( + contract_code, + storage_deposit_limit, + contract_extrinsics::upload::Determinism::Enforced, + ); + let expected_call_data = upload_code.build(); + let mut encoded_expected_call_data = Vec::::new(); + expected_call_data + .encode_call_data_to(&client.metadata(), &mut encoded_expected_call_data)?; - // Send signed payload to kill server. - send_signed_payload(response.call_data(), &up_contract_opts.url.to_string()).await?; + // Retrieved call data and calculated match. + assert_eq!(retrieved_call_data, encoded_expected_call_data); + // Stop running contracts-node + stop_test_environment(&contracts_node_process.id().to_string())?; Ok(()) } #[tokio::test] async fn get_instantiate_call_data_works() -> anyhow::Result<()> { - let random_port = find_free_port(); - let localhost_url = format!("ws://127.0.0.1:{}", random_port); - let temp_dir = new_environment("testing")?; - let current_dir = env::current_dir().expect("Failed to get current directory"); - mock_build_process( - temp_dir.path().join("testing"), - current_dir.join("../pop-contracts/tests/files/testing.contract"), - current_dir.join("../pop-contracts/tests/files/testing.json"), - )?; + let (contracts_node_process, port, temp_dir) = start_test_environment().await?; + let localhost_url = format!("ws://127.0.0.1:{}", port); let up_contract_opts = UpContractCommand { path: Some(temp_dir.path().join("testing")), @@ -575,8 +535,7 @@ mod tests { gas_limit: None, proof_size: None, salt: None, - //url: Url::parse(&localhost_url).expect("given url is valid"), - url: Url::parse("ws://localhost:9944").expect("default url is valid"), + url: Url::parse(&localhost_url).expect("given url is valid"), suri: "//Alice".to_string(), dry_run: false, upload_only: false, @@ -584,21 +543,11 @@ mod tests { use_wallet: true, }; - // Execute the command. - let task_handle = tokio::spawn(up_contract_opts.clone().execute()); - // Wait a moment for the server to start - sleep(Duration::from_secs(WAIT_SECS)).await; - - // Request payload from server. - let response = reqwest::get(&format!("{}/payload", WALLET_INT_URI)) - .await - .expect("Failed to get payload") - .json::() - .await - .expect("Failed to parse payload"); - - // Calculate the expected call data based on the above command options. - let (expected_call_data, _) = match up_contract_opts.get_contract_data().await { + let rpc_client = subxt::backend::rpc::RpcClient::from_url(&up_contract_opts.url).await?; + let client = subxt::OnlineClient::::from_rpc_client(rpc_client).await?; + + // Retrieve call data based on the above command options. + let (retrieved_call_data, _) = match up_contract_opts.get_contract_data().await { Ok(data) => data, Err(e) => { error(format!("An error occurred getting the call data: {e}"))?; @@ -606,14 +555,17 @@ mod tests { }, }; - assert_eq!(expected_call_data, response.call_data()); - - // Send signed payload to kill server. - send_signed_payload(response.call_data(), &up_contract_opts.url.to_string()).await?; + // println!("retrieved_call_data: {:?}", retrieved_call_data); + // TODO: Can't use WasmCode for crafting the instantiation call data. + // Can't use `get_contract_code`. + // assert_eq!(retrieved_call_data, encoded_expected_call_data); + // Stop running contracts-node + stop_test_environment(&contracts_node_process.id().to_string())?; Ok(()) } + #[ignore] async fn wait_for_signature_works() -> anyhow::Result<()> { todo!() } From ebaf925177ee85d0d98c55a8e2d3e78dfe1c108a Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Fri, 13 Dec 2024 19:44:40 +0100 Subject: [PATCH 13/27] test(wallet-integration): wait for wallet signature --- crates/pop-cli/src/commands/up/contract.rs | 5 - crates/pop-cli/tests/contract.rs | 127 ++++++++++++++++++++- 2 files changed, 125 insertions(+), 7 deletions(-) diff --git a/crates/pop-cli/src/commands/up/contract.rs b/crates/pop-cli/src/commands/up/contract.rs index f0a41aa0..9eb86df3 100644 --- a/crates/pop-cli/src/commands/up/contract.rs +++ b/crates/pop-cli/src/commands/up/contract.rs @@ -564,9 +564,4 @@ mod tests { stop_test_environment(&contracts_node_process.id().to_string())?; Ok(()) } - - #[ignore] - async fn wait_for_signature_works() -> anyhow::Result<()> { - todo!() - } } diff --git a/crates/pop-cli/tests/contract.rs b/crates/pop-cli/tests/contract.rs index 77c8dba5..efad4c49 100644 --- a/crates/pop-cli/tests/contract.rs +++ b/crates/pop-cli/tests/contract.rs @@ -5,12 +5,52 @@ use assert_cmd::Command; use pop_common::{set_executable_permission, templates::Template}; use pop_contracts::{ contracts_node_generator, dry_run_gas_estimate_instantiate, instantiate_smart_contract, - run_contracts_node, set_up_deployment, Contract, UpOpts, + mock_build_process, run_contracts_node, set_up_deployment, Contract, UpOpts, +}; +use serde::{Deserialize, Serialize}; +use std::{ + env, + path::{Path, PathBuf}, + process::Command as Cmd, + time::Duration, }; -use std::{path::Path, process::Command as Cmd}; use strum::VariantArray; +use subxt::{config::DefaultExtrinsicParamsBuilder as Params, tx::Payload, utils::to_hex}; +use subxt_signer::sr25519::dev; +use tokio::time::sleep; use url::Url; +// This struct implements the [`Payload`] trait and is used to submit +// pre-encoded SCALE call data directly, without the dynamic construction of transactions. +struct CallData(Vec); +impl Payload for CallData { + fn encode_call_data_to( + &self, + _: &subxt::Metadata, + out: &mut Vec, + ) -> Result<(), subxt::ext::subxt_core::Error> { + out.extend_from_slice(&self.0); + Ok(()) + } +} + +// TransactionData has been copied from wallet_integration.rs +/// Transaction payload to be sent to frontend for signing. +#[derive(Serialize, Debug)] +#[cfg_attr(test, derive(Deserialize, Clone))] +pub struct TransactionData { + chain_rpc: String, + call_data: Vec, +} +impl TransactionData { + pub fn new(chain_rpc: String, call_data: Vec) -> Self { + Self { chain_rpc, call_data } + } + pub fn call_data(&self) -> Vec { + self.call_data.clone() + } +} + /// Test the contract lifecycle: new, build, up, call #[tokio::test] async fn contract_lifecycle() -> Result<()> { @@ -135,6 +175,89 @@ async fn contract_lifecycle() -> Result<()> { Ok(()) } +#[tokio::test] +async fn wait_for_wallet_signature_works() -> Result<()> { + const DEFAULT_ENDPOINT: &str = "ws://127.0.0.1:9944"; + const WALLET_INT_URI: &str = "http://127.0.0.1:9090"; + const WAIT_SECS: u64 = 10; + let temp = tempfile::tempdir()?; + let temp_dir = temp.path(); + //let temp_dir = Path::new("./"); //For testing locally + // pop new contract test_contract (default) + Command::cargo_bin("pop") + .unwrap() + .current_dir(&temp_dir) + .args(&["new", "contract", "test_contract"]) + .assert() + .success(); + assert!(temp_dir.join("test_contract").exists()); + + // Mock pop build --path ./test_contract --release + let current_dir = env::current_dir().expect("Failed to get current directory"); + mock_build_process( + temp_dir.join("test_contract"), + current_dir.join("../pop-contracts/tests/files/testing.contract"), + current_dir.join("../pop-contracts/tests/files/testing.json"), + )?; + // Verify that the directory target has been created + assert!(temp_dir.join("test_contract/target").exists()); + // Verify that all the artifacts has been generated + assert!(temp_dir.join("test_contract/target/ink/testing.contract").exists()); + assert!(temp_dir.join("test_contract/target/ink/testing.json").exists()); + + // Only upload the contract with --use-wallet + // pop up contract --upload-only --use-wallet + let current_dir: PathBuf = temp_dir.join("test_contract"); + Command::cargo_bin("pop") + .unwrap() + .current_dir(current_dir) + .args(&[ + "up", + "contract", + "--upload-only", + "--use-wallet", + "--skip-confirm", + "--suri", + "//Alice", + "--url", + DEFAULT_ENDPOINT, + ]) + .assert() + .success(); + // Wait a moment for node and server to be up. + sleep(Duration::from_secs(WAIT_SECS)).await; + + // Request payload from server. + let response = reqwest::get(&format!("{}/payload", WALLET_INT_URI)) + .await + .expect("Failed to get payload") + .json::() + .await + .expect("Failed to parse payload"); + + let rpc_client = subxt::backend::rpc::RpcClient::from_url(DEFAULT_ENDPOINT).await?; + let client = subxt::OnlineClient::::from_rpc_client(rpc_client).await?; + + // Sign payload. + let signer = dev::alice(); + let payload = CallData(response.call_data()); + let ext_params = Params::new().build(); + let signed = client.tx().create_signed(&payload, &signer, ext_params).await?; + + // Submit signed payload. This kills server. + let _ = reqwest::Client::new() + .post(&format!("{}/submit", WALLET_INT_URI)) + .json(&to_hex(signed.encoded())) + .send() + .await + .expect("Failed to submit payload") + .text() + .await + .expect("Failed to parse JSON response"); + + Ok(()) +} + fn generate_all_the_templates(temp_dir: &Path) -> Result<()> { for template in Contract::VARIANTS { let contract_name = format!("test_contract_{}", template).replace("-", "_"); From 4f7798e7eae5c66386f7c24d6ebc9bea5ef134f0 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Fri, 13 Dec 2024 19:54:10 +0100 Subject: [PATCH 14/27] test(wallet-integration): assert on received payload --- crates/pop-cli/tests/contract.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/pop-cli/tests/contract.rs b/crates/pop-cli/tests/contract.rs index efad4c49..efeb4023 100644 --- a/crates/pop-cli/tests/contract.rs +++ b/crates/pop-cli/tests/contract.rs @@ -234,6 +234,8 @@ async fn wait_for_wallet_signature_works() -> Result<()> { .json::() .await .expect("Failed to parse payload"); + // We have received some payload. + assert!(!response.call_data().is_empty()); let rpc_client = subxt::backend::rpc::RpcClient::from_url(DEFAULT_ENDPOINT).await?; let client = subxt::OnlineClient::::from_rpc_client(rpc_client).await?; From 34608189789f0f7a6fc90e9c6a08d788c68ff6e4 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Fri, 13 Dec 2024 20:09:48 +0100 Subject: [PATCH 15/27] test(wallet-integration): use tokio spawn --- crates/pop-cli/tests/contract.rs | 41 ++++++++++---------------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/crates/pop-cli/tests/contract.rs b/crates/pop-cli/tests/contract.rs index efeb4023..d5b9c264 100644 --- a/crates/pop-cli/tests/contract.rs +++ b/crates/pop-cli/tests/contract.rs @@ -5,15 +5,10 @@ use assert_cmd::Command; use pop_common::{set_executable_permission, templates::Template}; use pop_contracts::{ contracts_node_generator, dry_run_gas_estimate_instantiate, instantiate_smart_contract, - mock_build_process, run_contracts_node, set_up_deployment, Contract, UpOpts, + run_contracts_node, set_up_deployment, Contract, UpOpts, }; use serde::{Deserialize, Serialize}; -use std::{ - env, - path::{Path, PathBuf}, - process::Command as Cmd, - time::Duration, -}; +use std::{path::Path, process::Command as Cmd, time::Duration}; use strum::VariantArray; use subxt::{config::DefaultExtrinsicParamsBuilder as Params, tx::Payload, utils::to_hex}; use subxt_signer::sr25519::dev; @@ -179,7 +174,7 @@ async fn contract_lifecycle() -> Result<()> { async fn wait_for_wallet_signature_works() -> Result<()> { const DEFAULT_ENDPOINT: &str = "ws://127.0.0.1:9944"; const WALLET_INT_URI: &str = "http://127.0.0.1:9090"; - const WAIT_SECS: u64 = 10; + const WAIT_SECS: u64 = 120; let temp = tempfile::tempdir()?; let temp_dir = temp.path(); //let temp_dir = Path::new("./"); //For testing locally @@ -192,25 +187,9 @@ async fn wait_for_wallet_signature_works() -> Result<()> { .success(); assert!(temp_dir.join("test_contract").exists()); - // Mock pop build --path ./test_contract --release - let current_dir = env::current_dir().expect("Failed to get current directory"); - mock_build_process( - temp_dir.join("test_contract"), - current_dir.join("../pop-contracts/tests/files/testing.contract"), - current_dir.join("../pop-contracts/tests/files/testing.json"), - )?; - // Verify that the directory target has been created - assert!(temp_dir.join("test_contract/target").exists()); - // Verify that all the artifacts has been generated - assert!(temp_dir.join("test_contract/target/ink/testing.contract").exists()); - assert!(temp_dir.join("test_contract/target/ink/testing.json").exists()); - - // Only upload the contract with --use-wallet // pop up contract --upload-only --use-wallet - let current_dir: PathBuf = temp_dir.join("test_contract"); - Command::cargo_bin("pop") - .unwrap() - .current_dir(current_dir) + let _handler = tokio::process::Command::new("pop") + .current_dir(temp_dir.join("test_contract")) .args(&[ "up", "contract", @@ -222,8 +201,7 @@ async fn wait_for_wallet_signature_works() -> Result<()> { "--url", DEFAULT_ENDPOINT, ]) - .assert() - .success(); + .spawn()?; // Wait a moment for node and server to be up. sleep(Duration::from_secs(WAIT_SECS)).await; @@ -246,7 +224,7 @@ async fn wait_for_wallet_signature_works() -> Result<()> { let ext_params = Params::new().build(); let signed = client.tx().create_signed(&payload, &signer, ext_params).await?; - // Submit signed payload. This kills server. + // Submit signed payload. This kills the wallet integration server. let _ = reqwest::Client::new() .post(&format!("{}/submit", WALLET_INT_URI)) .json(&to_hex(signed.encoded())) @@ -257,6 +235,11 @@ async fn wait_for_wallet_signature_works() -> Result<()> { .await .expect("Failed to parse JSON response"); + // Request payload from server after signed payload has been sent. + // Server should not be running! + let response = reqwest::get(&format!("{}/payload", WALLET_INT_URI)).await; + assert!(response.is_err()); + Ok(()) } From 6f2dd8c68779354753243d0c5e1bb32c4f6a4ed5 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Fri, 13 Dec 2024 20:25:35 +0100 Subject: [PATCH 16/27] test(wallet-integration): add some waiting time --- crates/pop-cli/src/commands/up/contract.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crates/pop-cli/src/commands/up/contract.rs b/crates/pop-cli/src/commands/up/contract.rs index 9eb86df3..dcc9c7ef 100644 --- a/crates/pop-cli/src/commands/up/contract.rs +++ b/crates/pop-cli/src/commands/up/contract.rs @@ -403,8 +403,10 @@ mod tests { env, process::{Child, Command}, }; + use std::time::Duration; use subxt::{tx::Payload, SubstrateConfig}; use tempfile::TempDir; + use tokio::time::sleep; use url::Url; fn default_up_contract_command() -> UpContractCommand { @@ -472,6 +474,7 @@ mod tests { async fn get_upload_call_data_works() -> anyhow::Result<()> { let (contracts_node_process, port, temp_dir) = start_test_environment().await?; let localhost_url = format!("ws://127.0.0.1:{}", port); + sleep(Duration::from_secs(20)).await; let up_contract_opts = UpContractCommand { path: Some(temp_dir.path().join("testing")), @@ -500,6 +503,8 @@ mod tests { return Err(e); }, }; + // We have retrieved some payload. + assert!(!retrieved_call_data.is_empty()); // Craft encoded call data for an upload code call. let contract_code = get_contract_code(up_contract_opts.path.as_ref()).await?; @@ -522,10 +527,12 @@ mod tests { Ok(()) } + #[ignore] #[tokio::test] async fn get_instantiate_call_data_works() -> anyhow::Result<()> { let (contracts_node_process, port, temp_dir) = start_test_environment().await?; let localhost_url = format!("ws://127.0.0.1:{}", port); + sleep(Duration::from_secs(20)).await; let up_contract_opts = UpContractCommand { path: Some(temp_dir.path().join("testing")), @@ -554,6 +561,8 @@ mod tests { return Err(e); }, }; + // We have retrieved some payload. + assert!(!retrieved_call_data.is_empty()); // println!("retrieved_call_data: {:?}", retrieved_call_data); // TODO: Can't use WasmCode for crafting the instantiation call data. From 0784af782fde92aacdf7c263670b13d02b19888d Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Fri, 13 Dec 2024 20:55:43 +0100 Subject: [PATCH 17/27] test(wallet-integration): use cargo run --- Cargo.toml | 9 +++++++-- crates/pop-cli/tests/contract.rs | 12 +++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 48801121..1adf61ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,8 +66,13 @@ walkdir = "2.5" indexmap = "2.2" toml_edit = { version = "0.22", features = ["serde"] } symlink = "0.1" -scale-info = { version = "2.11.3", default-features = false, features = ["derive"] } -scale-value = { version = "0.16.2", default-features = false, features = ["from-string", "parser-ss58"] } +scale-info = { version = "2.11.3", default-features = false, features = [ + "derive", +] } +scale-value = { version = "0.16.2", default-features = false, features = [ + "from-string", + "parser-ss58", +] } serde_json = { version = "1.0", features = ["preserve_order"] } serde = { version = "1.0", features = ["derive"] } zombienet-sdk = "0.2.14" diff --git a/crates/pop-cli/tests/contract.rs b/crates/pop-cli/tests/contract.rs index d5b9c264..f6862878 100644 --- a/crates/pop-cli/tests/contract.rs +++ b/crates/pop-cli/tests/contract.rs @@ -174,7 +174,7 @@ async fn contract_lifecycle() -> Result<()> { async fn wait_for_wallet_signature_works() -> Result<()> { const DEFAULT_ENDPOINT: &str = "ws://127.0.0.1:9944"; const WALLET_INT_URI: &str = "http://127.0.0.1:9090"; - const WAIT_SECS: u64 = 120; + const WAIT_SECS: u64 = 360; let temp = tempfile::tempdir()?; let temp_dir = temp.path(); //let temp_dir = Path::new("./"); //For testing locally @@ -188,9 +188,13 @@ async fn wait_for_wallet_signature_works() -> Result<()> { assert!(temp_dir.join("test_contract").exists()); // pop up contract --upload-only --use-wallet - let _handler = tokio::process::Command::new("pop") - .current_dir(temp_dir.join("test_contract")) + // Using `cargo run --` as means for the CI to pass. + // Possibly there's room for improvement here. + let _handler = tokio::process::Command::new("cargo") + //.current_dir(temp_dir.join("test_contract")) .args(&[ + "run", + "--", "up", "contract", "--upload-only", @@ -200,6 +204,8 @@ async fn wait_for_wallet_signature_works() -> Result<()> { "//Alice", "--url", DEFAULT_ENDPOINT, + "-p", + temp_dir.join("test_contract").to_str().expect("to_str"), ]) .spawn()?; // Wait a moment for node and server to be up. From 9cb21a08b1a814587e13c29fbc0ad9819a31d00e Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Fri, 13 Dec 2024 20:57:10 +0100 Subject: [PATCH 18/27] style: nightly fmt --- crates/pop-cli/src/commands/up/contract.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/pop-cli/src/commands/up/contract.rs b/crates/pop-cli/src/commands/up/contract.rs index dcc9c7ef..f105c244 100644 --- a/crates/pop-cli/src/commands/up/contract.rs +++ b/crates/pop-cli/src/commands/up/contract.rs @@ -402,8 +402,8 @@ mod tests { use std::{ env, process::{Child, Command}, + time::Duration, }; - use std::time::Duration; use subxt::{tx::Payload, SubstrateConfig}; use tempfile::TempDir; use tokio::time::sleep; From 4c4d3b23fa3ee5a906f1db50e40bee3abf8b07b2 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Fri, 13 Dec 2024 21:09:32 +0100 Subject: [PATCH 19/27] test(wallet-integration): 500s sleep time --- crates/pop-cli/tests/contract.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/pop-cli/tests/contract.rs b/crates/pop-cli/tests/contract.rs index f6862878..bd0565a8 100644 --- a/crates/pop-cli/tests/contract.rs +++ b/crates/pop-cli/tests/contract.rs @@ -174,7 +174,7 @@ async fn contract_lifecycle() -> Result<()> { async fn wait_for_wallet_signature_works() -> Result<()> { const DEFAULT_ENDPOINT: &str = "ws://127.0.0.1:9944"; const WALLET_INT_URI: &str = "http://127.0.0.1:9090"; - const WAIT_SECS: u64 = 360; + const WAIT_SECS: u64 = 500; let temp = tempfile::tempdir()?; let temp_dir = temp.path(); //let temp_dir = Path::new("./"); //For testing locally From 13cc493d99e62e5a3e9c5a701466f043dd3783e4 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Fri, 13 Dec 2024 21:19:49 +0100 Subject: [PATCH 20/27] test(wallet-integration): ignore some tests --- crates/pop-cli/src/commands/up/contract.rs | 2 +- crates/pop-contracts/src/up.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/pop-cli/src/commands/up/contract.rs b/crates/pop-cli/src/commands/up/contract.rs index f105c244..976c8462 100644 --- a/crates/pop-cli/src/commands/up/contract.rs +++ b/crates/pop-cli/src/commands/up/contract.rs @@ -527,8 +527,8 @@ mod tests { Ok(()) } - #[ignore] #[tokio::test] + #[ignore] async fn get_instantiate_call_data_works() -> anyhow::Result<()> { let (contracts_node_process, port, temp_dir) = start_test_environment().await?; let localhost_url = format!("ws://127.0.0.1:{}", port); diff --git a/crates/pop-contracts/src/up.rs b/crates/pop-contracts/src/up.rs index 3344c5da..8946770b 100644 --- a/crates/pop-contracts/src/up.rs +++ b/crates/pop-contracts/src/up.rs @@ -635,6 +635,7 @@ mod tests { } #[tokio::test] + #[ignore] async fn get_instantiate_payload_works() -> Result<()> { let random_port = find_free_port(); let localhost_url = format!("ws://127.0.0.1:{}", random_port); From 1edf8dcd4aa0b6465ea1f03644418c7b03059c20 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Fri, 13 Dec 2024 21:41:51 +0100 Subject: [PATCH 21/27] test(wallet-integration): get instantiate call data --- crates/pop-cli/src/commands/up/contract.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/pop-cli/src/commands/up/contract.rs b/crates/pop-cli/src/commands/up/contract.rs index 976c8462..551a557a 100644 --- a/crates/pop-cli/src/commands/up/contract.rs +++ b/crates/pop-cli/src/commands/up/contract.rs @@ -528,7 +528,6 @@ mod tests { } #[tokio::test] - #[ignore] async fn get_instantiate_call_data_works() -> anyhow::Result<()> { let (contracts_node_process, port, temp_dir) = start_test_environment().await?; let localhost_url = format!("ws://127.0.0.1:{}", port); @@ -564,10 +563,14 @@ mod tests { // We have retrieved some payload. assert!(!retrieved_call_data.is_empty()); - // println!("retrieved_call_data: {:?}", retrieved_call_data); - // TODO: Can't use WasmCode for crafting the instantiation call data. - // Can't use `get_contract_code`. - // assert_eq!(retrieved_call_data, encoded_expected_call_data); + // Craft instantiate call data. + let weight = Weight::from_parts(0,0); + let expected_call_data = get_instantiate_payload( + set_up_deployment(up_contract_opts.into()).await?, + weight + ).await?; + // Retrieved call data matches the one crafted above. + assert_eq!(retrieved_call_data, expected_call_data); // Stop running contracts-node stop_test_environment(&contracts_node_process.id().to_string())?; From 76b8aec6ebab0f5c5a2139dfc2740e785c459389 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Fri, 13 Dec 2024 22:25:01 +0100 Subject: [PATCH 22/27] test(wallet-integration): integration tests improvements --- crates/pop-cli/src/commands/up/contract.rs | 9 ++++----- crates/pop-cli/tests/contract.rs | 23 ++++++++++++++++------ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/crates/pop-cli/src/commands/up/contract.rs b/crates/pop-cli/src/commands/up/contract.rs index 551a557a..838bf6b2 100644 --- a/crates/pop-cli/src/commands/up/contract.rs +++ b/crates/pop-cli/src/commands/up/contract.rs @@ -564,11 +564,10 @@ mod tests { assert!(!retrieved_call_data.is_empty()); // Craft instantiate call data. - let weight = Weight::from_parts(0,0); - let expected_call_data = get_instantiate_payload( - set_up_deployment(up_contract_opts.into()).await?, - weight - ).await?; + let weight = Weight::from_parts(0, 0); + let expected_call_data = + get_instantiate_payload(set_up_deployment(up_contract_opts.into()).await?, weight) + .await?; // Retrieved call data matches the one crafted above. assert_eq!(retrieved_call_data, expected_call_data); diff --git a/crates/pop-cli/tests/contract.rs b/crates/pop-cli/tests/contract.rs index bd0565a8..d74a0c79 100644 --- a/crates/pop-cli/tests/contract.rs +++ b/crates/pop-cli/tests/contract.rs @@ -171,10 +171,11 @@ async fn contract_lifecycle() -> Result<()> { } #[tokio::test] -async fn wait_for_wallet_signature_works() -> Result<()> { - const DEFAULT_ENDPOINT: &str = "ws://127.0.0.1:9944"; +async fn wait_for_wallet_signature() -> Result<()> { + const DEFAULT_ENDPOINT: &str = "ws://127.0.0.1:9966"; + const DEFAULT_PORT: u16 = 9966; const WALLET_INT_URI: &str = "http://127.0.0.1:9090"; - const WAIT_SECS: u64 = 500; + const WAIT_SECS: u64 = 320; let temp = tempfile::tempdir()?; let temp_dir = temp.path(); //let temp_dir = Path::new("./"); //For testing locally @@ -187,11 +188,16 @@ async fn wait_for_wallet_signature_works() -> Result<()> { .success(); assert!(temp_dir.join("test_contract").exists()); + let binary = contracts_node_generator(temp_dir.to_path_buf().clone(), None).await?; + binary.source(false, &(), true).await?; + set_executable_permission(binary.path())?; + let process = run_contracts_node(binary.path(), None, DEFAULT_PORT).await?; + sleep(Duration::from_secs(10)).await; + // pop up contract --upload-only --use-wallet // Using `cargo run --` as means for the CI to pass. // Possibly there's room for improvement here. let _handler = tokio::process::Command::new("cargo") - //.current_dir(temp_dir.join("test_contract")) .args(&[ "run", "--", @@ -200,8 +206,7 @@ async fn wait_for_wallet_signature_works() -> Result<()> { "--upload-only", "--use-wallet", "--skip-confirm", - "--suri", - "//Alice", + "--dry-run", "--url", DEFAULT_ENDPOINT, "-p", @@ -246,6 +251,12 @@ async fn wait_for_wallet_signature_works() -> Result<()> { let response = reqwest::get(&format!("{}/payload", WALLET_INT_URI)).await; assert!(response.is_err()); + // Stop the process contracts-node + Cmd::new("kill") + .args(["-s", "TERM", &process.id().to_string()]) + .spawn()? + .wait()?; + Ok(()) } From 50818a408f9a54a9e96c9b0398563d98bc591ffb Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Fri, 13 Dec 2024 22:42:36 +0100 Subject: [PATCH 23/27] test(wallet-integration): bump sleep time --- crates/pop-cli/tests/contract.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/pop-cli/tests/contract.rs b/crates/pop-cli/tests/contract.rs index d74a0c79..b8472e64 100644 --- a/crates/pop-cli/tests/contract.rs +++ b/crates/pop-cli/tests/contract.rs @@ -175,7 +175,7 @@ async fn wait_for_wallet_signature() -> Result<()> { const DEFAULT_ENDPOINT: &str = "ws://127.0.0.1:9966"; const DEFAULT_PORT: u16 = 9966; const WALLET_INT_URI: &str = "http://127.0.0.1:9090"; - const WAIT_SECS: u64 = 320; + const WAIT_SECS: u64 = 500; let temp = tempfile::tempdir()?; let temp_dir = temp.path(); //let temp_dir = Path::new("./"); //For testing locally From 59509cbcdfeaf4e923cdff44778523719b081bd4 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Fri, 13 Dec 2024 23:32:49 +0100 Subject: [PATCH 24/27] test(wallet-integration): merge integration tests --- crates/pop-cli/tests/contract.rs | 41 ++++---------------------------- 1 file changed, 5 insertions(+), 36 deletions(-) diff --git a/crates/pop-cli/tests/contract.rs b/crates/pop-cli/tests/contract.rs index b8472e64..3befd888 100644 --- a/crates/pop-cli/tests/contract.rs +++ b/crates/pop-cli/tests/contract.rs @@ -50,6 +50,9 @@ impl TransactionData { #[tokio::test] async fn contract_lifecycle() -> Result<()> { const DEFAULT_PORT: u16 = 9944; + const DEFAULT_ENDPOINT: &str = "ws://127.0.0.1:9944"; + const WALLET_INT_URI: &str = "http://127.0.0.1:9090"; + const WAIT_SECS: u64 = 240; let temp = tempfile::tempdir().unwrap(); let temp_dir = temp.path(); //let temp_dir = Path::new("./"); //For testing locally @@ -161,43 +164,11 @@ async fn contract_lifecycle() -> Result<()> { .assert() .success(); - // Stop the process contracts-node - Cmd::new("kill") - .args(["-s", "TERM", &process.id().to_string()]) - .spawn()? - .wait()?; - - Ok(()) -} - -#[tokio::test] -async fn wait_for_wallet_signature() -> Result<()> { - const DEFAULT_ENDPOINT: &str = "ws://127.0.0.1:9966"; - const DEFAULT_PORT: u16 = 9966; - const WALLET_INT_URI: &str = "http://127.0.0.1:9090"; - const WAIT_SECS: u64 = 500; - let temp = tempfile::tempdir()?; - let temp_dir = temp.path(); - //let temp_dir = Path::new("./"); //For testing locally - // pop new contract test_contract (default) - Command::cargo_bin("pop") - .unwrap() - .current_dir(&temp_dir) - .args(&["new", "contract", "test_contract"]) - .assert() - .success(); - assert!(temp_dir.join("test_contract").exists()); - - let binary = contracts_node_generator(temp_dir.to_path_buf().clone(), None).await?; - binary.source(false, &(), true).await?; - set_executable_permission(binary.path())?; - let process = run_contracts_node(binary.path(), None, DEFAULT_PORT).await?; - sleep(Duration::from_secs(10)).await; - // pop up contract --upload-only --use-wallet + // Will run http server for wallet integration. // Using `cargo run --` as means for the CI to pass. // Possibly there's room for improvement here. - let _handler = tokio::process::Command::new("cargo") + let _ = tokio::process::Command::new("cargo") .args(&[ "run", "--", @@ -207,8 +178,6 @@ async fn wait_for_wallet_signature() -> Result<()> { "--use-wallet", "--skip-confirm", "--dry-run", - "--url", - DEFAULT_ENDPOINT, "-p", temp_dir.join("test_contract").to_str().expect("to_str"), ]) From f9851d1ec0bd761e83f0f4ab833dec344b9b5ba2 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Sun, 15 Dec 2024 19:54:37 +0100 Subject: [PATCH 25/27] test(wallet-integration): remove sign_call_data test --- crates/pop-cli/src/common/wallet.rs | 61 ----------------------------- 1 file changed, 61 deletions(-) diff --git a/crates/pop-cli/src/common/wallet.rs b/crates/pop-cli/src/common/wallet.rs index 6d18460c..468c153f 100644 --- a/crates/pop-cli/src/common/wallet.rs +++ b/crates/pop-cli/src/common/wallet.rs @@ -36,64 +36,3 @@ pub async fn wait_for_signature(call_data: Vec, url: String) -> anyhow::Resu let signed_payload = wallet.state.lock().await.signed_payload.clone(); Ok(signed_payload) } - -#[cfg(test)] -mod tests { - use super::*; - use subxt::utils::to_hex; - - // TODO: delete this test. - // This is a helper test for an actual running pop CLI. - // It can serve as the "frontend" to query the payload, sign it - // and submit back to the CLI. - #[ignore] - #[tokio::test] - async fn sign_call_data() -> anyhow::Result<()> { - use subxt::{config::DefaultExtrinsicParamsBuilder as Params, tx::Payload}; - // This struct implements the [`Payload`] trait and is used to submit - // pre-encoded SCALE call data directly, without the dynamic construction of transactions. - struct CallData(Vec); - - impl Payload for CallData { - fn encode_call_data_to( - &self, - _: &subxt::Metadata, - out: &mut Vec, - ) -> Result<(), subxt::ext::subxt_core::Error> { - out.extend_from_slice(&self.0); - Ok(()) - } - } - - use subxt_signer::sr25519::dev; - let payload = reqwest::get(&format!("{}/payload", "http://127.0.0.1:9090")) - .await - .expect("Failed to get payload") - .json::() - .await - .expect("Failed to parse payload"); - - let url = "ws://localhost:9944"; - let rpc_client = subxt::backend::rpc::RpcClient::from_url(url).await?; - let client = - subxt::OnlineClient::::from_rpc_client(rpc_client).await?; - - let signer = dev::alice(); - - let payload = CallData(payload.call_data()); - let ext_params = Params::new().build(); - let signed = client.tx().create_signed(&payload, &signer, ext_params).await?; - - let response = reqwest::Client::new() - .post(&format!("{}/submit", "http://localhost:9090")) - .json(&to_hex(signed.encoded())) - .send() - .await - .expect("Failed to submit payload") - .text() - .await - .expect("Failed to parse JSON response"); - - Ok(()) - } -} From 80f4f7bd79f5a6b3f0f64b0baea7f4e840b6d7ca Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Sun, 15 Dec 2024 20:33:14 +0100 Subject: [PATCH 26/27] test(wallet-integration): use random free port --- crates/pop-cli/tests/contract.rs | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/crates/pop-cli/tests/contract.rs b/crates/pop-cli/tests/contract.rs index 3befd888..6effb4d2 100644 --- a/crates/pop-cli/tests/contract.rs +++ b/crates/pop-cli/tests/contract.rs @@ -2,7 +2,7 @@ use anyhow::Result; use assert_cmd::Command; -use pop_common::{set_executable_permission, templates::Template}; +use pop_common::{find_free_port, set_executable_permission, templates::Template}; use pop_contracts::{ contracts_node_generator, dry_run_gas_estimate_instantiate, instantiate_smart_contract, run_contracts_node, set_up_deployment, Contract, UpOpts, @@ -49,10 +49,10 @@ impl TransactionData { /// Test the contract lifecycle: new, build, up, call #[tokio::test] async fn contract_lifecycle() -> Result<()> { - const DEFAULT_PORT: u16 = 9944; - const DEFAULT_ENDPOINT: &str = "ws://127.0.0.1:9944"; const WALLET_INT_URI: &str = "http://127.0.0.1:9090"; const WAIT_SECS: u64 = 240; + let endpoint_port = find_free_port(); + let default_endpoint: &str = &format!("ws://127.0.0.1:{}", endpoint_port); let temp = tempfile::tempdir().unwrap(); let temp_dir = temp.path(); //let temp_dir = Path::new("./"); //For testing locally @@ -84,14 +84,15 @@ async fn contract_lifecycle() -> Result<()> { let binary = contracts_node_generator(temp_dir.to_path_buf().clone(), None).await?; binary.source(false, &(), true).await?; set_executable_permission(binary.path())?; - let process = run_contracts_node(binary.path(), None, DEFAULT_PORT).await?; + let process = run_contracts_node(binary.path(), None, endpoint_port).await?; + sleep(Duration::from_secs(5)).await; // Only upload the contract // pop up contract --upload-only Command::cargo_bin("pop") .unwrap() .current_dir(&temp_dir.join("test_contract")) - .args(&["up", "contract", "--upload-only"]) + .args(&["up", "contract", "--upload-only", "--url", default_endpoint]) .assert() .success(); // Instantiate contract, only dry-run @@ -108,6 +109,8 @@ async fn contract_lifecycle() -> Result<()> { "--suri", "//Alice", "--dry-run", + "--url", + default_endpoint, ]) .assert() .success(); @@ -121,7 +124,7 @@ async fn contract_lifecycle() -> Result<()> { gas_limit: None, proof_size: None, salt: None, - url: Url::parse("ws://127.0.0.1:9944")?, + url: Url::parse(default_endpoint)?, suri: "//Alice".to_string(), }) .await?; @@ -141,6 +144,8 @@ async fn contract_lifecycle() -> Result<()> { "get", "--suri", "//Alice", + "--url", + default_endpoint, ]) .assert() .success(); @@ -160,6 +165,8 @@ async fn contract_lifecycle() -> Result<()> { "--suri", "//Alice", "-x", + "--url", + default_endpoint, ]) .assert() .success(); @@ -180,6 +187,8 @@ async fn contract_lifecycle() -> Result<()> { "--dry-run", "-p", temp_dir.join("test_contract").to_str().expect("to_str"), + "--url", + default_endpoint, ]) .spawn()?; // Wait a moment for node and server to be up. @@ -195,7 +204,7 @@ async fn contract_lifecycle() -> Result<()> { // We have received some payload. assert!(!response.call_data().is_empty()); - let rpc_client = subxt::backend::rpc::RpcClient::from_url(DEFAULT_ENDPOINT).await?; + let rpc_client = subxt::backend::rpc::RpcClient::from_url(default_endpoint).await?; let client = subxt::OnlineClient::::from_rpc_client(rpc_client).await?; // Sign payload. From 86ab4b88eadfd6955982e12ca849fe0bcd2bab55 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Sun, 15 Dec 2024 21:12:31 +0100 Subject: [PATCH 27/27] test(wallet-integration): define gas_limit & proof_size --- crates/pop-cli/src/commands/up/contract.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/pop-cli/src/commands/up/contract.rs b/crates/pop-cli/src/commands/up/contract.rs index 838bf6b2..4ccc318b 100644 --- a/crates/pop-cli/src/commands/up/contract.rs +++ b/crates/pop-cli/src/commands/up/contract.rs @@ -538,8 +538,8 @@ mod tests { constructor: "new".to_string(), args: vec!["false".to_string()], value: "0".to_string(), - gas_limit: None, - proof_size: None, + gas_limit: Some(200_000_000), + proof_size: Some(30_000), salt: None, url: Url::parse(&localhost_url).expect("given url is valid"), suri: "//Alice".to_string(), @@ -564,7 +564,7 @@ mod tests { assert!(!retrieved_call_data.is_empty()); // Craft instantiate call data. - let weight = Weight::from_parts(0, 0); + let weight = Weight::from_parts(200_000_000, 30_000); let expected_call_data = get_instantiate_payload(set_up_deployment(up_contract_opts.into()).await?, weight) .await?;