@@ -36,8 +36,10 @@ import (
3636 "github.com/lightninglabs/loop/swap"
3737 "github.com/lightninglabs/loop/swapserverrpc"
3838 "github.com/lightninglabs/taproot-assets/rfqmath"
39+ "github.com/lightningnetwork/lnd/input"
3940 "github.com/lightningnetwork/lnd/lnrpc/walletrpc"
4041 "github.com/lightningnetwork/lnd/lntypes"
42+ "github.com/lightningnetwork/lnd/lnwallet"
4143 "github.com/lightningnetwork/lnd/queue"
4244 "github.com/lightningnetwork/lnd/routing/route"
4345 "github.com/lightningnetwork/lnd/zpay32"
@@ -884,21 +886,26 @@ func (s *swapClientServer) GetLoopInQuote(ctx context.Context,
884886 infof ("Loop in quote request received" )
885887
886888 var (
887- numDeposits = uint32 (len (req .DepositOutpoints ))
888- err error
889+ selectedAmount = btcutil .Amount (req .Amt )
890+ totalDepositAmount btcutil.Amount
891+ numDeposits = len (req .DepositOutpoints )
892+ err error
889893 )
890894
891895 htlcConfTarget , err := validateLoopInRequest (
892- req .ConfTarget , req .ExternalHtlc , numDeposits , req .Amt ,
896+ req .ConfTarget , req .ExternalHtlc , uint32 (numDeposits ),
897+ int64 (selectedAmount ),
893898 )
894899 if err != nil {
895900 return nil , err
896901 }
897902
898903 // Retrieve deposits to calculate their total value.
899904 var depositList * looprpc.ListStaticAddressDepositsResponse
900- amount := btcutil .Amount (req .Amt )
901- if len (req .DepositOutpoints ) > 0 {
905+
906+ // If deposits are selected, we need to retrieve them to calculate the
907+ // total value which we request a quote for.
908+ if numDeposits > 0 {
902909 depositList , err = s .ListStaticAddressDeposits (
903910 ctx , & looprpc.ListStaticAddressDepositsRequest {
904911 Outpoints : req .DepositOutpoints ,
@@ -913,20 +920,45 @@ func (s *swapClientServer) GetLoopInQuote(ctx context.Context,
913920 "deposit outpoints" )
914921 }
915922
916- // The requested amount should be 0 here if the request
917- // contained deposit outpoints.
918- if amount != 0 && len (depositList .FilteredDeposits ) > 0 {
919- return nil , fmt .Errorf ("amount should be 0 for " +
920- "deposit quotes" )
923+ if numDeposits != len (depositList .FilteredDeposits ) {
924+ return nil , fmt .Errorf ("expected %d deposits, got %d" ,
925+ numDeposits , len (depositList .FilteredDeposits ))
921926 }
922927
923928 // In case we quote for deposits we send the server both the
924- // total value and the number of deposits. This is so the server
925- // can probe the total amount and calculate the per input fee.
926- if amount == 0 && len (depositList .FilteredDeposits ) > 0 {
927- for _ , deposit := range depositList .FilteredDeposits {
928- amount += btcutil .Amount (deposit .Value )
929- }
929+ // selected value and the number of deposits. This is so the
930+ // server can probe the selected value and calculate the per
931+ // input fee.
932+ for _ , deposit := range depositList .FilteredDeposits {
933+ totalDepositAmount += btcutil .Amount (
934+ deposit .Value ,
935+ )
936+ }
937+
938+ // If the selected amount would leave a dust change output or
939+ // exceeds the total deposits value, we return an error.
940+ dustLimit := lnwallet .DustLimitForSize (input .P2TRSize )
941+ remainingAmount := totalDepositAmount - selectedAmount
942+ switch {
943+ case remainingAmount < 0 :
944+ return nil , fmt .Errorf ("selected amount %v exceeds " +
945+ "total deposit value %v" , selectedAmount ,
946+ totalDepositAmount )
947+
948+ case remainingAmount > 0 && remainingAmount < dustLimit :
949+ return nil , fmt .Errorf ("selected amount %v leaves " +
950+ "dust change %v" , selectedAmount ,
951+ totalDepositAmount )
952+
953+ default :
954+ // If the remaining amount is 0 or equal or greater than
955+ // the dust limit, we can proceed with the swap.
956+ }
957+
958+ // If the client didn't select an amount we quote for the total
959+ // deposits value.
960+ if selectedAmount == 0 {
961+ selectedAmount = totalDepositAmount
930962 }
931963 }
932964
@@ -953,14 +985,14 @@ func (s *swapClientServer) GetLoopInQuote(ctx context.Context,
953985 }
954986
955987 quote , err := s .impl .LoopInQuote (ctx , & loop.LoopInQuoteRequest {
956- Amount : amount ,
988+ Amount : selectedAmount ,
957989 HtlcConfTarget : htlcConfTarget ,
958990 ExternalHtlc : req .ExternalHtlc ,
959991 LastHop : lastHop ,
960992 RouteHints : routeHints ,
961993 Private : req .Private ,
962994 Initiator : defaultLoopdInitiator ,
963- NumDeposits : numDeposits ,
995+ NumDeposits : uint32 ( numDeposits ) ,
964996 })
965997 if err != nil {
966998 return nil , err
@@ -1804,6 +1836,7 @@ func (s *swapClientServer) StaticAddressLoopIn(ctx context.Context,
18041836 }
18051837
18061838 req := & loop.StaticAddressLoopInRequest {
1839+ SelectedAmount : btcutil .Amount (in .Amount ),
18071840 DepositOutpoints : in .Outpoints ,
18081841 MaxSwapFee : btcutil .Amount (in .MaxSwapFeeSatoshis ),
18091842 Label : in .Label ,
0 commit comments