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