@@ -95,6 +95,10 @@ pub struct SwapParams {
9595 pub required_confirms : u32 ,
9696 /// User selected UTXOs (optional, for manual UTXO selection)
9797 pub manually_selected_outpoints : Option < Vec < OutPoint > > ,
98+ /// Optional list of maker addresses explicitly selected by the user for the swap.
99+ /// If set, the taker will only attempt to use these makers instead of selecting
100+ /// from the offerbook automatically.
101+ pub manually_selected_makers : Option < Vec < MakerAddress > > ,
98102}
99103
100104#[ derive( Clone ) ]
@@ -738,6 +742,13 @@ impl Taker {
738742
739743 /// Choose makers for the swap by negotiating with them
740744 fn choose_makers_for_swap ( & mut self , swap_params : SwapParams ) -> Result < ( ) , TakerError > {
745+ if let Some ( ref makers) = swap_params. manually_selected_makers {
746+ if makers. len ( ) != swap_params. maker_count {
747+ return Err ( TakerError :: General (
748+ "Number of manually selected makers must equal maker_count" . to_string ( ) ,
749+ ) ) ;
750+ }
751+ }
741752 // Find suitable maker asks for an offer from the makers
742753 let mut suitable_makers = self . find_suitable_makers ( & swap_params) ;
743754 log:: info!(
@@ -758,6 +769,9 @@ impl Taker {
758769
759770 // Set swap params early so they're available for SwapDetails
760771 self . ongoing_swap_state . swap_params = swap_params. clone ( ) ;
772+ if let Some ( manual_makers) = & swap_params. manually_selected_makers {
773+ return self . choose_manual_makers ( manual_makers) ;
774+ }
761775
762776 // Send SwapDetails message to all the makers
763777 // Receive the Ack or Nack message from the maker
@@ -881,7 +895,89 @@ impl Taker {
881895
882896 Ok ( ( ) )
883897 }
898+ fn choose_manual_makers ( & mut self , manual_makers : & [ MakerAddress ] ) -> Result < ( ) , TakerError > {
899+ for ( chain_position, maker_addr) in manual_makers. iter ( ) . enumerate ( ) {
900+ // Find maker in offerbook
901+ let maker = self
902+ . offerbook
903+ . active_makers ( & MakerProtocol :: Taproot )
904+ . into_iter ( )
905+ . find ( |oa| & oa. address == maker_addr)
906+ . ok_or_else ( || {
907+ TakerError :: General ( format ! ( "Maker {} not found in offerbook" , maker_addr) )
908+ } ) ?;
909+
910+ // Reject bad makers
911+ if self . offerbook . is_bad_maker ( & maker) {
912+ return Err ( TakerError :: General ( format ! (
913+ "Maker {} is marked as bad" ,
914+ maker. address
915+ ) ) ) ;
916+ }
884917
918+ // Perform the same GetOffer + SwapDetails handshake
919+ let get_offer_msg = GetOffer {
920+ id : self . ongoing_swap_state . id . clone ( ) ,
921+ protocol_version_min : 1 ,
922+ protocol_version_max : 1 ,
923+ number_of_transactions : 1 ,
924+ } ;
925+
926+ let response = self . send_to_maker_and_get_response (
927+ & maker. address ,
928+ TakerToMakerMessage :: GetOffer ( get_offer_msg) ,
929+ ) ?;
930+
931+ match response {
932+ MakerToTakerMessage :: RespOffer ( fresh_offer) => {
933+ let mut maker = maker. clone ( ) ;
934+ maker. offer . tweakable_point = fresh_offer. tweakable_point ;
935+
936+ let maker_timelock = REFUND_LOCKTIME
937+ + REFUND_LOCKTIME_STEP
938+ * ( self . ongoing_swap_state . swap_params . maker_count - chain_position - 1 )
939+ as u16 ;
940+
941+ let swap_details = SwapDetails {
942+ id : self . ongoing_swap_state . id . clone ( ) ,
943+ amount : self . ongoing_swap_state . swap_params . send_amount ,
944+ no_of_tx : self . ongoing_swap_state . swap_params . tx_count as u8 ,
945+ timelock : maker_timelock,
946+ } ;
947+
948+ let ack = self . send_to_maker_and_get_response (
949+ & maker. address ,
950+ TakerToMakerMessage :: SwapDetails ( swap_details) ,
951+ ) ?;
952+
953+ match ack {
954+ MakerToTakerMessage :: AckResponse ( AckResponse :: Ack ) => {
955+ self . ongoing_swap_state . chosen_makers . push ( maker) ;
956+ }
957+ _ => {
958+ return Err ( TakerError :: General ( format ! (
959+ "Maker {} rejected swap" ,
960+ maker. address
961+ ) ) ) ;
962+ }
963+ }
964+ }
965+ _ => {
966+ return Err ( TakerError :: General ( format ! (
967+ "Unexpected response from maker {}" ,
968+ maker. address
969+ ) ) ) ;
970+ }
971+ }
972+ }
973+
974+ // Init storage
975+ let n = self . ongoing_swap_state . chosen_makers . len ( ) ;
976+ self . ongoing_swap_state . maker_outgoing_privkeys = vec ! [ None ; n] ;
977+ self . ongoing_swap_state . maker_contract_txs = vec ! [ Vec :: new( ) ; n] ;
978+
979+ Ok ( ( ) )
980+ }
885981 /// Fetch offers from available makers
886982 /// This syncs the offerbook first and then returns a reference to it
887983 pub fn fetch_offers ( & mut self ) -> Result < OfferBook , TakerError > {
0 commit comments