ledger_lib/provider/
mod.rs1use std::time::Duration;
5
6use tokio::sync::{
7 mpsc::{unbounded_channel, UnboundedSender},
8 OnceCell,
9};
10
11mod context;
12use context::ProviderContext;
13
14use crate::{error::Error, info::LedgerInfo, transport::Transport, Exchange, Filters};
15
16pub struct LedgerProvider {
18 req_tx: ReqChannel,
19}
20
21#[derive(Debug)]
23pub struct LedgerHandle {
24 pub info: LedgerInfo,
25
26 index: usize,
28
29 req_tx: ReqChannel,
31}
32
33#[derive(Clone, Debug, PartialEq)]
35pub enum LedgerReq {
36 List(Filters),
38
39 Connect(LedgerInfo),
41
42 Req(usize, Vec<u8>, Duration),
44
45 Close(usize),
47}
48
49#[derive(Debug)]
51pub enum LedgerResp {
52 Devices(Vec<LedgerInfo>),
54
55 Handle(usize),
57
58 Resp(Vec<u8>),
60
61 Error(Error),
63}
64
65pub type ReqChannel = UnboundedSender<(LedgerReq, UnboundedSender<LedgerResp>)>;
67
68static PROVIDER_CTX: OnceCell<ProviderContext> = OnceCell::const_new();
70
71impl LedgerProvider {
72 pub async fn init() -> Self {
74 let ctx = PROVIDER_CTX
76 .get_or_init(|| async { ProviderContext::new().await })
77 .await;
78
79 Self {
81 req_tx: ctx.req_tx(),
82 }
83 }
84}
85
86#[cfg_attr(not(feature = "unstable_async_trait"), async_trait::async_trait)]
88impl Transport for LedgerProvider {
89 type Device = LedgerHandle;
90 type Info = LedgerInfo;
91 type Filters = Filters;
92
93 async fn list(&mut self, filters: Filters) -> Result<Vec<LedgerInfo>, Error> {
95 let (tx, mut rx) = unbounded_channel::<LedgerResp>();
96
97 self.req_tx
99 .send((LedgerReq::List(filters), tx))
100 .map_err(|_| Error::Unknown)?;
101
102 match rx.recv().await {
104 Some(LedgerResp::Devices(i)) => Ok(i),
105 Some(LedgerResp::Error(e)) => Err(e),
106 _ => Err(Error::Unknown),
107 }
108 }
109
110 async fn connect(&mut self, info: LedgerInfo) -> Result<LedgerHandle, Error> {
112 let (tx, mut rx) = unbounded_channel::<LedgerResp>();
113
114 self.req_tx
116 .send((LedgerReq::Connect(info.clone()), tx))
117 .map_err(|_| Error::Unknown)?;
118
119 match rx.recv().await {
121 Some(LedgerResp::Handle(index)) => Ok(LedgerHandle {
122 info,
123 index,
124 req_tx: self.req_tx.clone(),
125 }),
126 Some(LedgerResp::Error(e)) => Err(e),
127 _ => Err(Error::Unknown),
128 }
129 }
130}
131
132#[cfg_attr(not(feature = "unstable_async_trait"), async_trait::async_trait)]
134impl Exchange for LedgerHandle {
135 async fn exchange(&mut self, command: &[u8], timeout: Duration) -> Result<Vec<u8>, Error> {
136 let (tx, mut rx) = unbounded_channel::<LedgerResp>();
137
138 self.req_tx
140 .send((LedgerReq::Req(self.index, command.to_vec(), timeout), tx))
141 .map_err(|_| Error::Unknown)?;
142
143 match rx.recv().await {
145 Some(LedgerResp::Resp(data)) => Ok(data),
146 Some(LedgerResp::Error(e)) => Err(e),
147 _ => Err(Error::Unknown),
148 }
149 }
150}
151
152impl Drop for LedgerHandle {
154 fn drop(&mut self) {
155 let (tx, _rx) = unbounded_channel::<LedgerResp>();
156 let _ = self.req_tx.send((LedgerReq::Close(self.index), tx));
157 }
158}