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,141 @@ func existingInFromRequest(in *loop.LoopInRequest, initTime time.Time,
15201524 },
15211525 }
15221526}
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