Skip to content

Commit b3fe9a9

Browse files
committed
loopd: add instantout quote
1 parent ca8f91a commit b3fe9a9

File tree

3 files changed

+72
-0
lines changed

3 files changed

+72
-0
lines changed

instantout/manager.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import (
77
"sync"
88
"time"
99

10+
"github.com/btcsuite/btcd/btcutil"
1011
"github.com/lightninglabs/loop/instantout/reservation"
12+
"github.com/lightninglabs/loop/swapserverrpc"
1113
"github.com/lightningnetwork/lnd/lntypes"
1214
)
1315

@@ -199,3 +201,50 @@ func (m *Manager) GetActiveInstantOut(swapHash lntypes.Hash) (*FSM, error) {
199201

200202
return fsm, nil
201203
}
204+
205+
type Quote struct {
206+
// ServiceFee is the fee in sat that is paid to the loop service.
207+
ServiceFee btcutil.Amount
208+
209+
// OnChainFee is the estimated on chain fee in sat.
210+
OnChainFee btcutil.Amount
211+
}
212+
213+
// GetInstantOutQuote returns a quote for an instant out.
214+
func (m *Manager) GetInstantOutQuote(ctx context.Context,
215+
amt btcutil.Amount, numReservations int) (Quote, error) {
216+
217+
if numReservations <= 0 {
218+
return Quote{}, fmt.Errorf("no reservations selected")
219+
}
220+
221+
if amt <= 0 {
222+
return Quote{}, fmt.Errorf("no amount selected")
223+
}
224+
225+
// Get the service fee.
226+
quoteRes, err := m.cfg.InstantOutClient.GetInstantOutQuote(
227+
ctx, &swapserverrpc.GetInstantOutQuoteRequest{
228+
Amount: uint64(amt),
229+
},
230+
)
231+
if err != nil {
232+
return Quote{}, err
233+
}
234+
235+
// Get the offchain fee by getting the fee estimate from the lnd client
236+
// and multiplying it by the estimated sweepless sweep transaction.
237+
feeRate, err := m.cfg.Wallet.EstimateFeeRate(ctx, normalConfTarget)
238+
if err != nil {
239+
return Quote{}, err
240+
}
241+
242+
// The on chain chainFee is the chainFee rate times the estimated
243+
// sweepless sweep transaction size.
244+
chainFee := feeRate.FeeForWeight(sweeplessSweepWeight(numReservations))
245+
246+
return Quote{
247+
ServiceFee: btcutil.Amount(quoteRes.SwapFee),
248+
OnChainFee: chainFee,
249+
}, nil
250+
}

loopd/perms/perms.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,8 @@ var RequiredPermissions = map[string][]bakery.Op{
104104
Entity: "swap",
105105
Action: "execute",
106106
}},
107+
"/looprpc.SwapClient/InstantOutQuote": {{
108+
Entity: "swap",
109+
Action: "read",
110+
}},
107111
}

loopd/swapclient_server.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,25 @@ func (s *swapClientServer) InstantOut(ctx context.Context,
12091209
return res, nil
12101210
}
12111211

1212+
// InstantOutQuote returns a quote for an instant out swap with the provided
1213+
// parameters.
1214+
func (s *swapClientServer) InstantOutQuote(ctx context.Context,
1215+
req *clientrpc.InstantOutQuoteRequest) (
1216+
*clientrpc.InstantOutQuoteResponse, error) {
1217+
1218+
quote, err := s.instantOutManager.GetInstantOutQuote(
1219+
ctx, btcutil.Amount(req.Amt), int(req.NumReservations),
1220+
)
1221+
if err != nil {
1222+
return nil, err
1223+
}
1224+
1225+
return &clientrpc.InstantOutQuoteResponse{
1226+
ServiceFeeSat: int64(quote.ServiceFee),
1227+
SweepFeeSat: int64(quote.OnChainFee),
1228+
}, nil
1229+
}
1230+
12121231
func rpcAutoloopReason(reason liquidity.Reason) (clientrpc.AutoReason, error) {
12131232
switch reason {
12141233
case liquidity.ReasonNone:

0 commit comments

Comments
 (0)