1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#[doc(hidden)]
#[cfg(not(target_arch = "wasm32"))]
pub mod hid;
#[cfg(all(target_arch = "wasm32"))]
pub mod wasm;
#[cfg(all(target_arch = "wasm32"))]
pub use wasm::LedgerTransport as DefaultTransport;
#[cfg(not(target_arch = "wasm32"))]
pub mod native;
#[cfg(not(target_arch = "wasm32"))]
pub use native::NativeTransport as DefaultTransport;
#[cfg(target_arch = "wasm32")]
use log::{debug, error};
#[cfg(not(target_arch = "wasm32"))]
use tracing::{debug, error};
use crate::{
common::{APDUAnswer, APDUCommand},
errors::LedgerError,
};
use async_trait::async_trait;
pub struct Ledger(DefaultTransport);
#[async_trait(?Send)]
pub trait LedgerAsync: Sized {
async fn init() -> Result<Self, LedgerError>;
async fn exchange(&self, packet: &APDUCommand) -> Result<APDUAnswer, LedgerError>;
fn close(self) {}
}
#[async_trait(?Send)]
impl LedgerAsync for Ledger {
#[cfg(not(target_arch = "wasm32"))]
async fn init() -> Result<Self, LedgerError> {
Ok(Self(DefaultTransport::new()?))
}
#[cfg(target_arch = "wasm32")]
async fn init() -> Result<Self, LedgerError> {
let res: Result<DefaultTransport, wasm_bindgen::JsValue> = DefaultTransport::create().await;
let res: Result<DefaultTransport, LedgerError> = res.map_err(|err| err.into());
Ok(Self(res?))
}
#[cfg(not(target_arch = "wasm32"))]
async fn exchange(&self, packet: &APDUCommand) -> Result<APDUAnswer, LedgerError> {
debug!(command = %packet, "dispatching APDU to device");
let resp = self.0.exchange(packet).await;
match &resp {
Ok(resp) => {
debug!(
retcode = resp.retcode(),
response = hex::encode(resp.data().unwrap()),
"Received response from device"
)
}
Err(e) => error!(err = format!("{}", &e), "Received error from device"),
}
resp
}
#[cfg(target_arch = "wasm32")]
async fn exchange(&self, packet: &APDUCommand) -> Result<APDUAnswer, LedgerError> {
debug!("Exchanging Packet {:#?}", packet);
let resp = self.0.exchange(packet).await;
match &resp {
Ok(resp) => debug!("Got response: {:#?}", &resp),
Err(e) => error!("Got error: {}", e),
}
resp
}
}