mirror of
https://github.com/lightninglabs/loop.git
synced 2026-08-13 12:33:03 +02:00
liquidity: add swap suggestions for threshold rule for loop out
This commit is contained in:
parent
cd8a7704af
commit
8db6b32d74
4 changed files with 137 additions and 0 deletions
|
|
@ -2,6 +2,7 @@ package liquidity
|
|||
|
||||
import (
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
)
|
||||
|
||||
// balances summarizes the state of the balances of a channel. Channel reserve,
|
||||
|
|
@ -15,4 +16,7 @@ type balances struct {
|
|||
|
||||
// outgoing is the local balance of the channel.
|
||||
outgoing btcutil.Amount
|
||||
|
||||
// channelID is the channel that has these balances.
|
||||
channelID lnwire.ShortChannelID
|
||||
}
|
||||
|
|
|
|||
26
liquidity/suggestions.go
Normal file
26
liquidity/suggestions.go
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
package liquidity
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
)
|
||||
|
||||
// LoopOutRecommendation contains the information required to recommend a loop
|
||||
// out.
|
||||
type LoopOutRecommendation struct {
|
||||
// Amount is the total amount to swap.
|
||||
Amount btcutil.Amount
|
||||
|
||||
// Channel is the target outgoing channel.
|
||||
Channel lnwire.ShortChannelID
|
||||
}
|
||||
|
||||
// newLoopOutRecommendation creates a new loop out swap.
|
||||
func newLoopOutRecommendation(amount btcutil.Amount,
|
||||
channelID lnwire.ShortChannelID) *LoopOutRecommendation {
|
||||
|
||||
return &LoopOutRecommendation{
|
||||
Amount: amount,
|
||||
Channel: channelID,
|
||||
}
|
||||
}
|
||||
|
|
@ -62,6 +62,34 @@ func (r *ThresholdRule) validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// suggestSwap suggests a swap based on the liquidity thresholds configured,
|
||||
// returning nil if no swap is recommended.
|
||||
func (r *ThresholdRule) suggestSwap(channel *balances,
|
||||
outRestrictions *Restrictions) *LoopOutRecommendation {
|
||||
|
||||
// Examine our total balance and required ratios to decide whether we
|
||||
// need to swap.
|
||||
amount := loopOutSwapAmount(
|
||||
channel, r.MinimumIncoming, r.MinimumOutgoing,
|
||||
)
|
||||
|
||||
// Limit our swap amount by the minimum/maximum thresholds set.
|
||||
switch {
|
||||
case amount < outRestrictions.Minimum:
|
||||
return nil
|
||||
|
||||
case amount > outRestrictions.Maximum:
|
||||
return newLoopOutRecommendation(
|
||||
outRestrictions.Maximum, channel.channelID,
|
||||
)
|
||||
|
||||
default:
|
||||
return newLoopOutRecommendation(
|
||||
amount, channel.channelID,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// loopOutSwapAmount determines whether we can perform a loop out swap, and
|
||||
// returns the amount we need to swap to reach the desired liquidity balance
|
||||
// specified by the incoming and outgoing thresholds.
|
||||
|
|
|
|||
|
|
@ -174,3 +174,82 @@ func TestLoopOutAmount(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestSuggestSwaps tests swap suggestions for the threshold rule. It does not
|
||||
// many different values because we have separate tests for swap amount
|
||||
// calculation.
|
||||
func TestSuggestSwap(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
rule *ThresholdRule
|
||||
channel *balances
|
||||
outRestrictions *Restrictions
|
||||
swap *LoopOutRecommendation
|
||||
}{
|
||||
{
|
||||
name: "liquidity ok",
|
||||
rule: NewThresholdRule(10, 10),
|
||||
outRestrictions: NewRestrictions(10, 100),
|
||||
channel: &balances{
|
||||
capacity: 100,
|
||||
incoming: 50,
|
||||
outgoing: 50,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "loop out",
|
||||
rule: NewThresholdRule(40, 40),
|
||||
outRestrictions: NewRestrictions(10, 100),
|
||||
channel: &balances{
|
||||
capacity: 100,
|
||||
incoming: 0,
|
||||
outgoing: 100,
|
||||
},
|
||||
swap: &LoopOutRecommendation{Amount: 50},
|
||||
},
|
||||
{
|
||||
name: "amount below minimum",
|
||||
rule: NewThresholdRule(40, 40),
|
||||
outRestrictions: NewRestrictions(200, 300),
|
||||
channel: &balances{
|
||||
capacity: 100,
|
||||
incoming: 0,
|
||||
outgoing: 100,
|
||||
},
|
||||
swap: nil,
|
||||
},
|
||||
{
|
||||
name: "amount above maximum",
|
||||
rule: NewThresholdRule(40, 40),
|
||||
outRestrictions: NewRestrictions(10, 20),
|
||||
channel: &balances{
|
||||
capacity: 100,
|
||||
incoming: 0,
|
||||
outgoing: 100,
|
||||
},
|
||||
swap: &LoopOutRecommendation{Amount: 20},
|
||||
},
|
||||
{
|
||||
name: "loop in",
|
||||
rule: NewThresholdRule(10, 10),
|
||||
outRestrictions: NewRestrictions(10, 100),
|
||||
channel: &balances{
|
||||
capacity: 100,
|
||||
incoming: 100,
|
||||
outgoing: 0,
|
||||
},
|
||||
swap: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
test := test
|
||||
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
swap := test.rule.suggestSwap(
|
||||
test.channel, test.outRestrictions,
|
||||
)
|
||||
require.Equal(t, test.swap, swap)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue