Skip to content

Commit 2b227c8

Browse files
committed
liquidity: add asset loop out unit test
1 parent cc73062 commit 2b227c8

File tree

1 file changed

+144
-0
lines changed

1 file changed

+144
-0
lines changed

liquidity/autoloop_test.go

+144
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package liquidity
22

33
import (
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

Comments
 (0)