11# Closing a Channel
22
3- Close Channel
3+ Close Channel.
44
55<CodeSwitcher :languages =" {rust:'Rust', java:'Java', swift:'Swift'} " >
66 <template v-slot:rust >
@@ -32,7 +32,7 @@ if res!.isOk() {
3232</CodeSwitcher >
3333
3434
35- Claim Funds using Custom KeysManager. (Single Fees)
35+ Claim Funds directly into the BDK wallet using Custom KeysManager.
3636
3737<CodeSwitcher :languages =" {rust:'Rust', java:'Java', swift:'Swift'} " >
3838 <template v-slot:rust >
@@ -52,41 +52,58 @@ Claim Funds using Custom KeysManager. (Single Fees)
5252 <template v-slot:swift >
5353
5454``` Swift
55- // Custom KeysManager to get funds directly back to the BDK wallet after Channel Close
55+ import Foundation
56+ import LightningDevKit
57+ import BitcoinDevKit
58+
5659class MyKeysManager {
57- let keysManager: KeysManager
58- let signerProvider: MySignerProvider
60+ let inner: KeysManager
5961 let wallet: BitcoinDevKit.Wallet
62+ let signerProvider: MySignerProvider
6063
6164 init (seed : [UInt8 ], startingTimeSecs : UInt64 , startingTimeNanos : UInt32 , wallet : BitcoinDevKit.Wallet) {
62- self .keysManager = KeysManager (seed : seed, startingTimeSecs : startingTimeSecs, startingTimeNanos : startingTimeNanos)
65+ self .inner = KeysManager (seed : seed, startingTimeSecs : startingTimeSecs, startingTimeNanos : startingTimeNanos)
6366 self .wallet = wallet
6467 signerProvider = MySignerProvider ()
6568 signerProvider.myKeysManager = self
6669 }
70+
71+ // We drop all occurences of `SpendableOutputDescriptor::StaticOutput` (since they will be
72+ // spendable by the BDK wallet) and forward any other descriptors to
73+ // `KeysManager::spend_spendable_outputs`.
74+ //
75+ // Note you should set `locktime` to the current block height to mitigate fee sniping.
76+ // See https://bitcoinops.org/en/topics/fee-sniping/ for more information.
77+ func spendSpendableOutputs (descriptors : [SpendableOutputDescriptor], outputs : [Bindings.TxOut],
78+ changeDestinationScript : [UInt8 ], feerateSatPer1000Weight : UInt32 ,
79+ locktime : UInt32 ? ) -> Result_TransactionNoneZ {
80+ let onlyNonStatic: [SpendableOutputDescriptor] = descriptors.filter { desc in
81+ if desc.getValueType () == .StaticOutput {
82+ return false
83+ }
84+ return true
85+ }
86+ let res = self .inner .spendSpendableOutputs (
87+ descriptors : onlyNonStatic,
88+ outputs : outputs,
89+ changeDestinationScript : changeDestinationScript,
90+ feerateSatPer1000Weight : feerateSatPer1000Weight,
91+ locktime : locktime
92+ )
93+ return res
94+ }
6795}
6896
69- // Custom SignerProvider to override getDestinationScript() and getShutdownScriptpubkey()
7097class MySignerProvider : SignerProvider {
7198 weak var myKeysManager: MyKeysManager?
72- override func deriveChannelSigner (channelValueSatoshis : UInt64 , channelKeysId : [UInt8 ]) -> Bindings.WriteableEcdsaChannelSigner {
73- return myKeysManager! .keysManager .asSignerProvider ().deriveChannelSigner (channelValueSatoshis : channelValueSatoshis, channelKeysId : channelKeysId)
74- }
75-
76- override func generateChannelKeysId (inbound : Bool , channelValueSatoshis : UInt64 , userChannelId : [UInt8 ]) -> [UInt8 ] {
77- return myKeysManager! .keysManager .asSignerProvider ().generateChannelKeysId (inbound : inbound, channelValueSatoshis : channelValueSatoshis, userChannelId : userChannelId)
78- }
79-
80- override func readChanSigner (reader : [UInt8 ]) -> Bindings.Result_WriteableEcdsaChannelSignerDecodeErrorZ {
81- return myKeysManager! .keysManager .asSignerProvider ().readChanSigner (reader : reader)
82- }
8399
100+ // We return the destination and shutdown scripts derived by the BDK wallet.
84101 override func getDestinationScript () -> Bindings.Result_ScriptNoneZ {
85102 do {
86103 let address = try myKeysManager! .wallet .getAddress (addressIndex : .new )
87104 return Bindings.Result_ScriptNoneZ .initWithOk (o : address.address .scriptPubkey ().toBytes ())
88105 } catch {
89- return myKeysManager ! . keysManager . asSignerProvider (). getDestinationScript ()
106+ return . initWithErr ()
90107 }
91108 }
92109
@@ -137,19 +154,38 @@ class MySignerProvider: SignerProvider {
137154 return Bindings.Result_ShutdownScriptNoneZ .initWithOk (o : res.getValue ()! )
138155 }
139156 }
140- return myKeysManager ! . keysManager . asSignerProvider (). getShutdownScriptpubkey ()
157+ return . initWithErr ()
141158 } catch {
142- return myKeysManager ! . keysManager . asSignerProvider (). getShutdownScriptpubkey ()
159+ return . initWithErr ()
143160 }
144161 }
162+
163+ // ... and redirect all other trait method implementations to the `inner` `KeysManager`.
164+ override func deriveChannelSigner (channelValueSatoshis : UInt64 , channelKeysId : [UInt8 ]) -> Bindings.WriteableEcdsaChannelSigner {
165+ return myKeysManager! .inner .asSignerProvider ().deriveChannelSigner (
166+ channelValueSatoshis : channelValueSatoshis,
167+ channelKeysId : channelKeysId
168+ )
169+ }
170+
171+ override func generateChannelKeysId (inbound : Bool , channelValueSatoshis : UInt64 , userChannelId : [UInt8 ]) -> [UInt8 ] {
172+ return myKeysManager! .inner .asSignerProvider ().generateChannelKeysId (
173+ inbound : inbound,
174+ channelValueSatoshis : channelValueSatoshis,
175+ userChannelId : userChannelId
176+ )
177+ }
178+
179+ override func readChanSigner (reader : [UInt8 ]) -> Bindings.Result_WriteableEcdsaChannelSignerDecodeErrorZ {
180+ return myKeysManager! .inner .asSignerProvider ().readChanSigner (reader : reader)
181+ }
145182}
146-
147183```
148184
149185 </template >
150186</CodeSwitcher >
151187
152- Claim Funds using Events. (Double Fees)
188+ Handle Spendable Outputs event.
153189
154190<CodeSwitcher :languages =" {rust:'Rust', java:'Java', swift:'Swift'} " >
155191 <template v-slot:rust >
@@ -171,21 +207,21 @@ Claim Funds using Events. (Double Fees)
171207``` Swift
172208func handleEvent (event : Event) {
173209 if let event = event.getValueAsSpendableOutputs () {
210+ print (" handleEvent: trying to spend output" )
174211 let outputs = event.getOutputs ()
175212 do {
176- let address = // Get an address to transfer the funds
213+ let address = ldkManager ! . bdkManager . getAddress ( addressIndex : . new ) !
177214 let script = try Address (address : address).scriptPubkey ().toBytes ()
178- let res = ldkManager. keysManager .spendSpendableOutputs (
215+ let res = ldkManager! . myKeysManager .spendSpendableOutputs (
179216 descriptors : outputs,
180217 outputs : [],
181218 changeDestinationScript : script,
182219 feerateSatPer1000Weight : 1000 ,
183- locktime : nil
184- )
220+ locktime : nil )
185221 if res.isOk () {
186222 var txs: [[UInt8 ]] = []
187223 txs.append (res.getValue ()! )
188- ldkManager.broadcaster .broadcastTransactions (txs : txs)
224+ ldkManager! .broadcaster .broadcastTransactions (txs : txs)
189225 }
190226 } catch {
191227 print (error.localizedDescription )
0 commit comments