@@ -110,7 +110,7 @@ use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
110110use crate :: scoring:: setup_background_pathfinding_scores_sync;
111111pub use balance:: { BalanceDetails , LightningBalance , PendingSweepBalance } ;
112112use bitcoin:: secp256k1:: PublicKey ;
113- use bitcoin:: Amount ;
113+ use bitcoin:: { Address , Amount } ;
114114#[ cfg( feature = "uniffi" ) ]
115115pub use builder:: ArcedNodeBuilder as Builder ;
116116pub use builder:: BuildError ;
@@ -1323,6 +1323,59 @@ impl Node {
13231323 }
13241324 }
13251325
1326+ /// Remove funds from an existing channel, sending them to an on-chain address.
1327+ ///
1328+ /// This provides for decreasing a channel's outbound liquidity without re-balancing or closing
1329+ /// it. Once negotiation with the counterparty is complete, the channel remains operational
1330+ /// while waiting for a new funding transaction to confirm.
1331+ pub fn splice_out (
1332+ & self , user_channel_id : & UserChannelId , counterparty_node_id : PublicKey , address : Address ,
1333+ splice_amount_sats : u64 ,
1334+ ) -> Result < ( ) , Error > {
1335+ let open_channels =
1336+ self . channel_manager . list_channels_with_counterparty ( & counterparty_node_id) ;
1337+ if let Some ( channel_details) =
1338+ open_channels. iter ( ) . find ( |c| c. user_channel_id == user_channel_id. 0 )
1339+ {
1340+ if splice_amount_sats > channel_details. outbound_capacity_msat {
1341+ return Err ( Error :: ChannelSplicingFailed ) ;
1342+ }
1343+
1344+ self . wallet . parse_and_validate_address ( & address) ?;
1345+
1346+ let contribution = SpliceContribution :: SpliceOut {
1347+ outputs : vec ! [ bitcoin:: TxOut {
1348+ value: Amount :: from_sat( splice_amount_sats) ,
1349+ script_pubkey: address. script_pubkey( ) ,
1350+ } ] ,
1351+ } ;
1352+
1353+ let fee_rate = self . wallet . estimate_channel_funding_fee_rate ( ) ;
1354+ let funding_feerate_per_kw = fee_rate. to_sat_per_kwu ( ) . try_into ( ) . unwrap_or ( u32:: MAX ) ;
1355+
1356+ self . channel_manager
1357+ . splice_channel (
1358+ & channel_details. channel_id ,
1359+ & counterparty_node_id,
1360+ contribution,
1361+ funding_feerate_per_kw,
1362+ None ,
1363+ )
1364+ . map_err ( |e| {
1365+ log_error ! ( self . logger, "Failed to splice channel: {:?}" , e) ;
1366+ Error :: ChannelSplicingFailed
1367+ } )
1368+ } else {
1369+ log_error ! (
1370+ self . logger,
1371+ "Channel not found for user_channel_id: {:?} and counterparty: {}" ,
1372+ user_channel_id,
1373+ counterparty_node_id
1374+ ) ;
1375+ Err ( Error :: ChannelSplicingFailed )
1376+ }
1377+ }
1378+
13261379 /// Manually sync the LDK and BDK wallets with the current chain state and update the fee rate
13271380 /// cache.
13281381 ///
0 commit comments