11package liquidity
22
33import (
4+ "context"
5+ "encoding/hex"
6+ "encoding/json"
47 "testing"
58 "time"
69
@@ -11,6 +14,7 @@ import (
1114 "github.com/lightninglabs/loop/loopdb"
1215 "github.com/lightninglabs/loop/swap"
1316 "github.com/lightninglabs/loop/test"
17+ "github.com/lightninglabs/taproot-assets/rfqmsg"
1418 "github.com/lightningnetwork/lnd/lntypes"
1519 "github.com/lightningnetwork/lnd/lnwire"
1620 "github.com/lightningnetwork/lnd/routing/route"
@@ -1520,3 +1524,144 @@ func existingInFromRequest(in *loop.LoopInRequest, initTime time.Time,
15201524 },
15211525 }
15221526}
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