From f14a8285f5d082d5a98a2f70123b39eea93e8dab Mon Sep 17 00:00:00 2001 From: Adithya Vardhan Date: Sun, 22 Sep 2024 11:01:36 +0530 Subject: [PATCH] fix: use channel balance api in get balances (LND) (#671) * fix: use channel balance api in get balances * fix: lnd lightning balances * fix: lnd channel spendable amounts, improved naming, add comments --------- Co-authored-by: Roland Bewick --- lnclient/ldk/ldk.go | 14 ++++++++------ lnclient/lnd/lnd.go | 34 +++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/lnclient/ldk/ldk.go b/lnclient/ldk/ldk.go index 4c38130d..4b65a3ef 100644 --- a/lnclient/ldk/ldk.go +++ b/lnclient/ldk/ldk.go @@ -1485,15 +1485,17 @@ func (ls *LDKService) GetBalances(ctx context.Context) (*lnclient.BalancesRespon channels := ls.node.ListChannels() for _, channel := range channels { if channel.IsUsable { - channelMinSpendable := min(int64(channel.OutboundCapacityMsat), int64(*channel.CounterpartyOutboundHtlcMaximumMsat)) - channelMinReceivable := min(int64(channel.InboundCapacityMsat), int64(*channel.InboundHtlcMaximumMsat)) + // spending or receiving amount may be constrained by channel configuration (e.g. ACINQ does this) + channelConstrainedSpendable := min(int64(channel.OutboundCapacityMsat), int64(*channel.CounterpartyOutboundHtlcMaximumMsat)) + channelConstrainedReceivable := min(int64(channel.InboundCapacityMsat), int64(*channel.InboundHtlcMaximumMsat)) - nextMaxSpendable = max(nextMaxSpendable, channelMinSpendable) - nextMaxReceivable = max(nextMaxReceivable, channelMinReceivable) + nextMaxSpendable = max(nextMaxSpendable, channelConstrainedSpendable) + nextMaxReceivable = max(nextMaxReceivable, channelConstrainedReceivable) - nextMaxSpendableMPP += channelMinSpendable - nextMaxReceivableMPP += channelMinReceivable + nextMaxSpendableMPP += channelConstrainedSpendable + nextMaxReceivableMPP += channelConstrainedReceivable + // these are what the wallet can send and receive, but not necessarily in one go totalSpendable += int64(channel.OutboundCapacityMsat) totalReceivable += int64(channel.InboundCapacityMsat) } diff --git a/lnclient/lnd/lnd.go b/lnclient/lnd/lnd.go index be6900d8..fdeb0dc3 100644 --- a/lnclient/lnd/lnd.go +++ b/lnclient/lnd/lnd.go @@ -831,30 +831,42 @@ func (svc *LNDService) GetBalances(ctx context.Context) (*lnclient.BalancesRespo var nextMaxSpendable int64 = 0 var nextMaxReceivableMPP int64 = 0 var nextMaxSpendableMPP int64 = 0 + resp, err := svc.client.ListChannels(ctx, &lnrpc.ListChannelsRequest{}) + if err != nil { + logger.Logger.WithError(err).Error("Failed to list channels") + return nil, err + } for _, channel := range resp.Channels { // Unnecessary since ListChannels only returns active channels if channel.Active { - channelMinSpendable := channel.LocalBalance * 1000 - channelMinReceivable := channel.RemoteBalance * 1000 + channelSpendable := max(channel.LocalBalance*1000-int64(channel.LocalConstraints.ChanReserveSat*1000), 0) + channelReceivable := max(channel.RemoteBalance*1000-int64(channel.RemoteConstraints.ChanReserveSat*1000), 0) + + // spending or receiving amount may be constrained by channel configuration (e.g. ACINQ does this) + channelConstrainedSpendable := min(channelSpendable, int64(channel.RemoteConstraints.MaxPendingAmtMsat)) + channelConstrainedReceivable := min(channelReceivable, int64(channel.LocalConstraints.MaxPendingAmtMsat)) + + nextMaxSpendable = max(nextMaxSpendable, channelConstrainedSpendable) + nextMaxReceivable = max(nextMaxReceivable, channelConstrainedReceivable) - nextMaxSpendable = max(nextMaxSpendable, channelMinSpendable) - nextMaxReceivable = max(nextMaxReceivable, channelMinReceivable) + nextMaxSpendableMPP += channelConstrainedSpendable + nextMaxReceivableMPP += channelConstrainedReceivable - totalSpendable += channelMinSpendable - totalReceivable += channelMinReceivable + // these are what the wallet can send and receive, but not necessarily in one go + totalSpendable += channelSpendable + totalReceivable += channelReceivable } } return &lnclient.BalancesResponse{ Onchain: *onchainBalance, Lightning: lnclient.LightningBalanceResponse{ - TotalSpendable: totalSpendable, - TotalReceivable: totalReceivable, - NextMaxSpendable: nextMaxSpendable, - NextMaxReceivable: nextMaxReceivable, - // TODO: return actuall MPP instead of 0 + TotalSpendable: totalSpendable, + TotalReceivable: totalReceivable, + NextMaxSpendable: nextMaxSpendable, + NextMaxReceivable: nextMaxReceivable, NextMaxSpendableMPP: nextMaxSpendableMPP, NextMaxReceivableMPP: nextMaxReceivableMPP, },