mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-03-11 00:49:22 -04:00
Add checks to max_giveable amount.
We need to check two things: - balance to be higher than dust amount (546). - balance to be higher than min-relay fee. Additionally, the tx_builder might fail if not enough funds are in the wallet to pay for the overall transaction fees.
This commit is contained in:
parent
6bc21a9318
commit
7fc5a47619
@ -30,6 +30,7 @@ const SLED_TREE_NAME: &str = "default_tree";
|
|||||||
/// amount for tx fees.
|
/// amount for tx fees.
|
||||||
const MAX_RELATIVE_TX_FEE: Decimal = dec!(0.03);
|
const MAX_RELATIVE_TX_FEE: Decimal = dec!(0.03);
|
||||||
const MAX_ABSOLUTE_TX_FEE: Decimal = dec!(100_000);
|
const MAX_ABSOLUTE_TX_FEE: Decimal = dec!(100_000);
|
||||||
|
const DUST_AMOUNT: u64 = 546;
|
||||||
|
|
||||||
pub struct Wallet<B = ElectrumBlockchain, D = bdk::sled::Tree, C = Client> {
|
pub struct Wallet<B = ElectrumBlockchain, D = bdk::sled::Tree, C = Client> {
|
||||||
client: Arc<Mutex<C>>,
|
client: Arc<Mutex<C>>,
|
||||||
@ -316,7 +317,17 @@ where
|
|||||||
/// transaction confirmed.
|
/// transaction confirmed.
|
||||||
pub async fn max_giveable(&self, locking_script_size: usize) -> Result<Amount> {
|
pub async fn max_giveable(&self, locking_script_size: usize) -> Result<Amount> {
|
||||||
let wallet = self.wallet.lock().await;
|
let wallet = self.wallet.lock().await;
|
||||||
|
let balance = wallet.get_balance()?;
|
||||||
|
if balance < DUST_AMOUNT {
|
||||||
|
return Ok(Amount::ZERO);
|
||||||
|
}
|
||||||
let client = self.client.lock().await;
|
let client = self.client.lock().await;
|
||||||
|
let min_relay_fee = client.min_relay_fee()?.as_sat();
|
||||||
|
|
||||||
|
if balance < min_relay_fee {
|
||||||
|
return Ok(Amount::ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
let fee_rate = client.estimate_feerate(self.target_block)?;
|
let fee_rate = client.estimate_feerate(self.target_block)?;
|
||||||
|
|
||||||
let mut tx_builder = wallet.build_tx();
|
let mut tx_builder = wallet.build_tx();
|
||||||
@ -325,11 +336,16 @@ where
|
|||||||
tx_builder.set_single_recipient(dummy_script);
|
tx_builder.set_single_recipient(dummy_script);
|
||||||
tx_builder.drain_wallet();
|
tx_builder.drain_wallet();
|
||||||
tx_builder.fee_rate(fee_rate);
|
tx_builder.fee_rate(fee_rate);
|
||||||
let (_, details) = tx_builder.finish().context("Failed to build transaction")?;
|
|
||||||
|
|
||||||
let max_giveable = details.sent - details.fees;
|
let response = tx_builder.finish();
|
||||||
|
match response {
|
||||||
Ok(Amount::from_sat(max_giveable))
|
Ok((_, details)) => {
|
||||||
|
let max_giveable = details.sent - details.fees;
|
||||||
|
Ok(Amount::from_sat(max_giveable))
|
||||||
|
}
|
||||||
|
Err(bdk::Error::InsufficientFunds { .. }) => Ok(Amount::ZERO),
|
||||||
|
Err(e) => bail!("Failed to build transaction. {:#}", e),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Estimate total tx fee for a pre-defined target block based on the
|
/// Estimate total tx fee for a pre-defined target block based on the
|
||||||
@ -758,6 +774,7 @@ impl fmt::Display for ScriptStatus {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::bitcoin::TxLock;
|
||||||
use proptest::prelude::*;
|
use proptest::prelude::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -945,4 +962,46 @@ mod tests {
|
|||||||
assert!(estimate_fee(weight, amount, fee_rate, relay_fee).is_err());
|
assert!(estimate_fee(weight, amount, fee_rate, relay_fee).is_err());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct StaticFeeRate {
|
||||||
|
min_relay_fee: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EstimateFeeRate for StaticFeeRate {
|
||||||
|
fn estimate_feerate(&self, _target_block: usize) -> Result<FeeRate> {
|
||||||
|
Ok(FeeRate::default_min_relay_fee())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn min_relay_fee(&self) -> Result<bitcoin::Amount> {
|
||||||
|
Ok(bitcoin::Amount::from_sat(self.min_relay_fee))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn given_no_balance_returns_amount_0() {
|
||||||
|
let wallet = Wallet::new_funded(0, StaticFeeRate { min_relay_fee: 1 });
|
||||||
|
let amount = wallet.max_giveable(TxLock::script_size()).await.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(amount, Amount::ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn given_balance_below_min_relay_fee_returns_amount_0() {
|
||||||
|
let wallet = Wallet::new_funded(1000, StaticFeeRate {
|
||||||
|
min_relay_fee: 1001,
|
||||||
|
});
|
||||||
|
let amount = wallet.max_giveable(TxLock::script_size()).await.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(amount, Amount::ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn given_balance_above_relay_fee_returns_amount_greater_0() {
|
||||||
|
let wallet = Wallet::new_funded(10_000, StaticFeeRate {
|
||||||
|
min_relay_fee: 1000,
|
||||||
|
});
|
||||||
|
let amount = wallet.max_giveable(TxLock::script_size()).await.unwrap();
|
||||||
|
|
||||||
|
assert!(amount.as_sat() > 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user