@@ -2,8 +2,8 @@ use bdk_bitcoind_rpc::Emitter;
2
2
use bdk_chain:: { bdk_core, local_chain:: LocalChain , Balance } ;
3
3
use bdk_testenv:: { bitcoincore_rpc:: RpcApi , TestEnv } ;
4
4
use bdk_tx:: {
5
- filter_unspendable_now, group_by_spk, no_grouping, ChangePolicyType , CoinControl , Output ,
6
- PsbtParams , RbfSet , Selector , SelectorParams , Signer ,
5
+ filter_unspendable_now, group_by_spk, no_grouping, selection_algorithm_lowest_fee_bnb ,
6
+ ChangePolicyType , CoinControl , Output , PsbtParams , RbfSet , Selector , SelectorParams , Signer ,
7
7
} ;
8
8
use bitcoin:: { absolute, key:: Secp256k1 , Address , Amount , BlockHash , FeeRate , Sequence , Txid } ;
9
9
use miniscript:: { plan:: Assets , Descriptor , DescriptorPublicKey , ForEachKey } ;
@@ -138,42 +138,29 @@ fn synopsis() -> anyhow::Result<()> {
138
138
println ! ( "balance: {}" , wallet. balance( ) ) ;
139
139
140
140
let ( tip_height, tip_time) = wallet. tip_info ( env. rpc_client ( ) ) ?;
141
+ let longterm_feerate = FeeRate :: from_sat_per_vb_unchecked ( 1 ) ;
141
142
142
143
let recipient_addr = env
143
144
. rpc_client ( )
144
145
. get_new_address ( None , None ) ?
145
146
. assume_checked ( ) ;
146
147
147
148
// okay now create tx.
148
- let coin_control = wallet. coin_control ( None ) ?;
149
- println ! ( "excluded: {:?}" , coin_control. excluded( ) ) ;
150
- let input_candidates =
151
- coin_control. into_candidates ( group_by_spk ( ) , filter_unspendable_now ( tip_height, tip_time) ) ;
152
- println ! (
153
- ":: input candidate groups: {}" ,
154
- input_candidates. groups( ) . len( )
155
- ) ;
156
-
157
- let longterm_feerate = FeeRate :: from_sat_per_vb_unchecked ( 1 ) ;
158
- let mut selector = Selector :: new (
159
- & input_candidates,
160
- SelectorParams :: new (
161
- FeeRate :: from_sat_per_vb_unchecked ( 10 ) ,
162
- vec ! [ Output :: with_script(
163
- recipient_addr. script_pubkey( ) ,
164
- Amount :: from_sat( 21_000_000 ) ,
165
- ) ] ,
166
- internal. at_derivation_index ( 0 ) ?,
167
- bdk_tx:: ChangePolicyType :: NoDustAndLeastWaste { longterm_feerate } ,
168
- ) ,
169
- ) ?;
170
- println ! (
171
- "bnb score: {}" ,
172
- selector. select_for_lowest_fee( longterm_feerate, 100_000 ) ?
173
- ) ;
174
- let selection = selector
175
- . try_finalize ( )
176
- . ok_or ( anyhow:: anyhow!( "failed to find solution" ) ) ?;
149
+ let selection = wallet
150
+ . coin_control ( None ) ?
151
+ . into_candidates ( group_by_spk ( ) , filter_unspendable_now ( tip_height, tip_time) )
152
+ . into_selection (
153
+ selection_algorithm_lowest_fee_bnb ( longterm_feerate, 100_000 ) ,
154
+ SelectorParams :: new (
155
+ FeeRate :: from_sat_per_vb_unchecked ( 10 ) ,
156
+ vec ! [ Output :: with_script(
157
+ recipient_addr. script_pubkey( ) ,
158
+ Amount :: from_sat( 21_000_000 ) ,
159
+ ) ] ,
160
+ internal. at_derivation_index ( 0 ) ?,
161
+ bdk_tx:: ChangePolicyType :: NoDustAndLeastWaste { longterm_feerate } ,
162
+ ) ,
163
+ ) ?;
177
164
178
165
let mut psbt = selection. create_psbt ( PsbtParams {
179
166
fallback_sequence : Sequence :: ENABLE_RBF_NO_LOCKTIME ,
@@ -227,7 +214,7 @@ fn synopsis() -> anyhow::Result<()> {
227
214
. expect ( "must have no missing prevouts" ) ;
228
215
229
216
// Input candidates.
230
- let candidates = wallet
217
+ let selection = wallet
231
218
// We canonicalize first.
232
219
// This ensures all input candidates are of a consistent UTXO set.
233
220
// The canonicalization is modified by excluding the original txs and their
@@ -242,34 +229,26 @@ fn synopsis() -> anyhow::Result<()> {
242
229
// need to guarantee atleast one prevout of each original tx is picked, otherwise we
243
230
// may not actually replace the original txs.
244
231
// The policy used here is to choose the largest value prevout of each original tx.
245
- . with_must_select_policy ( rbf_set. must_select_largest_input_per_tx ( ) )
246
- . expect ( "this cannot fail here" ) ;
247
-
248
- // Now we actually do coin selection.
249
- let mut selector = Selector :: new (
250
- & candidates,
251
- SelectorParams {
252
- // This is just a lower-bound feerate. The actual result will be much higher to
253
- // satisfy mempool-replacement policy.
254
- target_feerate : FeeRate :: from_sat_per_vb_unchecked ( 1 ) ,
255
- // We cancel the tx by specifying no target outputs. This way, all excess returns
256
- // to our change output (unless if the prevouts picked are so small that it will
257
- // be less wasteful to have no output, however that will not be a valid tx).
258
- // If you only want to fee bump, put the original txs' recipients here.
259
- target_outputs : vec ! [ ] ,
260
- change_descriptor : internal. at_derivation_index ( 1 ) ?,
261
- change_policy : ChangePolicyType :: NoDustAndLeastWaste { longterm_feerate } ,
262
- // This ensures that we satisfy mempool-replacement policy rules 4 and 6.
263
- replace : Some ( rbf_set. selector_rbf_params ( ) ) ,
264
- } ,
265
- ) ?;
266
- println ! (
267
- "replacement tx score: {}" ,
268
- selector. select_for_lowest_fee( longterm_feerate, 100_000 ) ?
269
- ) ;
270
- let selection = selector
271
- . try_finalize ( )
272
- . expect ( "failed to finalize replacement tx" ) ;
232
+ . with_must_select_policy ( rbf_set. must_select_largest_input_per_tx ( ) ) ?
233
+ // Do coin selection.
234
+ . into_selection (
235
+ // Coin selection algorithm.
236
+ selection_algorithm_lowest_fee_bnb ( longterm_feerate, 100_000 ) ,
237
+ SelectorParams {
238
+ // This is just a lower-bound feerate. The actual result will be much higher to
239
+ // satisfy mempool-replacement policy.
240
+ target_feerate : FeeRate :: from_sat_per_vb_unchecked ( 1 ) ,
241
+ // We cancel the tx by specifying no target outputs. This way, all excess returns
242
+ // to our change output (unless if the prevouts picked are so small that it will
243
+ // be less wasteful to have no output, however that will not be a valid tx).
244
+ // If you only want to fee bump, put the original txs' recipients here.
245
+ target_outputs : vec ! [ ] ,
246
+ change_descriptor : internal. at_derivation_index ( 1 ) ?,
247
+ change_policy : ChangePolicyType :: NoDustAndLeastWaste { longterm_feerate } ,
248
+ // This ensures that we satisfy mempool-replacement policy rules 4 and 6.
249
+ replace : Some ( rbf_set. selector_rbf_params ( ) ) ,
250
+ } ,
251
+ ) ?;
273
252
274
253
let mut psbt = selection. create_psbt ( PsbtParams {
275
254
// Not strictly necessary, but it may help us replace this replacement faster.
0 commit comments