diff --git a/CHANGELOG.md b/CHANGELOG.md index f2be354..7eeb382 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Versions +## 1.5.8 + +- Ignore forwards < 1000 sats in statistics and autofees +- Show 7 day Fee Log for individual channels + ## 1.5.7 - AutoFee: Fix enable/disable all individual channels diff --git a/cmd/psweb/handlers.go b/cmd/psweb/handlers.go index db3db68..26225f6 100644 --- a/cmd/psweb/handlers.go +++ b/cmd/psweb/handlers.go @@ -893,8 +893,13 @@ func afHandler(w http.ResponseWriter, r *http.Request) { var feeLog []FeeLog - // load the last 24 hours of fee changes - startTS := time.Now().Add(-24 * time.Hour).Unix() + // 24 hours fee log for all channels + days := 1 + if channelId > 0 { + // or 7 days for a single one + days = 7 + } + startTS := time.Now().AddDate(0, 0, -days).Unix() for id := range ln.AutoFeeLog { for _, event := range ln.AutoFeeLog[id] { @@ -1147,8 +1152,11 @@ func updateHandler(w http.ResponseWriter, r *http.Request) { swapData += `Swap Cost:` swapData += formatSigned(cost) + " sats" - swapData += `Cost PPM:` - swapData += formatSigned(ppm) + + if swap.State == "State_ClaimedPreimage" { + swapData += `Cost PPM:` + swapData += formatSigned(ppm) + } } swapData += ` diff --git a/cmd/psweb/ln/cln.go b/cmd/psweb/ln/cln.go index 52fe9ab..e005893 100644 --- a/cmd/psweb/ln/cln.go +++ b/cmd/psweb/ln/cln.go @@ -416,7 +416,7 @@ func CacheForwards() { forwardsLastIndex = newForwards.Forwards[n-1].CreatedIndex + 1 for _, f := range newForwards.Forwards { chOut := ConvertClnToLndChannelId(f.OutChannel) - if f.Status == "settled" { + if f.Status == "settled" && f.OutMsat > ignoreForwardsMsat { chIn := ConvertClnToLndChannelId(f.InChannel) forwardsIn[chIn] = append(forwardsIn[chIn], f) forwardsOut[chOut] = append(forwardsOut[chOut], f) @@ -465,7 +465,7 @@ func GetForwardingStats(lndChannelId uint64) *ForwardingStats { timestamp6m := float64(now.AddDate(0, -6, 0).Unix()) for _, e := range forwardsOut[lndChannelId] { - if e.ResolvedTime > timestamp6m { + if e.ResolvedTime > timestamp6m && e.OutMsat > ignoreForwardsMsat { amountOut6m += e.OutMsat feeMsat6m += e.FeeMsat if e.ResolvedTime > timestamp30d { @@ -479,7 +479,7 @@ func GetForwardingStats(lndChannelId uint64) *ForwardingStats { } } for _, e := range forwardsIn[lndChannelId] { - if e.ResolvedTime > timestamp6m { + if e.ResolvedTime > timestamp6m && e.OutMsat > ignoreForwardsMsat { amountIn6m += e.OutMsat assistedMsat6m += e.FeeMsat if e.ResolvedTime > timestamp30d { @@ -620,13 +620,13 @@ func GetChannelStats(lndChannelId uint64, timeStamp uint64) *ChannelStats { timeStampF := float64(timeStamp) for _, e := range forwardsOut[lndChannelId] { - if e.ResolvedTime > timeStampF { + if e.ResolvedTime > timeStampF && e.OutMsat > ignoreForwardsMsat { amountOut += e.OutMsat feeMsat += e.FeeMsat } } for _, e := range forwardsIn[lndChannelId] { - if e.ResolvedTime > timeStampF { + if e.ResolvedTime > timeStampF && e.OutMsat > ignoreForwardsMsat { amountIn += e.OutMsat assistedMsat += e.FeeMsat } @@ -1216,7 +1216,7 @@ func PlotPPM(channelId uint64) *[]DataPoint { for _, e := range forwardsOut[channelId] { // ignore small forwards - if e.OutMsat > 1000000 { + if e.OutMsat > ignoreForwardsMsat { plot = append(plot, DataPoint{ TS: uint64(e.ResolvedTime), Amount: e.OutMsat / 1000, diff --git a/cmd/psweb/ln/common.go b/cmd/psweb/ln/common.go index 798d679..ed7c665 100644 --- a/cmd/psweb/ln/common.go +++ b/cmd/psweb/ln/common.go @@ -132,6 +132,9 @@ type DataPoint struct { Label string } +// ignore small forwards +const ignoreForwardsMsat = 1_000_000 + var ( // lightning payments from swap out initiator to receiver SwapRebates = make(map[string]int64) @@ -270,15 +273,16 @@ func LoadDB() { func calculateAutoFee(channelId uint64, params *AutoFeeParams, liqPct int, oldFee int) int { newFee := oldFee - if liqPct > params.LowLiqPct { + if liqPct >= params.LowLiqPct { // normal or high liquidity regime, check if fee can be dropped lastUpdate := int64(0) lastLog := LastAutoFeeLog(channelId, false) if lastLog != nil { lastUpdate = lastLog.TimeStamp } + // see if cool-off period has passed if lastUpdate < time.Now().Add(-time.Duration(params.CoolOffHours)*time.Hour).Unix() { - // check the last outbound timestamp + // check the inactivity period if lastForwardTS[channelId] < time.Now().AddDate(0, 0, -params.InactivityDays).Unix() { // decrease the fee newFee -= params.InactivityDropPPM @@ -345,7 +349,7 @@ func moveLowLiqThreshold(channelId uint64, bump int) { *AutoFee[channelId] = AutoFeeDefaults } - // do not alow exeeding high liquidity threshold + // do not allow reaching high liquidity threshold if AutoFee[channelId].LowLiqPct+bump < AutoFee[channelId].ExcessPct { AutoFee[channelId].LowLiqPct += bump // persist to db @@ -357,6 +361,4 @@ func moveLowLiqThreshold(channelId uint64, bump int) { func saveSwapRabate(swapId string, rebate int64) { // save rebate payment SwapRebates[swapId] = rebate - // save to db - db.Save("Swaps", "SwapRebates", SwapRebates) } diff --git a/cmd/psweb/ln/lnd.go b/cmd/psweb/ln/lnd.go index 6f83b2b..3252bb0 100644 --- a/cmd/psweb/ln/lnd.go +++ b/cmd/psweb/ln/lnd.go @@ -45,9 +45,6 @@ const ( // https://github.com/ElementsProject/peerswap/blob/master/peerswaprpc/server.go#L234 SwapFeeReserveLBTC = uint64(1000) SwapFeeReserveBTC = uint64(2000) - - // used in outbound forwards tracking for auto fees - forwardAmountThreshold = uint64(1000) ) type InflightHTLC struct { @@ -774,10 +771,9 @@ func downloadForwards(client lnrpc.LightningClient) { // sort by in and out channels for _, event := range res.ForwardingEvents { - forwardsIn[event.ChanIdIn] = append(forwardsIn[event.ChanIdIn], event) - forwardsOut[event.ChanIdOut] = append(forwardsOut[event.ChanIdOut], event) - // record for autofees - if event.AmtOut >= forwardAmountThreshold { + if event.AmtOutMsat > ignoreForwardsMsat { + forwardsIn[event.ChanIdIn] = append(forwardsIn[event.ChanIdIn], event) + forwardsOut[event.ChanIdOut] = append(forwardsOut[event.ChanIdOut], event) lastForwardTS[event.ChanIdOut] = int64(event.TimestampNs / 1_000_000_000) } } @@ -980,30 +976,31 @@ func subscribeForwards(ctx context.Context, client routerrpc.RouterClient) error // find HTLC in queue for _, htlc := range inflightHTLCs[htlcEvent.IncomingChannelId] { if htlc.IncomingHtlcId == htlcEvent.IncomingHtlcId { - // add our stored forwards - forwardsIn[htlcEvent.IncomingChannelId] = append(forwardsIn[htlcEvent.IncomingChannelId], htlc.forwardingEvent) - // settled htlcEvent has no Outgoing info, take from queue - forwardsOut[htlc.OutgoingChannelId] = append(forwardsOut[htlc.OutgoingChannelId], htlc.forwardingEvent) // store the last timestamp lastForwardCreationTs = htlc.forwardingEvent.TimestampNs / 1_000_000_000 // delete from queue removeInflightHTLC(htlcEvent.IncomingChannelId, htlcEvent.IncomingHtlcId) - // record for autofees - if htlc.forwardingEvent.AmtOut >= forwardAmountThreshold { + // ignore dust + if htlc.forwardingEvent.AmtOutMsat > ignoreForwardsMsat { + // add our stored forwards + forwardsIn[htlcEvent.IncomingChannelId] = append(forwardsIn[htlcEvent.IncomingChannelId], htlc.forwardingEvent) + // settled htlcEvent has no Outgoing info, take from queue + forwardsOut[htlc.OutgoingChannelId] = append(forwardsOut[htlc.OutgoingChannelId], htlc.forwardingEvent) + // TS for autofee lastForwardTS[htlc.forwardingEvent.ChanIdOut] = int64(htlc.forwardingEvent.TimestampNs / 1_000_000_000) - } - // execute autofee - client, cleanup, err := GetClient() - if err != nil { - return err - } - defer cleanup() + // execute autofee + client, cleanup, err := GetClient() + if err != nil { + return err + } + defer cleanup() - // calculate with new balance - applyAutoFee(client, htlc.forwardingEvent.ChanIdOut, false) - break + // calculate with new balance + applyAutoFee(client, htlc.forwardingEvent.ChanIdOut, false) + break + } } } } @@ -1170,7 +1167,7 @@ func GetForwardingStats(channelId uint64) *ForwardingStats { timestamp6m := uint64(now.AddDate(0, -6, 0).Unix()) * 1_000_000_000 for _, e := range forwardsOut[channelId] { - if e.TimestampNs > timestamp6m { + if e.TimestampNs > timestamp6m && e.AmtOutMsat > ignoreForwardsMsat { result.AmountOut6m += e.AmtOut feeMsat6m += e.FeeMsat if e.TimestampNs > timestamp30d { @@ -1185,7 +1182,7 @@ func GetForwardingStats(channelId uint64) *ForwardingStats { } for _, e := range forwardsIn[channelId] { - if e.TimestampNs > timestamp6m { + if e.TimestampNs > timestamp6m && e.AmtOutMsat > ignoreForwardsMsat { result.AmountIn6m += e.AmtIn assistedMsat6m += e.FeeMsat if e.TimestampNs > timestamp30d { @@ -1285,13 +1282,13 @@ func GetChannelStats(channelId uint64, timeStamp uint64) *ChannelStats { timestampNs := timeStamp * 1_000_000_000 for _, e := range forwardsOut[channelId] { - if e.TimestampNs > timestampNs { + if e.TimestampNs > timestampNs && e.AmtOutMsat > ignoreForwardsMsat { routedOutMsat += e.AmtOutMsat feeMsat += e.FeeMsat } } for _, e := range forwardsIn[channelId] { - if e.TimestampNs > timestampNs { + if e.TimestampNs > timestampNs && e.AmtOutMsat > ignoreForwardsMsat { routedInMsat += e.AmtInMsat assistedMsat += e.FeeMsat } @@ -1751,7 +1748,7 @@ func applyAutoFee(client lnrpc.LightningClient, channelId uint64, htlcFail bool) liqPct := int(localBalance * 100 / r.Capacity) if htlcFail { - if liqPct <= params.LowLiqPct { + if liqPct < params.LowLiqPct { // increase fee to help prevent further failed HTLCs newFee += params.FailedBumpPPM } else { @@ -1888,7 +1885,7 @@ func PlotPPM(channelId uint64) *[]DataPoint { for _, e := range forwardsOut[channelId] { // ignore small forwards - if e.AmtOut > 1000 { + if e.AmtOutMsat > ignoreForwardsMsat { plot = append(plot, DataPoint{ TS: e.TimestampNs / 1_000_000_000, Amount: e.AmtOut, diff --git a/cmd/psweb/main.go b/cmd/psweb/main.go index f714cc5..d0628c4 100644 --- a/cmd/psweb/main.go +++ b/cmd/psweb/main.go @@ -35,7 +35,7 @@ import ( const ( // App version tag - version = "v1.5.7" + version = "v1.5.8" ) type SwapParams struct { @@ -220,6 +220,15 @@ func main() { sig := <-signalChan log.Printf("Received termination signal: %s\n", sig) + // persist to db + if db.Save("Swaps", "txFee", txFee) != nil { + log.Printf("Failed to persist txFee to db") + } + + if db.Save("Swaps", "SwapRebates", ln.SwapRebates) != nil { + log.Printf("Failed to persist SwapRebates to db") + } + // Exit the program gracefully os.Exit(0) } @@ -656,7 +665,11 @@ func convertPeersToHTMLTable( peerTable += "" + formatWithThousandSeparators(totalFees) + "" if totalCost > 0 { - peerTable += " -" + formatWithThousandSeparators(totalCost) + "" + color := "red" + if config.Config.ColorScheme == "dark" { + color = "pink" + } + peerTable += " -" + formatWithThousandSeparators(totalCost) + "" } peerTable += "" @@ -865,7 +878,11 @@ func convertOtherPeersToHTMLTable(peers []*peerswaprpc.PeerSwapPeer, ppmCost = totalCost * 1_000_000 / totalPayments } if totalCost > 0 { - peerTable += " -" + formatWithThousandSeparators(totalCost) + "" + color := "red" + if config.Config.ColorScheme == "dark" { + color = "pink" + } + peerTable += " -" + formatWithThousandSeparators(totalCost) + "" } peerTable += "" @@ -1237,17 +1254,6 @@ func executeAutoSwap() { } defer cleanup() - res, err := ps.LiquidGetBalance(client) - if err != nil { - return - } - - satAmount := res.GetSatAmount() - - if satAmount < config.Config.AutoSwapThresholdAmount { - return - } - res2, err := ps.ListActiveSwaps(client) if err != nil { return @@ -1255,27 +1261,33 @@ func executeAutoSwap() { activeSwaps := res2.GetSwaps() - // cannot have active swaps pending if len(activeSwaps) > 0 { if autoSwapPending { // save the Id autoSwapId = activeSwaps[0].Id } + // cannot have active swaps pending to initiate auto swap return } - if autoSwapPending && autoSwapId != "" { - autoSwapPending = false + if autoSwapPending { disable := false - // check the state - res, err := ps.GetSwap(client, autoSwapId) - if err != nil { - log.Println("GetSwap:", err) - disable = true - } - - if res.GetSwap().State != "State_ClaimedPreimage" { + // no active swaps means completed + if autoSwapId != "" { + // check the state + res, err := ps.GetSwap(client, autoSwapId) + if err != nil { + log.Println("GetSwap:", err) + disable = true + } + if res.GetSwap().State != "State_ClaimedPreimage" { + log.Println("The last auto swap failed") + disable = true + } + } else { + // did not catch an Id is an exception disable = true + log.Println("Unable to check the status of the last auto swap") } if disable { @@ -1283,8 +1295,23 @@ func executeAutoSwap() { config.Config.AutoSwapEnabled = false config.Save() log.Println("Automatic swap-ins Disabled") - return } + + // stop following + autoSwapPending = false + autoSwapId = "" + return + } + + res, err := ps.LiquidGetBalance(client) + if err != nil { + return + } + + satAmount := res.GetSatAmount() + + if satAmount < config.Config.AutoSwapThresholdAmount { + return } var candidate SwapParams @@ -1378,8 +1405,6 @@ func onchainTxFee(asset, txId string) int64 { // save to cache if fee > 0 { txFee[txId] = fee - // persist to db - db.Save("Swaps", "txFee", txFee) } return fee } diff --git a/cmd/psweb/templates/af.gohtml b/cmd/psweb/templates/af.gohtml index a3980fd..3dd79ab 100644 --- a/cmd/psweb/templates/af.gohtml +++ b/cmd/psweb/templates/af.gohtml @@ -228,7 +228,7 @@ {{end}}
-

24h Fee Log

+

Fee Log

diff --git a/cmd/psweb/templates/config.gohtml b/cmd/psweb/templates/config.gohtml index 540f2a3..115c009 100644 --- a/cmd/psweb/templates/config.gohtml +++ b/cmd/psweb/templates/config.gohtml @@ -246,12 +246,14 @@
-

* Changing these values will restart {{if eq .Implementation "CLN"}} + * Changing these values will restart {{if eq .Implementation "CLN"}} lightningd {{else}} peerswapd {{end}}

-

** Changing these values will restart PSWeb

+ {{if .IsPossibleHTTPS}} +

** Changing these values will restart PSWeb

+ {{end}}