@@ -34,8 +34,10 @@ import (
3434 "github.com/lightninglabs/loop/swap"
3535 "github.com/lightninglabs/loop/swapserverrpc"
3636 "github.com/lightninglabs/taproot-assets/rfqmath"
37+ "github.com/lightningnetwork/lnd/input"
3738 "github.com/lightningnetwork/lnd/lnrpc/walletrpc"
3839 "github.com/lightningnetwork/lnd/lntypes"
40+ "github.com/lightningnetwork/lnd/lnwallet"
3941 "github.com/lightningnetwork/lnd/queue"
4042 "github.com/lightningnetwork/lnd/routing/route"
4143 "github.com/lightningnetwork/lnd/zpay32"
@@ -843,21 +845,26 @@ func (s *swapClientServer) GetLoopInQuote(ctx context.Context,
843845 infof ("Loop in quote request received" )
844846
845847 var (
846- numDeposits = uint32 (len (req .DepositOutpoints ))
847- err error
848+ selectedAmount = btcutil .Amount (req .Amt )
849+ totalDepositAmount btcutil.Amount
850+ numDeposits = len (req .DepositOutpoints )
851+ err error
848852 )
849853
850854 htlcConfTarget , err := validateLoopInRequest (
851- req .ConfTarget , req .ExternalHtlc , numDeposits , req .Amt ,
855+ req .ConfTarget , req .ExternalHtlc , uint32 (numDeposits ),
856+ int64 (selectedAmount ),
852857 )
853858 if err != nil {
854859 return nil , err
855860 }
856861
857862 // Retrieve deposits to calculate their total value.
858863 var depositList * looprpc.ListStaticAddressDepositsResponse
859- amount := btcutil .Amount (req .Amt )
860- if len (req .DepositOutpoints ) > 0 {
864+
865+ // If deposits are selected, we need to retrieve them to calculate the
866+ // total value which we request a quote for.
867+ if numDeposits > 0 {
861868 depositList , err = s .ListStaticAddressDeposits (
862869 ctx , & looprpc.ListStaticAddressDepositsRequest {
863870 Outpoints : req .DepositOutpoints ,
@@ -872,20 +879,45 @@ func (s *swapClientServer) GetLoopInQuote(ctx context.Context,
872879 "deposit outpoints" )
873880 }
874881
875- // The requested amount should be 0 here if the request
876- // contained deposit outpoints.
877- if amount != 0 && len (depositList .FilteredDeposits ) > 0 {
878- return nil , fmt .Errorf ("amount should be 0 for " +
879- "deposit quotes" )
882+ if numDeposits != len (depositList .FilteredDeposits ) {
883+ return nil , fmt .Errorf ("expected %d deposits, got %d" ,
884+ numDeposits , len (depositList .FilteredDeposits ))
880885 }
881886
882887 // In case we quote for deposits we send the server both the
883- // total value and the number of deposits. This is so the server
884- // can probe the total amount and calculate the per input fee.
885- if amount == 0 && len (depositList .FilteredDeposits ) > 0 {
886- for _ , deposit := range depositList .FilteredDeposits {
887- amount += btcutil .Amount (deposit .Value )
888- }
888+ // selected value and the number of deposits. This is so the
889+ // server can probe the selected value and calculate the per
890+ // input fee.
891+ for _ , deposit := range depositList .FilteredDeposits {
892+ totalDepositAmount += btcutil .Amount (
893+ deposit .Value ,
894+ )
895+ }
896+
897+ // If the selected amount would leave a dust change output or
898+ // exceeds the total deposits value, we return an error.
899+ dustLimit := lnwallet .DustLimitForSize (input .P2TRSize )
900+ remainingAmount := totalDepositAmount - selectedAmount
901+ switch {
902+ case remainingAmount < 0 :
903+ return nil , fmt .Errorf ("selected amount %v exceeds " +
904+ "total deposit value %v" , selectedAmount ,
905+ totalDepositAmount )
906+
907+ case remainingAmount > 0 && remainingAmount < dustLimit :
908+ return nil , fmt .Errorf ("selected amount %v leaves " +
909+ "dust change %v" , selectedAmount ,
910+ totalDepositAmount )
911+
912+ default :
913+ // If the remaining amount is 0 or equal or greater than
914+ // the dust limit, we can proceed with the swap.
915+ }
916+
917+ // If the client didn't select an amount we quote for the total
918+ // deposits value.
919+ if selectedAmount == 0 {
920+ selectedAmount = totalDepositAmount
889921 }
890922 }
891923
@@ -912,14 +944,14 @@ func (s *swapClientServer) GetLoopInQuote(ctx context.Context,
912944 }
913945
914946 quote , err := s .impl .LoopInQuote (ctx , & loop.LoopInQuoteRequest {
915- Amount : amount ,
947+ Amount : selectedAmount ,
916948 HtlcConfTarget : htlcConfTarget ,
917949 ExternalHtlc : req .ExternalHtlc ,
918950 LastHop : lastHop ,
919951 RouteHints : routeHints ,
920952 Private : req .Private ,
921953 Initiator : defaultLoopdInitiator ,
922- NumDeposits : numDeposits ,
954+ NumDeposits : uint32 ( numDeposits ) ,
923955 })
924956 if err != nil {
925957 return nil , err
@@ -1762,6 +1794,7 @@ func (s *swapClientServer) StaticAddressLoopIn(ctx context.Context,
17621794 }
17631795
17641796 req := & loop.StaticAddressLoopInRequest {
1797+ SelectedAmount : btcutil .Amount (in .Amount ),
17651798 DepositOutpoints : in .Outpoints ,
17661799 MaxSwapFee : btcutil .Amount (in .MaxSwapFeeSatoshis ),
17671800 Label : in .Label ,
0 commit comments