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,143 @@ 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+ 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