mirror of
https://github.com/lightninglabs/loop
synced 2024-11-11 13:11:12 +00:00
liquidity: add swap suggestions endpoint to manager
This commit is contained in:
parent
8db6b32d74
commit
340766fbb5
@ -2,6 +2,7 @@ package liquidity
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
|
"github.com/lightninglabs/lndclient"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -20,3 +21,13 @@ type balances struct {
|
|||||||
// channelID is the channel that has these balances.
|
// channelID is the channel that has these balances.
|
||||||
channelID lnwire.ShortChannelID
|
channelID lnwire.ShortChannelID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newBalances creates a balances struct from lndclient channel information.
|
||||||
|
func newBalances(info lndclient.ChannelInfo) *balances {
|
||||||
|
return &balances{
|
||||||
|
capacity: info.Capacity,
|
||||||
|
incoming: info.RemoteBalance,
|
||||||
|
outgoing: info.LocalBalance,
|
||||||
|
channelID: lnwire.NewShortChanIDFromInt(info.ChannelID),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/lightninglabs/lndclient"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -23,6 +24,9 @@ type Config struct {
|
|||||||
// LoopOutRestrictions returns the restrictions that the server applies
|
// LoopOutRestrictions returns the restrictions that the server applies
|
||||||
// to loop out swaps.
|
// to loop out swaps.
|
||||||
LoopOutRestrictions func(ctx context.Context) (*Restrictions, error)
|
LoopOutRestrictions func(ctx context.Context) (*Restrictions, error)
|
||||||
|
|
||||||
|
// Lnd provides us with access to lnd's main rpc.
|
||||||
|
Lnd lndclient.LightningClient
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parameters is a set of parameters provided by the user which guide
|
// Parameters is a set of parameters provided by the user which guide
|
||||||
@ -131,3 +135,51 @@ func cloneParameters(params Parameters) Parameters {
|
|||||||
|
|
||||||
return paramCopy
|
return paramCopy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SuggestSwaps returns a set of swap suggestions based on our current liquidity
|
||||||
|
// balance for the set of rules configured for the manager, failing if there are
|
||||||
|
// no rules set.
|
||||||
|
func (m *Manager) SuggestSwaps(ctx context.Context) (
|
||||||
|
[]*LoopOutRecommendation, error) {
|
||||||
|
|
||||||
|
m.paramsLock.Lock()
|
||||||
|
defer m.paramsLock.Unlock()
|
||||||
|
|
||||||
|
// If we have no rules set, exit early to avoid unnecessary calls to
|
||||||
|
// lnd and the server.
|
||||||
|
if len(m.params.ChannelRules) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
channels, err := m.cfg.Lnd.ListChannels(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the current server side restrictions.
|
||||||
|
outRestrictions, err := m.cfg.LoopOutRestrictions(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var suggestions []*LoopOutRecommendation
|
||||||
|
for _, channel := range channels {
|
||||||
|
channelID := lnwire.NewShortChanIDFromInt(channel.ChannelID)
|
||||||
|
rule, ok := m.params.ChannelRules[channelID]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
balance := newBalances(channel)
|
||||||
|
|
||||||
|
suggestion := rule.suggestSwap(balance, outRestrictions)
|
||||||
|
|
||||||
|
// We can have nil suggestions in the case where no action is
|
||||||
|
// required, so only add non-nil suggestions.
|
||||||
|
if suggestion != nil {
|
||||||
|
suggestions = append(suggestions, suggestion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return suggestions, nil
|
||||||
|
}
|
||||||
|
@ -4,6 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/lightninglabs/lndclient"
|
||||||
|
"github.com/lightninglabs/loop/test"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@ -16,6 +18,7 @@ func newTestConfig() *Config {
|
|||||||
|
|
||||||
return NewRestrictions(1, 10000), nil
|
return NewRestrictions(1, 10000), nil
|
||||||
},
|
},
|
||||||
|
Lnd: test.NewMockLnd().Client,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,3 +67,89 @@ func TestParameters(t *testing.T) {
|
|||||||
err = manager.SetParameters(expected)
|
err = manager.SetParameters(expected)
|
||||||
require.Equal(t, ErrZeroChannelID, err)
|
require.Equal(t, ErrZeroChannelID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestSuggestSwaps tests getting of swap suggestions.
|
||||||
|
func TestSuggestSwaps(t *testing.T) {
|
||||||
|
var (
|
||||||
|
chanID1 = lnwire.NewShortChanIDFromInt(1)
|
||||||
|
chanID2 = lnwire.NewShortChanIDFromInt(2)
|
||||||
|
)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
channels []lndclient.ChannelInfo
|
||||||
|
parameters Parameters
|
||||||
|
swaps []*LoopOutRecommendation
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "no rules",
|
||||||
|
channels: nil,
|
||||||
|
parameters: newParameters(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "loop out",
|
||||||
|
channels: []lndclient.ChannelInfo{
|
||||||
|
{
|
||||||
|
ChannelID: 1,
|
||||||
|
Capacity: 1000,
|
||||||
|
LocalBalance: 1000,
|
||||||
|
RemoteBalance: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
parameters: Parameters{
|
||||||
|
ChannelRules: map[lnwire.ShortChannelID]*ThresholdRule{
|
||||||
|
chanID1: NewThresholdRule(
|
||||||
|
10, 10,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
swaps: []*LoopOutRecommendation{
|
||||||
|
{
|
||||||
|
Channel: chanID1,
|
||||||
|
Amount: 500,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no rule for channel",
|
||||||
|
channels: []lndclient.ChannelInfo{
|
||||||
|
{
|
||||||
|
ChannelID: 1,
|
||||||
|
Capacity: 1000,
|
||||||
|
LocalBalance: 0,
|
||||||
|
RemoteBalance: 1000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
parameters: Parameters{
|
||||||
|
ChannelRules: map[lnwire.ShortChannelID]*ThresholdRule{
|
||||||
|
chanID2: NewThresholdRule(10, 10),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
swaps: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range tests {
|
||||||
|
testCase := testCase
|
||||||
|
|
||||||
|
t.Run(testCase.name, func(t *testing.T) {
|
||||||
|
cfg := newTestConfig()
|
||||||
|
|
||||||
|
// Create a mock lnd with the set of channels set in our
|
||||||
|
// test case.
|
||||||
|
mock := test.NewMockLnd()
|
||||||
|
mock.Channels = testCase.channels
|
||||||
|
cfg.Lnd = mock.Client
|
||||||
|
|
||||||
|
manager := NewManager(cfg)
|
||||||
|
|
||||||
|
// Set our test case parameters.
|
||||||
|
err := manager.SetParameters(testCase.parameters)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
swaps, err := manager.SuggestSwaps(context.Background())
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, testCase.swaps, swaps)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -46,6 +46,7 @@ func getLiquidityManager(client *loop.Client) *liquidity.Manager {
|
|||||||
outTerms.MinSwapAmount, outTerms.MaxSwapAmount,
|
outTerms.MinSwapAmount, outTerms.MaxSwapAmount,
|
||||||
), nil
|
), nil
|
||||||
},
|
},
|
||||||
|
Lnd: client.LndServices.Client,
|
||||||
}
|
}
|
||||||
|
|
||||||
return liquidity.NewManager(mngrCfg)
|
return liquidity.NewManager(mngrCfg)
|
||||||
|
Loading…
Reference in New Issue
Block a user