@@ -67,6 +67,129 @@ val createChannelResult = channelManager.create_channel(
6767 </template >
6868</CodeSwitcher >
6969
70+ # FundingGenerationReady Event Handling
71+
72+ At this point, an outbound channel has been initiated with your peer and it will appear in ` ChannelManager::list_channels ` . However, the channel is not yet funded. Once your peer accepts the channel, you will be notified with a ` FundingGenerationReady ` event. It's then your responsibility to construct the funding transaction and pass it to ChannelManager, which will broadcast it once it receives your channel counterparty's signature.
73+
74+
75+ <CodeSwitcher :languages =" {rust:'Rust', java:'Java', kotlin:'Kotlin'} " >
76+ <template v-slot:rust >
77+
78+ ``` rust
79+ // In the event handler passed to BackgroundProcessor::start
80+ match event {
81+ Event :: FundingGenerationReady {
82+ temporary_channel_id ,
83+ channel_value_satoshis ,
84+ output_script ,
85+ user_channel_id ,
86+ } => {
87+ // This is the same channel created earler.
88+ assert_eq! (event . user_channel_id, 42 );
89+
90+ // Construct the raw transaction with one output, that is paid the amount of the
91+ // channel.
92+ let network = bitcoin_bech32 :: constants :: Network :: Testnet ;
93+ let address = WitnessProgram :: from_scriptpubkey (& output_script [.. ], network )
94+ . unwrap (). to_address;
95+ let mut outputs = vec! [HashMap :: with_capacity (1 )];
96+ outputs [0 ]. insert (address , channel_value_satoshis as f64 / 100_000_000.0 );
97+ let raw_tx = bitcoind_client . create_raw_transaction (outputs ). await ;
98+
99+ // Have your wallet put the inputs into the transaction such that the output is
100+ // satisfied.
101+ let funded_tx = bitcoind_client . fund_raw_transaction (raw_tx ). await ;
102+ assert! (funded_tx . changepos == 0 || funded_tx . changepos == 1 );
103+
104+ // Sign the funding transaction and give it to ChannelManager to broadcast.
105+ let signed_tx = bitcoind_client . sign_raw_transaction_with_wallet (funded_tx . hex). await ;
106+ assert_eq! (signed_tx . complete, true );
107+ let final_tx : Transaction =
108+ encode :: deserialize (& hex_utils :: to_vec (& signed_tx . hex). unwrap ()). unwrap ();
109+ channel_manager . funding_transaction_generated (& temporary_channel_id , final_tx ). unwrap ();
110+ }
111+ // ...
112+ }
113+ ```
114+
115+ </template >
116+
117+ <template v-slot:java >
118+
119+ ``` java
120+ // After the peer responds with an `accept_channel` message, an
121+ // Event.FundingGenerationReady event will be generated.
122+
123+ // In the `handle_event` method of ChannelManagerPersister implementation
124+ if (e instanceof Event . FundingGenerationReady ) {
125+ Event . FundingGenerationReady event = (Event . FundingGenerationReady ) e;
126+ byte [] funding_scriptpubkey = event. output_script;
127+ long output_value = event. channel_value_satoshis;
128+
129+ // This is the same channel created earler
130+ assert event. user_channel_id == 42 ;
131+
132+ // The output is always a P2WSH:
133+ assert funding_scriptpubkey. length == 34 && funding_scriptpubkey[0 ] == 0 &&
134+ funding_scriptpubkey[1 ] == 32 ;
135+
136+ // Generate the funding transaction for the channel based on the channel amount
137+ // The following uses the bitcoinj library to do so, but you can use any
138+ // standard Bitcoin library for on-chain logic.
139+ NetworkParameters bitcoinj_net =
140+ NetworkParameters . fromID(NetworkParameters . ID_MAINNET );
141+ Transaction funding_tx = new Transaction (bitcoinj_net);
142+ funding_tx. addInput(new TransactionInput (bitcoinj_net, funding, new byte [0 ]));
143+ // Note that all inputs in the funding transaction MUST spend SegWit outputs
144+ // (and have witnesses)
145+ funding_tx. getInputs(). get(0 ). setWitness(new TransactionWitness (2 ));
146+ funding_tx. getInput(0 ). getWitness(). setPush(0 , new byte []{0x1 });
147+ funding_tx. addOutput(Coin . SATOSHI. multiply(output_value),
148+ new Script (funding_scriptpubkey));
149+
150+ // Give the funding transaction back to the ChannelManager.
151+ Result_NoneAPIErrorZ funding_res = channel_manager. funding_transaction_generated(
152+ event. temporary_channel_id, funding_tx. bitcoinSerialize());
153+ // funding_transaction_generated should only generate an error if the
154+ // transaction didn't meet the required format (or the counterparty already
155+ // closed the channel on us):
156+ assert funding_res instanceof Result_NoneAPIErrorZ . Result_NoneAPIErrorZ_OK ;
157+ }
158+ ```
159+
160+ </template >
161+
162+ <template v-slot:kotlin >
163+
164+ ``` kotlin
165+ // After the peer responds with an `accept_channel` message, an
166+ // Event.FundingGenerationReady event will be generated.
167+
168+ if (event is Event .FundingGenerationReady ) {
169+ val funding_spk = event.output_script
170+
171+ if (funding_spk.size == 34 && funding_spk[0 ].toInt() == 0 && funding_spk[1 ].toInt() == 32 ) {
172+ // Generate the funding transaction for the channel based on the channel amount
173+ // The following uses BDK for on-chain logic
174+ val rawTx = OnchainWallet .buildFundingTx(event.channel_value_satoshis, event.output_script)
175+
176+ channelManager.funding_transaction_generated(
177+ event.temporary_channel_id,
178+ event.counterparty_node_id,
179+ rawTx
180+ )
181+ }
182+ }
183+ ```
184+
185+ </template >
186+
187+
188+
189+
190+ </CodeSwitcher >
191+
192+
70193
71194
72195
0 commit comments