Skip to content

Commit 5ecc620

Browse files
committed
liquidity: add asset loop out unit test
1 parent b70d578 commit 5ecc620

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed

liquidity/autoloop_test.go

+142
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,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

Comments
 (0)