1
1
package liquidity
2
2
3
3
import (
4
+ "context"
5
+ "encoding/hex"
6
+ "encoding/json"
4
7
"testing"
5
8
"time"
6
9
@@ -11,6 +14,7 @@ import (
11
14
"github.com/lightninglabs/loop/loopdb"
12
15
"github.com/lightninglabs/loop/swap"
13
16
"github.com/lightninglabs/loop/test"
17
+ "github.com/lightninglabs/taproot-assets/rfqmsg"
14
18
"github.com/lightningnetwork/lnd/lntypes"
15
19
"github.com/lightningnetwork/lnd/lnwire"
16
20
"github.com/lightningnetwork/lnd/routing/route"
@@ -1520,3 +1524,144 @@ func existingInFromRequest(in *loop.LoopInRequest, initTime time.Time,
1520
1524
},
1521
1525
}
1522
1526
}
1527
+
1528
+ // TestEasyAssetAutoloop tests that the easy asset autoloop logic works as
1529
+ //
1530
+ // expected. This involves testing that channels are correctly selected and
1531
+ //
1532
+ // that the balance target is successfully met.
1533
+ func TestEasyAssetAutoloop (t * testing.T ) {
1534
+ defer test .Guard (t )
1535
+
1536
+ assetId := [32 ]byte {0x01 }
1537
+ assetStr := hex .EncodeToString (assetId [:])
1538
+
1539
+ // Decode a dummy p2wkh address to use as the destination address for
1540
+ // the swaps.
1541
+ p2wkhAddr := "bcrt1qq68r6ff4k4pjx39efs44gcyccf7unqnu5qtjjz"
1542
+ addr , err := btcutil .DecodeAddress (p2wkhAddr , nil )
1543
+ require .NoError (t , err )
1544
+
1545
+ customChanData1 := rfqmsg.JsonAssetChannel {
1546
+ Assets : []rfqmsg.JsonAssetChanInfo {
1547
+ {
1548
+ AssetInfo : rfqmsg.JsonAssetUtxo {
1549
+ AssetGenesis : rfqmsg.JsonAssetGenesis {
1550
+ AssetID : assetStr ,
1551
+ },
1552
+ },
1553
+ LocalBalance : 950000 ,
1554
+ RemoteBalance : 0 ,
1555
+ Capacity : 100000 ,
1556
+ },
1557
+ },
1558
+ }
1559
+ customChanData1Bytes , err := json .Marshal (customChanData1 )
1560
+ require .NoError (t , err )
1561
+
1562
+ // We need to change the default channels we use for tests so that they
1563
+ // have different local balances in order to know which one is going to
1564
+ // be selected by easy autoloop.
1565
+ assetChan := lndclient.ChannelInfo {
1566
+ Active : true ,
1567
+ ChannelID : chanID1 .ToUint64 (),
1568
+ PubKeyBytes : peer1 ,
1569
+ LocalBalance : 95000 ,
1570
+ RemoteBalance : 0 ,
1571
+ Capacity : 100000 ,
1572
+ CustomChannelData : customChanData1Bytes ,
1573
+ }
1574
+
1575
+ // As the asset price func we'll just return a 1:1 conversion of asset units
1576
+ // to satoshis.
1577
+ assetPriceFunc := func (ctx context.Context , assetId string ,
1578
+ peerPubkey []byte , assetAmt uint64 , minSatAmt btcutil.Amount ) (
1579
+ btcutil.Amount , error ) {
1580
+
1581
+ return btcutil .Amount (assetAmt ), nil
1582
+ }
1583
+
1584
+ var (
1585
+ channels = []lndclient.ChannelInfo {assetChan }
1586
+
1587
+ params = Parameters {
1588
+ Autoloop : true ,
1589
+ DestAddr : addr ,
1590
+ AutoFeeBudget : 36000 ,
1591
+ AutoFeeRefreshPeriod : time .Hour * 3 ,
1592
+ AutoloopBudgetLastRefresh : testBudgetStart ,
1593
+ MaxAutoInFlight : 2 ,
1594
+ FailureBackOff : time .Hour ,
1595
+ SweepConfTarget : 10 ,
1596
+ HtlcConfTarget : defaultHtlcConfTarget ,
1597
+ FeeLimit : defaultFeePortion (),
1598
+ AssetAutoloopParams : map [string ]AssetParams {
1599
+ assetStr : AssetParams {
1600
+ EnableEasyOut : true ,
1601
+ LocalTargetAssetAmount : 75000 ,
1602
+ },
1603
+ },
1604
+ }
1605
+ )
1606
+
1607
+ c := newAutoloopTestCtx (t , params , channels , testRestrictions )
1608
+ // Return a fixed price for the asset.
1609
+ c .manager .cfg .GetAssetPrice = assetPriceFunc
1610
+
1611
+ c .start ()
1612
+
1613
+ var (
1614
+ maxAmt = 50000
1615
+
1616
+ chan1Swap = & loop.OutRequest {
1617
+ Amount : btcutil .Amount (maxAmt ),
1618
+ DestAddr : addr ,
1619
+ OutgoingChanSet : loopdb.ChannelSet {assetChan .ChannelID },
1620
+ Label : labels .AutoloopLabel (swap .TypeOut ),
1621
+ Initiator : autoloopSwapInitiator ,
1622
+ }
1623
+
1624
+ quotesOut1 = []quoteRequestResp {
1625
+ {
1626
+ request : & loop.LoopOutQuoteRequest {
1627
+ Amount : btcutil .Amount (maxAmt ),
1628
+ AssetRFQRequest : & loop.AssetRFQRequest {
1629
+ AssetId : assetId [:],
1630
+ AssetEdgeNode : []byte ("edge" ),
1631
+ },
1632
+ },
1633
+ quote : & loop.LoopOutQuote {
1634
+ SwapFee : 1 ,
1635
+ PrepayAmount : 1 ,
1636
+ MinerFee : 1 ,
1637
+ // We'll add a fake rfq info to use in the actual swap.
1638
+ LoopOutRfq : & loop.LoopOutRfq {
1639
+ PrepayRfqId : []byte ("prepay" ),
1640
+ SwapRfqId : []byte ("swap" ),
1641
+ },
1642
+ },
1643
+ },
1644
+ }
1645
+
1646
+ loopOut1 = []loopOutRequestResp {
1647
+ {
1648
+ request : chan1Swap ,
1649
+ response : & loop.LoopOutSwapInfo {
1650
+ SwapHash : lntypes.Hash {1 },
1651
+ },
1652
+ },
1653
+ }
1654
+ )
1655
+
1656
+ // We expected one max size swap to be dispatched on our channel with
1657
+ // the biggest local balance.
1658
+ step := & easyAutoloopStep {
1659
+ minAmt : 1 ,
1660
+ maxAmt : 50000 ,
1661
+ quotesOut : quotesOut1 ,
1662
+ expectedOut : loopOut1 ,
1663
+ }
1664
+
1665
+ c .easyautoloop (step , false )
1666
+ c .stop ()
1667
+ }
0 commit comments