diff --git a/wallet/src/signer/ledger_signer/tests/mod.rs b/wallet/src/signer/ledger_signer/tests/mod.rs index 206a03d00..db177ee0d 100644 --- a/wallet/src/signer/ledger_signer/tests/mod.rs +++ b/wallet/src/signer/ledger_signer/tests/mod.rs @@ -62,7 +62,7 @@ use crypto::key::{ use logging::log; use randomness::make_true_rng; use serialization::hex::HexEncode; -use speculos::{Button, ButtonAction, Device, Handle, TouchScreenElement}; +use speculos::{Device, Handle}; use test_utils::random::{make_seedable_rng, Seed}; use utils::env_utils::{bool_from_env, get_from_env}; use wallet_storage::WalletStorageReadLocked; @@ -95,29 +95,14 @@ async fn auto_confirmer(mut control_msg_rx: mpsc::Receiver, hand loop { tokio::select! { _ = sleep(Duration::from_millis(500)) => { - // Logic depends on whether we are using a touch screen or buttons - if handle.device().is_touch() { - // TOUCH DEVICE STRATEGY - // On Speculos, blindly tapping coordinates is safe. - // 1. Try to go to the next page (Tap the "Next/Tap" zone) - // 2. Try to confirm (Tap the "Confirm" zone) - - // Attempt to advance review - let _ = handle.tap(TouchScreenElement::ReviewTap).await; - sleep(Duration::from_millis(100)).await; - - // Attempt to confirm review - let _ = handle.hold(TouchScreenElement::ReviewConfirm).await; - sleep(Duration::from_millis(100)).await; - } else { - // BUTTON DEVICE STRATEGY (Nano S/S+/X) - // 1. Press Right to scroll - // 2. Press Both to confirm - let _ = handle.button(Button::Right, ButtonAction::PressAndRelease).await; - sleep(Duration::from_millis(100)).await; - let _ = handle.button(Button::Both, ButtonAction::PressAndRelease).await; - sleep(Duration::from_millis(100)).await; - let _ = handle.button(Button::Both, ButtonAction::PressAndRelease).await; + if let Ok(events) = handle.current_screen_events().await { + let to_sign = events.iter().any(|e| e.contains("Sign ")); + + if to_sign { + let _ = handle.confirm().await; + } else { + let _ = handle.navigate_next().await; + } } } msg = control_msg_rx.recv() => { diff --git a/wallet/src/signer/ledger_signer/tests/speculos.rs b/wallet/src/signer/ledger_signer/tests/speculos.rs index c1aec70ac..b2110876a 100644 --- a/wallet/src/signer/ledger_signer/tests/speculos.rs +++ b/wallet/src/signer/ledger_signer/tests/speculos.rs @@ -119,6 +119,22 @@ impl TouchScreenElement { } } +// ----------------------------------------------------------------- +// Screen Events +// ----------------------------------------------------------------- + +/// Response format for the /events endpoint +#[derive(Debug, Deserialize)] +struct EventsResponse { + events: Vec, +} + +/// A single event inside the events array +#[derive(Debug, Deserialize)] +struct Event { + text: String, +} + // ----------------------------------------------------------------- // RUNTIME HANDLE // ----------------------------------------------------------------- @@ -204,6 +220,43 @@ impl Handle { self.finger(x, y, ButtonAction::PressAndRelease).await?; Ok(()) } + + pub async fn navigate_next(&self) -> anyhow::Result<()> { + if self.device().is_touch() { + self.tap(TouchScreenElement::ReviewTap).await + } else { + self.button(Button::Right, ButtonAction::PressAndRelease).await + } + } + + pub async fn confirm(&self) -> anyhow::Result<()> { + if self.device().is_touch() { + self.hold(TouchScreenElement::ReviewConfirm).await + } else { + self.button(Button::Both, ButtonAction::PressAndRelease).await + } + } + + /// Fetch the current screen events from the emulator and extract their text + pub async fn current_screen_events(&self) -> anyhow::Result> { + log::debug!("Fetching current screen events"); + + let r = Client::new() + .get(format!("http://{}/events", self.addr())) + .query(&[("currentscreenonly", "true")]) + .send() + .await?; + + if !r.status().is_success() { + anyhow::bail!("Events request failed: {}", r.status()); + } + + let response: EventsResponse = r.json().await?; + + let texts = response.events.into_iter().map(|event| event.text).collect(); + + Ok(texts) + } } #[cfg(test)]