Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: wallet integration pop call chain #379

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
25e8df1
feat(wallet-integration): server and API (#362)
peterwht Dec 9, 2024
b5fa054
feat(up-contract): get call data for upload-only and pass to wallet i…
peterwht Dec 6, 2024
4cd63cd
feat(up-contract): get call data for instantiate and pass to wallet i…
peterwht Dec 6, 2024
bfbbd0f
feat(up-contract): run server and pass call_data for signing -- PoC
peterwht Dec 7, 2024
8b1c8bf
feat(up-contract): submit signed payload to node
peterwht Dec 7, 2024
b709778
fix(up-contract): update to FrontendFromDir type
peterwht Dec 8, 2024
d3c3b12
refactor(pop-up): create functions for wallet integration, plus gener…
peterwht Dec 9, 2024
e82d018
chore: use git branch for cargo contract
peterwht Dec 9, 2024
ddbc759
feat(pop-up-contract): better error handling and prompt displays
peterwht Dec 9, 2024
604cecd
chore(up-contract): outdated field name and clippy allow
peterwht Dec 9, 2024
26b8f47
feat(up-contract): handle subxt events better, various improvements
peterwht Dec 11, 2024
1f95acb
feat(up-contract): custom errors in contracts crate
peterwht Dec 11, 2024
2a09b0a
fix: minor fixes after rebase
peterwht Dec 13, 2024
81ed681
fix(up-contract): test compilation after rebase
peterwht Dec 13, 2024
4c1431b
feat(up-contract): suri and use-wallet can't be used together
peterwht Dec 13, 2024
47ececb
refactor: wait for finalization
peterwht Dec 15, 2024
40c7ce6
feat(up-contract): serve HTML from string, fix deployment message on …
peterwht Dec 15, 2024
cfa4edb
feat(wallet-integration): server and API (#362)
peterwht Dec 9, 2024
e5e1786
feat(up-contract): get call data for upload-only and pass to wallet i…
peterwht Dec 6, 2024
e0b1f4e
refactor(pop-up): create functions for wallet integration, plus gener…
peterwht Dec 9, 2024
10a3bb8
chore: use git branch for cargo contract
peterwht Dec 9, 2024
bbe8d6f
feat(up-contract): handle subxt events better, various improvements
peterwht Dec 11, 2024
76b7fb5
feat(wallet-integration): implement server and API
peterwht Dec 4, 2024
3a8043b
feat(wallet-integration): add a few tests to server. Needs more
peterwht Dec 4, 2024
c6aae64
refactor(wallet-integration): just use call_data, remove data types
peterwht Dec 5, 2024
620790e
feat(wallet-integration): add frontend type for flexible serving
peterwht Dec 5, 2024
9f1a410
feat(wallet-integration): StateHandler in WalletIntegrationManager. A…
peterwht Dec 5, 2024
8b4dd63
refactor(wallet-integration): move to module with pop-cli crate
peterwht Dec 5, 2024
76fde8e
feat(wallet-integration): server-side error handling, update port to …
peterwht Dec 5, 2024
ba2e946
refactor(wallet-integration): restructure server for easier use in th…
peterwht Dec 7, 2024
c07902a
fix(wallet-integration): remove invalid fn `finish`
peterwht Dec 7, 2024
dc2c989
docs(wallet-integration): inline comments
peterwht Dec 7, 2024
304c706
test(wallet-integration): unit tests for wallet-integration server. A…
peterwht Dec 8, 2024
15fbc45
feat(wallet-integration): two new routes: error and terminate
peterwht Dec 8, 2024
bfb4619
refactor(wallet-integration): consistent comments, remove unnecessary…
peterwht Dec 9, 2024
ddf4768
feat: guide user to call a contract (#306)
AlexD10S Nov 29, 2024
d2bbc5f
fix: support new substrate-contracts-node structure and stabilize int…
AlexD10S Dec 3, 2024
018e8b1
feat: guide user to call a parachain (#316)
AlexD10S Dec 10, 2024
3dee596
feat(wallet-integration): server and API (#362)
peterwht Dec 9, 2024
ad03c74
feat(up-contract): get call data for upload-only and pass to wallet i…
peterwht Dec 6, 2024
8391835
chore: use git branch for cargo contract
peterwht Dec 9, 2024
7935009
feat(up-contract): handle subxt events better, various improvements
peterwht Dec 11, 2024
84bde34
refactor: reuse pop up logic
AlexD10S Dec 11, 2024
ec56f5f
chore: rebase fixes
AlexD10S Dec 11, 2024
2cb9a70
refactor: clean after rebase
AlexD10S Dec 11, 2024
9177dc0
fix: cargo.lock after rebase
AlexD10S Dec 11, 2024
64997f2
refactor: move terminate node into common::contracts
AlexD10S Dec 11, 2024
79a70cf
fix: sp-core not only for contracts
AlexD10S Dec 11, 2024
c607a10
feat(up-contract): serve HTML from string, fix deployment message on …
peterwht Dec 12, 2024
a10ec5a
fix: rebase
AlexD10S Dec 12, 2024
9140c14
feat: secure signing logic for pop call chain
AlexD10S Dec 12, 2024
fee5dd7
test: unit tests in pop-cli
AlexD10S Dec 12, 2024
7aa808f
feat: secure signing for call from call_data
AlexD10S Dec 12, 2024
5b5ebf7
refactor: docs and remove unneded functions
AlexD10S Dec 13, 2024
5cbb729
refactor: replace hex library
AlexD10S Dec 13, 2024
8c8d65c
fix: rebase issues
AlexD10S Dec 13, 2024
0a3271c
fix: rebase
AlexD10S Dec 13, 2024
6ea2002
refactor: small changes
AlexD10S Dec 13, 2024
ffb57f7
refactor: renaming
AlexD10S Dec 14, 2024
6c6de9a
feat: wallet integration call contract (#378)
AlexD10S Dec 16, 2024
16f2da6
chore: merge
peterwht Dec 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
462 changes: 231 additions & 231 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ contract-extrinsics = { git = "https://github.com/use-ink/cargo-contract", branc
#contract-transcode = "5.0.0"
contract-transcode = { git = "https://github.com/use-ink/cargo-contract", branch = "peter/chore-make-types-pub" }
heck = "0.5.0"
hex = { version = "0.4.3", default-features = false }
Copy link
Collaborator Author

@AlexD10S AlexD10S Dec 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed for consistency. In the main feat PR we are using other libraries, so refactored to use the same and remove this dependency.


# parachains
askama = "0.12"
Expand Down
4 changes: 2 additions & 2 deletions crates/pop-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ url.workspace = true
clap.workspace = true
cliclack.workspace = true
console.workspace = true
sp-core.workspace = true
strum.workspace = true
strum_macros.workspace = true

# contracts
pop-contracts = { path = "../pop-contracts", version = "0.5.0", optional = true }
sp-core = { workspace = true, optional = true }
sp-weights = { workspace = true, optional = true }

# parachains
Expand All @@ -59,6 +59,6 @@ subxt-signer.workspace = true

[features]
default = ["contract", "parachain", "telemetry"]
contract = ["dep:pop-contracts", "dep:sp-core", "dep:sp-weights", "dep:dirs"]
contract = ["dep:pop-contracts", "dep:sp-weights", "dep:dirs"]
parachain = ["dep:pop-parachains", "dep:dirs"]
telemetry = ["dep:pop-telemetry"]
1 change: 0 additions & 1 deletion crates/pop-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ impl traits::Confirm for Confirm {

/// A input prompt using cliclack.
struct Input(cliclack::Input);

impl traits::Input for Input {
/// Sets the default value for the input.
fn default_input(mut self, value: &str) -> Self {
Expand Down
129 changes: 113 additions & 16 deletions crates/pop-cli/src/commands/call/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@

use std::path::Path;

use crate::cli::{self, traits::*};
use crate::{
cli::{self, traits::*},
common::wallet::wait_for_signature,
};
use anyhow::{anyhow, Result};
use clap::Args;
use pop_parachains::{
construct_extrinsic, construct_sudo_extrinsic, decode_call_data, encode_call_data,
find_dispatchable_by_name, find_pallet_by_name, parse_chain_metadata, set_up_client,
sign_and_submit_extrinsic, supported_actions, Action, CallData, DynamicPayload, Function,
OnlineClient, Pallet, Param, SubstrateConfig,
sign_and_submit_extrinsic, submit_signed_extrinsic, supported_actions, Action, CallData,
DynamicPayload, Function, OnlineClient, Pallet, Param, Payload, SubstrateConfig,
};
use url::Url;

Expand Down Expand Up @@ -40,6 +43,9 @@
/// - with a password "//Alice///SECRET_PASSWORD"
#[arg(short, long)]
suri: Option<String>,
/// Use your browser wallet to sign the extrinsic.
#[arg(name = "use-wallet", short('w'), long, default_value = "false", conflicts_with = "suri")]
use_wallet: bool,
/// SCALE encoded bytes representing the call data of the extrinsic.
#[arg(name = "call", short, long, conflicts_with_all = ["pallet", "function", "args"])]
call_data: Option<String>,
Expand Down Expand Up @@ -95,7 +101,14 @@
};

// Sign and submit the extrinsic.
if let Err(e) = call.submit_extrinsic(&chain.client, &chain.url, xt, &mut cli).await {
let result = if self.use_wallet {
let call_data = xt.encode_call_data(&chain.client.metadata())?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize it's not specific to this PR, but xt isn't a very good name.. Can leave alone for now, just noting.

submit_extrinsic_with_wallet(&chain.client, &chain.url, call_data, &mut cli).await
} else {
call.submit_extrinsic(&chain.client, &chain.url, xt, &mut cli).await
};

if let Err(e) = result {
display_message(&e.to_string(), false, &mut cli)?;
break;
}
Expand Down Expand Up @@ -197,11 +210,25 @@
// sudo.
self.configure_sudo(chain, cli)?;

// Resolve who is signing the extrinsic.
// Resolve who is signing the extrinsic. If a `suri` was provided via the command line,
// skip the prompt.
let suri = match self.suri.as_ref() {
Some(suri) => suri.clone(),
None =>
cli.input("Signer of the extrinsic:").default_input(DEFAULT_URI).interact()?,
None => {
if !self.use_wallet {
if cli.confirm("Do you want to use your browser wallet to sign the transaction? (Selecting 'No' will prompt you to manually enter the secret key URI for signing, e.g., '//Alice')")
.initial_value(true)
.interact()? {
self.use_wallet = true;
DEFAULT_URI.to_string() // Default value because the user is using the browser wallet.
}
else {
cli.input("Signer of the extrinsic:").default_input(DEFAULT_URI).interact()?
}
} else {
DEFAULT_URI.to_string() // Default value because the user is using the browser wallet.
}
},
};

return Ok(Call {
Expand All @@ -210,6 +237,7 @@
suri,
skip_confirm: self.skip_confirm,
sudo: self.sudo,
use_wallet: self.use_wallet,
});
}
}
Expand All @@ -222,11 +250,36 @@
call_data: &str,
cli: &mut impl Cli,
) -> Result<()> {
// Resolve who is signing the extrinsic.
// Resolve who is signing the extrinsic. If a `suri` was provided via the command line,
// skip the prompt.
let mut use_wallet = self.use_wallet;
let suri = match self.suri.as_ref() {
Some(suri) => suri,
None => &cli.input("Signer of the extrinsic:").default_input(DEFAULT_URI).interact()?,
Some(suri) => suri.clone(),
None =>
if !self.use_wallet {
if cli.confirm("Do you want to use your browser wallet to sign the transaction? (Selecting 'No' will prompt you to manually enter the secret key URI for signing, e.g., '//Alice')")
.initial_value(true)
.interact()? {
use_wallet = true;
DEFAULT_URI.to_string()
}
else {
cli.input("Signer of the extrinsic:").default_input(DEFAULT_URI).interact()?
}
} else {
DEFAULT_URI.to_string()
},
};
// Perform signing steps with wallet integration and return early.
if use_wallet {
let call_data_bytes =
decode_call_data(call_data).map_err(|err| anyhow!("{}", format!("{err:?}")))?;
submit_extrinsic_with_wallet(client, &url, call_data_bytes, cli)

Check warning on line 277 in crates/pop-cli/src/commands/call/chain.rs

View workflow job for this annotation

GitHub Actions / clippy

this expression creates a reference which is immediately dereferenced by the compiler

warning: this expression creates a reference which is immediately dereferenced by the compiler --> crates/pop-cli/src/commands/call/chain.rs:277:41 | 277 | submit_extrinsic_with_wallet(client, &url, call_data_bytes, cli) | ^^^^ help: change this to: `url` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow = note: `#[warn(clippy::needless_borrow)]` on by default
.await
.map_err(|err| anyhow!("{}", format!("{err:?}")))?;
display_message("Call complete.", true, cli)?;
return Ok(());
}
cli.info(format!("Encoded call data: {}", call_data))?;
if !self.skip_confirm &&
!cli.confirm("Do you want to submit the extrinsic?")
Expand All @@ -244,7 +297,7 @@
spinner.start("Signing and submitting the extrinsic and then waiting for finalization, please be patient...");
let call_data_bytes =
decode_call_data(call_data).map_err(|err| anyhow!("{}", format!("{err:?}")))?;
let result = sign_and_submit_extrinsic(client, url, CallData::new(call_data_bytes), suri)
let result = sign_and_submit_extrinsic(client, url, CallData::new(call_data_bytes), &suri)
.await
.map_err(|err| anyhow!("{}", format!("{err:?}")))?;

Expand Down Expand Up @@ -283,6 +336,7 @@
self.function = None;
self.args.clear();
self.sudo = false;
self.use_wallet = false;
}

// Function to check if all required fields are specified.
Expand Down Expand Up @@ -334,6 +388,8 @@
/// - for a dev account "//Alice"
/// - with a password "//Alice///SECRET_PASSWORD"
suri: String,
/// Whether to use your browser wallet to sign the extrinsic.
use_wallet: bool,
/// Whether to automatically sign and submit the extrinsic without prompting for confirmation.
skip_confirm: bool,
/// Whether to dispatch the function call with `Root` origin.
Expand Down Expand Up @@ -411,14 +467,45 @@
.collect();
full_message.push_str(&format!(" --args {}", args.join(" ")));
}
full_message.push_str(&format!(" --url {} --suri {}", chain.url, self.suri));
full_message.push_str(&format!(" --url {}", chain.url));
if self.use_wallet {
full_message.push_str(" --use-wallet");
} else {
full_message.push_str(&format!(" --suri {}", self.suri));
}
if self.sudo {
full_message.push_str(" --sudo");
}
full_message
}
}

// Sign and submit an extrinsic using wallet integration.
async fn submit_extrinsic_with_wallet(
client: &OnlineClient<SubstrateConfig>,
url: &Url,
call_data: Vec<u8>,
cli: &mut impl Cli,
) -> Result<()> {
let maybe_payload = wait_for_signature(call_data, url.to_string()).await?;
if let Some(payload) = maybe_payload {
cli.success("Signed payload received.")?;
let spinner = cliclack::spinner();
spinner.start(
"Submitting the extrinsic and then waiting for finalization, please be patient...",
);

let result = submit_signed_extrinsic(client.clone(), payload)
.await
.map_err(|err| anyhow!("{}", format!("{err:?}")))?;

spinner.stop(format!("Extrinsic submitted with hash: {:?}", result));
} else {
display_message("No signed payload received.", false, cli)?;
}
Ok(())
}

// Displays a message to the user, with formatting based on the success status.
fn display_message(message: &str, success: bool, cli: &mut impl Cli) -> Result<()> {
if success {
Expand Down Expand Up @@ -642,7 +729,7 @@
)
.expect_input("The value for `remark` might be too large to enter. You may enter the path to a file instead.", "0x11".into())
.expect_confirm("Would you like to dispatch this function call with `Root` origin?", true)
.expect_input("Signer of the extrinsic:", "//Bob".into());
.expect_confirm("Do you want to use your browser wallet to sign the transaction? (Selecting 'No' will prompt you to manually enter the secret key URI for signing, e.g., '//Alice')", true);

let chain = call_config.configure_chain(&mut cli).await?;
assert_eq!(chain.url, Url::parse(POP_NETWORK_TESTNET_URL)?);
Expand All @@ -651,9 +738,10 @@
assert_eq!(call_chain.function.pallet, "System");
assert_eq!(call_chain.function.name, "remark");
assert_eq!(call_chain.args, ["0x11".to_string()].to_vec());
assert_eq!(call_chain.suri, "//Bob");
assert_eq!(call_chain.suri, "//Alice"); // Default value
assert!(call_chain.use_wallet);
assert!(call_chain.sudo);
assert_eq!(call_chain.display(&chain), "pop call chain --pallet System --function remark --args \"0x11\" --url wss://rpc1.paseo.popnetwork.xyz/ --suri //Bob --sudo");
assert_eq!(call_chain.display(&chain), "pop call chain --pallet System --function remark --args \"0x11\" --url wss://rpc1.paseo.popnetwork.xyz/ --use-wallet --sudo");
cli.verify()
}

Expand Down Expand Up @@ -714,6 +802,7 @@
},
args: vec!["0x11".to_string()].to_vec(),
suri: DEFAULT_URI.to_string(),
use_wallet: false,
skip_confirm: false,
sudo: false,
};
Expand Down Expand Up @@ -753,6 +842,7 @@
function: find_dispatchable_by_name(&pallets, "System", "remark")?.clone(),
args: vec!["0x11".to_string()].to_vec(),
suri: DEFAULT_URI.to_string(),
use_wallet: false,
skip_confirm: false,
sudo: false,
};
Expand All @@ -776,11 +866,13 @@
args: vec![].to_vec(),
url: Some(Url::parse(POP_NETWORK_TESTNET_URL)?),
suri: None,
use_wallet: false,
skip_confirm: false,
call_data: Some("0x00000411".to_string()),
sudo: false,
};
let mut cli = MockCli::new()
.expect_confirm("Do you want to use your browser wallet to sign the transaction? (Selecting 'No' will prompt you to manually enter the secret key URI for signing, e.g., '//Alice')", false)
.expect_input("Signer of the extrinsic:", "//Bob".into())
.expect_confirm("Do you want to submit the extrinsic?", false)
.expect_outro_cancel("Extrinsic with call data 0x00000411 was not submitted.");
Expand All @@ -803,8 +895,9 @@
pallet: None,
function: None,
args: vec![].to_vec(),
url: Some(Url::parse("wss://polkadot-rpc.publicnode.com")?),
url: Some(Url::parse(POLKADOT_NETWORK_URL)?),
suri: Some("//Alice".to_string()),
use_wallet: false,
skip_confirm: false,
call_data: Some("0x00000411".to_string()),
sudo: true,
Expand Down Expand Up @@ -836,6 +929,7 @@
function: Some("remark".to_string()),
args: vec!["0x11".to_string()].to_vec(),
url: Some(Url::parse(POP_NETWORK_TESTNET_URL)?),
use_wallet: true,
suri: Some(DEFAULT_URI.to_string()),
skip_confirm: false,
call_data: None,
Expand All @@ -846,6 +940,7 @@
assert_eq!(call_config.function, None);
assert_eq!(call_config.args.len(), 0);
assert!(!call_config.sudo);
assert!(!call_config.use_wallet);
Ok(())
}

Expand All @@ -857,6 +952,7 @@
args: vec!["0x11".to_string()].to_vec(),
url: Some(Url::parse(POP_NETWORK_TESTNET_URL)?),
suri: Some(DEFAULT_URI.to_string()),
use_wallet: false,
skip_confirm: false,
call_data: None,
sudo: false,
Expand All @@ -875,6 +971,7 @@
args: vec!["2000".to_string(), "0x1".to_string(), "0x12".to_string()].to_vec(),
url: Some(Url::parse(POP_NETWORK_TESTNET_URL)?),
suri: Some(DEFAULT_URI.to_string()),
use_wallet: false,
call_data: None,
skip_confirm: false,
sudo: false,
Expand Down
Loading
Loading