Use electrum http api to get height of the last block

The bdk wallet needs to be synced to use the block height api. This was causing issues when we tried doing a swap using the public blockstream testnet node. This was probably because it was being called rapidly in a loop.
fix-confirmations
rishflab 3 years ago
parent b9f0c2cc9d
commit 181e7c5096

@ -20,7 +20,6 @@ use reqwest::{Method, Url};
use serde::{Deserialize, Serialize};
use std::{path::Path, sync::Arc, time::Duration};
use tokio::{sync::Mutex, time::interval};
use url::ParseError;
const SLED_TREE_NAME: &str = "default_tree";
@ -180,8 +179,27 @@ impl GetRawTransaction for Wallet {
#[async_trait]
impl GetBlockHeight for Wallet {
async fn get_block_height(&self) -> BlockHeight {
// todo: create this url using the join() api in the Url type
let url = format!("{}{}", self.http_url.as_str(), "blocks/tip/height");
#[derive(Debug)]
enum Error {
Io(reqwest::Error),
Parse(std::num::ParseIntError),
}
let height = retry(ConstantBackoff::new(Duration::from_secs(1)), || async {
Ok(self.inner.lock().await.client().get_height()?)
// todo: We may want to return early if we cannot connect to the electrum node
// rather than retrying
let height = reqwest::Client::new()
.request(Method::GET, &url)
.send()
.await
.map_err(Error::Io)?
.text()
.await
.map_err(Error::Io)?
.parse::<u32>()
.map_err(Error::Parse)?;
Result::<_, backoff::Error<Error>>::Ok(height)
})
.await
.expect("transient errors to be retried");
@ -193,36 +211,27 @@ impl GetBlockHeight for Wallet {
#[async_trait]
impl TransactionBlockHeight for Wallet {
async fn transaction_block_height(&self, txid: Txid) -> BlockHeight {
#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
// todo: create this url using the join() api in the Url type
let url = format!("{}tx/{}/status", self.http_url, txid);
#[derive(Serialize, Deserialize, Debug, Clone)]
struct TransactionStatus {
block_height: Option<u32>,
confirmed: bool,
}
// todo: Implement conversion to anyhow::error so we can dont have to wrap these
// todo: See if we can make this error handling more elegant
// errors
#[derive(Debug)]
enum Error {
Io,
Io(reqwest::Error),
NotYetMined,
JsonDeserialisation(reqwest::Error),
UrlDeserialisation(ParseError),
}
let height = retry(ConstantBackoff::new(Duration::from_secs(1)), || async {
let path = &format!("/tx/{}/status", txid);
let url = self
.http_url
.clone()
.join(path)
.map_err(|err| backoff::Error::Permanent(Error::UrlDeserialisation(err)))?;
let resp = reqwest::Client::new()
.request(Method::GET, url)
.request(Method::GET, &url)
.send()
.await
.map_err(|err| {
tracing::error!("Fetching TxStatus failed: {}", err);
backoff::Error::Transient(Error::Io)
})?;
.map_err(|err| backoff::Error::Transient(Error::Io(err)))?;
let tx_status: TransactionStatus = resp
.json()
@ -256,7 +265,6 @@ impl WaitForTransactionFinality for Wallet {
loop {
tracing::debug!("syncing wallet");
self.inner.lock().await.sync(noop_progress(), None)?;
let tx_block_height = self.transaction_block_height(txid).await;
let block_height = self.get_block_height().await;
let confirmations = block_height - tx_block_height;

Loading…
Cancel
Save