|
2 | 2 |
|
3 | 3 | use std::borrow::Borrow;
|
4 | 4 | use std::convert::TryInto;
|
| 5 | +use std::ops::Deref; |
5 | 6 |
|
6 | 7 | use bitcoin::consensus::encode::{deserialize, serialize};
|
7 | 8 | use bitcoin::{block, Script, Transaction, Txid};
|
8 | 9 |
|
9 | 10 | use crate::batch::Batch;
|
10 | 11 | use crate::types::*;
|
11 | 12 |
|
| 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 | + |
12 | 174 | /// API calls exposed by an Electrum client
|
13 | 175 | pub trait ElectrumApi {
|
14 | 176 | /// Gets the block header for height `height`.
|
@@ -222,3 +384,214 @@ pub trait ElectrumApi {
|
222 | 384 | /// Returns the number of network calls made since the creation of the client.
|
223 | 385 | fn calls_made(&self) -> Result<usize, Error>;
|
224 | 386 | }
|
| 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