Skip to content

Commit 372eda9

Browse files
authored
Merge pull request #163 from evanlinjin/electrum_api_deref
Allow types that reference `ElectrumApi` to also implement `ElectrumApi`
2 parents 83747b1 + eb38c03 commit 372eda9

File tree

1 file changed

+373
-0
lines changed

1 file changed

+373
-0
lines changed

src/api.rs

+373
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,175 @@
22
33
use std::borrow::Borrow;
44
use std::convert::TryInto;
5+
use std::ops::Deref;
56

67
use bitcoin::consensus::encode::{deserialize, serialize};
78
use bitcoin::{block, Script, Transaction, Txid};
89

910
use crate::batch::Batch;
1011
use crate::types::*;
1112

13+
impl<E: Deref> ElectrumApi for E
14+
where
15+
E::Target: ElectrumApi,
16+
{
17+
fn raw_call(
18+
&self,
19+
method_name: &str,
20+
params: impl IntoIterator<Item = Param>,
21+
) -> Result<serde_json::Value, Error> {
22+
(**self).raw_call(method_name, params)
23+
}
24+
25+
fn batch_call(&self, batch: &Batch) -> Result<Vec<serde_json::Value>, Error> {
26+
(**self).batch_call(batch)
27+
}
28+
29+
fn block_headers_subscribe_raw(&self) -> Result<RawHeaderNotification, Error> {
30+
(**self).block_headers_subscribe_raw()
31+
}
32+
33+
fn block_headers_pop_raw(&self) -> Result<Option<RawHeaderNotification>, Error> {
34+
(**self).block_headers_pop_raw()
35+
}
36+
37+
fn block_header_raw(&self, height: usize) -> Result<Vec<u8>, Error> {
38+
(**self).block_header_raw(height)
39+
}
40+
41+
fn block_headers(&self, start_height: usize, count: usize) -> Result<GetHeadersRes, Error> {
42+
(**self).block_headers(start_height, count)
43+
}
44+
45+
fn estimate_fee(&self, number: usize) -> Result<f64, Error> {
46+
(**self).estimate_fee(number)
47+
}
48+
49+
fn relay_fee(&self) -> Result<f64, Error> {
50+
(**self).relay_fee()
51+
}
52+
53+
fn script_subscribe(&self, script: &Script) -> Result<Option<ScriptStatus>, Error> {
54+
(**self).script_subscribe(script)
55+
}
56+
57+
fn batch_script_subscribe<'s, I>(&self, scripts: I) -> Result<Vec<Option<ScriptStatus>>, Error>
58+
where
59+
I: IntoIterator + Clone,
60+
I::Item: Borrow<&'s Script>,
61+
{
62+
(**self).batch_script_subscribe(scripts)
63+
}
64+
65+
fn script_unsubscribe(&self, script: &Script) -> Result<bool, Error> {
66+
(**self).script_unsubscribe(script)
67+
}
68+
69+
fn script_pop(&self, script: &Script) -> Result<Option<ScriptStatus>, Error> {
70+
(**self).script_pop(script)
71+
}
72+
73+
fn script_get_balance(&self, script: &Script) -> Result<GetBalanceRes, Error> {
74+
(**self).script_get_balance(script)
75+
}
76+
77+
fn batch_script_get_balance<'s, I>(&self, scripts: I) -> Result<Vec<GetBalanceRes>, Error>
78+
where
79+
I: IntoIterator + Clone,
80+
I::Item: Borrow<&'s Script>,
81+
{
82+
(**self).batch_script_get_balance(scripts)
83+
}
84+
85+
fn script_get_history(&self, script: &Script) -> Result<Vec<GetHistoryRes>, Error> {
86+
(**self).script_get_history(script)
87+
}
88+
89+
fn batch_script_get_history<'s, I>(&self, scripts: I) -> Result<Vec<Vec<GetHistoryRes>>, Error>
90+
where
91+
I: IntoIterator + Clone,
92+
I::Item: Borrow<&'s Script>,
93+
{
94+
(**self).batch_script_get_history(scripts)
95+
}
96+
97+
fn script_list_unspent(&self, script: &Script) -> Result<Vec<ListUnspentRes>, Error> {
98+
(**self).script_list_unspent(script)
99+
}
100+
101+
fn batch_script_list_unspent<'s, I>(
102+
&self,
103+
scripts: I,
104+
) -> Result<Vec<Vec<ListUnspentRes>>, Error>
105+
where
106+
I: IntoIterator + Clone,
107+
I::Item: Borrow<&'s Script>,
108+
{
109+
(**self).batch_script_list_unspent(scripts)
110+
}
111+
112+
fn transaction_get_raw(&self, txid: &Txid) -> Result<Vec<u8>, Error> {
113+
(**self).transaction_get_raw(txid)
114+
}
115+
116+
fn batch_transaction_get_raw<'t, I>(&self, txids: I) -> Result<Vec<Vec<u8>>, Error>
117+
where
118+
I: IntoIterator + Clone,
119+
I::Item: Borrow<&'t Txid>,
120+
{
121+
(**self).batch_transaction_get_raw(txids)
122+
}
123+
124+
fn batch_block_header_raw<I>(&self, heights: I) -> Result<Vec<Vec<u8>>, Error>
125+
where
126+
I: IntoIterator + Clone,
127+
I::Item: Borrow<u32>,
128+
{
129+
(**self).batch_block_header_raw(heights)
130+
}
131+
132+
fn batch_estimate_fee<I>(&self, numbers: I) -> Result<Vec<f64>, Error>
133+
where
134+
I: IntoIterator + Clone,
135+
I::Item: Borrow<usize>,
136+
{
137+
(**self).batch_estimate_fee(numbers)
138+
}
139+
140+
fn transaction_broadcast_raw(&self, raw_tx: &[u8]) -> Result<Txid, Error> {
141+
(**self).transaction_broadcast_raw(raw_tx)
142+
}
143+
144+
fn transaction_get_merkle(&self, txid: &Txid, height: usize) -> Result<GetMerkleRes, Error> {
145+
(**self).transaction_get_merkle(txid, height)
146+
}
147+
148+
fn txid_from_pos(&self, height: usize, tx_pos: usize) -> Result<Txid, Error> {
149+
(**self).txid_from_pos(height, tx_pos)
150+
}
151+
152+
fn txid_from_pos_with_merkle(
153+
&self,
154+
height: usize,
155+
tx_pos: usize,
156+
) -> Result<TxidFromPosRes, Error> {
157+
(**self).txid_from_pos_with_merkle(height, tx_pos)
158+
}
159+
160+
fn server_features(&self) -> Result<ServerFeaturesRes, Error> {
161+
(**self).server_features()
162+
}
163+
164+
fn ping(&self) -> Result<(), Error> {
165+
(**self).ping()
166+
}
167+
168+
#[cfg(feature = "debug-calls")]
169+
fn calls_made(&self) -> Result<usize, Error> {
170+
(**self).calls_made()
171+
}
172+
}
173+
12174
/// API calls exposed by an Electrum client
13175
pub trait ElectrumApi {
14176
/// Gets the block header for height `height`.
@@ -222,3 +384,214 @@ pub trait ElectrumApi {
222384
/// Returns the number of network calls made since the creation of the client.
223385
fn calls_made(&self) -> Result<usize, Error>;
224386
}
387+
388+
#[cfg(test)]
389+
mod test {
390+
use std::{borrow::Cow, sync::Arc};
391+
392+
use super::ElectrumApi;
393+
394+
#[derive(Debug, Clone)]
395+
struct FakeApi;
396+
397+
impl ElectrumApi for FakeApi {
398+
fn raw_call(
399+
&self,
400+
_: &str,
401+
_: impl IntoIterator<Item = super::Param>,
402+
) -> Result<serde_json::Value, super::Error> {
403+
unreachable!()
404+
}
405+
406+
fn batch_call(&self, _: &crate::Batch) -> Result<Vec<serde_json::Value>, super::Error> {
407+
unreachable!()
408+
}
409+
410+
fn block_headers_subscribe_raw(
411+
&self,
412+
) -> Result<super::RawHeaderNotification, super::Error> {
413+
unreachable!()
414+
}
415+
416+
fn block_headers_pop_raw(
417+
&self,
418+
) -> Result<Option<super::RawHeaderNotification>, super::Error> {
419+
unreachable!()
420+
}
421+
422+
fn block_header_raw(&self, _: usize) -> Result<Vec<u8>, super::Error> {
423+
unreachable!()
424+
}
425+
426+
fn block_headers(&self, _: usize, _: usize) -> Result<super::GetHeadersRes, super::Error> {
427+
unreachable!()
428+
}
429+
430+
fn estimate_fee(&self, _: usize) -> Result<f64, super::Error> {
431+
unreachable!()
432+
}
433+
434+
fn relay_fee(&self) -> Result<f64, super::Error> {
435+
unreachable!()
436+
}
437+
438+
fn script_subscribe(
439+
&self,
440+
_: &bitcoin::Script,
441+
) -> Result<Option<super::ScriptStatus>, super::Error> {
442+
unreachable!()
443+
}
444+
445+
fn batch_script_subscribe<'s, I>(
446+
&self,
447+
_: I,
448+
) -> Result<Vec<Option<super::ScriptStatus>>, super::Error>
449+
where
450+
I: IntoIterator + Clone,
451+
I::Item: std::borrow::Borrow<&'s bitcoin::Script>,
452+
{
453+
unreachable!()
454+
}
455+
456+
fn script_unsubscribe(&self, _: &bitcoin::Script) -> Result<bool, super::Error> {
457+
unreachable!()
458+
}
459+
460+
fn script_pop(
461+
&self,
462+
_: &bitcoin::Script,
463+
) -> Result<Option<super::ScriptStatus>, super::Error> {
464+
unreachable!()
465+
}
466+
467+
fn script_get_balance(
468+
&self,
469+
_: &bitcoin::Script,
470+
) -> Result<super::GetBalanceRes, super::Error> {
471+
unreachable!()
472+
}
473+
474+
fn batch_script_get_balance<'s, I>(
475+
&self,
476+
_: I,
477+
) -> Result<Vec<super::GetBalanceRes>, super::Error>
478+
where
479+
I: IntoIterator + Clone,
480+
I::Item: std::borrow::Borrow<&'s bitcoin::Script>,
481+
{
482+
unreachable!()
483+
}
484+
485+
fn script_get_history(
486+
&self,
487+
_: &bitcoin::Script,
488+
) -> Result<Vec<super::GetHistoryRes>, super::Error> {
489+
unreachable!()
490+
}
491+
492+
fn batch_script_get_history<'s, I>(
493+
&self,
494+
_: I,
495+
) -> Result<Vec<Vec<super::GetHistoryRes>>, super::Error>
496+
where
497+
I: IntoIterator + Clone,
498+
I::Item: std::borrow::Borrow<&'s bitcoin::Script>,
499+
{
500+
unreachable!()
501+
}
502+
503+
fn script_list_unspent(
504+
&self,
505+
_: &bitcoin::Script,
506+
) -> Result<Vec<super::ListUnspentRes>, super::Error> {
507+
unreachable!()
508+
}
509+
510+
fn batch_script_list_unspent<'s, I>(
511+
&self,
512+
_: I,
513+
) -> Result<Vec<Vec<super::ListUnspentRes>>, super::Error>
514+
where
515+
I: IntoIterator + Clone,
516+
I::Item: std::borrow::Borrow<&'s bitcoin::Script>,
517+
{
518+
unreachable!()
519+
}
520+
521+
fn transaction_get_raw(&self, _: &bitcoin::Txid) -> Result<Vec<u8>, super::Error> {
522+
unreachable!()
523+
}
524+
525+
fn batch_transaction_get_raw<'t, I>(&self, _: I) -> Result<Vec<Vec<u8>>, super::Error>
526+
where
527+
I: IntoIterator + Clone,
528+
I::Item: std::borrow::Borrow<&'t bitcoin::Txid>,
529+
{
530+
unreachable!()
531+
}
532+
533+
fn batch_block_header_raw<I>(&self, _: I) -> Result<Vec<Vec<u8>>, super::Error>
534+
where
535+
I: IntoIterator + Clone,
536+
I::Item: std::borrow::Borrow<u32>,
537+
{
538+
unreachable!()
539+
}
540+
541+
fn batch_estimate_fee<I>(&self, _: I) -> Result<Vec<f64>, super::Error>
542+
where
543+
I: IntoIterator + Clone,
544+
I::Item: std::borrow::Borrow<usize>,
545+
{
546+
unreachable!()
547+
}
548+
549+
fn transaction_broadcast_raw(&self, _: &[u8]) -> Result<bitcoin::Txid, super::Error> {
550+
unreachable!()
551+
}
552+
553+
fn transaction_get_merkle(
554+
&self,
555+
_: &bitcoin::Txid,
556+
_: usize,
557+
) -> Result<super::GetMerkleRes, super::Error> {
558+
unreachable!()
559+
}
560+
561+
fn txid_from_pos(&self, _: usize, _: usize) -> Result<bitcoin::Txid, super::Error> {
562+
unreachable!()
563+
}
564+
565+
fn txid_from_pos_with_merkle(
566+
&self,
567+
_: usize,
568+
_: usize,
569+
) -> Result<super::TxidFromPosRes, super::Error> {
570+
unreachable!()
571+
}
572+
573+
fn server_features(&self) -> Result<super::ServerFeaturesRes, super::Error> {
574+
unreachable!()
575+
}
576+
577+
fn ping(&self) -> Result<(), super::Error> {
578+
unreachable!()
579+
}
580+
581+
#[cfg(feature = "debug-calls")]
582+
fn calls_made(&self) -> Result<usize, super::Error> {
583+
unreachable!()
584+
}
585+
}
586+
587+
fn is_impl<A: ElectrumApi>() {}
588+
589+
#[test]
590+
fn deref() {
591+
is_impl::<FakeApi>();
592+
is_impl::<&FakeApi>();
593+
is_impl::<Arc<FakeApi>>();
594+
is_impl::<Box<FakeApi>>();
595+
is_impl::<Cow<FakeApi>>();
596+
}
597+
}

0 commit comments

Comments
 (0)