Skip to content

Commit 75ad3d3

Browse files
authored
Merge pull request #2017 from mintlayer/fix/ledger-test-events
Use events in ledger tests
2 parents 03be587 + 4f04ea1 commit 75ad3d3

2 files changed

Lines changed: 70 additions & 30 deletions

File tree

wallet/src/signer/ledger_signer/tests/mod.rs

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ use crypto::key::{
6262
use logging::log;
6363
use randomness::make_true_rng;
6464
use serialization::hex::HexEncode;
65-
use speculos::{Button, ButtonAction, Device, Handle, TouchScreenElement};
65+
use speculos::{Device, Handle};
6666
use test_utils::random::{make_seedable_rng, Seed};
6767
use utils::env_utils::{bool_from_env, get_from_env};
6868
use wallet_storage::WalletStorageReadLocked;
@@ -95,29 +95,16 @@ async fn auto_confirmer(mut control_msg_rx: mpsc::Receiver<ControlMessage>, hand
9595
loop {
9696
tokio::select! {
9797
_ = sleep(Duration::from_millis(500)) => {
98-
// Logic depends on whether we are using a touch screen or buttons
99-
if handle.device().is_touch() {
100-
// TOUCH DEVICE STRATEGY
101-
// On Speculos, blindly tapping coordinates is safe.
102-
// 1. Try to go to the next page (Tap the "Next/Tap" zone)
103-
// 2. Try to confirm (Tap the "Confirm" zone)
104-
105-
// Attempt to advance review
106-
let _ = handle.tap(TouchScreenElement::ReviewTap).await;
107-
sleep(Duration::from_millis(100)).await;
108-
109-
// Attempt to confirm review
110-
let _ = handle.hold(TouchScreenElement::ReviewConfirm).await;
111-
sleep(Duration::from_millis(100)).await;
112-
} else {
113-
// BUTTON DEVICE STRATEGY (Nano S/S+/X)
114-
// 1. Press Right to scroll
115-
// 2. Press Both to confirm
116-
let _ = handle.button(Button::Right, ButtonAction::PressAndRelease).await;
117-
sleep(Duration::from_millis(100)).await;
118-
let _ = handle.button(Button::Both, ButtonAction::PressAndRelease).await;
119-
sleep(Duration::from_millis(100)).await;
120-
let _ = handle.button(Button::Both, ButtonAction::PressAndRelease).await;
98+
if let Ok(events) = handle.current_screen_events().await {
99+
let to_sign = events.iter().any(|e|
100+
e.contains("Sign transaction") || e.contains("Sign message")
101+
);
102+
103+
if to_sign {
104+
let _ = handle.confirm().await;
105+
} else {
106+
let _ = handle.navigate_next().await;
107+
}
121108
}
122109
}
123110
msg = control_msg_rx.recv() => {

wallet/src/signer/ledger_signer/tests/speculos.rs

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,22 @@ impl TouchScreenElement {
119119
}
120120
}
121121

122+
// -----------------------------------------------------------------
123+
// Screen Events
124+
// -----------------------------------------------------------------
125+
126+
/// Response format for the /events endpoint
127+
#[derive(Debug, Deserialize)]
128+
struct EventsResponse {
129+
events: Vec<Event>,
130+
}
131+
132+
/// A single event inside the events array
133+
#[derive(Debug, Deserialize)]
134+
struct Event {
135+
text: String,
136+
}
137+
122138
// -----------------------------------------------------------------
123139
// RUNTIME HANDLE
124140
// -----------------------------------------------------------------
@@ -154,14 +170,14 @@ impl Handle {
154170

155171
log::debug!("Sending button request: {}:{}", button, action);
156172

157-
let r = Client::new()
173+
let response = Client::new()
158174
.post(format!("http://{}/button/{}", self.addr(), button))
159175
.json(&ButtonPayload { action })
160176
.send()
161177
.await?;
162178

163-
if !r.status().is_success() {
164-
anyhow::bail!("Button request failed: {}", r.status());
179+
if !response.status().is_success() {
180+
anyhow::bail!("Button request failed: {}", response.status());
165181
}
166182

167183
Ok(())
@@ -178,14 +194,14 @@ impl Handle {
178194
delay: None,
179195
};
180196

181-
let r = Client::new()
197+
let response = Client::new()
182198
.post(format!("http://{}/finger", self.addr()))
183199
.json(&payload)
184200
.send()
185201
.await?;
186202

187-
if !r.status().is_success() {
188-
anyhow::bail!("Finger request failed: {}", r.status());
203+
if !response.status().is_success() {
204+
anyhow::bail!("Finger request failed: {}", response.status());
189205
}
190206

191207
Ok(())
@@ -204,6 +220,43 @@ impl Handle {
204220
self.finger(x, y, ButtonAction::PressAndRelease).await?;
205221
Ok(())
206222
}
223+
224+
pub async fn navigate_next(&self) -> anyhow::Result<()> {
225+
if self.device().is_touch() {
226+
self.tap(TouchScreenElement::ReviewTap).await
227+
} else {
228+
self.button(Button::Right, ButtonAction::PressAndRelease).await
229+
}
230+
}
231+
232+
pub async fn confirm(&self) -> anyhow::Result<()> {
233+
if self.device().is_touch() {
234+
self.hold(TouchScreenElement::ReviewConfirm).await
235+
} else {
236+
self.button(Button::Both, ButtonAction::PressAndRelease).await
237+
}
238+
}
239+
240+
/// Fetch the current screen events from the emulator and extract their text
241+
pub async fn current_screen_events(&self) -> anyhow::Result<Vec<String>> {
242+
log::debug!("Fetching current screen events");
243+
244+
let response = Client::new()
245+
.get(format!("http://{}/events", self.addr()))
246+
.query(&[("currentscreenonly", "true")])
247+
.send()
248+
.await?;
249+
250+
if !response.status().is_success() {
251+
anyhow::bail!("Events request failed: {}", response.status());
252+
}
253+
254+
let parsed_response: EventsResponse = response.json().await?;
255+
256+
let texts = parsed_response.events.into_iter().map(|event| event.text).collect();
257+
258+
Ok(texts)
259+
}
207260
}
208261

209262
#[cfg(test)]

0 commit comments

Comments
 (0)