|
2 | 2 | //! |
3 | 3 | //! See [ledger_lib] for APIs used in this application. |
4 | 4 |
|
5 | | -use std::fs::File; |
6 | | -use std::io::{self, BufRead}; |
7 | 5 | use std::str::FromStr; |
8 | 6 |
|
9 | 7 | use clap::Parser; |
10 | 8 | use hex::ToHex; |
11 | | -use ledger_proto::{ApduHeader, DecodeOwned, GenericApdu}; |
| 9 | +use ledger_proto::{ApduHeader, GenericApdu}; |
12 | 10 | use tracing::{debug, error}; |
13 | 11 | use tracing_subscriber::{filter::LevelFilter, EnvFilter, FmtSubscriber}; |
14 | 12 |
|
@@ -165,21 +163,23 @@ async fn main() -> anyhow::Result<()> { |
165 | 163 | } |
166 | 164 | Command::File { filename } => match filename { |
167 | 165 | Some(path) => { |
168 | | - let f = File::open(path)?; |
169 | | - let lines = io::BufReader::new(f).lines(); |
170 | | - |
| 166 | + let data = std::fs::read_to_string(path)?; |
171 | 167 | let mut d = connect(&mut p, &devices, args.index).await?; |
172 | 168 | let mut buff = [0u8; 256]; |
173 | 169 |
|
174 | | - for line in lines.into_iter().flatten() { |
175 | | - if let Some(s) = line.strip_prefix("=> ") { |
176 | | - let req = build_apdu(s); |
| 170 | + let apdu_seq: Vec<GenericApdu> = serde_json::from_str(data.as_str()).unwrap(); |
177 | 171 |
|
178 | | - let resp = d |
179 | | - .request::<GenericApdu>(req, &mut buff, args.timeout.into()) |
180 | | - .await?; |
| 172 | + for apdu_input in apdu_seq { |
| 173 | + let resp = d |
| 174 | + .request::<GenericApdu>(apdu_input, &mut buff, args.timeout.into()) |
| 175 | + .await; |
181 | 176 |
|
182 | | - println!("Response: {}", resp.data.encode_hex::<String>()); |
| 177 | + match resp { |
| 178 | + Ok(apdu_output) => { |
| 179 | + println!("Response: {}", apdu_output.data.encode_hex::<String>()) |
| 180 | + } |
| 181 | + Err(Error::Response(0x90, 0x00)) => println!("App OK"), |
| 182 | + Err(e) => println!("Command failed: {e:?}"), |
183 | 183 | } |
184 | 184 | } |
185 | 185 | } |
@@ -219,34 +219,3 @@ async fn connect( |
219 | 219 | } |
220 | 220 | } |
221 | 221 | } |
222 | | - |
223 | | -/// Build APDU from string |
224 | | -fn build_apdu(s: &str) -> GenericApdu { |
225 | | - let mut p: Vec<&str> = s.split_whitespace().collect(); |
226 | | - // Build APDU header |
227 | | - let header: Vec<&str> = p.drain(0..=3).collect(); |
228 | | - |
229 | | - let mut header_bytes: Vec<u8> = Default::default(); |
230 | | - for e in header { |
231 | | - header_bytes.push(u8::from_str_radix(e, 16).unwrap()) |
232 | | - } |
233 | | - let apdu_header: ApduHeader = match ApduHeader::decode_owned(header_bytes.as_slice()) { |
234 | | - Ok(t) => t.0, |
235 | | - Err(_) => Default::default(), |
236 | | - }; |
237 | | - |
238 | | - // Get APDU data |
239 | | - let data_bytes = match p.pop() { |
240 | | - Some(b) => match hex::decode(b) { |
241 | | - Ok(v) => v, |
242 | | - Err(_e) => Default::default(), |
243 | | - }, |
244 | | - None => Default::default(), |
245 | | - }; |
246 | | - |
247 | | - //Build APDU |
248 | | - GenericApdu { |
249 | | - header: apdu_header, |
250 | | - data: data_bytes, |
251 | | - } |
252 | | -} |
0 commit comments