1pub(crate) mod command;
2pub(crate) mod types;
3
4pub use command::get_address::*;
5pub use command::get_app_configuration::*;
6pub use command::provide_erc20_token_info::*;
7pub use command::sign_transaction::*;
8use ledger_transport::{APDUCommand, APDUErrorCode, Exchange};
9use ledger_zondax_generic::{App, LedgerAppError};
10pub use types::*;
11
12#[derive(Debug)]
15pub struct EthApp<E: Exchange> {
16 transport: E,
17}
18
19impl<E: Exchange> App for EthApp<E> {
20 const CLA: u8 = 0xe0;
21}
22
23impl<E: Exchange> EthApp<E> {
24 pub const fn new(transport: E) -> Self {
26 EthApp { transport }
27 }
28}
29
30impl<E> EthApp<E>
31where
32 E: Exchange + Send + Sync,
33 E::Error: std::error::Error,
34{
35 pub async fn send_chunks(
36 &self,
37 mut command: APDUCommand<Vec<u8>>,
38 ) -> Result<ledger_transport::APDUAnswer<E::AnswerType>, LedgerAppError<E::Error>> {
39 let chunks = command
40 .data
41 .chunks(250)
42 .map(|c| c.to_vec())
43 .collect::<Vec<Vec<u8>>>();
44 match chunks.len() {
45 0 => return Err(LedgerAppError::InvalidEmptyMessage),
46 n if n > 255 => return Err(LedgerAppError::InvalidMessageSize),
47 _ => (),
48 }
49
50 let (first, rest) = chunks.split_first().unwrap();
51 command.data = first.to_owned();
52
53 if command.p1 != ChunkPayloadType::First as u8 {
54 return Err(LedgerAppError::InvalidChunkPayloadType);
55 }
56
57 let mut response = self.transport.exchange(&command).await?;
58 match response.error_code() {
59 Ok(APDUErrorCode::NoError) => {}
60 Ok(err) => return Err(LedgerAppError::AppSpecific(err as _, err.description())),
61 Err(err) => return Err(LedgerAppError::Unknown(err as _)),
62 }
63
64 let p1 = ChunkPayloadType::Subsequent as u8;
66 for chunk in rest {
67 dbg!(&chunk);
68 let command = APDUCommand {
69 cla: command.cla,
70 ins: command.ins,
71 p1,
72 p2: 0,
73 data: chunk.to_vec(),
74 };
75
76 response = self.transport.exchange(&command).await?;
77 match response.error_code() {
78 Ok(APDUErrorCode::NoError) => {}
79 Ok(err) => return Err(LedgerAppError::AppSpecific(err as _, err.description())),
80 Err(err) => return Err(LedgerAppError::Unknown(err as _)),
81 }
82 }
83
84 Ok(response)
85 }
86}