make fee in TransactionDetails Option, add confirmation_time field as Option
confirmation_time contains both a block height and block timestamp and is Some only for confirmed transaction
This commit is contained in:
parent
18254110c6
commit
0bbfa5f989
1
.github/workflows/cont_integration.yml
vendored
1
.github/workflows/cont_integration.yml
vendored
@ -78,6 +78,7 @@ jobs:
|
|||||||
name: Test ${{ matrix.blockchain.name }}
|
name: Test ${{ matrix.blockchain.name }}
|
||||||
runs-on: ubuntu-16.04
|
runs-on: ubuntu-16.04
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
blockchain:
|
blockchain:
|
||||||
- name: electrum
|
- name: electrum
|
||||||
|
@ -71,7 +71,7 @@ use super::{Blockchain, Capability, ConfigurableBlockchain, Progress};
|
|||||||
use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
|
use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::types::{KeychainKind, LocalUtxo, TransactionDetails};
|
use crate::types::{KeychainKind, LocalUtxo, TransactionDetails};
|
||||||
use crate::FeeRate;
|
use crate::{ConfirmationTime, FeeRate};
|
||||||
|
|
||||||
use peer::*;
|
use peer::*;
|
||||||
use store::*;
|
use store::*;
|
||||||
@ -146,7 +146,7 @@ impl CompactFiltersBlockchain {
|
|||||||
database: &mut D,
|
database: &mut D,
|
||||||
tx: &Transaction,
|
tx: &Transaction,
|
||||||
height: Option<u32>,
|
height: Option<u32>,
|
||||||
timestamp: u64,
|
timestamp: Option<u64>,
|
||||||
internal_max_deriv: &mut Option<u32>,
|
internal_max_deriv: &mut Option<u32>,
|
||||||
external_max_deriv: &mut Option<u32>,
|
external_max_deriv: &mut Option<u32>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
@ -206,9 +206,8 @@ impl CompactFiltersBlockchain {
|
|||||||
transaction: Some(tx.clone()),
|
transaction: Some(tx.clone()),
|
||||||
received: incoming,
|
received: incoming,
|
||||||
sent: outgoing,
|
sent: outgoing,
|
||||||
height,
|
confirmation_time: ConfirmationTime::new(height, timestamp),
|
||||||
timestamp,
|
fee: Some(inputs_sum.saturating_sub(outputs_sum)),
|
||||||
fees: inputs_sum.saturating_sub(outputs_sum),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
info!("Saving tx {}", tx.txid);
|
info!("Saving tx {}", tx.txid);
|
||||||
@ -364,8 +363,8 @@ impl Blockchain for CompactFiltersBlockchain {
|
|||||||
);
|
);
|
||||||
let mut updates = database.begin_batch();
|
let mut updates = database.begin_batch();
|
||||||
for details in database.iter_txs(false)? {
|
for details in database.iter_txs(false)? {
|
||||||
match details.height {
|
match details.confirmation_time {
|
||||||
Some(height) if (height as usize) < last_synced_block => continue,
|
Some(c) if (c.height as usize) < last_synced_block => continue,
|
||||||
_ => updates.del_tx(&details.txid, false)?,
|
_ => updates.del_tx(&details.txid, false)?,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -387,7 +386,7 @@ impl Blockchain for CompactFiltersBlockchain {
|
|||||||
database,
|
database,
|
||||||
tx,
|
tx,
|
||||||
Some(height as u32),
|
Some(height as u32),
|
||||||
0,
|
None,
|
||||||
&mut internal_max_deriv,
|
&mut internal_max_deriv,
|
||||||
&mut external_max_deriv,
|
&mut external_max_deriv,
|
||||||
)?;
|
)?;
|
||||||
@ -398,7 +397,7 @@ impl Blockchain for CompactFiltersBlockchain {
|
|||||||
database,
|
database,
|
||||||
tx,
|
tx,
|
||||||
None,
|
None,
|
||||||
0,
|
None,
|
||||||
&mut internal_max_deriv,
|
&mut internal_max_deriv,
|
||||||
&mut external_max_deriv,
|
&mut external_max_deriv,
|
||||||
)?;
|
)?;
|
||||||
|
@ -33,7 +33,7 @@ use crate::blockchain::{Blockchain, Capability, ConfigurableBlockchain, Progress
|
|||||||
use crate::database::{BatchDatabase, DatabaseUtils};
|
use crate::database::{BatchDatabase, DatabaseUtils};
|
||||||
use crate::descriptor::{get_checksum, IntoWalletDescriptor};
|
use crate::descriptor::{get_checksum, IntoWalletDescriptor};
|
||||||
use crate::wallet::utils::SecpCtx;
|
use crate::wallet::utils::SecpCtx;
|
||||||
use crate::{Error, FeeRate, KeychainKind, LocalUtxo, TransactionDetails};
|
use crate::{ConfirmationTime, Error, FeeRate, KeychainKind, LocalUtxo, TransactionDetails};
|
||||||
use bitcoincore_rpc::json::{
|
use bitcoincore_rpc::json::{
|
||||||
GetAddressInfoResultLabel, ImportMultiOptions, ImportMultiRequest,
|
GetAddressInfoResultLabel, ImportMultiOptions, ImportMultiRequest,
|
||||||
ImportMultiRequestScriptPubkey, ImportMultiRescanSince,
|
ImportMultiRequestScriptPubkey, ImportMultiRescanSince,
|
||||||
@ -189,13 +189,15 @@ impl Blockchain for RpcBlockchain {
|
|||||||
let txid = tx_result.info.txid;
|
let txid = tx_result.info.txid;
|
||||||
list_txs_ids.insert(txid);
|
list_txs_ids.insert(txid);
|
||||||
if let Some(mut known_tx) = known_txs.get_mut(&txid) {
|
if let Some(mut known_tx) = known_txs.get_mut(&txid) {
|
||||||
if tx_result.info.blockheight != known_tx.height {
|
let confirmation_time =
|
||||||
|
ConfirmationTime::new(tx_result.info.blockheight, tx_result.info.blocktime);
|
||||||
|
if confirmation_time != known_tx.confirmation_time {
|
||||||
// reorg may change tx height
|
// reorg may change tx height
|
||||||
debug!(
|
debug!(
|
||||||
"updating tx({}) height to: {:?}",
|
"updating tx({}) confirmation time to: {:?}",
|
||||||
txid, tx_result.info.blockheight
|
txid, confirmation_time
|
||||||
);
|
);
|
||||||
known_tx.height = tx_result.info.blockheight;
|
known_tx.confirmation_time = confirmation_time;
|
||||||
db.set_tx(&known_tx)?;
|
db.set_tx(&known_tx)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -224,17 +226,17 @@ impl Blockchain for RpcBlockchain {
|
|||||||
let td = TransactionDetails {
|
let td = TransactionDetails {
|
||||||
transaction: Some(tx),
|
transaction: Some(tx),
|
||||||
txid: tx_result.info.txid,
|
txid: tx_result.info.txid,
|
||||||
timestamp: tx_result.info.time,
|
confirmation_time: ConfirmationTime::new(
|
||||||
|
tx_result.info.blockheight,
|
||||||
|
tx_result.info.blocktime,
|
||||||
|
),
|
||||||
received,
|
received,
|
||||||
sent,
|
sent,
|
||||||
//TODO it could happen according to the node situation/configuration that the
|
fee: tx_result.fee.map(|f| f.as_sat().abs() as u64),
|
||||||
// fee is not known [TransactionDetails:fee] should be made [Option]
|
|
||||||
fees: tx_result.fee.map(|f| f.as_sat().abs() as u64).unwrap_or(0),
|
|
||||||
height: tx_result.info.blockheight,
|
|
||||||
};
|
};
|
||||||
debug!(
|
debug!(
|
||||||
"saving tx: {} tx_result.fee:{:?} td.fees:{:?}",
|
"saving tx: {} tx_result.fee:{:?} td.fees:{:?}",
|
||||||
td.txid, tx_result.fee, td.fees
|
td.txid, tx_result.fee, td.fee
|
||||||
);
|
);
|
||||||
db.set_tx(&td)?;
|
db.set_tx(&td)?;
|
||||||
}
|
}
|
||||||
@ -519,7 +521,7 @@ mod test {
|
|||||||
wallet.sync(noop_progress(), None).unwrap();
|
wallet.sync(noop_progress(), None).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
wallet.get_balance().unwrap(),
|
wallet.get_balance().unwrap(),
|
||||||
100_000 - 50_000 - details.fees
|
100_000 - 50_000 - details.fee.unwrap_or(0)
|
||||||
);
|
);
|
||||||
drop(wallet);
|
drop(wallet);
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ use bitcoin::{BlockHeader, OutPoint, Script, Transaction, Txid};
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
|
use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::types::{KeychainKind, LocalUtxo, TransactionDetails};
|
use crate::types::{ConfirmationTime, KeychainKind, LocalUtxo, TransactionDetails};
|
||||||
use crate::wallet::time::Instant;
|
use crate::wallet::time::Instant;
|
||||||
use crate::wallet::utils::ChunksIterator;
|
use crate::wallet::utils::ChunksIterator;
|
||||||
|
|
||||||
@ -147,13 +147,14 @@ pub trait ElectrumLikeSync {
|
|||||||
// save any tx details not in db but in history_txs_id or with different height/timestamp
|
// save any tx details not in db but in history_txs_id or with different height/timestamp
|
||||||
for txid in history_txs_id.iter() {
|
for txid in history_txs_id.iter() {
|
||||||
let height = txid_height.get(txid).cloned().flatten();
|
let height = txid_height.get(txid).cloned().flatten();
|
||||||
let timestamp = *new_timestamps.get(txid).unwrap_or(&0u64);
|
let timestamp = new_timestamps.get(txid).cloned();
|
||||||
if let Some(tx_details) = txs_details_in_db.get(txid) {
|
if let Some(tx_details) = txs_details_in_db.get(txid) {
|
||||||
// check if height matches, otherwise updates it
|
// check if tx height matches, otherwise updates it. timestamp is not in the if clause
|
||||||
if tx_details.height != height {
|
// because we are not asking headers for confirmed tx we know about
|
||||||
|
if tx_details.confirmation_time.as_ref().map(|c| c.height) != height {
|
||||||
|
let confirmation_time = ConfirmationTime::new(height, timestamp);
|
||||||
let mut new_tx_details = tx_details.clone();
|
let mut new_tx_details = tx_details.clone();
|
||||||
new_tx_details.height = height;
|
new_tx_details.confirmation_time = confirmation_time;
|
||||||
new_tx_details.timestamp = timestamp;
|
|
||||||
batch.set_tx(&new_tx_details)?;
|
batch.set_tx(&new_tx_details)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -238,9 +239,13 @@ pub trait ElectrumLikeSync {
|
|||||||
chunk_size: usize,
|
chunk_size: usize,
|
||||||
) -> Result<HashMap<Txid, u64>, Error> {
|
) -> Result<HashMap<Txid, u64>, Error> {
|
||||||
let mut txid_timestamp = HashMap::new();
|
let mut txid_timestamp = HashMap::new();
|
||||||
|
let txid_in_db_with_conf: HashSet<_> = txs_details_in_db
|
||||||
|
.values()
|
||||||
|
.filter_map(|details| details.confirmation_time.as_ref().map(|_| details.txid))
|
||||||
|
.collect();
|
||||||
let needed_txid_height: HashMap<&Txid, u32> = txid_height
|
let needed_txid_height: HashMap<&Txid, u32> = txid_height
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(t, _)| txs_details_in_db.get(*t).is_none())
|
.filter(|(t, _)| !txid_in_db_with_conf.contains(*t))
|
||||||
.filter_map(|(t, o)| o.map(|h| (t, h)))
|
.filter_map(|(t, o)| o.map(|h| (t, h)))
|
||||||
.collect();
|
.collect();
|
||||||
let needed_heights: HashSet<u32> = needed_txid_height.values().cloned().collect();
|
let needed_heights: HashSet<u32> = needed_txid_height.values().cloned().collect();
|
||||||
@ -292,7 +297,7 @@ pub trait ElectrumLikeSync {
|
|||||||
fn save_transaction_details_and_utxos<D: BatchDatabase>(
|
fn save_transaction_details_and_utxos<D: BatchDatabase>(
|
||||||
txid: &Txid,
|
txid: &Txid,
|
||||||
db: &mut D,
|
db: &mut D,
|
||||||
timestamp: u64,
|
timestamp: Option<u64>,
|
||||||
height: Option<u32>,
|
height: Option<u32>,
|
||||||
updates: &mut dyn BatchOperations,
|
updates: &mut dyn BatchOperations,
|
||||||
utxo_deps: &HashMap<OutPoint, OutPoint>,
|
utxo_deps: &HashMap<OutPoint, OutPoint>,
|
||||||
@ -355,9 +360,8 @@ fn save_transaction_details_and_utxos<D: BatchDatabase>(
|
|||||||
transaction: Some(tx),
|
transaction: Some(tx),
|
||||||
received: incoming,
|
received: incoming,
|
||||||
sent: outgoing,
|
sent: outgoing,
|
||||||
height,
|
confirmation_time: ConfirmationTime::new(height, timestamp),
|
||||||
timestamp,
|
fee: Some(inputs_sum.saturating_sub(outputs_sum)), /* if the tx is a coinbase, fees would be negative */
|
||||||
fees: inputs_sum.saturating_sub(outputs_sum), /* if the tx is a coinbase, fees would be negative */
|
|
||||||
};
|
};
|
||||||
updates.set_tx(&tx_details)?;
|
updates.set_tx(&tx_details)?;
|
||||||
|
|
||||||
|
@ -473,18 +473,18 @@ macro_rules! populate_test_db {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let txid = tx.txid();
|
let txid = tx.txid();
|
||||||
let height = tx_meta
|
let confirmation_time = tx_meta.min_confirmations.map(|conf| ConfirmationTime {
|
||||||
.min_confirmations
|
height: current_height.unwrap().checked_sub(conf as u32).unwrap(),
|
||||||
.map(|conf| current_height.unwrap().checked_sub(conf as u32).unwrap());
|
timestamp: 0,
|
||||||
|
});
|
||||||
|
|
||||||
let tx_details = TransactionDetails {
|
let tx_details = TransactionDetails {
|
||||||
transaction: Some(tx.clone()),
|
transaction: Some(tx.clone()),
|
||||||
txid,
|
txid,
|
||||||
timestamp: 0,
|
fee: Some(0),
|
||||||
height,
|
|
||||||
received: 0,
|
received: 0,
|
||||||
sent: 0,
|
sent: 0,
|
||||||
fees: 0,
|
confirmation_time,
|
||||||
};
|
};
|
||||||
|
|
||||||
db.set_tx(&tx_details).unwrap();
|
db.set_tx(&tx_details).unwrap();
|
||||||
|
@ -314,11 +314,13 @@ pub mod test {
|
|||||||
let mut tx_details = TransactionDetails {
|
let mut tx_details = TransactionDetails {
|
||||||
transaction: Some(tx),
|
transaction: Some(tx),
|
||||||
txid,
|
txid,
|
||||||
timestamp: 123456,
|
|
||||||
received: 1337,
|
received: 1337,
|
||||||
sent: 420420,
|
sent: 420420,
|
||||||
fees: 140,
|
fee: Some(140),
|
||||||
height: Some(1000),
|
confirmation_time: Some(ConfirmationTime {
|
||||||
|
timestamp: 123456,
|
||||||
|
height: 1000,
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
tree.set_tx(&tx_details).unwrap();
|
tree.set_tx(&tx_details).unwrap();
|
||||||
|
@ -396,7 +396,7 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
assert_eq!(list_tx_item.txid, txid, "incorrect txid");
|
assert_eq!(list_tx_item.txid, txid, "incorrect txid");
|
||||||
assert_eq!(list_tx_item.received, 50_000, "incorrect received");
|
assert_eq!(list_tx_item.received, 50_000, "incorrect received");
|
||||||
assert_eq!(list_tx_item.sent, 0, "incorrect sent");
|
assert_eq!(list_tx_item.sent, 0, "incorrect sent");
|
||||||
assert_eq!(list_tx_item.height, None, "incorrect height");
|
assert_eq!(list_tx_item.confirmation_time, None, "incorrect confirmation time");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -454,7 +454,7 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
assert_eq!(list_tx_item.txid, txid, "incorrect txid");
|
assert_eq!(list_tx_item.txid, txid, "incorrect txid");
|
||||||
assert_eq!(list_tx_item.received, 105_000, "incorrect received");
|
assert_eq!(list_tx_item.received, 105_000, "incorrect received");
|
||||||
assert_eq!(list_tx_item.sent, 0, "incorrect sent");
|
assert_eq!(list_tx_item.sent, 0, "incorrect sent");
|
||||||
assert_eq!(list_tx_item.height, None, "incorrect height");
|
assert_eq!(list_tx_item.confirmation_time, None, "incorrect confirmation_time");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -515,7 +515,7 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
assert_eq!(list_tx_item.txid, txid, "incorrect txid");
|
assert_eq!(list_tx_item.txid, txid, "incorrect txid");
|
||||||
assert_eq!(list_tx_item.received, 50_000, "incorrect received");
|
assert_eq!(list_tx_item.received, 50_000, "incorrect received");
|
||||||
assert_eq!(list_tx_item.sent, 0, "incorrect sent");
|
assert_eq!(list_tx_item.sent, 0, "incorrect sent");
|
||||||
assert_eq!(list_tx_item.height, None, "incorrect height");
|
assert_eq!(list_tx_item.confirmation_time, None, "incorrect confirmation_time");
|
||||||
|
|
||||||
let new_txid = test_client.bump_fee(&txid);
|
let new_txid = test_client.bump_fee(&txid);
|
||||||
|
|
||||||
@ -529,7 +529,7 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
assert_eq!(list_tx_item.txid, new_txid, "incorrect txid after bump");
|
assert_eq!(list_tx_item.txid, new_txid, "incorrect txid after bump");
|
||||||
assert_eq!(list_tx_item.received, 50_000, "incorrect received after bump");
|
assert_eq!(list_tx_item.received, 50_000, "incorrect received after bump");
|
||||||
assert_eq!(list_tx_item.sent, 0, "incorrect sent after bump");
|
assert_eq!(list_tx_item.sent, 0, "incorrect sent after bump");
|
||||||
assert_eq!(list_tx_item.height, None, "incorrect height after bump");
|
assert_eq!(list_tx_item.confirmation_time, None, "incorrect height after bump");
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: I would like this to be cfg_attr(not(feature = "test-esplora"), ignore) but it
|
// FIXME: I would like this to be cfg_attr(not(feature = "test-esplora"), ignore) but it
|
||||||
@ -552,7 +552,7 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
|
|
||||||
let list_tx_item = &wallet.list_transactions(false).unwrap()[0];
|
let list_tx_item = &wallet.list_transactions(false).unwrap()[0];
|
||||||
assert_eq!(list_tx_item.txid, txid, "incorrect txid");
|
assert_eq!(list_tx_item.txid, txid, "incorrect txid");
|
||||||
assert!(list_tx_item.height.is_some(), "incorrect height");
|
assert!(list_tx_item.confirmation_time.is_some(), "incorrect confirmation_time");
|
||||||
|
|
||||||
// Invalidate 1 block
|
// Invalidate 1 block
|
||||||
test_client.invalidate(1);
|
test_client.invalidate(1);
|
||||||
@ -563,7 +563,7 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
|
|
||||||
let list_tx_item = &wallet.list_transactions(false).unwrap()[0];
|
let list_tx_item = &wallet.list_transactions(false).unwrap()[0];
|
||||||
assert_eq!(list_tx_item.txid, txid, "incorrect txid after invalidate");
|
assert_eq!(list_tx_item.txid, txid, "incorrect txid after invalidate");
|
||||||
assert_eq!(list_tx_item.height, None, "incorrect height after invalidate");
|
assert_eq!(list_tx_item.confirmation_time, None, "incorrect confirmation time after invalidate");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -596,6 +596,34 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
assert_eq!(wallet.list_unspent().unwrap().len(), 1, "incorrect number of unspents");
|
assert_eq!(wallet.list_unspent().unwrap().len(), 1, "incorrect number of unspents");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
fn test_update_confirmation_time_after_generate() {
|
||||||
|
let (wallet, descriptors, mut test_client) = init_single_sig();
|
||||||
|
println!("{}", descriptors.0);
|
||||||
|
let node_addr = test_client.get_node_address(None);
|
||||||
|
|
||||||
|
let received_txid = test_client.receive(testutils! {
|
||||||
|
@tx ( (@external descriptors, 0) => 50_000 )
|
||||||
|
});
|
||||||
|
|
||||||
|
wallet.sync(noop_progress(), None).unwrap();
|
||||||
|
assert_eq!(wallet.get_balance().unwrap(), 50_000, "incorrect balance");
|
||||||
|
|
||||||
|
let tx_map = wallet.list_transactions(false).unwrap().into_iter().map(|tx| (tx.txid, tx)).collect::<std::collections::HashMap<_, _>>();
|
||||||
|
let details = tx_map.get(&received_txid).unwrap();
|
||||||
|
assert!(details.confirmation_time.is_none());
|
||||||
|
|
||||||
|
test_client.generate(1, Some(node_addr));
|
||||||
|
wallet.sync(noop_progress(), None).unwrap();
|
||||||
|
|
||||||
|
let tx_map = wallet.list_transactions(false).unwrap().into_iter().map(|tx| (tx.txid, tx)).collect::<std::collections::HashMap<_, _>>();
|
||||||
|
let details = tx_map.get(&received_txid).unwrap();
|
||||||
|
assert!(details.confirmation_time.is_some());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
#[serial]
|
||||||
fn test_sync_outgoing_from_scratch() {
|
fn test_sync_outgoing_from_scratch() {
|
||||||
@ -635,7 +663,7 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
let sent = tx_map.get(&sent_txid).unwrap();
|
let sent = tx_map.get(&sent_txid).unwrap();
|
||||||
assert_eq!(sent.received, details.received, "incorrect received from sender");
|
assert_eq!(sent.received, details.received, "incorrect received from sender");
|
||||||
assert_eq!(sent.sent, details.sent, "incorrect sent from sender");
|
assert_eq!(sent.sent, details.sent, "incorrect sent from sender");
|
||||||
assert_eq!(sent.fees, details.fees, "incorrect fees from sender");
|
assert_eq!(sent.fee.unwrap_or(0), details.fee.unwrap_or(0), "incorrect fees from sender");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -662,7 +690,7 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
|
|
||||||
wallet.sync(noop_progress(), None).unwrap();
|
wallet.sync(noop_progress(), None).unwrap();
|
||||||
|
|
||||||
total_sent += 5_000 + details.fees;
|
total_sent += 5_000 + details.fee.unwrap_or(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
wallet.sync(noop_progress(), None).unwrap();
|
wallet.sync(noop_progress(), None).unwrap();
|
||||||
@ -700,7 +728,7 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
assert!(finalized, "Cannot finalize transaction");
|
assert!(finalized, "Cannot finalize transaction");
|
||||||
wallet.broadcast(psbt.extract_tx()).unwrap();
|
wallet.broadcast(psbt.extract_tx()).unwrap();
|
||||||
wallet.sync(noop_progress(), None).unwrap();
|
wallet.sync(noop_progress(), None).unwrap();
|
||||||
assert_eq!(wallet.get_balance().unwrap(), 50_000 - details.fees - 5_000, "incorrect balance from fees");
|
assert_eq!(wallet.get_balance().unwrap(), 50_000 - details.fee.unwrap_or(0) - 5_000, "incorrect balance from fees");
|
||||||
assert_eq!(wallet.get_balance().unwrap(), details.received, "incorrect balance from received");
|
assert_eq!(wallet.get_balance().unwrap(), details.received, "incorrect balance from received");
|
||||||
|
|
||||||
let mut builder = wallet.build_fee_bump(details.txid).unwrap();
|
let mut builder = wallet.build_fee_bump(details.txid).unwrap();
|
||||||
@ -710,10 +738,10 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
assert!(finalized, "Cannot finalize transaction");
|
assert!(finalized, "Cannot finalize transaction");
|
||||||
wallet.broadcast(new_psbt.extract_tx()).unwrap();
|
wallet.broadcast(new_psbt.extract_tx()).unwrap();
|
||||||
wallet.sync(noop_progress(), None).unwrap();
|
wallet.sync(noop_progress(), None).unwrap();
|
||||||
assert_eq!(wallet.get_balance().unwrap(), 50_000 - new_details.fees - 5_000, "incorrect balance from fees after bump");
|
assert_eq!(wallet.get_balance().unwrap(), 50_000 - new_details.fee.unwrap_or(0) - 5_000, "incorrect balance from fees after bump");
|
||||||
assert_eq!(wallet.get_balance().unwrap(), new_details.received, "incorrect balance from received after bump");
|
assert_eq!(wallet.get_balance().unwrap(), new_details.received, "incorrect balance from received after bump");
|
||||||
|
|
||||||
assert!(new_details.fees > details.fees, "incorrect fees");
|
assert!(new_details.fee.unwrap_or(0) > details.fee.unwrap_or(0), "incorrect fees");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -736,7 +764,7 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
assert!(finalized, "Cannot finalize transaction");
|
assert!(finalized, "Cannot finalize transaction");
|
||||||
wallet.broadcast(psbt.extract_tx()).unwrap();
|
wallet.broadcast(psbt.extract_tx()).unwrap();
|
||||||
wallet.sync(noop_progress(), None).unwrap();
|
wallet.sync(noop_progress(), None).unwrap();
|
||||||
assert_eq!(wallet.get_balance().unwrap(), 1_000 - details.fees, "incorrect balance after send");
|
assert_eq!(wallet.get_balance().unwrap(), 1_000 - details.fee.unwrap_or(0), "incorrect balance after send");
|
||||||
assert_eq!(wallet.get_balance().unwrap(), details.received, "incorrect received after send");
|
assert_eq!(wallet.get_balance().unwrap(), details.received, "incorrect received after send");
|
||||||
|
|
||||||
let mut builder = wallet.build_fee_bump(details.txid).unwrap();
|
let mut builder = wallet.build_fee_bump(details.txid).unwrap();
|
||||||
@ -749,12 +777,12 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
assert_eq!(wallet.get_balance().unwrap(), 0, "incorrect balance after change removal");
|
assert_eq!(wallet.get_balance().unwrap(), 0, "incorrect balance after change removal");
|
||||||
assert_eq!(new_details.received, 0, "incorrect received after change removal");
|
assert_eq!(new_details.received, 0, "incorrect received after change removal");
|
||||||
|
|
||||||
assert!(new_details.fees > details.fees, "incorrect fees");
|
assert!(new_details.fee.unwrap_or(0) > details.fee.unwrap_or(0), "incorrect fees");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
#[serial]
|
||||||
fn test_sync_bump_fee_add_input() {
|
fn test_sync_bump_fee_add_input_simple() {
|
||||||
let (wallet, descriptors, mut test_client) = init_single_sig();
|
let (wallet, descriptors, mut test_client) = init_single_sig();
|
||||||
let node_addr = test_client.get_node_address(None);
|
let node_addr = test_client.get_node_address(None);
|
||||||
|
|
||||||
@ -772,8 +800,8 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
assert!(finalized, "Cannot finalize transaction");
|
assert!(finalized, "Cannot finalize transaction");
|
||||||
wallet.broadcast(psbt.extract_tx()).unwrap();
|
wallet.broadcast(psbt.extract_tx()).unwrap();
|
||||||
wallet.sync(noop_progress(), None).unwrap();
|
wallet.sync(noop_progress(), None).unwrap();
|
||||||
assert_eq!(wallet.get_balance().unwrap(), 26_000 - details.fees, "incorrect balance after send");
|
assert_eq!(wallet.get_balance().unwrap(), 26_000 - details.fee.unwrap_or(0), "incorrect balance after send");
|
||||||
assert_eq!(details.received, 1_000 - details.fees, "incorrect received after send");
|
assert_eq!(details.received, 1_000 - details.fee.unwrap_or(0), "incorrect received after send");
|
||||||
|
|
||||||
let mut builder = wallet.build_fee_bump(details.txid).unwrap();
|
let mut builder = wallet.build_fee_bump(details.txid).unwrap();
|
||||||
builder.fee_rate(FeeRate::from_sat_per_vb(10.0));
|
builder.fee_rate(FeeRate::from_sat_per_vb(10.0));
|
||||||
@ -806,8 +834,8 @@ macro_rules! bdk_blockchain_tests {
|
|||||||
assert!(finalized, "Cannot finalize transaction");
|
assert!(finalized, "Cannot finalize transaction");
|
||||||
wallet.broadcast(psbt.extract_tx()).unwrap();
|
wallet.broadcast(psbt.extract_tx()).unwrap();
|
||||||
wallet.sync(noop_progress(), None).unwrap();
|
wallet.sync(noop_progress(), None).unwrap();
|
||||||
assert_eq!(wallet.get_balance().unwrap(), 26_000 - details.fees, "incorrect balance after send");
|
assert_eq!(wallet.get_balance().unwrap(), 26_000 - details.fee.unwrap_or(0), "incorrect balance after send");
|
||||||
assert_eq!(details.received, 1_000 - details.fees, "incorrect received after send");
|
assert_eq!(details.received, 1_000 - details.fee.unwrap_or(0), "incorrect received after send");
|
||||||
|
|
||||||
let mut builder = wallet.build_fee_bump(details.txid).unwrap();
|
let mut builder = wallet.build_fee_bump(details.txid).unwrap();
|
||||||
builder.fee_rate(FeeRate::from_sat_per_vb(123.0));
|
builder.fee_rate(FeeRate::from_sat_per_vb(123.0));
|
||||||
|
31
src/types.rs
31
src/types.rs
@ -155,16 +155,35 @@ pub struct TransactionDetails {
|
|||||||
pub transaction: Option<Transaction>,
|
pub transaction: Option<Transaction>,
|
||||||
/// Transaction id
|
/// Transaction id
|
||||||
pub txid: Txid,
|
pub txid: Txid,
|
||||||
/// Timestamp
|
|
||||||
pub timestamp: u64,
|
|
||||||
/// Received value (sats)
|
/// Received value (sats)
|
||||||
pub received: u64,
|
pub received: u64,
|
||||||
/// Sent value (sats)
|
/// Sent value (sats)
|
||||||
pub sent: u64,
|
pub sent: u64,
|
||||||
/// Fee value (sats)
|
/// Fee value (sats) if available
|
||||||
pub fees: u64,
|
pub fee: Option<u64>,
|
||||||
/// Confirmed in block height, `None` means unconfirmed
|
/// If the transaction is confirmed, contains height and timestamp of the block containing the
|
||||||
pub height: Option<u32>,
|
/// transaction, unconfirmed transaction contains `None`.
|
||||||
|
pub confirmation_time: Option<ConfirmationTime>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Block height and timestamp of the block containing the confirmed transaction
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
|
||||||
|
pub struct ConfirmationTime {
|
||||||
|
/// confirmation block height
|
||||||
|
pub height: u32,
|
||||||
|
/// confirmation block timestamp
|
||||||
|
pub timestamp: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfirmationTime {
|
||||||
|
/// Returns `Some` `ConfirmationTime` if both `height` and `timestamp` are `Some`
|
||||||
|
pub fn new(height: Option<u32>, timestamp: Option<u64>) -> Option<Self> {
|
||||||
|
match (height, timestamp) {
|
||||||
|
(Some(height), Some(timestamp)) => Some(ConfirmationTime { height, timestamp }),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -128,7 +128,7 @@ impl WalletExport {
|
|||||||
Ok(txs) => {
|
Ok(txs) => {
|
||||||
let mut heights = txs
|
let mut heights = txs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|tx| tx.height.unwrap_or(0))
|
.map(|tx| tx.confirmation_time.map(|c| c.height).unwrap_or(0))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
heights.sort_unstable();
|
heights.sort_unstable();
|
||||||
|
|
||||||
@ -212,6 +212,7 @@ mod test {
|
|||||||
use crate::database::{memory::MemoryDatabase, BatchOperations};
|
use crate::database::{memory::MemoryDatabase, BatchOperations};
|
||||||
use crate::types::TransactionDetails;
|
use crate::types::TransactionDetails;
|
||||||
use crate::wallet::Wallet;
|
use crate::wallet::Wallet;
|
||||||
|
use crate::ConfirmationTime;
|
||||||
|
|
||||||
fn get_test_db() -> MemoryDatabase {
|
fn get_test_db() -> MemoryDatabase {
|
||||||
let mut db = MemoryDatabase::new();
|
let mut db = MemoryDatabase::new();
|
||||||
@ -221,11 +222,14 @@ mod test {
|
|||||||
"4ddff1fa33af17f377f62b72357b43107c19110a8009b36fb832af505efed98a",
|
"4ddff1fa33af17f377f62b72357b43107c19110a8009b36fb832af505efed98a",
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
timestamp: 12345678,
|
|
||||||
received: 100_000,
|
received: 100_000,
|
||||||
sent: 0,
|
sent: 0,
|
||||||
fees: 500,
|
fee: Some(500),
|
||||||
height: Some(5000),
|
confirmation_time: Some(ConfirmationTime {
|
||||||
|
timestamp: 12345678,
|
||||||
|
height: 5000,
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -706,11 +706,10 @@ where
|
|||||||
let transaction_details = TransactionDetails {
|
let transaction_details = TransactionDetails {
|
||||||
transaction: None,
|
transaction: None,
|
||||||
txid,
|
txid,
|
||||||
timestamp: time::get_timestamp(),
|
confirmation_time: None,
|
||||||
received,
|
received,
|
||||||
sent,
|
sent,
|
||||||
fees: fee_amount,
|
fee: Some(fee_amount),
|
||||||
height: None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((psbt, transaction_details))
|
Ok((psbt, transaction_details))
|
||||||
@ -769,7 +768,7 @@ where
|
|||||||
let mut details = match self.database.borrow().get_tx(&txid, true)? {
|
let mut details = match self.database.borrow().get_tx(&txid, true)? {
|
||||||
None => return Err(Error::TransactionNotFound),
|
None => return Err(Error::TransactionNotFound),
|
||||||
Some(tx) if tx.transaction.is_none() => return Err(Error::TransactionNotFound),
|
Some(tx) if tx.transaction.is_none() => return Err(Error::TransactionNotFound),
|
||||||
Some(tx) if tx.height.is_some() => return Err(Error::TransactionConfirmed),
|
Some(tx) if tx.confirmation_time.is_some() => return Err(Error::TransactionConfirmed),
|
||||||
Some(tx) => tx,
|
Some(tx) => tx,
|
||||||
};
|
};
|
||||||
let mut tx = details.transaction.take().unwrap();
|
let mut tx = details.transaction.take().unwrap();
|
||||||
@ -778,7 +777,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
let vbytes = tx.get_weight() as f32 / 4.0;
|
let vbytes = tx.get_weight() as f32 / 4.0;
|
||||||
let feerate = details.fees as f32 / vbytes;
|
let feerate = details.fee.ok_or(Error::FeeRateUnavailable)? as f32 / vbytes;
|
||||||
|
|
||||||
// remove the inputs from the tx and process them
|
// remove the inputs from the tx and process them
|
||||||
let original_txin = tx.input.drain(..).collect::<Vec<_>>();
|
let original_txin = tx.input.drain(..).collect::<Vec<_>>();
|
||||||
@ -854,7 +853,7 @@ where
|
|||||||
.collect(),
|
.collect(),
|
||||||
utxos: original_utxos,
|
utxos: original_utxos,
|
||||||
bumping_fee: Some(tx_builder::PreviousFee {
|
bumping_fee: Some(tx_builder::PreviousFee {
|
||||||
absolute: details.fees,
|
absolute: details.fee.ok_or(Error::FeeRateUnavailable)?,
|
||||||
rate: feerate,
|
rate: feerate,
|
||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -993,7 +992,7 @@ where
|
|||||||
.database
|
.database
|
||||||
.borrow()
|
.borrow()
|
||||||
.get_tx(&input.previous_output.txid, false)?
|
.get_tx(&input.previous_output.txid, false)?
|
||||||
.map(|tx| tx.height.unwrap_or(std::u32::MAX));
|
.map(|tx| tx.confirmation_time.map(|c| c.height).unwrap_or(u32::MAX));
|
||||||
let current_height = sign_options.assume_height.or(self.current_height);
|
let current_height = sign_options.assume_height.or(self.current_height);
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
@ -1231,7 +1230,7 @@ where
|
|||||||
|
|
||||||
let satisfies_confirmed = match must_only_use_confirmed_tx {
|
let satisfies_confirmed = match must_only_use_confirmed_tx {
|
||||||
true => {
|
true => {
|
||||||
let database = self.database.borrow_mut();
|
let database = self.database.borrow();
|
||||||
may_spend
|
may_spend
|
||||||
.iter()
|
.iter()
|
||||||
.map(|u| {
|
.map(|u| {
|
||||||
@ -1239,7 +1238,7 @@ where
|
|||||||
.get_tx(&u.0.outpoint.txid, true)
|
.get_tx(&u.0.outpoint.txid, true)
|
||||||
.map(|tx| match tx {
|
.map(|tx| match tx {
|
||||||
None => false,
|
None => false,
|
||||||
Some(tx) => tx.height.is_some(),
|
Some(tx) => tx.confirmation_time.is_some(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, _>>()?
|
.collect::<Result<Vec<_>, _>>()?
|
||||||
@ -1986,7 +1985,7 @@ pub(crate) mod test {
|
|||||||
assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
|
assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
psbt.global.unsigned_tx.output[0].value,
|
psbt.global.unsigned_tx.output[0].value,
|
||||||
50_000 - details.fees
|
50_000 - details.fee.unwrap_or(0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1998,7 +1997,7 @@ pub(crate) mod test {
|
|||||||
builder.add_recipient(addr.script_pubkey(), 25_000);
|
builder.add_recipient(addr.script_pubkey(), 25_000);
|
||||||
let (psbt, details) = builder.finish().unwrap();
|
let (psbt, details) = builder.finish().unwrap();
|
||||||
|
|
||||||
assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::default(), @add_signature);
|
assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::default(), @add_signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -2011,7 +2010,7 @@ pub(crate) mod test {
|
|||||||
.fee_rate(FeeRate::from_sat_per_vb(5.0));
|
.fee_rate(FeeRate::from_sat_per_vb(5.0));
|
||||||
let (psbt, details) = builder.finish().unwrap();
|
let (psbt, details) = builder.finish().unwrap();
|
||||||
|
|
||||||
assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(5.0), @add_signature);
|
assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(5.0), @add_signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -2025,11 +2024,11 @@ pub(crate) mod test {
|
|||||||
.fee_absolute(100);
|
.fee_absolute(100);
|
||||||
let (psbt, details) = builder.finish().unwrap();
|
let (psbt, details) = builder.finish().unwrap();
|
||||||
|
|
||||||
assert_eq!(details.fees, 100);
|
assert_eq!(details.fee.unwrap_or(0), 100);
|
||||||
assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
|
assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
psbt.global.unsigned_tx.output[0].value,
|
psbt.global.unsigned_tx.output[0].value,
|
||||||
50_000 - details.fees
|
50_000 - details.fee.unwrap_or(0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2044,11 +2043,11 @@ pub(crate) mod test {
|
|||||||
.fee_absolute(0);
|
.fee_absolute(0);
|
||||||
let (psbt, details) = builder.finish().unwrap();
|
let (psbt, details) = builder.finish().unwrap();
|
||||||
|
|
||||||
assert_eq!(details.fees, 0);
|
assert_eq!(details.fee.unwrap_or(0), 0);
|
||||||
assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
|
assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
psbt.global.unsigned_tx.output[0].value,
|
psbt.global.unsigned_tx.output[0].value,
|
||||||
50_000 - details.fees
|
50_000 - details.fee.unwrap_or(0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2081,7 +2080,7 @@ pub(crate) mod test {
|
|||||||
assert_eq!(psbt.global.unsigned_tx.output[0].value, 25_000);
|
assert_eq!(psbt.global.unsigned_tx.output[0].value, 25_000);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
psbt.global.unsigned_tx.output[1].value,
|
psbt.global.unsigned_tx.output[1].value,
|
||||||
25_000 - details.fees
|
25_000 - details.fee.unwrap_or(0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2095,7 +2094,7 @@ pub(crate) mod test {
|
|||||||
|
|
||||||
assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
|
assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
|
||||||
assert_eq!(psbt.global.unsigned_tx.output[0].value, 49_800);
|
assert_eq!(psbt.global.unsigned_tx.output[0].value, 49_800);
|
||||||
assert_eq!(details.fees, 200);
|
assert_eq!(details.fee.unwrap_or(0), 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -2126,7 +2125,7 @@ pub(crate) mod test {
|
|||||||
assert_eq!(psbt.global.unsigned_tx.output.len(), 3);
|
assert_eq!(psbt.global.unsigned_tx.output.len(), 3);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
psbt.global.unsigned_tx.output[0].value,
|
psbt.global.unsigned_tx.output[0].value,
|
||||||
10_000 - details.fees
|
10_000 - details.fee.unwrap_or(0)
|
||||||
);
|
);
|
||||||
assert_eq!(psbt.global.unsigned_tx.output[1].value, 10_000);
|
assert_eq!(psbt.global.unsigned_tx.output[1].value, 10_000);
|
||||||
assert_eq!(psbt.global.unsigned_tx.output[2].value, 30_000);
|
assert_eq!(psbt.global.unsigned_tx.output[2].value, 30_000);
|
||||||
@ -2496,7 +2495,7 @@ pub(crate) mod test {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
details.sent - details.received,
|
details.sent - details.received,
|
||||||
10_000 + details.fees,
|
10_000 + details.fee.unwrap_or(0),
|
||||||
"we should have only net spent ~10_000"
|
"we should have only net spent ~10_000"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -2762,7 +2761,10 @@ pub(crate) mod test {
|
|||||||
let txid = tx.txid();
|
let txid = tx.txid();
|
||||||
// skip saving the utxos, we know they can't be used anyways
|
// skip saving the utxos, we know they can't be used anyways
|
||||||
details.transaction = Some(tx);
|
details.transaction = Some(tx);
|
||||||
details.height = Some(42);
|
details.confirmation_time = Some(ConfirmationTime {
|
||||||
|
timestamp: 12345678,
|
||||||
|
height: 42,
|
||||||
|
});
|
||||||
wallet.database.borrow_mut().set_tx(&details).unwrap();
|
wallet.database.borrow_mut().set_tx(&details).unwrap();
|
||||||
|
|
||||||
wallet.build_fee_bump(txid).unwrap().finish().unwrap();
|
wallet.build_fee_bump(txid).unwrap().finish().unwrap();
|
||||||
@ -2867,10 +2869,10 @@ pub(crate) mod test {
|
|||||||
|
|
||||||
assert_eq!(details.sent, original_details.sent);
|
assert_eq!(details.sent, original_details.sent);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
details.received + details.fees,
|
details.received + details.fee.unwrap_or(0),
|
||||||
original_details.received + original_details.fees
|
original_details.received + original_details.fee.unwrap_or(0)
|
||||||
);
|
);
|
||||||
assert!(details.fees > original_details.fees);
|
assert!(details.fee.unwrap_or(0) > original_details.fee.unwrap_or(0));
|
||||||
|
|
||||||
let tx = &psbt.global.unsigned_tx;
|
let tx = &psbt.global.unsigned_tx;
|
||||||
assert_eq!(tx.output.len(), 2);
|
assert_eq!(tx.output.len(), 2);
|
||||||
@ -2891,7 +2893,7 @@ pub(crate) mod test {
|
|||||||
details.received
|
details.received
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(2.5), @add_signature);
|
assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(2.5), @add_signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -2928,14 +2930,14 @@ pub(crate) mod test {
|
|||||||
|
|
||||||
assert_eq!(details.sent, original_details.sent);
|
assert_eq!(details.sent, original_details.sent);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
details.received + details.fees,
|
details.received + details.fee.unwrap_or(0),
|
||||||
original_details.received + original_details.fees
|
original_details.received + original_details.fee.unwrap_or(0)
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
details.fees > original_details.fees,
|
details.fee.unwrap_or(0) > original_details.fee.unwrap_or(0),
|
||||||
"{} > {}",
|
"{} > {}",
|
||||||
details.fees,
|
details.fee.unwrap_or(0),
|
||||||
original_details.fees
|
original_details.fee.unwrap_or(0)
|
||||||
);
|
);
|
||||||
|
|
||||||
let tx = &psbt.global.unsigned_tx;
|
let tx = &psbt.global.unsigned_tx;
|
||||||
@ -2957,7 +2959,7 @@ pub(crate) mod test {
|
|||||||
details.received
|
details.received
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(details.fees, 200);
|
assert_eq!(details.fee.unwrap_or(0), 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -2995,13 +2997,13 @@ pub(crate) mod test {
|
|||||||
let (psbt, details) = builder.finish().unwrap();
|
let (psbt, details) = builder.finish().unwrap();
|
||||||
|
|
||||||
assert_eq!(details.sent, original_details.sent);
|
assert_eq!(details.sent, original_details.sent);
|
||||||
assert!(details.fees > original_details.fees);
|
assert!(details.fee.unwrap_or(0) > original_details.fee.unwrap_or(0));
|
||||||
|
|
||||||
let tx = &psbt.global.unsigned_tx;
|
let tx = &psbt.global.unsigned_tx;
|
||||||
assert_eq!(tx.output.len(), 1);
|
assert_eq!(tx.output.len(), 1);
|
||||||
assert_eq!(tx.output[0].value + details.fees, details.sent);
|
assert_eq!(tx.output[0].value + details.fee.unwrap_or(0), details.sent);
|
||||||
|
|
||||||
assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(2.5), @add_signature);
|
assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(2.5), @add_signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -3039,13 +3041,13 @@ pub(crate) mod test {
|
|||||||
let (psbt, details) = builder.finish().unwrap();
|
let (psbt, details) = builder.finish().unwrap();
|
||||||
|
|
||||||
assert_eq!(details.sent, original_details.sent);
|
assert_eq!(details.sent, original_details.sent);
|
||||||
assert!(details.fees > original_details.fees);
|
assert!(details.fee.unwrap_or(0) > original_details.fee.unwrap_or(0));
|
||||||
|
|
||||||
let tx = &psbt.global.unsigned_tx;
|
let tx = &psbt.global.unsigned_tx;
|
||||||
assert_eq!(tx.output.len(), 1);
|
assert_eq!(tx.output.len(), 1);
|
||||||
assert_eq!(tx.output[0].value + details.fees, details.sent);
|
assert_eq!(tx.output[0].value + details.fee.unwrap_or(0), details.sent);
|
||||||
|
|
||||||
assert_eq!(details.fees, 300);
|
assert_eq!(details.fee.unwrap_or(0), 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -3190,7 +3192,7 @@ pub(crate) mod test {
|
|||||||
let (psbt, details) = builder.finish().unwrap();
|
let (psbt, details) = builder.finish().unwrap();
|
||||||
|
|
||||||
assert_eq!(details.sent, original_details.sent + 25_000);
|
assert_eq!(details.sent, original_details.sent + 25_000);
|
||||||
assert_eq!(details.fees + details.received, 30_000);
|
assert_eq!(details.fee.unwrap_or(0) + details.received, 30_000);
|
||||||
|
|
||||||
let tx = &psbt.global.unsigned_tx;
|
let tx = &psbt.global.unsigned_tx;
|
||||||
assert_eq!(tx.input.len(), 2);
|
assert_eq!(tx.input.len(), 2);
|
||||||
@ -3212,7 +3214,7 @@ pub(crate) mod test {
|
|||||||
details.received
|
details.received
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(50.0), @add_signature);
|
assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(50.0), @add_signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -3253,7 +3255,7 @@ pub(crate) mod test {
|
|||||||
let (psbt, details) = builder.finish().unwrap();
|
let (psbt, details) = builder.finish().unwrap();
|
||||||
|
|
||||||
assert_eq!(details.sent, original_details.sent + 25_000);
|
assert_eq!(details.sent, original_details.sent + 25_000);
|
||||||
assert_eq!(details.fees + details.received, 30_000);
|
assert_eq!(details.fee.unwrap_or(0) + details.received, 30_000);
|
||||||
|
|
||||||
let tx = &psbt.global.unsigned_tx;
|
let tx = &psbt.global.unsigned_tx;
|
||||||
assert_eq!(tx.input.len(), 2);
|
assert_eq!(tx.input.len(), 2);
|
||||||
@ -3275,7 +3277,7 @@ pub(crate) mod test {
|
|||||||
details.received
|
details.received
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(details.fees, 6_000);
|
assert_eq!(details.fee.unwrap_or(0), 6_000);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -3325,11 +3327,11 @@ pub(crate) mod test {
|
|||||||
builder.fee_rate(FeeRate::from_sat_per_vb(50.0));
|
builder.fee_rate(FeeRate::from_sat_per_vb(50.0));
|
||||||
let (psbt, details) = builder.finish().unwrap();
|
let (psbt, details) = builder.finish().unwrap();
|
||||||
|
|
||||||
let original_send_all_amount = original_details.sent - original_details.fees;
|
let original_send_all_amount = original_details.sent - original_details.fee.unwrap_or(0);
|
||||||
assert_eq!(details.sent, original_details.sent + 50_000);
|
assert_eq!(details.sent, original_details.sent + 50_000);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
details.received,
|
details.received,
|
||||||
75_000 - original_send_all_amount - details.fees
|
75_000 - original_send_all_amount - details.fee.unwrap_or(0)
|
||||||
);
|
);
|
||||||
|
|
||||||
let tx = &psbt.global.unsigned_tx;
|
let tx = &psbt.global.unsigned_tx;
|
||||||
@ -3349,10 +3351,10 @@ pub(crate) mod test {
|
|||||||
.find(|txout| txout.script_pubkey != addr.script_pubkey())
|
.find(|txout| txout.script_pubkey != addr.script_pubkey())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.value,
|
.value,
|
||||||
75_000 - original_send_all_amount - details.fees
|
75_000 - original_send_all_amount - details.fee.unwrap_or(0)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(50.0), @add_signature);
|
assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(50.0), @add_signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -3394,10 +3396,13 @@ pub(crate) mod test {
|
|||||||
builder.fee_rate(FeeRate::from_sat_per_vb(140.0));
|
builder.fee_rate(FeeRate::from_sat_per_vb(140.0));
|
||||||
let (psbt, details) = builder.finish().unwrap();
|
let (psbt, details) = builder.finish().unwrap();
|
||||||
|
|
||||||
assert_eq!(original_details.received, 5_000 - original_details.fees);
|
assert_eq!(
|
||||||
|
original_details.received,
|
||||||
|
5_000 - original_details.fee.unwrap_or(0)
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(details.sent, original_details.sent + 25_000);
|
assert_eq!(details.sent, original_details.sent + 25_000);
|
||||||
assert_eq!(details.fees, 30_000);
|
assert_eq!(details.fee.unwrap_or(0), 30_000);
|
||||||
assert_eq!(details.received, 0);
|
assert_eq!(details.received, 0);
|
||||||
|
|
||||||
let tx = &psbt.global.unsigned_tx;
|
let tx = &psbt.global.unsigned_tx;
|
||||||
@ -3412,7 +3417,7 @@ pub(crate) mod test {
|
|||||||
45_000
|
45_000
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(140.0), @dust_change, @add_signature);
|
assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(140.0), @dust_change, @add_signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -3461,7 +3466,7 @@ pub(crate) mod test {
|
|||||||
let (psbt, details) = builder.finish().unwrap();
|
let (psbt, details) = builder.finish().unwrap();
|
||||||
|
|
||||||
assert_eq!(details.sent, original_details.sent + 25_000);
|
assert_eq!(details.sent, original_details.sent + 25_000);
|
||||||
assert_eq!(details.fees + details.received, 30_000);
|
assert_eq!(details.fee.unwrap_or(0) + details.received, 30_000);
|
||||||
|
|
||||||
let tx = &psbt.global.unsigned_tx;
|
let tx = &psbt.global.unsigned_tx;
|
||||||
assert_eq!(tx.input.len(), 2);
|
assert_eq!(tx.input.len(), 2);
|
||||||
@ -3483,7 +3488,7 @@ pub(crate) mod test {
|
|||||||
details.received
|
details.received
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(5.0), @add_signature);
|
assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(5.0), @add_signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -3532,7 +3537,7 @@ pub(crate) mod test {
|
|||||||
let (psbt, details) = builder.finish().unwrap();
|
let (psbt, details) = builder.finish().unwrap();
|
||||||
|
|
||||||
assert_eq!(details.sent, original_details.sent + 25_000);
|
assert_eq!(details.sent, original_details.sent + 25_000);
|
||||||
assert_eq!(details.fees + details.received, 30_000);
|
assert_eq!(details.fee.unwrap_or(0) + details.received, 30_000);
|
||||||
|
|
||||||
let tx = &psbt.global.unsigned_tx;
|
let tx = &psbt.global.unsigned_tx;
|
||||||
assert_eq!(tx.input.len(), 2);
|
assert_eq!(tx.input.len(), 2);
|
||||||
@ -3554,7 +3559,7 @@ pub(crate) mod test {
|
|||||||
details.received
|
details.received
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(details.fees, 250);
|
assert_eq!(details.fee.unwrap_or(0), 250);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user