Skip to content

Commit c0ea458

Browse files
committed
loopout: add asset id and edge node
1 parent a0712e2 commit c0ea458

File tree

5 files changed

+126
-5
lines changed

5 files changed

+126
-5
lines changed

client.go

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,40 @@ func (s *Client) resumeSwaps(ctx context.Context,
506506
func (s *Client) LoopOut(globalCtx context.Context,
507507
request *OutRequest) (*LoopOutSwapInfo, error) {
508508

509+
if request.AssetId != nil {
510+
if request.AssetEdgeNode == nil {
511+
return nil, errors.New("asset edge node must be set " +
512+
"when using an asset id")
513+
}
514+
// Verify that if we have an asset id set, we have a valid asset
515+
// client to use.
516+
if s.assetClient == nil {
517+
return nil, errors.New("asset client must be set " +
518+
"when using an asset id")
519+
}
520+
521+
rfq, err := s.assetClient.GetRfqForAsset(
522+
globalCtx, request.AssetAmount, request.AssetId,
523+
request.AssetEdgeNode,
524+
)
525+
if err != nil {
526+
return nil, err
527+
}
528+
529+
satAmt, err := assets.GetSatAmtFromRfq(
530+
request.AssetAmount, rfq.BidAssetRate,
531+
)
532+
if err != nil {
533+
return nil, err
534+
}
535+
536+
log.Infof("LoopOut %v sats to %v (channels: %v) with asset %x",
537+
satAmt, request.DestAddr, request.OutgoingChanSet,
538+
request.AssetId,
539+
)
540+
request.Amount = satAmt
541+
}
542+
509543
log.Infof("LoopOut %v to %v (channels: %v)",
510544
request.Amount, request.DestAddr, request.OutgoingChanSet,
511545
)
@@ -530,6 +564,7 @@ func (s *Client) LoopOut(globalCtx context.Context,
530564

531565
// Create a new swap object for this swap.
532566
swapCfg := newSwapConfig(s.lndServices, s.Store, s.Server, s.assetClient)
567+
533568
initResult, err := newLoopOutSwap(
534569
globalCtx, swapCfg, initiationHeight, request,
535570
)
@@ -579,11 +614,31 @@ func (s *Client) LoopOutQuote(ctx context.Context,
579614
return nil, err
580615
}
581616

582-
if request.Amount < terms.MinSwapAmount {
617+
invoiceAmountSat := request.Amount
618+
// If we use an Asset we'll rfq to check if the sat amount meets the
619+
// min swap amount criteria.
620+
if request.AssetId != nil {
621+
rfq, err := s.assetClient.GetRfqForAsset(
622+
ctx, request.Amount, request.AssetId,
623+
request.AssetEdgeNode,
624+
)
625+
if err != nil {
626+
return nil, err
627+
}
628+
629+
invoiceAmountSat, err = assets.GetSatAmtFromRfq(
630+
request.Amount, rfq.BidAssetRate,
631+
)
632+
if err != nil {
633+
return nil, err
634+
}
635+
}
636+
637+
if invoiceAmountSat < terms.MinSwapAmount {
583638
return nil, ErrSwapAmountTooLow
584639
}
585640

586-
if request.Amount > terms.MaxSwapAmount {
641+
if invoiceAmountSat > terms.MaxSwapAmount {
587642
return nil, ErrSwapAmountTooHigh
588643
}
589644

@@ -594,7 +649,7 @@ func (s *Client) LoopOutQuote(ctx context.Context,
594649
}
595650

596651
quote, err := s.Server.GetLoopOutQuote(
597-
ctx, request.Amount, expiry, request.SwapPublicationDeadline,
652+
ctx, invoiceAmountSat, expiry, request.SwapPublicationDeadline,
598653
request.Initiator,
599654
)
600655
if err != nil {
@@ -613,6 +668,7 @@ func (s *Client) LoopOutQuote(ctx context.Context,
613668
MinerFee: minerFee,
614669
PrepayAmount: quote.PrepayAmount,
615670
SwapPaymentDest: quote.SwapPaymentDest,
671+
InvoiceAmtSat: invoiceAmountSat,
616672
}, nil
617673
}
618674

interface.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,20 @@ type OutRequest struct {
9898
// the configured maximum payment timeout) the total time spent may be
9999
// a multiple of this value.
100100
PaymentTimeout time.Duration
101+
102+
// AssetId is an optional asset id that can be used to specify the asset
103+
// that will be used to pay for the swap. If this is set, a connection
104+
// to a tapd server is required to pay for the asset.
105+
AssetId []byte
106+
107+
// AssetEdgeNode is an optional Parameter that is required should the
108+
// tapd server have multiple channels with different peers for the given
109+
// asset id.
110+
AssetEdgeNode []byte
111+
112+
// AssetAmount is the amount of the asset that will be used to pay for
113+
// the swap. This is only set if the asset id is set.
114+
AssetAmount btcutil.Amount
101115
}
102116

103117
// Out contains the full details of a loop out request. This includes things
@@ -145,6 +159,12 @@ type LoopOutQuoteRequest struct {
145159
// initiated the swap (loop CLI, autolooper, LiT UI and so on) and is
146160
// appended to the user agent string.
147161
Initiator string
162+
163+
// AssetId is the asset that we'll quote for.
164+
AssetId []byte
165+
166+
// AssetEdgeNode is the pubkey of the peer that we'll quote for.
167+
AssetEdgeNode []byte
148168
}
149169

150170
// LoopOutTerms are the server terms on which it executes swaps.
@@ -181,6 +201,9 @@ type LoopOutQuote struct {
181201
// SwapPaymentDest is the node pubkey where to swap payment needs to be
182202
// sent to.
183203
SwapPaymentDest [33]byte
204+
205+
// InvoiceAmtSat is the amount of the invoice in satoshis.
206+
InvoiceAmtSat btcutil.Amount
184207
}
185208

186209
// LoopInRequest contains the required parameters for the swap.

loopd/swapclient_server.go

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,25 @@ func (s *swapClientServer) LoopOut(ctx context.Context,
208208
PaymentTimeout: paymentTimeout,
209209
}
210210

211+
// If the asset id is set, we need to set the asset amount and asset id
212+
// in the request.
213+
if in.AssetInfo != nil {
214+
if in.AssetInfo.AssetId == nil ||
215+
in.AssetInfo.AssetEdgeNode == nil {
216+
return nil, fmt.Errorf(
217+
"asset id and edge node must both be set",
218+
)
219+
}
220+
221+
req.AssetAmount = btcutil.Amount(in.Amt)
222+
req.AssetId = in.AssetInfo.AssetId
223+
req.AssetEdgeNode = in.AssetInfo.AssetEdgeNode
224+
225+
// We'll set the sat amount to zero, as this gets set later
226+
// when we calculate the total amount to send.
227+
req.Amount = 0
228+
}
229+
211230
switch {
212231
case in.LoopOutChannel != 0 && len(in.OutgoingChanSet) > 0: // nolint:staticcheck
213232
return nil, errors.New("loop_out_channel and outgoing_" +
@@ -707,12 +726,25 @@ func (s *swapClientServer) LoopOutQuote(ctx context.Context,
707726
req.SwapPublicationDeadline,
708727
)
709728

710-
quote, err := s.impl.LoopOutQuote(ctx, &loop.LoopOutQuoteRequest{
729+
loopOutQuoteReq := &loop.LoopOutQuoteRequest{
711730
Amount: btcutil.Amount(req.Amt),
712731
SweepConfTarget: confTarget,
713732
SwapPublicationDeadline: publicactionDeadline,
714733
Initiator: defaultLoopdInitiator,
715-
})
734+
}
735+
736+
if req.AssetInfo != nil {
737+
if req.AssetInfo.AssetId == nil ||
738+
req.AssetInfo.AssetEdgeNode == nil {
739+
return nil, fmt.Errorf(
740+
"asset id and edge node must be set")
741+
742+
}
743+
loopOutQuoteReq.AssetId = req.AssetInfo.AssetId
744+
loopOutQuoteReq.AssetEdgeNode = req.AssetInfo.AssetEdgeNode
745+
}
746+
747+
quote, err := s.impl.LoopOutQuote(ctx, loopOutQuoteReq)
716748
if err != nil {
717749
return nil, err
718750
}
@@ -723,6 +755,7 @@ func (s *swapClientServer) LoopOutQuote(ctx context.Context,
723755
SwapFeeSat: int64(quote.SwapFee),
724756
SwapPaymentDest: quote.SwapPaymentDest[:],
725757
ConfTarget: confTarget,
758+
InvoiceAmtSat: int64(quote.InvoiceAmtSat),
726759
}, nil
727760
}
728761

loopdb/loopout.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ type LoopOutContract struct {
6565
// PaymentTimeout is the timeout for any individual off-chain payment
6666
// attempt.
6767
PaymentTimeout time.Duration
68+
69+
// AssetId is the optional asset id that is used to pay the swap invoice.
70+
AssetId []byte
71+
72+
// AssetEdgeNode is the asset edge node that is used to pay the
73+
// swap invoice.
74+
AssetEdgeNode []byte
6875
}
6976

7077
// ChannelSet stores a set of channels.

loopout.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ func newLoopOutSwap(globalCtx context.Context, cfg *swapConfig,
206206
},
207207
OutgoingChanSet: chanSet,
208208
PaymentTimeout: request.PaymentTimeout,
209+
AssetId: request.AssetId,
210+
AssetEdgeNode: request.AssetEdgeNode,
209211
}
210212

211213
swapKit := newSwapKit(

0 commit comments

Comments
 (0)