Skip to content

Commit

Permalink
staticaddr: fractional loop-in amount
Browse files Browse the repository at this point in the history
  • Loading branch information
hieblmi committed Feb 20, 2025
1 parent 51bac8f commit 76e8edf
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 8 deletions.
2 changes: 2 additions & 0 deletions interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,8 @@ type StaticAddressLoopInRequest struct {
// swap payment. If the timeout is reached the swap will be aborted and
// the client can retry the swap if desired with different parameters.
PaymentTimeoutSeconds uint32

SelectedAmount btcutil.Amount
}

// LoopInTerms are the server terms on which it executes loop in swaps.
Expand Down
11 changes: 8 additions & 3 deletions staticaddr/loopin/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,14 @@ func (f *FSM) InitHtlcAction(ctx context.Context,
}

// Calculate the swap invoice amount. The server needs to pay us the
// sum of all deposits minus the fees that the server charges for the
// swap.
swapInvoiceAmt := f.loopIn.TotalDepositAmount() - f.loopIn.QuotedSwapFee
// swap amount minus the fees that the server charges for the swap. The
// swap amount is either the total value of the selected deposits, or
// the selected amount if a specific amount was requested.
swapAmount := f.loopIn.TotalDepositAmount()
if f.loopIn.SelectedAmount > 0 {
swapAmount = f.loopIn.SelectedAmount
}
swapInvoiceAmt := swapAmount - f.loopIn.QuotedSwapFee

// Generate random preimage.
var swapPreimage lntypes.Preimage
Expand Down
24 changes: 21 additions & 3 deletions staticaddr/loopin/loopin.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ type StaticAddressLoopIn struct {
// swap.
DepositOutpoints []string

SelectedAmount btcutil.Amount

// state is the current state of the swap.
state fsm.StateType

Expand Down Expand Up @@ -287,10 +289,18 @@ func (l *StaticAddressLoopIn) createHtlcTx(chainParams *chaincfg.Params,
weight := l.htlcWeight()
fee := feeRate.FeeForWeight(weight)

// Check if the server breaches our fee limits.
amt := float64(l.TotalDepositAmount())
feeLimit := btcutil.Amount(amt * maxFeePercentage)
// Determine the swap amount. If the user selected a specific amount, we
// use that and use the difference to the total deposit amount as the
// change.
swapAmt := float64(l.TotalDepositAmount())
var changeAmount btcutil.Amount
if l.SelectedAmount > 0 {
swapAmt = float64(l.SelectedAmount)
changeAmount = l.TotalDepositAmount() - l.SelectedAmount
}

// Check if the server breaches our fee limits.
feeLimit := btcutil.Amount(swapAmt * maxFeePercentage)
if fee > feeLimit {
return nil, fmt.Errorf("htlc tx fee %v exceeds max fee %v",
fee, feeLimit)
Expand All @@ -314,6 +324,14 @@ func (l *StaticAddressLoopIn) createHtlcTx(chainParams *chaincfg.Params,

msgTx.AddTxOut(sweepOutput)

// We expect change to be sent back to our static address output script.
if changeAmount > 0 {
msgTx.AddTxOut(&wire.TxOut{
Value: int64(changeAmount),
PkScript: l.AddressParams.PkScript,
})
}

return msgTx, nil
}

Expand Down
16 changes: 14 additions & 2 deletions staticaddr/loopin/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ import (
"github.com/lightninglabs/loop/staticaddr/deposit"
"github.com/lightninglabs/loop/swapserverrpc"
looprpc "github.com/lightninglabs/loop/swapserverrpc"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/routing/route"
)

Expand Down Expand Up @@ -205,8 +207,8 @@ func (m *Manager) Run(ctx context.Context, currentHeight uint32) error {
case request.respChan <- resp:

case <-ctx.Done():
// Noify subroutines that the main loop has been
// canceled.
// Notify subroutines that the main loop has
// been canceled.
close(m.exitChan)

return ctx.Err()
Expand Down Expand Up @@ -549,6 +551,15 @@ func (m *Manager) initiateLoopIn(ctx context.Context,
}
totalDepositAmount := tmp.TotalDepositAmount()

// If the selected amount would leave a dust change output or exceeds
// the total deposits value, we return an error.
dustLimit := lnwallet.DustLimitForSize(input.P2TRSize)
if totalDepositAmount-req.SelectedAmount < dustLimit {
return nil, fmt.Errorf("selected amount %v leaves "+
"dust or exceeds total deposit value %v",
req.SelectedAmount, totalDepositAmount)
}

// Check that the label is valid.
err := labels.Validate(req.Label)
if err != nil {
Expand Down Expand Up @@ -616,6 +627,7 @@ func (m *Manager) initiateLoopIn(ctx context.Context,
}

swap := &StaticAddressLoopIn{
SelectedAmount: req.SelectedAmount,
DepositOutpoints: req.DepositOutpoints,
Deposits: deposits,
Label: req.Label,
Expand Down

0 comments on commit 76e8edf

Please sign in to comment.