liquidity: count static loop-ins

Teach the liquidity manager to include persisted static loop-ins
in budget accounting, in-flight limits, and peer traffic backoff.
This adds the static fee model used for conservative accounting
and passes storage errors through the relevant planner helpers.

The daemon wiring now exposes static loop-ins to liquidity so the
manager can see the same ongoing swaps that the static-address
subsystem persists, while easy autoloop keeps working with the new
fallible traffic lookup path.
This commit is contained in:
Boris Nagaev 2026-04-10 23:51:19 -05:00
parent 94fc04a71a
commit 7cf0a87c2b
No known key found for this signature in database
10 changed files with 822 additions and 47 deletions

View file

@ -734,12 +734,16 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
)
}
liquidityMgr := getLiquidityManager(
swapClient, staticLoopInManager,
)
// Now finally fully initialize the swap client RPC server instance.
d.swapClientServer = swapClientServer{
config: d.cfg,
network: lndclient.Network(d.cfg.Network),
impl: swapClient,
liquidityMgr: getLiquidityManager(swapClient),
liquidityMgr: liquidityMgr,
lnd: &d.lnd.LndServices,
swaps: make(map[lntypes.Hash]loop.SwapInfo),
subscribers: make(map[int]chan<- any),

View file

@ -3,6 +3,7 @@ package loopd
import (
"context"
"fmt"
"slices"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg"
@ -12,6 +13,7 @@ import (
"github.com/lightninglabs/loop/assets"
"github.com/lightninglabs/loop/liquidity"
"github.com/lightninglabs/loop/loopdb"
"github.com/lightninglabs/loop/staticaddr/loopin"
"github.com/lightninglabs/loop/swap"
"github.com/lightninglabs/loop/sweepbatcher"
"github.com/lightningnetwork/lnd/clock"
@ -115,7 +117,50 @@ func openDatabase(cfg *Config, chainParams *chaincfg.Params) (loopdb.SwapStore,
return db, &baseDb, nil
}
func getLiquidityManager(client *loop.Client) *liquidity.Manager {
func getLiquidityManager(client *loop.Client,
staticLoopInManager *loopin.Manager) *liquidity.Manager {
listStaticLoopIn := func(
ctx context.Context) ([]*liquidity.StaticLoopInInfo, error) {
if staticLoopInManager == nil {
return nil, nil
}
swaps, err := staticLoopInManager.GetAllSwaps(ctx)
if err != nil {
return nil, err
}
result := make(
[]*liquidity.StaticLoopInInfo, 0, len(swaps),
)
for _, staticSwap := range swaps {
state := staticSwap.GetState()
pending := slices.Contains(loopin.PendingStates, state)
failed := state == loopin.Failed ||
state == loopin.HtlcTimeoutSwept
result = append(result, &liquidity.StaticLoopInInfo{
Label: staticSwap.Label,
QuotedSwapFee: staticSwap.QuotedSwapFee,
HtlcTxFeeRate: staticSwap.HtlcTxFeeRate,
LastHop: staticSwap.LastHopVertex(),
LastUpdateTime: staticSwap.LastUpdateTime,
Pending: pending,
Failed: failed,
BlocksLoopIn: pending &&
state != loopin.PaymentReceived,
NumDeposits: len(staticSwap.Deposits),
HasChange: staticSwap.SelectedAmount > 0 &&
staticSwap.SelectedAmount <
staticSwap.TotalDepositAmount(),
})
}
return result, nil
}
mngrCfg := &liquidity.Config{
AutoloopTicker: ticker.NewForce(liquidity.DefaultAutoloopTicker),
LoopOut: client.LoopOut,
@ -150,6 +195,7 @@ func getLiquidityManager(client *loop.Client) *liquidity.Manager {
ListLoopOut: client.Store.FetchLoopOutSwaps,
GetLoopOut: client.Store.FetchLoopOutSwap,
ListLoopIn: client.Store.FetchLoopInSwaps,
ListStaticLoopIn: listStaticLoopIn,
LoopInTerms: client.LoopInTerms,
LoopOutTerms: client.LoopOutTerms,
GetAssetPrice: client.AssetClient.GetAssetPrice,