Skip to content

Commit 0f54b96

Browse files
committedJan 21, 2025
loopout: add asset accounting
1 parent 1532cb1 commit 0f54b96

File tree

6 files changed

+922
-683
lines changed

6 files changed

+922
-683
lines changed
 

‎client.go

+4
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,10 @@ func (s *Client) FetchSwaps(ctx context.Context) ([]*SwapInfo, error) {
349349
return nil, swap.ErrInvalidOutputType
350350
}
351351

352+
if swp.Contract.AssetSwapInfo != nil {
353+
swapInfo.AssetSwapInfo = swp.Contract.AssetSwapInfo
354+
}
355+
352356
swaps = append(swaps, swapInfo)
353357
}
354358

‎loopd/swapclient_server.go

+32-7
Original file line numberDiff line numberDiff line change
@@ -309,8 +309,8 @@ func toWalletAddrType(addrType looprpc.AddressType) (walletrpc.AddressType,
309309
}
310310
}
311311

312-
func (s *swapClientServer) marshallSwap(loopSwap *loop.SwapInfo) (
313-
*looprpc.SwapStatus, error) {
312+
func (s *swapClientServer) marshallSwap(ctx context.Context,
313+
loopSwap *loop.SwapInfo) (*looprpc.SwapStatus, error) {
314314

315315
var (
316316
state looprpc.SwapState
@@ -383,6 +383,7 @@ func (s *swapClientServer) marshallSwap(loopSwap *loop.SwapInfo) (
383383
)
384384
var outGoingChanSet []uint64
385385
var lastHop []byte
386+
var assetInfo *looprpc.AssetLoopOutInfo
386387

387388
switch loopSwap.SwapType {
388389
case swap.TypeIn:
@@ -413,6 +414,23 @@ func (s *swapClientServer) marshallSwap(loopSwap *loop.SwapInfo) (
413414

414415
outGoingChanSet = loopSwap.OutgoingChanSet
415416

417+
if loopSwap.AssetSwapInfo != nil {
418+
assetName, err := s.assetClient.GetAssetName(
419+
ctx, loopSwap.AssetSwapInfo.AssetId,
420+
)
421+
if err != nil {
422+
return nil, err
423+
}
424+
425+
assetInfo = &looprpc.AssetLoopOutInfo{
426+
AssetId: hex.EncodeToString(loopSwap.AssetSwapInfo.AssetId), // nolint:lll
427+
AssetCostOffchain: uint64(
428+
loopSwap.AssetSwapInfo.PrepayPaidAmt +
429+
loopSwap.AssetSwapInfo.SwapPaidAmt), // nolint:lll
430+
AssetName: assetName,
431+
}
432+
}
433+
416434
default:
417435
return nil, errors.New("unknown swap type")
418436
}
@@ -435,6 +453,7 @@ func (s *swapClientServer) marshallSwap(loopSwap *loop.SwapInfo) (
435453
Label: loopSwap.Label,
436454
LastHop: lastHop,
437455
OutgoingChanSet: outGoingChanSet,
456+
AssetInfo: assetInfo,
438457
}, nil
439458
}
440459

@@ -445,7 +464,7 @@ func (s *swapClientServer) Monitor(in *looprpc.MonitorRequest,
445464
log.Infof("Monitor request received")
446465

447466
send := func(info loop.SwapInfo) error {
448-
rpcSwap, err := s.marshallSwap(&info)
467+
rpcSwap, err := s.marshallSwap(server.Context(), &info)
449468
if err != nil {
450469
return err
451470
}
@@ -540,7 +559,7 @@ func (s *swapClientServer) Monitor(in *looprpc.MonitorRequest,
540559

541560
// ListSwaps returns a list of all currently known swaps and their current
542561
// status.
543-
func (s *swapClientServer) ListSwaps(_ context.Context,
562+
func (s *swapClientServer) ListSwaps(ctx context.Context,
544563
req *looprpc.ListSwapsRequest) (*looprpc.ListSwapsResponse, error) {
545564

546565
var (
@@ -563,7 +582,7 @@ func (s *swapClientServer) ListSwaps(_ context.Context,
563582
continue
564583
}
565584

566-
rpcSwap, err := s.marshallSwap(&swp)
585+
rpcSwap, err := s.marshallSwap(ctx, &swp)
567586
if err != nil {
568587
return nil, err
569588
}
@@ -641,11 +660,17 @@ func filterSwap(swapInfo *loop.SwapInfo, filter *looprpc.ListSwapsFilter) bool {
641660
}
642661
}
643662

663+
// If we only want to return asset swaps, we only return swaps that have
664+
// an asset id set.
665+
if filter.AssetSwapOnly && swapInfo.AssetSwapInfo == nil {
666+
return false
667+
}
668+
644669
return true
645670
}
646671

647672
// SwapInfo returns all known details about a single swap.
648-
func (s *swapClientServer) SwapInfo(_ context.Context,
673+
func (s *swapClientServer) SwapInfo(ctx context.Context,
649674
req *looprpc.SwapInfoRequest) (*looprpc.SwapStatus, error) {
650675

651676
swapHash, err := lntypes.MakeHash(req.Id)
@@ -659,7 +684,7 @@ func (s *swapClientServer) SwapInfo(_ context.Context,
659684
if !ok {
660685
return nil, fmt.Errorf("swap with hash %s not found", req.Id)
661686
}
662-
return s.marshallSwap(&swp)
687+
return s.marshallSwap(ctx, &swp)
663688
}
664689

665690
// AbandonSwap requests the server to abandon a swap with the given hash.

‎loopout.go

+51-7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"crypto/rand"
66
"crypto/sha256"
7+
"encoding/json"
78
"errors"
89
"fmt"
910
"math"
@@ -355,6 +356,10 @@ func (s *loopOutSwap) sendUpdate(ctx context.Context) error {
355356
info.OutgoingChanSet = outgoingChanSet
356357
}
357358

359+
if s.AssetSwapInfo != nil {
360+
info.AssetSwapInfo = s.AssetSwapInfo
361+
}
362+
358363
select {
359364
case s.statusChan <- *info:
360365
case <-ctx.Done():
@@ -436,7 +441,7 @@ func (s *loopOutSwap) executeAndFinalize(globalCtx context.Context) error {
436441
case result := <-s.swapPaymentChan:
437442
s.swapPaymentChan = nil
438443

439-
err := s.handlePaymentResult(result, true)
444+
err := s.handlePaymentResult(globalCtx, result, true)
440445
if err != nil {
441446
return err
442447
}
@@ -452,7 +457,7 @@ func (s *loopOutSwap) executeAndFinalize(globalCtx context.Context) error {
452457
case result := <-s.prePaymentChan:
453458
s.prePaymentChan = nil
454459

455-
err := s.handlePaymentResult(result, false)
460+
err := s.handlePaymentResult(globalCtx, result, false)
456461
if err != nil {
457462
return err
458463
}
@@ -485,8 +490,8 @@ func (s *loopOutSwap) executeAndFinalize(globalCtx context.Context) error {
485490
// handlePaymentResult processes the result of a payment attempt. If the
486491
// payment was successful and this is the main swap payment, the cost of the
487492
// swap is updated.
488-
func (s *loopOutSwap) handlePaymentResult(result paymentResult,
489-
swapPayment bool) error {
493+
func (s *loopOutSwap) handlePaymentResult(ctx context.Context,
494+
result paymentResult, swapPayment bool) error {
490495

491496
switch {
492497
// If our result has a non-nil error, our status will be nil. In this
@@ -513,6 +518,17 @@ func (s *loopOutSwap) handlePaymentResult(result paymentResult,
513518
// the swap payment and the prepay.
514519
s.cost.Offchain += result.status.Fee.ToSatoshis()
515520

521+
// If this is an asset payment, we'll write the asset amounts
522+
// to the swap.
523+
if s.AssetSwapInfo != nil {
524+
err := s.fillAssetOffchainPaymentResult(
525+
ctx, result, swapPayment,
526+
)
527+
if err != nil {
528+
return err
529+
}
530+
}
531+
516532
return nil
517533

518534
case result.status.State == lnrpc.Payment_FAILED:
@@ -675,7 +691,7 @@ func (s *loopOutSwap) payInvoices(ctx context.Context) {
675691
if s.AssetSwapInfo != nil {
676692
assetPrepayRfq = s.AssetSwapInfo.PrepayRfqId
677693
}
678-
694+
679695
s.prePaymentChan = s.payInvoice(
680696
ctx, s.PrepayInvoice, s.MaxPrepayRoutingFee,
681697
s.LoopOutContract.OutgoingChanSet,
@@ -1033,7 +1049,7 @@ func (s *loopOutSwap) waitForConfirmedHtlc(globalCtx context.Context) (
10331049
case result := <-s.swapPaymentChan:
10341050
s.swapPaymentChan = nil
10351051

1036-
err := s.handlePaymentResult(result, true)
1052+
err := s.handlePaymentResult(ctx, result, true)
10371053
if err != nil {
10381054
return nil, err
10391055
}
@@ -1055,7 +1071,7 @@ func (s *loopOutSwap) waitForConfirmedHtlc(globalCtx context.Context) (
10551071
case result := <-s.prePaymentChan:
10561072
s.prePaymentChan = nil
10571073

1058-
err := s.handlePaymentResult(result, false)
1074+
err := s.handlePaymentResult(ctx, result, false)
10591075
if err != nil {
10601076
return nil, err
10611077
}
@@ -1455,3 +1471,31 @@ func (s *loopOutSwap) canSweep() bool {
14551471

14561472
return true
14571473
}
1474+
1475+
func (s *loopOutSwap) fillAssetOffchainPaymentResult(ctx context.Context,
1476+
result paymentResult, isSwapInvoice bool) error {
1477+
1478+
if len(result.status.Htlcs) == 0 {
1479+
return fmt.Errorf("no htlcs in payment result")
1480+
}
1481+
1482+
// We only expect one htlc in the result.
1483+
htlc := result.status.Htlcs[0]
1484+
1485+
var assetData rfqmsg.JsonHtlc
1486+
1487+
err := json.Unmarshal(htlc.Route.CustomChannelData, &assetData)
1488+
if err != nil {
1489+
return err
1490+
}
1491+
1492+
assetSendAmt := btcutil.Amount(assetData.Balances[0].Amount)
1493+
if isSwapInvoice {
1494+
s.AssetSwapInfo.SwapPaidAmt = assetSendAmt
1495+
log.Debugf("Asset off-chain payment success: %v", assetSendAmt)
1496+
} else {
1497+
s.AssetSwapInfo.PrepayPaidAmt = assetSendAmt
1498+
}
1499+
1500+
return s.store.UpdateLoopOutAssetInfo(ctx, s.hash, s.AssetSwapInfo)
1501+
}

0 commit comments

Comments
 (0)