1use std::borrow::Borrow;
6use std::convert::TryInto;
7use std::ops::Deref;
8
9use bitcoin::consensus::encode::{deserialize, serialize};
10use bitcoin::{block, Script, Transaction, Txid};
11
12use crate::batch::Batch;
13use crate::types::*;
14
15impl<E: Deref> ElectrumApi for E
16where
17 E::Target: ElectrumApi,
18{
19 fn raw_call(
20 &self,
21 method_name: &str,
22 params: impl IntoIterator<Item = Param>,
23 ) -> Result<serde_json::Value, Error> {
24 (**self).raw_call(method_name, params)
25 }
26
27 fn batch_call(&self, batch: &Batch) -> Result<Vec<serde_json::Value>, Error> {
28 (**self).batch_call(batch)
29 }
30
31 fn block_headers_subscribe_raw(&self) -> Result<RawHeaderNotification, Error> {
32 (**self).block_headers_subscribe_raw()
33 }
34
35 fn block_headers_pop_raw(&self) -> Result<Option<RawHeaderNotification>, Error> {
36 (**self).block_headers_pop_raw()
37 }
38
39 fn block_header_raw(&self, height: usize) -> Result<Vec<u8>, Error> {
40 (**self).block_header_raw(height)
41 }
42
43 fn block_headers(&self, start_height: usize, count: usize) -> Result<GetHeadersRes, Error> {
44 (**self).block_headers(start_height, count)
45 }
46
47 fn estimate_fee(&self, number: usize, mode: Option<EstimationMode>) -> Result<f64, Error> {
48 (**self).estimate_fee(number, mode)
49 }
50
51 fn relay_fee(&self) -> Result<f64, Error> {
52 (**self).relay_fee()
53 }
54
55 fn script_subscribe(&self, script: &Script) -> Result<Option<ScriptStatus>, Error> {
56 (**self).script_subscribe(script)
57 }
58
59 fn batch_script_subscribe<'s, I>(&self, scripts: I) -> Result<Vec<Option<ScriptStatus>>, Error>
60 where
61 I: IntoIterator + Clone,
62 I::Item: Borrow<&'s Script>,
63 {
64 (**self).batch_script_subscribe(scripts)
65 }
66
67 fn script_unsubscribe(&self, script: &Script) -> Result<bool, Error> {
68 (**self).script_unsubscribe(script)
69 }
70
71 fn script_pop(&self, script: &Script) -> Result<Option<ScriptStatus>, Error> {
72 (**self).script_pop(script)
73 }
74
75 fn script_get_balance(&self, script: &Script) -> Result<GetBalanceRes, Error> {
76 (**self).script_get_balance(script)
77 }
78
79 fn batch_script_get_balance<'s, I>(&self, scripts: I) -> Result<Vec<GetBalanceRes>, Error>
80 where
81 I: IntoIterator + Clone,
82 I::Item: Borrow<&'s Script>,
83 {
84 (**self).batch_script_get_balance(scripts)
85 }
86
87 fn script_get_history(&self, script: &Script) -> Result<Vec<GetHistoryRes>, Error> {
88 (**self).script_get_history(script)
89 }
90
91 fn batch_script_get_history<'s, I>(&self, scripts: I) -> Result<Vec<Vec<GetHistoryRes>>, Error>
92 where
93 I: IntoIterator + Clone,
94 I::Item: Borrow<&'s Script>,
95 {
96 (**self).batch_script_get_history(scripts)
97 }
98
99 fn script_list_unspent(&self, script: &Script) -> Result<Vec<ListUnspentRes>, Error> {
100 (**self).script_list_unspent(script)
101 }
102
103 fn batch_script_list_unspent<'s, I>(
104 &self,
105 scripts: I,
106 ) -> Result<Vec<Vec<ListUnspentRes>>, Error>
107 where
108 I: IntoIterator + Clone,
109 I::Item: Borrow<&'s Script>,
110 {
111 (**self).batch_script_list_unspent(scripts)
112 }
113
114 fn transaction_get_raw(&self, txid: &Txid) -> Result<Vec<u8>, Error> {
115 (**self).transaction_get_raw(txid)
116 }
117
118 fn batch_transaction_get_raw<'t, I>(&self, txids: I) -> Result<Vec<Vec<u8>>, Error>
119 where
120 I: IntoIterator + Clone,
121 I::Item: Borrow<&'t Txid>,
122 {
123 (**self).batch_transaction_get_raw(txids)
124 }
125
126 fn batch_block_header_raw<I>(&self, heights: I) -> Result<Vec<Vec<u8>>, Error>
127 where
128 I: IntoIterator + Clone,
129 I::Item: Borrow<u32>,
130 {
131 (**self).batch_block_header_raw(heights)
132 }
133
134 fn batch_estimate_fee<I>(&self, numbers: I) -> Result<Vec<f64>, Error>
135 where
136 I: IntoIterator + Clone,
137 I::Item: Borrow<usize>,
138 {
139 (**self).batch_estimate_fee(numbers)
140 }
141
142 fn transaction_broadcast_raw(&self, raw_tx: &[u8]) -> Result<Txid, Error> {
143 (**self).transaction_broadcast_raw(raw_tx)
144 }
145
146 fn transaction_broadcast_package_raw<T: AsRef<[u8]>>(
147 &self,
148 raw_txs: &[T],
149 ) -> Result<BroadcastPackageRes, Error> {
150 (**self).transaction_broadcast_package_raw(raw_txs)
151 }
152
153 fn transaction_get_merkle(&self, txid: &Txid, height: usize) -> Result<GetMerkleRes, Error> {
154 (**self).transaction_get_merkle(txid, height)
155 }
156
157 fn batch_transaction_get_merkle<I>(
158 &self,
159 txids_and_heights: I,
160 ) -> Result<Vec<GetMerkleRes>, Error>
161 where
162 I: IntoIterator + Clone,
163 I::Item: Borrow<(Txid, usize)>,
164 {
165 (**self).batch_transaction_get_merkle(txids_and_heights)
166 }
167
168 fn txid_from_pos(&self, height: usize, tx_pos: usize) -> Result<Txid, Error> {
169 (**self).txid_from_pos(height, tx_pos)
170 }
171
172 fn txid_from_pos_with_merkle(
173 &self,
174 height: usize,
175 tx_pos: usize,
176 ) -> Result<TxidFromPosRes, Error> {
177 (**self).txid_from_pos_with_merkle(height, tx_pos)
178 }
179
180 fn server_features(&self) -> Result<ServerFeaturesRes, Error> {
181 (**self).server_features()
182 }
183
184 fn mempool_get_info(&self) -> Result<MempoolInfoRes, Error> {
185 (**self).mempool_get_info()
186 }
187
188 fn ping(&self) -> Result<(), Error> {
189 (**self).ping()
190 }
191
192 fn calls_made(&self) -> Result<usize, Error> {
193 (**self).calls_made()
194 }
195}
196
197pub trait ElectrumApi {
199 fn block_header(&self, height: usize) -> Result<block::Header, Error> {
201 Ok(deserialize(&self.block_header_raw(height)?)?)
202 }
203
204 fn block_headers_subscribe(&self) -> Result<HeaderNotification, Error> {
206 self.block_headers_subscribe_raw()?.try_into()
207 }
208
209 fn block_headers_pop(&self) -> Result<Option<HeaderNotification>, Error> {
212 self.block_headers_pop_raw()?
213 .map(|raw| raw.try_into())
214 .transpose()
215 }
216
217 fn transaction_get(&self, txid: &Txid) -> Result<Transaction, Error> {
219 Ok(deserialize(&self.transaction_get_raw(txid)?)?)
220 }
221
222 fn batch_transaction_get<'t, I>(&self, txids: I) -> Result<Vec<Transaction>, Error>
226 where
227 I: IntoIterator + Clone,
228 I::Item: Borrow<&'t Txid>,
229 {
230 self.batch_transaction_get_raw(txids)?
231 .iter()
232 .map(|s| Ok(deserialize(s)?))
233 .collect()
234 }
235
236 fn batch_block_header<I>(&self, heights: I) -> Result<Vec<block::Header>, Error>
240 where
241 I: IntoIterator + Clone,
242 I::Item: Borrow<u32>,
243 {
244 self.batch_block_header_raw(heights)?
245 .iter()
246 .map(|s| Ok(deserialize(s)?))
247 .collect()
248 }
249
250 fn transaction_broadcast(&self, tx: &Transaction) -> Result<Txid, Error> {
252 let buffer: Vec<u8> = serialize(tx);
253 self.transaction_broadcast_raw(&buffer)
254 }
255
256 fn transaction_broadcast_package(
264 &self,
265 txs: &[Transaction],
266 ) -> Result<BroadcastPackageRes, Error> {
267 let raw_txs: Vec<Vec<u8>> = txs.iter().map(serialize).collect();
268 self.transaction_broadcast_package_raw(&raw_txs)
269 }
270
271 fn raw_call(
273 &self,
274 method_name: &str,
275 params: impl IntoIterator<Item = Param>,
276 ) -> Result<serde_json::Value, Error>;
277
278 fn batch_call(&self, batch: &Batch) -> Result<Vec<serde_json::Value>, Error>;
282
283 fn block_headers_subscribe_raw(&self) -> Result<RawHeaderNotification, Error>;
286
287 fn block_headers_pop_raw(&self) -> Result<Option<RawHeaderNotification>, Error>;
290
291 fn block_header_raw(&self, height: usize) -> Result<Vec<u8>, Error>;
293
294 fn block_headers(&self, start_height: usize, count: usize) -> Result<GetHeadersRes, Error>;
296
297 fn estimate_fee(&self, number: usize, mode: Option<EstimationMode>) -> Result<f64, Error>;
302
303 fn relay_fee(&self) -> Result<f64, Error>;
309
310 fn script_subscribe(&self, script: &Script) -> Result<Option<ScriptStatus>, Error>;
318
319 fn batch_script_subscribe<'s, I>(&self, scripts: I) -> Result<Vec<Option<ScriptStatus>>, Error>
325 where
326 I: IntoIterator + Clone,
327 I::Item: Borrow<&'s Script>;
328
329 fn script_unsubscribe(&self, script: &Script) -> Result<bool, Error>;
336
337 fn script_pop(&self, script: &Script) -> Result<Option<ScriptStatus>, Error>;
339
340 fn script_get_balance(&self, script: &Script) -> Result<GetBalanceRes, Error>;
342
343 fn batch_script_get_balance<'s, I>(&self, scripts: I) -> Result<Vec<GetBalanceRes>, Error>
347 where
348 I: IntoIterator + Clone,
349 I::Item: Borrow<&'s Script>;
350
351 fn script_get_history(&self, script: &Script) -> Result<Vec<GetHistoryRes>, Error>;
353
354 fn batch_script_get_history<'s, I>(&self, scripts: I) -> Result<Vec<Vec<GetHistoryRes>>, Error>
358 where
359 I: IntoIterator + Clone,
360 I::Item: Borrow<&'s Script>;
361
362 fn script_list_unspent(&self, script: &Script) -> Result<Vec<ListUnspentRes>, Error>;
364
365 fn batch_script_list_unspent<'s, I>(
369 &self,
370 scripts: I,
371 ) -> Result<Vec<Vec<ListUnspentRes>>, Error>
372 where
373 I: IntoIterator + Clone,
374 I::Item: Borrow<&'s Script>;
375
376 fn transaction_get_raw(&self, txid: &Txid) -> Result<Vec<u8>, Error>;
378
379 fn batch_transaction_get_raw<'t, I>(&self, txids: I) -> Result<Vec<Vec<u8>>, Error>
383 where
384 I: IntoIterator + Clone,
385 I::Item: Borrow<&'t Txid>;
386
387 fn batch_block_header_raw<I>(&self, heights: I) -> Result<Vec<Vec<u8>>, Error>
391 where
392 I: IntoIterator + Clone,
393 I::Item: Borrow<u32>;
394
395 fn batch_estimate_fee<I>(&self, numbers: I) -> Result<Vec<f64>, Error>
400 where
401 I: IntoIterator + Clone,
402 I::Item: Borrow<usize>;
403
404 fn transaction_broadcast_raw(&self, raw_tx: &[u8]) -> Result<Txid, Error>;
406
407 fn transaction_broadcast_package_raw<T: AsRef<[u8]>>(
415 &self,
416 raw_txs: &[T],
417 ) -> Result<BroadcastPackageRes, Error>;
418
419 fn transaction_get_merkle(&self, txid: &Txid, height: usize) -> Result<GetMerkleRes, Error>;
421
422 fn batch_transaction_get_merkle<I>(
426 &self,
427 txids_and_heights: I,
428 ) -> Result<Vec<GetMerkleRes>, Error>
429 where
430 I: IntoIterator + Clone,
431 I::Item: Borrow<(Txid, usize)>;
432
433 fn txid_from_pos(&self, height: usize, tx_pos: usize) -> Result<Txid, Error>;
435
436 fn txid_from_pos_with_merkle(
439 &self,
440 height: usize,
441 tx_pos: usize,
442 ) -> Result<TxidFromPosRes, Error>;
443
444 fn server_features(&self) -> Result<ServerFeaturesRes, Error>;
446
447 fn mempool_get_info(&self) -> Result<MempoolInfoRes, Error>;
452
453 fn ping(&self) -> Result<(), Error>;
456
457 fn calls_made(&self) -> Result<usize, Error>;
459}
460
461#[cfg(test)]
462mod test {
463 use std::{borrow::Cow, sync::Arc};
464
465 use super::ElectrumApi;
466
467 #[derive(Debug, Clone)]
468 struct FakeApi;
469
470 impl ElectrumApi for FakeApi {
471 fn raw_call(
472 &self,
473 _: &str,
474 _: impl IntoIterator<Item = super::Param>,
475 ) -> Result<serde_json::Value, super::Error> {
476 unreachable!()
477 }
478
479 fn batch_call(&self, _: &crate::Batch) -> Result<Vec<serde_json::Value>, super::Error> {
480 unreachable!()
481 }
482
483 fn block_headers_subscribe_raw(
484 &self,
485 ) -> Result<super::RawHeaderNotification, super::Error> {
486 unreachable!()
487 }
488
489 fn block_headers_pop_raw(
490 &self,
491 ) -> Result<Option<super::RawHeaderNotification>, super::Error> {
492 unreachable!()
493 }
494
495 fn block_header_raw(&self, _: usize) -> Result<Vec<u8>, super::Error> {
496 unreachable!()
497 }
498
499 fn block_headers(&self, _: usize, _: usize) -> Result<super::GetHeadersRes, super::Error> {
500 unreachable!()
501 }
502
503 fn estimate_fee(
504 &self,
505 _: usize,
506 _: Option<super::EstimationMode>,
507 ) -> Result<f64, super::Error> {
508 unreachable!()
509 }
510
511 fn relay_fee(&self) -> Result<f64, super::Error> {
512 unreachable!()
513 }
514
515 fn script_subscribe(
516 &self,
517 _: &bitcoin::Script,
518 ) -> Result<Option<super::ScriptStatus>, super::Error> {
519 unreachable!()
520 }
521
522 fn batch_script_subscribe<'s, I>(
523 &self,
524 _: I,
525 ) -> Result<Vec<Option<super::ScriptStatus>>, super::Error>
526 where
527 I: IntoIterator + Clone,
528 I::Item: std::borrow::Borrow<&'s bitcoin::Script>,
529 {
530 unreachable!()
531 }
532
533 fn script_unsubscribe(&self, _: &bitcoin::Script) -> Result<bool, super::Error> {
534 unreachable!()
535 }
536
537 fn script_pop(
538 &self,
539 _: &bitcoin::Script,
540 ) -> Result<Option<super::ScriptStatus>, super::Error> {
541 unreachable!()
542 }
543
544 fn script_get_balance(
545 &self,
546 _: &bitcoin::Script,
547 ) -> Result<super::GetBalanceRes, super::Error> {
548 unreachable!()
549 }
550
551 fn batch_script_get_balance<'s, I>(
552 &self,
553 _: I,
554 ) -> Result<Vec<super::GetBalanceRes>, super::Error>
555 where
556 I: IntoIterator + Clone,
557 I::Item: std::borrow::Borrow<&'s bitcoin::Script>,
558 {
559 unreachable!()
560 }
561
562 fn script_get_history(
563 &self,
564 _: &bitcoin::Script,
565 ) -> Result<Vec<super::GetHistoryRes>, super::Error> {
566 unreachable!()
567 }
568
569 fn batch_script_get_history<'s, I>(
570 &self,
571 _: I,
572 ) -> Result<Vec<Vec<super::GetHistoryRes>>, super::Error>
573 where
574 I: IntoIterator + Clone,
575 I::Item: std::borrow::Borrow<&'s bitcoin::Script>,
576 {
577 unreachable!()
578 }
579
580 fn script_list_unspent(
581 &self,
582 _: &bitcoin::Script,
583 ) -> Result<Vec<super::ListUnspentRes>, super::Error> {
584 unreachable!()
585 }
586
587 fn batch_script_list_unspent<'s, I>(
588 &self,
589 _: I,
590 ) -> Result<Vec<Vec<super::ListUnspentRes>>, super::Error>
591 where
592 I: IntoIterator + Clone,
593 I::Item: std::borrow::Borrow<&'s bitcoin::Script>,
594 {
595 unreachable!()
596 }
597
598 fn transaction_get_raw(&self, _: &bitcoin::Txid) -> Result<Vec<u8>, super::Error> {
599 unreachable!()
600 }
601
602 fn batch_transaction_get_raw<'t, I>(&self, _: I) -> Result<Vec<Vec<u8>>, super::Error>
603 where
604 I: IntoIterator + Clone,
605 I::Item: std::borrow::Borrow<&'t bitcoin::Txid>,
606 {
607 unreachable!()
608 }
609
610 fn batch_block_header_raw<I>(&self, _: I) -> Result<Vec<Vec<u8>>, super::Error>
611 where
612 I: IntoIterator + Clone,
613 I::Item: std::borrow::Borrow<u32>,
614 {
615 unreachable!()
616 }
617
618 fn batch_estimate_fee<I>(&self, _: I) -> Result<Vec<f64>, super::Error>
619 where
620 I: IntoIterator + Clone,
621 I::Item: std::borrow::Borrow<usize>,
622 {
623 unreachable!()
624 }
625
626 fn transaction_broadcast_raw(&self, _: &[u8]) -> Result<bitcoin::Txid, super::Error> {
627 unreachable!()
628 }
629
630 fn transaction_broadcast_package_raw<T: AsRef<[u8]>>(
631 &self,
632 _: &[T],
633 ) -> Result<super::BroadcastPackageRes, super::Error> {
634 unreachable!()
635 }
636
637 fn transaction_get_merkle(
638 &self,
639 _: &bitcoin::Txid,
640 _: usize,
641 ) -> Result<super::GetMerkleRes, super::Error> {
642 unreachable!()
643 }
644
645 fn batch_transaction_get_merkle<I>(
646 &self,
647 _: I,
648 ) -> Result<Vec<crate::GetMerkleRes>, crate::Error>
649 where
650 I: IntoIterator + Clone,
651 I::Item: std::borrow::Borrow<(bitcoin::Txid, usize)>,
652 {
653 unreachable!()
654 }
655
656 fn txid_from_pos(&self, _: usize, _: usize) -> Result<bitcoin::Txid, super::Error> {
657 unreachable!()
658 }
659
660 fn txid_from_pos_with_merkle(
661 &self,
662 _: usize,
663 _: usize,
664 ) -> Result<super::TxidFromPosRes, super::Error> {
665 unreachable!()
666 }
667
668 fn server_features(&self) -> Result<super::ServerFeaturesRes, super::Error> {
669 unreachable!()
670 }
671
672 fn mempool_get_info(&self) -> Result<super::MempoolInfoRes, super::Error> {
673 unreachable!()
674 }
675
676 fn ping(&self) -> Result<(), super::Error> {
677 unreachable!()
678 }
679
680 fn calls_made(&self) -> Result<usize, super::Error> {
681 unreachable!()
682 }
683 }
684
685 fn is_impl<A: ElectrumApi>() {}
686
687 #[test]
688 fn deref() {
689 is_impl::<FakeApi>();
690 is_impl::<&FakeApi>();
691 is_impl::<Arc<FakeApi>>();
692 is_impl::<Box<FakeApi>>();
693 is_impl::<Cow<FakeApi>>();
694 }
695}