From e3f049ae6f2e30226ba835d9ab6cff9b5f297bda Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Mon, 17 Feb 2025 10:34:04 +0100 Subject: [PATCH] liquidity: add asset swap info to swap builder --- liquidity/interface.go | 3 +- liquidity/liquidity.go | 1 + liquidity/loopin_builder.go | 3 +- liquidity/loopin_builder_test.go | 2 +- liquidity/loopout_builder.go | 68 ++++++++++++++++++++++++++++++-- 5 files changed, 71 insertions(+), 6 deletions(-) diff --git a/liquidity/interface.go b/liquidity/interface.go index 1da7e875..96c5b064 100644 --- a/liquidity/interface.go +++ b/liquidity/interface.go @@ -62,7 +62,8 @@ type swapBuilder interface { // is just for a dry run. buildSwap(ctx context.Context, peer route.Vertex, channels []lnwire.ShortChannelID, amount btcutil.Amount, - params Parameters) (swapSuggestion, error) + params Parameters, swapOpts ...buildSwapOption) (swapSuggestion, + error) } // swapSuggestion is an interface implemented by suggested swaps for our diff --git a/liquidity/liquidity.go b/liquidity/liquidity.go index 2d3b8b1d..504e56d0 100644 --- a/liquidity/liquidity.go +++ b/liquidity/liquidity.go @@ -637,6 +637,7 @@ func (m *Manager) dispatchBestEasyAutoloopSwap(ctx context.Context) error { suggestion, err := builder.buildSwap( ctx, channel.PubKeyBytes, outgoing, swapAmt, easyParams, + nil, ) if err != nil { return err diff --git a/liquidity/loopin_builder.go b/liquidity/loopin_builder.go index f887719e..91c8c307 100644 --- a/liquidity/loopin_builder.go +++ b/liquidity/loopin_builder.go @@ -84,7 +84,8 @@ func (b *loopInBuilder) inUse(traffic *swapTraffic, peer route.Vertex, // For loop in, we do not add the autoloop label for dry runs. func (b *loopInBuilder) buildSwap(ctx context.Context, pubkey route.Vertex, _ []lnwire.ShortChannelID, amount btcutil.Amount, - params Parameters) (swapSuggestion, error) { + params Parameters, swapOpts ...buildSwapOption) (swapSuggestion, + error) { quote, err := b.cfg.LoopInQuote(ctx, &loop.LoopInQuoteRequest{ Amount: amount, diff --git a/liquidity/loopin_builder_test.go b/liquidity/loopin_builder_test.go index 6d0af181..35990bd0 100644 --- a/liquidity/loopin_builder_test.go +++ b/liquidity/loopin_builder_test.go @@ -184,7 +184,7 @@ func TestLoopinBuildSwap(t *testing.T) { swap, err := builder.buildSwap( context.Background(), peer1, []lnwire.ShortChannelID{ chan1, - }, swapAmt, params, + }, swapAmt, params, nil, ) assert.Equal(t, testCase.expectedSwap, swap) assert.Equal(t, testCase.expectedErr, err) diff --git a/liquidity/loopout_builder.go b/liquidity/loopout_builder.go index b2c60404..8fbd3760 100644 --- a/liquidity/loopout_builder.go +++ b/liquidity/loopout_builder.go @@ -2,6 +2,7 @@ package liquidity import ( "context" + "encoding/hex" "github.com/btcsuite/btcd/btcutil" "github.com/lightninglabs/loop" @@ -84,6 +85,33 @@ func (b *loopOutBuilder) inUse(traffic *swapTraffic, peer route.Vertex, return nil } +type assetSwapInfo struct { + assetID string + peerPubkey []byte +} + +// buildSwapOpts contains the options for building a swap. +type buildSwapOpts struct { + assetSwap *assetSwapInfo +} + +// defaultBuildSwapOpts returns the default options for building a swap. +func defaultBuildSwapOpts() *buildSwapOpts { + return &buildSwapOpts{} +} + +// buildSwapOption is a functional option that can be passed to the buildSwap +// method. +type buildSwapOption func(*buildSwapOpts) + +// withAssetSwapInfo is an option to provide asset swap information to the +// builder. +func withAssetSwapInfo(assetSwapInfo *assetSwapInfo) buildSwapOption { + return func(o *buildSwapOpts) { + o.assetSwap = assetSwapInfo + } +} + // buildSwap creates a swap for the target peer/channels provided. The autoloop // boolean indicates whether this swap will actually be executed, because there // are some calls we can leave out if this swap is just for a dry run (ie, when @@ -94,14 +122,42 @@ func (b *loopOutBuilder) inUse(traffic *swapTraffic, peer route.Vertex, // dry-run, and we do not add the autoloop label to the recommended swap. func (b *loopOutBuilder) buildSwap(ctx context.Context, pubkey route.Vertex, channels []lnwire.ShortChannelID, amount btcutil.Amount, - params Parameters) (swapSuggestion, error) { + params Parameters, swapOpts ...buildSwapOption) (swapSuggestion, + error) { + + var ( + assetRfqRequest *loop.AssetRFQRequest + assetIDBytes []byte + err error + ) + + opts := defaultBuildSwapOpts() + for _, opt := range swapOpts { + opt(opts) + } + + initiator := getInitiator(params) + + if opts.assetSwap != nil { + assetSwap := opts.assetSwap + assetIDBytes, err = hex.DecodeString(assetSwap.assetID) + if err != nil { + return nil, err + } + assetRfqRequest = &loop.AssetRFQRequest{ + AssetId: assetIDBytes, + AssetEdgeNode: assetSwap.peerPubkey, + } + initiator += "-" + assetSwap.assetID + } quote, err := b.cfg.LoopOutQuote( ctx, &loop.LoopOutQuoteRequest{ Amount: amount, SweepConfTarget: params.SweepConfTarget, SwapPublicationDeadline: b.cfg.Clock.Now(), - Initiator: getInitiator(params), + Initiator: initiator, + AssetRFQRequest: assetRfqRequest, }, ) if err != nil { @@ -146,7 +202,13 @@ func (b *loopOutBuilder) buildSwap(ctx context.Context, pubkey route.Vertex, MaxSwapFee: quote.SwapFee, MaxPrepayAmount: quote.PrepayAmount, SweepConfTarget: params.SweepConfTarget, - Initiator: getInitiator(params), + Initiator: initiator, + } + + if opts.assetSwap != nil { + request.AssetId = assetIDBytes + request.AssetPrepayRfqId = quote.LoopOutRfq.PrepayRfqId + request.AssetSwapRfqId = quote.LoopOutRfq.SwapRfqId } if params.Autoloop {