refactor: streamline blockchain clients error names
This commit is contained in:
parent
8f4c80cb98
commit
ca8a3d0471
@ -102,7 +102,7 @@ interface DescriptorKeyError {
|
||||
};
|
||||
|
||||
[Error]
|
||||
interface ElectrumClientError {
|
||||
interface ElectrumError {
|
||||
IOError(string error_message);
|
||||
Json(string error_message);
|
||||
Hex(string error_message);
|
||||
@ -493,16 +493,16 @@ interface EsploraClient {
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
interface ElectrumClient {
|
||||
[Throws=ElectrumClientError]
|
||||
[Throws=ElectrumError]
|
||||
constructor(string url);
|
||||
|
||||
[Throws=ElectrumClientError]
|
||||
[Throws=ElectrumError]
|
||||
Update full_scan(FullScanRequest full_scan_request, u64 stop_gap, u64 batch_size, boolean fetch_prev_txouts);
|
||||
|
||||
[Throws=ElectrumClientError]
|
||||
[Throws=ElectrumError]
|
||||
Update sync(SyncRequest sync_request, u64 batch_size, boolean fetch_prev_txouts);
|
||||
|
||||
[Throws=ElectrumClientError]
|
||||
[Throws=ElectrumError]
|
||||
string broadcast([ByRef] Transaction transaction);
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::error::ElectrumClientError;
|
||||
use crate::bitcoin::Transaction;
|
||||
use crate::error::ElectrumError;
|
||||
use crate::types::{FullScanRequest, SyncRequest};
|
||||
use crate::wallet::Update;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use bdk::bitcoin::Transaction as BdkTransaction;
|
||||
use bdk::chain::spk_client::FullScanRequest as BdkFullScanRequest;
|
||||
@ -12,13 +12,13 @@ use bdk::KeychainKind;
|
||||
use bdk_electrum::electrum_client::{Client as BdkBlockingClient, ElectrumApi};
|
||||
use bdk_electrum::{ElectrumExt, ElectrumFullScanResult, ElectrumSyncResult};
|
||||
|
||||
use crate::bitcoin::Transaction;
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct ElectrumClient(BdkBlockingClient);
|
||||
|
||||
impl ElectrumClient {
|
||||
pub fn new(url: String) -> Result<Self, ElectrumClientError> {
|
||||
pub fn new(url: String) -> Result<Self, ElectrumError> {
|
||||
let client = BdkBlockingClient::new(url.as_str())?;
|
||||
Ok(Self(client))
|
||||
}
|
||||
@ -29,14 +29,14 @@ impl ElectrumClient {
|
||||
stop_gap: u64,
|
||||
batch_size: u64,
|
||||
fetch_prev_txouts: bool,
|
||||
) -> Result<Arc<Update>, ElectrumClientError> {
|
||||
) -> Result<Arc<Update>, ElectrumError> {
|
||||
// using option and take is not ideal but the only way to take full ownership of the request
|
||||
let request: BdkFullScanRequest<KeychainKind> = request
|
||||
.0
|
||||
.lock()
|
||||
.unwrap()
|
||||
.take()
|
||||
.ok_or(ElectrumClientError::RequestAlreadyConsumed)?;
|
||||
.ok_or(ElectrumError::RequestAlreadyConsumed)?;
|
||||
|
||||
let electrum_result: ElectrumFullScanResult<KeychainKind> = self.0.full_scan(
|
||||
request,
|
||||
@ -61,14 +61,14 @@ impl ElectrumClient {
|
||||
request: Arc<SyncRequest>,
|
||||
batch_size: u64,
|
||||
fetch_prev_txouts: bool,
|
||||
) -> Result<Arc<Update>, ElectrumClientError> {
|
||||
) -> Result<Arc<Update>, ElectrumError> {
|
||||
// using option and take is not ideal but the only way to take full ownership of the request
|
||||
let request: BdkSyncRequest = request
|
||||
.0
|
||||
.lock()
|
||||
.unwrap()
|
||||
.take()
|
||||
.ok_or(ElectrumClientError::RequestAlreadyConsumed)?;
|
||||
.ok_or(ElectrumError::RequestAlreadyConsumed)?;
|
||||
|
||||
let electrum_result: ElectrumSyncResult =
|
||||
self.0
|
||||
@ -85,11 +85,11 @@ impl ElectrumClient {
|
||||
Ok(Arc::new(Update(update)))
|
||||
}
|
||||
|
||||
pub fn broadcast(&self, transaction: &Transaction) -> Result<String, ElectrumClientError> {
|
||||
pub fn broadcast(&self, transaction: &Transaction) -> Result<String, ElectrumError> {
|
||||
let bdk_transaction: BdkTransaction = transaction.into();
|
||||
self.0
|
||||
.transaction_broadcast(&bdk_transaction)
|
||||
.map_err(ElectrumClientError::from)
|
||||
.map_err(ElectrumError::from)
|
||||
.map(|txid| txid.to_string())
|
||||
}
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ pub enum DescriptorKeyError {
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ElectrumClientError {
|
||||
pub enum ElectrumError {
|
||||
#[error("{error_message}")]
|
||||
IOError { error_message: String },
|
||||
|
||||
@ -558,44 +558,44 @@ impl From<BdkAddressError> for AddressError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BdkElectrumError> for ElectrumClientError {
|
||||
impl From<BdkElectrumError> for ElectrumError {
|
||||
fn from(error: BdkElectrumError) -> Self {
|
||||
match error {
|
||||
BdkElectrumError::IOError(e) => ElectrumClientError::IOError {
|
||||
BdkElectrumError::IOError(e) => ElectrumError::IOError {
|
||||
error_message: e.to_string(),
|
||||
},
|
||||
BdkElectrumError::JSON(e) => ElectrumClientError::Json {
|
||||
BdkElectrumError::JSON(e) => ElectrumError::Json {
|
||||
error_message: e.to_string(),
|
||||
},
|
||||
BdkElectrumError::Hex(e) => ElectrumClientError::Hex {
|
||||
BdkElectrumError::Hex(e) => ElectrumError::Hex {
|
||||
error_message: e.to_string(),
|
||||
},
|
||||
BdkElectrumError::Protocol(e) => ElectrumClientError::Protocol {
|
||||
BdkElectrumError::Protocol(e) => ElectrumError::Protocol {
|
||||
error_message: e.to_string(),
|
||||
},
|
||||
BdkElectrumError::Bitcoin(e) => ElectrumClientError::Bitcoin {
|
||||
BdkElectrumError::Bitcoin(e) => ElectrumError::Bitcoin {
|
||||
error_message: e.to_string(),
|
||||
},
|
||||
BdkElectrumError::AlreadySubscribed(_) => ElectrumClientError::AlreadySubscribed,
|
||||
BdkElectrumError::NotSubscribed(_) => ElectrumClientError::NotSubscribed,
|
||||
BdkElectrumError::InvalidResponse(e) => ElectrumClientError::InvalidResponse {
|
||||
BdkElectrumError::AlreadySubscribed(_) => ElectrumError::AlreadySubscribed,
|
||||
BdkElectrumError::NotSubscribed(_) => ElectrumError::NotSubscribed,
|
||||
BdkElectrumError::InvalidResponse(e) => ElectrumError::InvalidResponse {
|
||||
error_message: e.to_string(),
|
||||
},
|
||||
BdkElectrumError::Message(e) => ElectrumClientError::Message {
|
||||
BdkElectrumError::Message(e) => ElectrumError::Message {
|
||||
error_message: e.to_string(),
|
||||
},
|
||||
BdkElectrumError::InvalidDNSNameError(domain) => {
|
||||
ElectrumClientError::InvalidDNSNameError { domain }
|
||||
ElectrumError::InvalidDNSNameError { domain }
|
||||
}
|
||||
BdkElectrumError::MissingDomain => ElectrumClientError::MissingDomain,
|
||||
BdkElectrumError::AllAttemptsErrored(_) => ElectrumClientError::AllAttemptsErrored,
|
||||
BdkElectrumError::SharedIOError(e) => ElectrumClientError::SharedIOError {
|
||||
BdkElectrumError::MissingDomain => ElectrumError::MissingDomain,
|
||||
BdkElectrumError::AllAttemptsErrored(_) => ElectrumError::AllAttemptsErrored,
|
||||
BdkElectrumError::SharedIOError(e) => ElectrumError::SharedIOError {
|
||||
error_message: e.to_string(),
|
||||
},
|
||||
BdkElectrumError::CouldntLockReader => ElectrumClientError::CouldntLockReader,
|
||||
BdkElectrumError::Mpsc => ElectrumClientError::Mpsc,
|
||||
BdkElectrumError::CouldntLockReader => ElectrumError::CouldntLockReader,
|
||||
BdkElectrumError::Mpsc => ElectrumError::Mpsc,
|
||||
BdkElectrumError::CouldNotCreateConnection(error_message) => {
|
||||
ElectrumClientError::CouldNotCreateConnection {
|
||||
ElectrumError::CouldNotCreateConnection {
|
||||
error_message: error_message.to_string(),
|
||||
}
|
||||
}
|
||||
@ -1079,7 +1079,7 @@ impl From<NewOrLoadError> for WalletCreationError {
|
||||
mod test {
|
||||
use crate::error::{
|
||||
AddressError, Bip32Error, Bip39Error, CannotConnectError, CreateTxError, DescriptorError,
|
||||
DescriptorKeyError, ElectrumClientError, EsploraError, ExtractTxError, FeeRateError,
|
||||
DescriptorKeyError, ElectrumError, EsploraError, ExtractTxError, FeeRateError,
|
||||
ParseAmountError, PersistenceError, PsbtParseError, TransactionError, TxidParseError,
|
||||
WalletCreationError,
|
||||
};
|
||||
@ -1488,77 +1488,77 @@ mod test {
|
||||
fn test_error_electrum_client() {
|
||||
let cases = vec![
|
||||
(
|
||||
ElectrumClientError::IOError { error_message: "message".to_string(), },
|
||||
ElectrumError::IOError { error_message: "message".to_string(), },
|
||||
"message",
|
||||
),
|
||||
(
|
||||
ElectrumClientError::Json { error_message: "message".to_string(), },
|
||||
ElectrumError::Json { error_message: "message".to_string(), },
|
||||
"message",
|
||||
),
|
||||
(
|
||||
ElectrumClientError::Hex { error_message: "message".to_string(), },
|
||||
ElectrumError::Hex { error_message: "message".to_string(), },
|
||||
"message",
|
||||
),
|
||||
(
|
||||
ElectrumClientError::Protocol { error_message: "message".to_string(), },
|
||||
ElectrumError::Protocol { error_message: "message".to_string(), },
|
||||
"electrum server error: message",
|
||||
),
|
||||
(
|
||||
ElectrumClientError::Bitcoin {
|
||||
ElectrumError::Bitcoin {
|
||||
error_message: "message".to_string(),
|
||||
},
|
||||
"message",
|
||||
),
|
||||
(
|
||||
ElectrumClientError::AlreadySubscribed,
|
||||
ElectrumError::AlreadySubscribed,
|
||||
"already subscribed to the notifications of an address",
|
||||
),
|
||||
(
|
||||
ElectrumClientError::NotSubscribed,
|
||||
ElectrumError::NotSubscribed,
|
||||
"not subscribed to the notifications of an address",
|
||||
),
|
||||
(
|
||||
ElectrumClientError::InvalidResponse {
|
||||
ElectrumError::InvalidResponse {
|
||||
error_message: "message".to_string(),
|
||||
},
|
||||
"error during the deserialization of a response from the server: message",
|
||||
),
|
||||
(
|
||||
ElectrumClientError::Message {
|
||||
ElectrumError::Message {
|
||||
error_message: "message".to_string(),
|
||||
},
|
||||
"message",
|
||||
),
|
||||
(
|
||||
ElectrumClientError::InvalidDNSNameError {
|
||||
ElectrumError::InvalidDNSNameError {
|
||||
domain: "domain".to_string(),
|
||||
},
|
||||
"invalid domain name domain not matching SSL certificate",
|
||||
),
|
||||
(
|
||||
ElectrumClientError::MissingDomain,
|
||||
ElectrumError::MissingDomain,
|
||||
"missing domain while it was explicitly asked to validate it",
|
||||
),
|
||||
(
|
||||
ElectrumClientError::AllAttemptsErrored,
|
||||
ElectrumError::AllAttemptsErrored,
|
||||
"made one or multiple attempts, all errored",
|
||||
),
|
||||
(
|
||||
ElectrumClientError::SharedIOError {
|
||||
ElectrumError::SharedIOError {
|
||||
error_message: "message".to_string(),
|
||||
},
|
||||
"message",
|
||||
),
|
||||
(
|
||||
ElectrumClientError::CouldntLockReader,
|
||||
ElectrumError::CouldntLockReader,
|
||||
"couldn't take a lock on the reader mutex. This means that there's already another reader thread is running"
|
||||
),
|
||||
(
|
||||
ElectrumClientError::Mpsc,
|
||||
ElectrumError::Mpsc,
|
||||
"broken IPC communication channel: the other thread probably has exited",
|
||||
),
|
||||
(
|
||||
ElectrumClientError::CouldNotCreateConnection {
|
||||
ElectrumError::CouldNotCreateConnection {
|
||||
error_message: "message".to_string(),
|
||||
},
|
||||
"message",
|
||||
|
@ -25,7 +25,7 @@ use crate::error::CannotConnectError;
|
||||
use crate::error::CreateTxError;
|
||||
use crate::error::DescriptorError;
|
||||
use crate::error::DescriptorKeyError;
|
||||
use crate::error::ElectrumClientError;
|
||||
use crate::error::ElectrumError;
|
||||
use crate::error::EsploraError;
|
||||
use crate::error::ExtractTxError;
|
||||
use crate::error::FeeRateError;
|
||||
|
@ -0,0 +1,44 @@
|
||||
import XCTest
|
||||
@testable import BitcoinDevKit
|
||||
|
||||
private let SIGNET_ELECTRUM_URL = "ssl://mempool.space:60602"
|
||||
|
||||
final class LiveElectrumClientTests: XCTestCase {
|
||||
func testSyncedBalance() throws {
|
||||
let descriptor = try Descriptor(
|
||||
descriptor: "wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)",
|
||||
network: Network.signet
|
||||
)
|
||||
let wallet = try Wallet.newNoPersist(
|
||||
descriptor: descriptor,
|
||||
changeDescriptor: nil,
|
||||
network: .signet
|
||||
)
|
||||
let electrumClient: ElectrumClient = try ElectrumClient(url: SIGNET_ELECTRUM_URL)
|
||||
let fullScanRequest: FullScanRequest = wallet.startFullScan()
|
||||
let update = try electrumClient.fullScan(
|
||||
fullScanRequest: fullScanRequest,
|
||||
stopGap: 10,
|
||||
batchSize: 10,
|
||||
fetchPrevTxouts: false
|
||||
)
|
||||
try wallet.applyUpdate(update: update)
|
||||
let _ = try wallet.commit()
|
||||
let address = try wallet.revealNextAddress(keychain: KeychainKind.external).address.asString()
|
||||
|
||||
XCTAssertGreaterThan(
|
||||
wallet.getBalance().total.toSat(),
|
||||
UInt64(0),
|
||||
"Wallet must have positive balance, please send funds to \(address)"
|
||||
)
|
||||
|
||||
print("Transactions count: \(wallet.transactions().count)")
|
||||
let transactions = wallet.transactions().prefix(3)
|
||||
for tx in transactions {
|
||||
let sentAndReceived = wallet.sentAndReceived(tx: tx.transaction)
|
||||
print("Transaction: \(tx.transaction.txid())")
|
||||
print("Sent \(sentAndReceived.sent)")
|
||||
print("Received \(sentAndReceived.received)")
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user