Skip to content

Commit 1bb1774

Browse files
committed
f Allow to withdraw all funds
1 parent 7519ca1 commit 1bb1774

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()
@@ -1218,23 +1243,6 @@ impl Node {
12181243
}
12191244
}
12201245

1221-
/// Send an on-chain payment to the given address.
1222-
pub fn send_onchain_payment(
1223-
&self, address: &bitcoin::Address, amount_sats: u64,
1224-
) -> Result<Txid, Error> {
1225-
let runtime_lock = self.running.read().unwrap();
1226-
if runtime_lock.is_none() {
1227-
return Err(Error::NotRunning);
1228-
}
1229-
1230-
let cur_balance = self.wallet.get_balance()?;
1231-
if cur_balance.get_spendable() < amount_sats {
1232-
log_error!(self.logger, "Unable to send payment due to insufficient funds.");
1233-
return Err(Error::InsufficientFunds);
1234-
}
1235-
self.wallet.send_to_address(address, amount_sats)
1236-
}
1237-
12381246
/// Returns a payable invoice that can be used to request and receive a payment of the amount
12391247
/// given.
12401248
pub fn receive_payment(

src/test/functional_tests.rs

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

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

329-
let txid = node_b.send_onchain_payment(&addr_a, 1000).unwrap();
329+
let txid = node_b.withdraw(&addr_a, 1000).unwrap();
330330
generate_blocks_and_wait(&bitcoind, &electrsd, 6);
331331
wait_for_tx(&electrsd, txid);
332332

@@ -336,4 +336,16 @@ fn onchain_spend_receive() {
336336
assert_eq!(node_a.onchain_balance().unwrap().get_spendable(), 1000);
337337
assert!(node_b.onchain_balance().unwrap().get_spendable() > 98000);
338338
assert!(node_b.onchain_balance().unwrap().get_spendable() < 100000);
339+
340+
let addr_b = node_b.new_funding_address().unwrap();
341+
let txid = node_a.withdraw_all(&addr_b).unwrap();
342+
generate_blocks_and_wait(&bitcoind, &electrsd, 6);
343+
wait_for_tx(&electrsd, txid);
344+
345+
node_a.sync_wallets().unwrap();
346+
node_b.sync_wallets().unwrap();
347+
348+
assert_eq!(node_a.onchain_balance().unwrap().get_total(), 0);
349+
assert!(node_b.onchain_balance().unwrap().get_spendable() > 99000);
350+
assert!(node_b.onchain_balance().unwrap().get_spendable() < 100000);
339351
}

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)