Appearance
Closing a Channel
Begins the process of closing a channel. After this call (plus some timeout), no new HTLCs will be accepted on the given channel, and after additional timeout/the closing of all pending HTLCs, the channel will be closed on chain.
rust
// Both close methods now require the counterparty's node id, so grab the full
// ChannelDetails. Note the field is `user_channel_id` (a u128) in 0.2.
let channel = channel_manager
.list_channels()
.into_iter()
.find(|channel| channel.user_channel_id == user_channel_id)
.expect("ERROR: Channel not found");
let channel_id = channel.channel_id;
let counterparty_node_id = channel.counterparty.node_id;
// Example: Cooperative close
channel_manager
.close_channel(&channel_id, &counterparty_node_id)
.expect("ERROR: Failed to close channel");
// Example: Unilateral close (renamed; now requires an error-message string)
channel_manager
.force_close_broadcasting_latest_txn(&channel_id, &counterparty_node_id, "manually force-closed".to_string())
.expect("ERROR: Failed to force-close channel");kotlin
val res = channelManager.close_channel(channelId, counterpartyNodeId)
if (res is Result_NoneAPIErrorZ.Result_NoneAPIErrorZ_Err) {
// Handle error
}
if (res.is_ok) {
// Handle successful close
}typescript
import * as ldk from "lightningdevkit";
// channelId: ChannelId, counterpartyNodeId: Uint8Array (from the ChannelDetails)
const res = channelManager.close_channel(channelId, counterpartyNodeId);
if (res instanceof ldk.Result_NoneAPIErrorZ_Err) {
// Handle error
} else {
// Handle successful close
}To claim Funds directly into a custom wallet like BDK wallet using a custom KeysManager see the Key Management guide for more info.
SpendableOutputs Event Handling
rust
Event::SpendableOutputs { outputs, channel_id: _ } => {
// SpendableOutputDescriptors, of which outputs is a vec of, are critical to keep track
// of! While a `StaticOutput` descriptor is just an output to a static, well-known key,
// other descriptors are not currently ever regenerated for you by LDK. Once we return
// from this method, the descriptor will be gone, and you may lose track of some funds.
//
// Here we simply persist them to disk, with a background task running which will try
// to spend them regularly (possibly duplicatively/RBF'ing them). These can just be
// treated as normal funds where possible - they are only spendable by us and there is
// no rush to claim them.
for output in outputs {
let key = hex_utils::hex_str(&keys_manager.get_secure_random_bytes());
// Note that if the type here changes our read code needs to change as well.
let output: SpendableOutputDescriptor = output;
fs_store.write(PENDING_SPENDABLE_OUTPUT_DIR, "", &key, &output.encode()).unwrap();
}
}kotlin
// Example where we spend straight to our BDK based wallet
if (event is Event.SpendableOutputs) {
val outputs = event.outputs
try {
val address = OnchainWallet.getNewAddress()
val script = Address(address).scriptPubkey().toBytes().toUByteArray().toByteArray()
val txOut: Array<TxOut> = arrayOf()
// `spend_spendable_outputs` moved from KeysManager onto the OutputSpender
// trait, and gained a trailing `locktime` argument.
val res = keysManager?.as_OutputSpender()?.spend_spendable_outputs(
outputs,
txOut,
script,
1000,
Option_u32Z.none() // locktime
)
if (res != null && res.is_ok) {
val tx = (res as Result_TransactionNoneZ.Result_TransactionNoneZ_OK).res
LDKBroadcaster.broadcast_transactions(arrayOf(tx))
}
} catch (e: Exception) {
Log.i(LDKTAG, "Error: ${e.message}")
}
}typescript
import * as ldk from "lightningdevkit";
if (event instanceof ldk.Event_SpendableOutputs) {
// `spend_spendable_outputs` is on the OutputSpender trait.
const res = keysManager.as_OutputSpender().spend_spendable_outputs(
event.outputs, // SpendableOutputDescriptor[]
[], // additional TxOut[]
changeDestinationScript, // Uint8Array (your change scriptPubKey)
1000, // feerate_sat_per_1000_weight
ldk.Option_u32Z.constructor_none() // locktime
);
if (res instanceof ldk.Result_TransactionNoneZ_OK) {
txBroadcaster.broadcast_transactions([res.res]);
}
}References: Rust SpendableOutputs docs, Rust OutputSpender docs, Java/Kotlin Event bindings, TypeScript OutputSpender bindings