use bp::{BlockHeader, ConsensusDecode, ConsensusEncode, ScriptPubkey, Tx, Txid};
use std::borrow::Borrow;
use std::convert::TryInto;
use std::ops::Deref;
use crate::batch::Batch;
use crate::types::*;
impl<E: Deref> ElectrumApi for E
where
E::Target: ElectrumApi,
{
fn raw_call(
&self,
method_name: &str,
params: impl IntoIterator<Item = Param>,
) -> Result<serde_json::Value, Error> {
(**self).raw_call(method_name, params)
}
fn batch_call(&self, batch: &Batch) -> Result<Vec<serde_json::Value>, Error> {
(**self).batch_call(batch)
}
fn block_headers_subscribe_raw(&self) -> Result<RawHeaderNotification, Error> {
(**self).block_headers_subscribe_raw()
}
fn block_headers_pop_raw(&self) -> Result<Option<RawHeaderNotification>, Error> {
(**self).block_headers_pop_raw()
}
fn block_header_raw(&self, height: usize) -> Result<Vec<u8>, Error> {
(**self).block_header_raw(height)
}
fn block_headers(&self, start_height: usize, count: usize) -> Result<GetHeadersRes, Error> {
(**self).block_headers(start_height, count)
}
fn estimate_fee(&self, number: usize) -> Result<f64, Error> {
(**self).estimate_fee(number)
}
fn relay_fee(&self) -> Result<f64, Error> {
(**self).relay_fee()
}
fn script_subscribe(&self, script: &ScriptPubkey) -> Result<Option<ScriptStatus>, Error> {
(**self).script_subscribe(script)
}
fn batch_script_subscribe<'s, I>(&self, scripts: I) -> Result<Vec<Option<ScriptStatus>>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<&'s ScriptPubkey>,
{
(**self).batch_script_subscribe(scripts)
}
fn script_unsubscribe(&self, script: &ScriptPubkey) -> Result<bool, Error> {
(**self).script_unsubscribe(script)
}
fn script_pop(&self, script: &ScriptPubkey) -> Result<Option<ScriptStatus>, Error> {
(**self).script_pop(script)
}
fn script_get_balance(&self, script: &ScriptPubkey) -> Result<GetBalanceRes, Error> {
(**self).script_get_balance(script)
}
fn batch_script_get_balance<'s, I>(&self, scripts: I) -> Result<Vec<GetBalanceRes>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<&'s ScriptPubkey>,
{
(**self).batch_script_get_balance(scripts)
}
fn script_get_history(&self, script: &ScriptPubkey) -> Result<Vec<GetHistoryRes>, Error> {
(**self).script_get_history(script)
}
fn batch_script_get_history<'s, I>(&self, scripts: I) -> Result<Vec<Vec<GetHistoryRes>>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<&'s ScriptPubkey>,
{
(**self).batch_script_get_history(scripts)
}
fn script_list_unspent(&self, script: &ScriptPubkey) -> Result<Vec<ListUnspentRes>, Error> {
(**self).script_list_unspent(script)
}
fn batch_script_list_unspent<'s, I>(
&self,
scripts: I,
) -> Result<Vec<Vec<ListUnspentRes>>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<&'s ScriptPubkey>,
{
(**self).batch_script_list_unspent(scripts)
}
fn script_get_mempool(&self, script: &ScriptPubkey) -> Result<Vec<GetMempoolRes>, Error> {
(**self).script_get_mempool(script)
}
fn transaction_get_verbose(&self, txid: &Txid) -> Result<Option<TxRes>, Error> {
(**self).transaction_get_verbose(txid)
}
fn transaction_get_raw(&self, txid: &Txid) -> Result<Option<Vec<u8>>, Error> {
(**self).transaction_get_raw(txid)
}
fn batch_transaction_get_raw<'t, I>(&self, txids: I) -> Result<Vec<Vec<u8>>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<&'t Txid>,
{
(**self).batch_transaction_get_raw(txids)
}
fn batch_block_header_raw<I>(&self, heights: I) -> Result<Vec<Vec<u8>>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<u32>,
{
(**self).batch_block_header_raw(heights)
}
fn batch_estimate_fee<I>(&self, numbers: I) -> Result<Vec<f64>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<usize>,
{
(**self).batch_estimate_fee(numbers)
}
fn transaction_broadcast_raw(&self, raw_tx: &[u8]) -> Result<Txid, Error> {
(**self).transaction_broadcast_raw(raw_tx)
}
fn transaction_get_merkle(&self, txid: &Txid, height: usize) -> Result<GetMerkleRes, Error> {
(**self).transaction_get_merkle(txid, height)
}
fn txid_from_pos(&self, height: usize, tx_pos: usize) -> Result<Txid, Error> {
(**self).txid_from_pos(height, tx_pos)
}
fn txid_from_pos_with_merkle(
&self,
height: usize,
tx_pos: usize,
) -> Result<TxidFromPosRes, Error> {
(**self).txid_from_pos_with_merkle(height, tx_pos)
}
fn server_features(&self) -> Result<ServerFeaturesRes, Error> {
(**self).server_features()
}
fn ping(&self) -> Result<(), Error> {
(**self).ping()
}
#[cfg(feature = "debug-calls")]
fn calls_made(&self) -> Result<usize, Error> {
(**self).calls_made()
}
}
pub trait ElectrumApi {
fn block_header(&self, height: usize) -> Result<BlockHeader, Error> {
Ok(BlockHeader::consensus_deserialize(
&self.block_header_raw(height)?,
)?)
}
fn block_headers_subscribe(&self) -> Result<HeaderNotification, Error> {
self.block_headers_subscribe_raw()?.try_into()
}
fn block_headers_pop(&self) -> Result<Option<HeaderNotification>, Error> {
self.block_headers_pop_raw()?
.map(|raw| raw.try_into())
.transpose()
}
fn transaction_get(&self, txid: &Txid) -> Result<Option<Tx>, Error> {
Ok(self
.transaction_get_raw(txid)?
.map(Tx::consensus_deserialize)
.transpose()?)
}
fn transaction_get_verbose(&self, txid: &Txid) -> Result<Option<TxRes>, Error>;
fn batch_transaction_get<'t, I>(&self, txids: I) -> Result<Vec<Tx>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<&'t Txid>,
{
self.batch_transaction_get_raw(txids)?
.iter()
.map(|s| Ok(Tx::consensus_deserialize(s)?))
.collect()
}
fn batch_block_header<I>(&self, heights: I) -> Result<Vec<BlockHeader>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<u32>,
{
self.batch_block_header_raw(heights)?
.iter()
.map(|s| Ok(BlockHeader::consensus_deserialize(s)?))
.collect()
}
fn transaction_broadcast(&self, tx: &Tx) -> Result<Txid, Error> {
let buffer: Vec<u8> = tx.consensus_serialize();
self.transaction_broadcast_raw(&buffer)
}
fn raw_call(
&self,
method_name: &str,
params: impl IntoIterator<Item = Param>,
) -> Result<serde_json::Value, Error>;
fn batch_call(&self, batch: &Batch) -> Result<Vec<serde_json::Value>, Error>;
fn block_headers_subscribe_raw(&self) -> Result<RawHeaderNotification, Error>;
fn block_headers_pop_raw(&self) -> Result<Option<RawHeaderNotification>, Error>;
fn block_header_raw(&self, height: usize) -> Result<Vec<u8>, Error>;
fn block_headers(&self, start_height: usize, count: usize) -> Result<GetHeadersRes, Error>;
fn estimate_fee(&self, number: usize) -> Result<f64, Error>;
fn relay_fee(&self) -> Result<f64, Error>;
fn script_subscribe(&self, script: &ScriptPubkey) -> Result<Option<ScriptStatus>, Error>;
fn batch_script_subscribe<'s, I>(&self, scripts: I) -> Result<Vec<Option<ScriptStatus>>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<&'s ScriptPubkey>;
fn script_unsubscribe(&self, script: &ScriptPubkey) -> Result<bool, Error>;
fn script_pop(&self, script: &ScriptPubkey) -> Result<Option<ScriptStatus>, Error>;
fn script_get_balance(&self, script: &ScriptPubkey) -> Result<GetBalanceRes, Error>;
fn batch_script_get_balance<'s, I>(&self, scripts: I) -> Result<Vec<GetBalanceRes>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<&'s ScriptPubkey>;
fn script_get_history(&self, script: &ScriptPubkey) -> Result<Vec<GetHistoryRes>, Error>;
fn batch_script_get_history<'s, I>(&self, scripts: I) -> Result<Vec<Vec<GetHistoryRes>>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<&'s ScriptPubkey>;
fn script_list_unspent(&self, script: &ScriptPubkey) -> Result<Vec<ListUnspentRes>, Error>;
fn batch_script_list_unspent<'s, I>(
&self,
scripts: I,
) -> Result<Vec<Vec<ListUnspentRes>>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<&'s ScriptPubkey>;
fn script_get_mempool(&self, script: &ScriptPubkey) -> Result<Vec<GetMempoolRes>, Error>;
fn transaction_get_raw(&self, txid: &Txid) -> Result<Option<Vec<u8>>, Error>;
fn batch_transaction_get_raw<'t, I>(&self, txids: I) -> Result<Vec<Vec<u8>>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<&'t Txid>;
fn batch_block_header_raw<I>(&self, heights: I) -> Result<Vec<Vec<u8>>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<u32>;
fn batch_estimate_fee<I>(&self, numbers: I) -> Result<Vec<f64>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<usize>;
fn transaction_broadcast_raw(&self, raw_tx: &[u8]) -> Result<Txid, Error>;
fn transaction_get_merkle(&self, txid: &Txid, height: usize) -> Result<GetMerkleRes, Error>;
fn txid_from_pos(&self, height: usize, tx_pos: usize) -> Result<Txid, Error>;
fn txid_from_pos_with_merkle(
&self,
height: usize,
tx_pos: usize,
) -> Result<TxidFromPosRes, Error>;
fn server_features(&self) -> Result<ServerFeaturesRes, Error>;
fn ping(&self) -> Result<(), Error>;
#[cfg(feature = "debug-calls")]
fn calls_made(&self) -> Result<usize, Error>;
}
#[cfg(test)]
mod test {
use super::ElectrumApi;
use crate::{
Batch, Error, GetBalanceRes, GetHeadersRes, GetHistoryRes, GetMempoolRes, GetMerkleRes,
ListUnspentRes, Param, RawHeaderNotification, ScriptStatus, ServerFeaturesRes, TxRes,
TxidFromPosRes,
};
use bp::{ScriptPubkey, Txid};
use serde_json::Value;
use std::borrow::Borrow;
use std::{borrow::Cow, sync::Arc};
#[derive(Debug, Clone)]
struct FakeApi;
#[allow(unused_variables)]
impl ElectrumApi for FakeApi {
fn transaction_get_verbose(&self, txid: &Txid) -> Result<Option<TxRes>, Error> {
unreachable!()
}
fn raw_call(
&self,
method_name: &str,
params: impl IntoIterator<Item = Param>,
) -> Result<Value, Error> {
unreachable!()
}
fn batch_call(&self, batch: &Batch) -> Result<Vec<Value>, Error> {
unreachable!()
}
fn block_headers_subscribe_raw(&self) -> Result<RawHeaderNotification, Error> {
unreachable!()
}
fn block_headers_pop_raw(&self) -> Result<Option<RawHeaderNotification>, Error> {
unreachable!()
}
fn block_header_raw(&self, height: usize) -> Result<Vec<u8>, Error> {
unreachable!()
}
fn block_headers(&self, start_height: usize, count: usize) -> Result<GetHeadersRes, Error> {
unreachable!()
}
fn estimate_fee(&self, number: usize) -> Result<f64, Error> {
unreachable!()
}
fn relay_fee(&self) -> Result<f64, Error> {
unreachable!()
}
fn script_subscribe(&self, script: &ScriptPubkey) -> Result<Option<ScriptStatus>, Error> {
unreachable!()
}
fn batch_script_subscribe<'s, I>(
&self,
scripts: I,
) -> Result<Vec<Option<ScriptStatus>>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<&'s ScriptPubkey>,
{
unreachable!()
}
fn script_unsubscribe(&self, script: &ScriptPubkey) -> Result<bool, Error> {
unreachable!()
}
fn script_pop(&self, script: &ScriptPubkey) -> Result<Option<ScriptStatus>, Error> {
unreachable!()
}
fn script_get_balance(&self, script: &ScriptPubkey) -> Result<GetBalanceRes, Error> {
unreachable!()
}
fn batch_script_get_balance<'s, I>(&self, scripts: I) -> Result<Vec<GetBalanceRes>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<&'s ScriptPubkey>,
{
unreachable!()
}
fn script_get_history(&self, script: &ScriptPubkey) -> Result<Vec<GetHistoryRes>, Error> {
unreachable!()
}
fn batch_script_get_history<'s, I>(
&self,
scripts: I,
) -> Result<Vec<Vec<GetHistoryRes>>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<&'s ScriptPubkey>,
{
unreachable!()
}
fn script_list_unspent(&self, script: &ScriptPubkey) -> Result<Vec<ListUnspentRes>, Error> {
unreachable!()
}
fn batch_script_list_unspent<'s, I>(
&self,
scripts: I,
) -> Result<Vec<Vec<ListUnspentRes>>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<&'s ScriptPubkey>,
{
unreachable!()
}
fn script_get_mempool(&self, script: &ScriptPubkey) -> Result<Vec<GetMempoolRes>, Error> {
unreachable!()
}
fn transaction_get_raw(&self, txid: &Txid) -> Result<Option<Vec<u8>>, Error> {
unreachable!()
}
fn batch_transaction_get_raw<'t, I>(&self, txids: I) -> Result<Vec<Vec<u8>>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<&'t Txid>,
{
unreachable!()
}
fn batch_block_header_raw<I>(&self, heights: I) -> Result<Vec<Vec<u8>>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<u32>,
{
unreachable!()
}
fn batch_estimate_fee<I>(&self, numbers: I) -> Result<Vec<f64>, Error>
where
I: IntoIterator + Clone,
I::Item: Borrow<usize>,
{
unreachable!()
}
fn transaction_broadcast_raw(&self, raw_tx: &[u8]) -> Result<Txid, Error> {
unreachable!()
}
fn transaction_get_merkle(
&self,
txid: &Txid,
height: usize,
) -> Result<GetMerkleRes, Error> {
unreachable!()
}
fn txid_from_pos(&self, height: usize, tx_pos: usize) -> Result<Txid, Error> {
unreachable!()
}
fn txid_from_pos_with_merkle(
&self,
height: usize,
tx_pos: usize,
) -> Result<TxidFromPosRes, Error> {
unreachable!()
}
fn server_features(&self) -> Result<ServerFeaturesRes, Error> {
unreachable!()
}
fn ping(&self) -> Result<(), Error> {
unreachable!()
}
#[cfg(feature = "debug-calls")]
fn calls_made(&self) -> Result<usize, Error> {
unreachable!()
}
}
fn is_impl<A: ElectrumApi>() {}
#[test]
fn deref() {
is_impl::<FakeApi>();
is_impl::<&FakeApi>();
is_impl::<Arc<FakeApi>>();
is_impl::<Box<FakeApi>>();
is_impl::<Cow<FakeApi>>();
}
}