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