Skip to content

Commit d5c5e01

Browse files
committed
f Allow to withdraw all funds
1 parent 0f30f9b commit d5c5e01

File tree

3 files changed

+91
-19
lines changed

3 files changed

+91
-19
lines changed

src/lib.rs

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,31 @@ impl Node {
836836
self.wallet.get_balance()
837837
}
838838

839+
/// Send an on-chain payment to the given address.
840+
pub fn withdraw(&self, address: &bitcoin::Address, amount_sats: u64) -> Result<Txid, Error> {
841+
let runtime_lock = self.running.read().unwrap();
842+
if runtime_lock.is_none() {
843+
return Err(Error::NotRunning);
844+
}
845+
846+
let cur_balance = self.wallet.get_balance()?;
847+
if cur_balance.get_spendable() < amount_sats {
848+
log_error!(self.logger, "Unable to send payment due to insufficient funds.");
849+
return Err(Error::InsufficientFunds);
850+
}
851+
self.wallet.send_to_address(address, amount_sats)
852+
}
853+
854+
/// Send an on-chain payment to the given address, draining all the available funds.
855+
pub fn withdraw_all(&self, address: &bitcoin::Address) -> Result<Txid, Error> {
856+
let runtime_lock = self.running.read().unwrap();
857+
if runtime_lock.is_none() {
858+
return Err(Error::NotRunning);
859+
}
860+
861+
self.wallet.drain_to_address(address)
862+
}
863+
839864
/// Retrieve a list of known channels.
840865
pub fn list_channels(&self) -> Vec<ChannelDetails> {
841866
self.channel_manager.list_channels()
@@ -1207,23 +1232,6 @@ impl Node {
12071232
}
12081233
}
12091234

1210-
/// Send an on-chain payment to the given address.
1211-
pub fn send_onchain_payment(
1212-
&self, address: &bitcoin::Address, amount_sats: u64,
1213-
) -> Result<Txid, Error> {
1214-
let runtime_lock = self.running.read().unwrap();
1215-
if runtime_lock.is_none() {
1216-
return Err(Error::NotRunning);
1217-
}
1218-
1219-
let cur_balance = self.wallet.get_balance()?;
1220-
if cur_balance.get_spendable() < amount_sats {
1221-
log_error!(self.logger, "Unable to send payment due to insufficient funds.");
1222-
return Err(Error::InsufficientFunds);
1223-
}
1224-
self.wallet.send_to_address(address, amount_sats)
1225-
}
1226-
12271235
/// Returns a payable invoice that can be used to request and receive a payment of the amount
12281236
/// given.
12291237
pub fn receive_payment(

src/test/functional_tests.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,9 +306,9 @@ fn onchain_spend_receive() {
306306
node_b.sync_wallets().unwrap();
307307
assert_eq!(node_b.onchain_balance().unwrap().get_spendable(), 100000);
308308

309-
assert_eq!(Err(Error::InsufficientFunds), node_a.send_onchain_payment(&addr_b, 1000));
309+
assert_eq!(Err(Error::InsufficientFunds), node_a.withdraw(&addr_b, 1000));
310310

311-
let txid = node_b.send_onchain_payment(&addr_a, 1000).unwrap();
311+
let txid = node_b.withdraw(&addr_a, 1000).unwrap();
312312
generate_blocks_and_wait(&bitcoind, &electrsd, 6);
313313
wait_for_tx(&electrsd, txid);
314314

@@ -318,4 +318,16 @@ fn onchain_spend_receive() {
318318
assert_eq!(node_a.onchain_balance().unwrap().get_spendable(), 1000);
319319
assert!(node_b.onchain_balance().unwrap().get_spendable() > 98000);
320320
assert!(node_b.onchain_balance().unwrap().get_spendable() < 100000);
321+
322+
let addr_b = node_b.new_funding_address().unwrap();
323+
let txid = node_a.withdraw_all(&addr_b).unwrap();
324+
generate_blocks_and_wait(&bitcoind, &electrsd, 6);
325+
wait_for_tx(&electrsd, txid);
326+
327+
node_a.sync_wallets().unwrap();
328+
node_b.sync_wallets().unwrap();
329+
330+
assert_eq!(node_a.onchain_balance().unwrap().get_total(), 0);
331+
assert!(node_b.onchain_balance().unwrap().get_spendable() > 99000);
332+
assert!(node_b.onchain_balance().unwrap().get_spendable() < 100000);
321333
}

src/wallet.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,58 @@ where
262262
Ok(txid)
263263
}
264264

265+
pub(crate) fn drain_to_address(&self, address: &bitcoin::Address) -> Result<Txid, Error> {
266+
let confirmation_target = ConfirmationTarget::Normal;
267+
let fee_rate = self.estimate_fee_rate(confirmation_target);
268+
269+
let tx = {
270+
let locked_wallet = self.inner.lock().unwrap();
271+
let mut tx_builder = locked_wallet.build_tx();
272+
273+
tx_builder
274+
.drain_wallet()
275+
.drain_to(address.script_pubkey())
276+
.fee_rate(fee_rate)
277+
.enable_rbf();
278+
279+
let mut psbt = match tx_builder.finish() {
280+
Ok((psbt, _)) => {
281+
log_trace!(self.logger, "Created PSBT: {:?}", psbt);
282+
psbt
283+
}
284+
Err(err) => {
285+
log_error!(self.logger, "Failed to create transaction: {}", err);
286+
return Err(err.into());
287+
}
288+
};
289+
290+
match locked_wallet.sign(&mut psbt, SignOptions::default()) {
291+
Ok(finalized) => {
292+
if !finalized {
293+
return Err(Error::OnchainTxCreationFailed);
294+
}
295+
}
296+
Err(err) => {
297+
log_error!(self.logger, "Failed to create transaction: {}", err);
298+
return Err(err.into());
299+
}
300+
}
301+
psbt.extract_tx()
302+
};
303+
304+
self.broadcast_transaction(&tx);
305+
306+
let txid = tx.txid();
307+
log_info!(
308+
self.logger,
309+
"Created new transaction {} sending all available on-chain funds to address {}",
310+
txid,
311+
address
312+
);
313+
314+
Ok(txid)
315+
}
316+
265317
fn estimate_fee_rate(&self, confirmation_target: ConfirmationTarget) -> FeeRate {
266318
let locked_fee_rate_cache = self.fee_rate_cache.read().unwrap();
267319

0 commit comments

Comments
 (0)