Browse Source

liquidity: add swap suggestions for threshold rule for loop out

pull/278/head
carla 4 months ago
parent
commit
8db6b32d74
No known key found for this signature in database GPG Key ID: 4CA7FE54A6213C91
4 changed files with 137 additions and 0 deletions
  1. +4
    -0
      liquidity/balances.go
  2. +26
    -0
      liquidity/suggestions.go
  3. +28
    -0
      liquidity/threshold_rule.go
  4. +79
    -0
      liquidity/threshold_rule_test.go

+ 4
- 0
liquidity/balances.go View File

@ -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
- 0
liquidity/suggestions.go View 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,
}
}

+ 28
- 0
liquidity/threshold_rule.go View File

@ -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.

+ 79
- 0
liquidity/threshold_rule_test.go View File

@ -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…
Cancel
Save