From bbaea5ac23158d0fc77d8890da45e1b7927b096d Mon Sep 17 00:00:00 2001 From: Impa10r Date: Fri, 28 Jun 2024 18:58:50 +0200 Subject: [PATCH 1/8] Add BTC receiving and sending with coin selection --- CHANGELOG.md | 4 + cmd/psweb/config/common.go | 1 + cmd/psweb/handlers.go | 139 +++++++++----- cmd/psweb/ln/lnd.go | 2 +- cmd/psweb/main.go | 64 +++---- cmd/psweb/telegram.go | 4 +- cmd/psweb/templates/bitcoin.gohtml | 284 ++++++++++++++++++----------- cmd/psweb/templates/liquid.gohtml | 58 +++--- 8 files changed, 337 insertions(+), 219 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7eeb382..107406e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Versions +## 1.5.9 + +- Add BTC receiving and sending with coin selection + ## 1.5.8 - Ignore forwards < 1000 sats in statistics and autofees diff --git a/cmd/psweb/config/common.go b/cmd/psweb/config/common.go index 73bb93e..e1a728d 100644 --- a/cmd/psweb/config/common.go +++ b/cmd/psweb/config/common.go @@ -148,6 +148,7 @@ func Save() error { filename := filepath.Join(Config.DataDir, "pswebconfig.json") err = os.WriteFile(filename, jsonData, 0644) if err != nil { + log.Println("Error saving config file:", err) return err } return nil diff --git a/cmd/psweb/handlers.go b/cmd/psweb/handlers.go index 26225f6..9484b71 100644 --- a/cmd/psweb/handlers.go +++ b/cmd/psweb/handlers.go @@ -19,7 +19,6 @@ import ( "peerswap-web/cmd/psweb/bitcoin" "peerswap-web/cmd/psweb/config" "peerswap-web/cmd/psweb/db" - "peerswap-web/cmd/psweb/internet" "peerswap-web/cmd/psweb/liquid" "peerswap-web/cmd/psweb/ln" "peerswap-web/cmd/psweb/ps" @@ -486,6 +485,13 @@ func bitcoinHandler(w http.ResponseWriter, r *http.Request) { popupMessage = keys[0] } + // newly genetated address + addr := "" + keys, ok = r.URL.Query()["addr"] + if ok && len(keys[0]) > 0 { + addr = keys[0] + } + var utxos []ln.UTXO cl, clean, er := ln.GetClient() if er != nil { @@ -502,6 +508,7 @@ func bitcoinHandler(w http.ResponseWriter, r *http.Request) { BitcoinBalance uint64 Outputs *[]ln.UTXO PeginTxId string + IsPegin bool // false for ordinary BTC withdrawal PeginAmount uint64 BitcoinApi string Confirmations int32 @@ -515,6 +522,7 @@ func bitcoinHandler(w http.ResponseWriter, r *http.Request) { CanBump bool CanRBF bool IsCLN bool + BitcoinAddress string } btcBalance := ln.ConfirmedWalletBalance(cl) @@ -536,8 +544,8 @@ func bitcoinHandler(w http.ResponseWriter, r *http.Request) { fee = fee + fee/2 } } - if fee < config.Config.PeginFeeRate+1 { - fee = config.Config.PeginFeeRate + 1 // min increment + if fee < config.Config.PeginFeeRate+2 { + fee = config.Config.PeginFeeRate + 2 // min increment } } } @@ -554,6 +562,7 @@ func bitcoinHandler(w http.ResponseWriter, r *http.Request) { BitcoinBalance: uint64(btcBalance), Outputs: &utxos, PeginTxId: config.Config.PeginTxId, + IsPegin: config.Config.PeginClaimScript != "", PeginAmount: uint64(config.Config.PeginAmount), BitcoinApi: config.Config.BitcoinApi, Confirmations: confs, @@ -563,16 +572,18 @@ func bitcoinHandler(w http.ResponseWriter, r *http.Request) { MempoolFeeRate: mempoolFeeRate, LiquidFeeRate: liquid.EstimateFee(), SuggestedFeeRate: fee, - MinBumpFeeRate: config.Config.PeginFeeRate + 1, + MinBumpFeeRate: config.Config.PeginFeeRate + 2, CanBump: canBump, CanRBF: ln.CanRBF(), IsCLN: ln.Implementation == "CLN", + BitcoinAddress: addr, } // executing template named "bitcoin" executeTemplate(w, "bitcoin", data) } +// handles Liquid pegin and Bitcoin send form func peginHandler(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodPost { // Parse the form data @@ -595,6 +606,7 @@ func peginHandler(w http.ResponseWriter, r *http.Request) { selectedOutputs := r.Form["selected_outputs[]"] subtractFeeFromAmount := r.FormValue("subtractfee") == "on" + isPegin := r.FormValue("isPegin") == "true" totalAmount := int64(0) @@ -638,69 +650,79 @@ func peginHandler(w http.ResponseWriter, r *http.Request) { return } - // test on pre-existing tx that bitcon core can complete the peg - tx := "b61ec844027ce18fd3eb91fa7bed8abaa6809c4d3f6cf4952b8ebaa7cd46583a" - if config.Config.Chain == "testnet" { - tx = "2c7ec5043fe8ee3cb4ce623212c0e52087d3151c9e882a04073cce1688d6fc1e" - } + address := "" + claimScript := "" + + if isPegin { + // test on pre-existing tx that bitcon core can complete the peg + tx := "b61ec844027ce18fd3eb91fa7bed8abaa6809c4d3f6cf4952b8ebaa7cd46583a" + if config.Config.Chain == "testnet" { + tx = "2c7ec5043fe8ee3cb4ce623212c0e52087d3151c9e882a04073cce1688d6fc1e" + } - _, err = bitcoin.GetTxOutProof(tx) - if err != nil { - // automatic fallback to getblock.io - config.Config.BitcoinHost = config.GetBlockIoHost() - config.Config.BitcoinUser = "" - config.Config.BitcoinPass = "" _, err = bitcoin.GetTxOutProof(tx) if err != nil { - redirectWithError(w, r, "/bitcoin?", errors.New("GetTxOutProof failed, check BitcoinHost in Config")) - return - } else { - // use getblock.io endpoint going forward - log.Println("Switching to getblock.io bitcoin host endpoint") - if err := config.Save(); err != nil { - log.Println("Error saving config file:", err) - redirectWithError(w, r, "/bitcoin?", err) + // automatic fallback to getblock.io + config.Config.BitcoinHost = config.GetBlockIoHost() + config.Config.BitcoinUser = "" + config.Config.BitcoinPass = "" + _, err = bitcoin.GetTxOutProof(tx) + if err != nil { + redirectWithError(w, r, "/bitcoin?", errors.New("GetTxOutProof failed, check BitcoinHost in Config")) return + } else { + // use getblock.io endpoint going forward + log.Println("Switching to getblock.io bitcoin host endpoint") + if err := config.Save(); err != nil { + redirectWithError(w, r, "/bitcoin?", err) + return + } } } - } - var addr liquid.PeginAddress + var addr liquid.PeginAddress - err = liquid.GetPeginAddress(&addr) - if err != nil { - redirectWithError(w, r, "/bitcoin?", err) - return + err = liquid.GetPeginAddress(&addr) + if err != nil { + redirectWithError(w, r, "/bitcoin?", err) + return + } + + address = addr.MainChainAddress + claimScript = addr.ClaimScript + } else { + address = r.FormValue("sendAddress") + claimScript = "" } - res, err := ln.SendCoinsWithUtxos(&selectedOutputs, addr.MainChainAddress, amount, fee, subtractFeeFromAmount) + res, err := ln.SendCoinsWithUtxos(&selectedOutputs, address, amount, fee, subtractFeeFromAmount) if err != nil { redirectWithError(w, r, "/bitcoin?", err) return } - // to speed things up, also broadcast it to mempool.space - internet.SendRawTransaction(res.RawHex) - - log.Println("Peg-in TxId:", res.TxId, "RawHex:", res.RawHex, "Claim script:", addr.ClaimScript) - duration := time.Duration(1020) * time.Minute - formattedDuration := time.Time{}.Add(duration).Format("15h 04m") + if isPegin { + log.Println("Peg-in TxId:", res.TxId, "RawHex:", res.RawHex, "Claim script:", claimScript) + duration := time.Duration(1020) * time.Minute + formattedDuration := time.Time{}.Add(duration).Format("15h 04m") + telegramSendMessage("⏰ Started peg-in " + formatWithThousandSeparators(uint64(res.AmountSat)) + " sats. Time left: " + formattedDuration) + } else { + log.Println("BTC withdrawal TxId:", res.TxId, "RawHex:", res.RawHex) + telegramSendMessage("BTC withdrawal: " + formatWithThousandSeparators(uint64(res.AmountSat)) + " sats.") + } - config.Config.PeginClaimScript = addr.ClaimScript - config.Config.PeginAddress = addr.MainChainAddress + config.Config.PeginClaimScript = claimScript + config.Config.PeginAddress = address config.Config.PeginAmount = res.AmountSat config.Config.PeginTxId = res.TxId config.Config.PeginReplacedTxId = "" config.Config.PeginFeeRate = uint32(fee) if err := config.Save(); err != nil { - log.Println("Error saving config file:", err) redirectWithError(w, r, "/bitcoin?", err) return } - telegramSendMessage("⏰ Started peg-in " + formatWithThousandSeparators(uint64(res.AmountSat)) + " sats. Time left: " + formattedDuration) - // Redirect to bitcoin page to follow the pegin progress http.Redirect(w, r, "/bitcoin", http.StatusSeeOther) } else { @@ -748,9 +770,6 @@ func bumpfeeHandler(w http.ResponseWriter, r *http.Request) { } if ln.CanRBF() { - // to speed things up, also broadcast it to mempool.space - internet.SendRawTransaction(res.RawHex) - log.Println("RBF TxId:", res.TxId) config.Config.PeginReplacedTxId = config.Config.PeginTxId config.Config.PeginAmount = res.AmountSat @@ -764,7 +783,6 @@ func bumpfeeHandler(w http.ResponseWriter, r *http.Request) { config.Config.PeginFeeRate = uint32(fee) if err := config.Save(); err != nil { - log.Println("Error saving config file:", err) redirectWithError(w, r, "/bitcoin?", err) return } @@ -1444,6 +1462,17 @@ func submitHandler(w http.ResponseWriter, r *http.Request) { defer cleanup() switch action { + case "deleteTxId": + // acknowledges BTC withdrawal + config.Config.PeginTxId = "" + if err := config.Save(); err != nil { + redirectWithError(w, r, "/bitcoin?", err) + return + } + + // all done + http.Redirect(w, r, "/", http.StatusSeeOther) + return case "saveAutoFee": channelId, err := strconv.ParseUint(r.FormValue("channelId"), 10, 64) if err != nil { @@ -1845,7 +1874,6 @@ func submitHandler(w http.ResponseWriter, r *http.Request) { // Save config if err := config.Save(); err != nil { - log.Println("Error saving config file:", err) redirectWithError(w, r, "/liquid?", err) return } @@ -1854,6 +1882,18 @@ func submitHandler(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/liquid?msg="+msg, http.StatusSeeOther) return + case "newBitcoinAddress": + addr, err := ln.NewAddress() + if err != nil { + log.Printf("unable to connect to RPC server: %v", err) + redirectWithError(w, r, "/bitcoin?", err) + return + } + + // Redirect to bitcoin page with new address + http.Redirect(w, r, "/bitcoin?addr="+addr, http.StatusSeeOther) + return + case "newAddress": res, err := ps.LiquidGetAddress(client) if err != nil { @@ -2012,7 +2052,10 @@ func saveConfigHandler(w http.ResponseWriter, r *http.Request) { // display CA certificate installation instructions if secureConnection && !config.Config.SecureConnection { config.Config.ServerIPs = r.FormValue("serverIPs") - config.Save() + if err := config.Save(); err != nil { + redirectWithError(w, r, "/config?", err) + return + } http.Redirect(w, r, "/ca", http.StatusSeeOther) return } @@ -2105,7 +2148,6 @@ func saveConfigHandler(w http.ResponseWriter, r *http.Request) { } if err := config.Save(); err != nil { - log.Println("Error saving config file:", err) redirectWithError(w, r, "/config?", err) return } @@ -2113,7 +2155,6 @@ func saveConfigHandler(w http.ResponseWriter, r *http.Request) { if mustRestart { // show progress bar and log go http.Redirect(w, r, "/loading", http.StatusSeeOther) - config.SavePS() ps.Stop() } else if clientIsDown { // configs did not work, try again redirectWithError(w, r, "/config?", err) diff --git a/cmd/psweb/ln/lnd.go b/cmd/psweb/ln/lnd.go index 3252bb0..e01c9f5 100644 --- a/cmd/psweb/ln/lnd.go +++ b/cmd/psweb/ln/lnd.go @@ -384,7 +384,7 @@ func releaseOutputs(cl walletrpc.WalletKitClient, utxos *[]string, lockId *[]byt }) if err != nil { - log.Println("ReleaseOutput:", err) + //log.Println("ReleaseOutput:", err) return err } } diff --git a/cmd/psweb/main.go b/cmd/psweb/main.go index d0628c4..e7bba36 100644 --- a/cmd/psweb/main.go +++ b/cmd/psweb/main.go @@ -35,7 +35,7 @@ import ( const ( // App version tag - version = "v1.5.8" + version = "v1.5.9" ) type SwapParams struct { @@ -421,10 +421,7 @@ func liquidBackup(force bool) { config.Config.ElementsBackupAmount = satAmount // Save config - if err := config.Save(); err != nil { - log.Println("Error saving config file:", err) - return - } + config.Save() } func setLogging() (func(), error) { @@ -1057,49 +1054,48 @@ func checkPegin() { // RBF replacement conflict: the old transaction mined before the new one config.Config.PeginTxId = config.Config.PeginReplacedTxId config.Config.PeginReplacedTxId = "" - log.Println("The last RBF failed as previous tx mined earlier, switching to prior txid for the peg-in progress:", config.Config.PeginTxId) + log.Println("The last RBF failed as previous tx mined earlier, switching to prior txid:", config.Config.PeginTxId) } } - if confs >= 102 { - // claim pegin - failed := false - proof := "" - txid := "" - rawTx, err := ln.GetRawTransaction(cl, config.Config.PeginTxId) - if err == nil { - proof, err = bitcoin.GetTxOutProof(config.Config.PeginTxId) + if confs > 101 { + if config.Config.PeginClaimScript != "" { + // claim pegin + failed := false + proof := "" + txid := "" + rawTx, err := ln.GetRawTransaction(cl, config.Config.PeginTxId) if err == nil { - txid, err = liquid.ClaimPegin(rawTx, proof, config.Config.PeginClaimScript) - // claimpegin takes long time, allow it to timeout - if err != nil && err.Error() != "timeout reading data from server" { + proof, err = bitcoin.GetTxOutProof(config.Config.PeginTxId) + if err == nil { + txid, err = liquid.ClaimPegin(rawTx, proof, config.Config.PeginClaimScript) + // claimpegin takes long time, allow it to timeout + if err != nil && err.Error() != "timeout reading data from server" { + failed = true + } + } else { failed = true } } else { failed = true } - } else { - failed = true - } - if failed { - log.Println("Peg-in claim FAILED!") - log.Println("Mainchain TxId:", config.Config.PeginTxId) - log.Println("Raw tx:", rawTx) - log.Println("Proof:", proof) - log.Println("Claim Script:", config.Config.PeginClaimScript) - telegramSendMessage("❗ Peg-in claim FAILED! See log for details.") - } else { - log.Println("Peg-in success! Liquid TxId:", txid) - telegramSendMessage("💸 Peg-in success!") + if failed { + log.Println("Peg-in claim FAILED!") + log.Println("Mainchain TxId:", config.Config.PeginTxId) + log.Println("Raw tx:", rawTx) + log.Println("Proof:", proof) + log.Println("Claim Script:", config.Config.PeginClaimScript) + telegramSendMessage("❗ Peg-in claim FAILED! See log for details.") + } else { + log.Println("Peg-in success! Liquid TxId:", txid) + telegramSendMessage("💸 Peg-in success!") + } } // stop trying after one attempt config.Config.PeginTxId = "" - - if err := config.Save(); err != nil { - log.Println("Error saving config file:", err) - } + config.Save() } } diff --git a/cmd/psweb/telegram.go b/cmd/psweb/telegram.go index 68ce62a..a72f5ab 100644 --- a/cmd/psweb/telegram.go +++ b/cmd/psweb/telegram.go @@ -162,9 +162,7 @@ func telegramConnect() { ) bot.Send(cmdCfg) config.Config.TelegramChatId = chatId - if err := config.Save(); err != nil { - log.Println("Error saving config file:", err) - } + config.Save() } else { chatId = 0 bot = nil diff --git a/cmd/psweb/templates/bitcoin.gohtml b/cmd/psweb/templates/bitcoin.gohtml index 700bc7e..07e641c 100644 --- a/cmd/psweb/templates/bitcoin.gohtml +++ b/cmd/psweb/templates/bitcoin.gohtml @@ -1,81 +1,108 @@ {{define "bitcoin"}} {{template "header" .}}
- {{if eq .PeginTxId ""}} -
- {{end}}

 {{fmt .BitcoinBalance}}

+
+

Receive Bitcoin

+ {{if eq .BitcoinAddress ""}} + +
+ + +
+ + {{else}} + + + {{end}} +
{{if eq .PeginTxId ""}}
-
-
-

Liquid Peg-In

-
-
- {{if .CanRBF}} -
-

- RBF -

-
- {{else}} -
-

- CPFP -

-
- {{end}} -
-
- -
-
- -
-
- -
+ -
-
- -
-
- +
+ + -
-
-
- +
+
+ +
+
+ +
-
- - +
+
+ +
+
+ +
-
-
-
+
+
+ +
+
+ + +
-
-
- +
+
+
+
+
+ +
-
-
- -
+ + +
+ +
{{else}}
-

Peg-In Progress

+ {{if .IsPegin}} +

Peg-In Progress

+ {{else}} +

Bitcoin Withdrawal

+ {{end}} - - - - + + + + @@ -136,7 +166,7 @@
@@ -90,15 +117,18 @@ Confs: - {{.Confirmations}} / 102 -
- T left: - - {{.Duration}} + {{.Confirmations}} + {{if .IsPegin}} + / 102 +
+ T left: + + {{.Duration}} + {{end}}
{{if .CanRBF}} - If the tx does not confirm for a long time, consider replacing the peg-in transaction with a new one, paying a higher fee rate. + If the tx does not confirm for a long time, consider replacing it with a new one, paying a higher fee rate. {{else}} If the tx does not confirm for a long time, consider bumping the fee to at least 1.5x the current market rate, then wait for the child tx to appear in mempool. If the effective rate is still too low, you may bump again. The second and subsequent bumps will be RBF (replacing the child). {{end}} @@ -164,16 +194,26 @@ {{else}} -
-
+ {{if .IsPegin}} +
+
+
-
- + + {{else}} +
+ +
+
+ +
+
+ {{end}} {{end}}
{{end}} @@ -220,6 +260,26 @@ {{if eq .PeginTxId ""}} + {{end}} + {{if eq .TxId ""}}

Send Liquid

@@ -173,35 +202,6 @@
{{end}} -
-

Receive Liquid

- {{if eq .LiquidAddress ""}} -
-
- - -
-
- {{else}} - - - {{end}} -
From 279128849bf44a0cb25bfe41bc72bb6ecb257a80 Mon Sep 17 00:00:00 2001 From: Impa10r Date: Fri, 28 Jun 2024 22:57:18 +0200 Subject: [PATCH 2/8] Fix load txFees from DB --- CHANGELOG.md | 2 +- cmd/psweb/config/common.go | 1 + cmd/psweb/ln/common.go | 2 +- cmd/psweb/main.go | 23 ++++++++++++----------- cmd/psweb/templates/bitcoin.gohtml | 5 ----- 5 files changed, 15 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 107406e..f44b291 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## 1.5.9 -- Add BTC receiving and sending with coin selection +- Add get BTC receiving address and send with coin selection ## 1.5.8 diff --git a/cmd/psweb/config/common.go b/cmd/psweb/config/common.go index e1a728d..bc294c3 100644 --- a/cmd/psweb/config/common.go +++ b/cmd/psweb/config/common.go @@ -143,6 +143,7 @@ func Load(dataDir string) { func Save() error { jsonData, err := json.MarshalIndent(Config, "", " ") if err != nil { + log.Println("Error saving config file:", err) return err } filename := filepath.Join(Config.DataDir, "pswebconfig.json") diff --git a/cmd/psweb/ln/common.go b/cmd/psweb/ln/common.go index ed7c665..12f5d87 100644 --- a/cmd/psweb/ln/common.go +++ b/cmd/psweb/ln/common.go @@ -244,7 +244,7 @@ func AutoFeeRatesSummary(channelId uint64) (string, bool) { func LoadDB() { // load rebates from db - db.Load("Swaps", "SwapRebates", SwapRebates) + db.Load("Swaps", "SwapRebates", &SwapRebates) // load auto fees from db db.Load("AutoFees", "AutoFeeEnabledAll", &AutoFeeEnabledAll) diff --git a/cmd/psweb/main.go b/cmd/psweb/main.go index e7bba36..2242489 100644 --- a/cmd/psweb/main.go +++ b/cmd/psweb/main.go @@ -115,6 +115,12 @@ func main() { } defer cleanup() + // Load persisted data from database (synchronous to protect map writes) + ln.LoadDB() + + // fetch all chain costs (synchronous to protect map writes) + cacheSwapCosts() + // Get all HTML template files from the embedded filesystem templateFiles, err := tplFolder.ReadDir("templates") if err != nil { @@ -197,12 +203,6 @@ func main() { log.Println("Listening on http://localhost:" + config.Config.ListenPort) } - // Load persisted data from database (synchronous to protect map writes) - ln.LoadDB() - - // fetch all chain costs (synchronous to protect map writes) - cacheSwapCosts() - // Start timer to run every minute go startTimer() @@ -221,10 +221,6 @@ func main() { 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") } @@ -1418,13 +1414,18 @@ func cacheSwapCosts() { } // load from db - db.Load("Swaps", "txFee", txFee) + db.Load("Swaps", "txFee", &txFee) swaps := res.GetSwaps() for _, swap := range swaps { swapCost(swap) } + + // save to db + if db.Save("Swaps", "txFee", txFee) != nil { + log.Printf("Failed to persist txFee to db") + } } func restart(w http.ResponseWriter, r *http.Request, enableHTTPS bool, password string) { diff --git a/cmd/psweb/templates/bitcoin.gohtml b/cmd/psweb/templates/bitcoin.gohtml index 07e641c..ab80fb5 100644 --- a/cmd/psweb/templates/bitcoin.gohtml +++ b/cmd/psweb/templates/bitcoin.gohtml @@ -492,11 +492,6 @@ const isPegin = document.getElementById("isPegin").value == "true"; if (!isPegin) { - if (sendAddress == "") { - document.getElementById('result').innerText = "Please enter destination address"; - return; - } - // identify send address type if (sendAddress.startsWith('bc1p') || sendAddress.startsWith('tb1p')) { // is P2TR output count From f7d3ace6e4ab76ca2b923cae725fd38e70c96239 Mon Sep 17 00:00:00 2001 From: Impa10r Date: Fri, 28 Jun 2024 23:42:25 +0200 Subject: [PATCH 3/8] Add colors --- cmd/psweb/templates/af.gohtml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmd/psweb/templates/af.gohtml b/cmd/psweb/templates/af.gohtml index 3dd79ab..1df52ca 100644 --- a/cmd/psweb/templates/af.gohtml +++ b/cmd/psweb/templates/af.gohtml @@ -68,7 +68,12 @@
{{if .ChannelId}} -

Capacity: {{m .Capacity}}, {{.LocalPct}}% local, Current fee rate: {{fs .FeeRate}}{{if .HasInboundFees}}, Inbound rate: {{.InboundRate}}{{end}}

+

Capacity: {{m .Capacity}}, {{.LocalPct}}% local, Current fee rate: {{fs .FeeRate}}{{if .HasInboundFees}}, Inbound rate: {{.InboundRate}}{{end}}

{{end}}
From 749492316271742c325da7ce2749e7c7ea1d879b Mon Sep 17 00:00:00 2001 From: Impa10r Date: Mon, 1 Jul 2024 14:31:24 +0200 Subject: [PATCH 4/8] Add flow days column --- cmd/psweb/handlers.go | 7 +++++++ cmd/psweb/ln/cln.go | 2 +- cmd/psweb/ln/common.go | 5 +++-- cmd/psweb/ln/lnd.go | 4 ++-- cmd/psweb/templates/af.gohtml | 8 ++++++++ 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/cmd/psweb/handlers.go b/cmd/psweb/handlers.go index 9484b71..586d91a 100644 --- a/cmd/psweb/handlers.go +++ b/cmd/psweb/handlers.go @@ -851,6 +851,7 @@ func afHandler(w http.ResponseWriter, r *http.Request) { localPct := uint64(0) feeRate := outboundFeeRates[channelId] inboundRate := inboundFeeRates[channelId] + currentTime := time.Now() for _, peer := range res.GetPeers() { alias := getNodeAlias(peer.NodeId) @@ -858,6 +859,11 @@ func afHandler(w http.ResponseWriter, r *http.Request) { rule, custom := ln.AutoFeeRatesSummary(ch.ChannelId) af, _ := ln.AutoFeeRule(ch.ChannelId) peerNodeId[ch.ChannelId] = peer.NodeId + daysNoFlow := 999 + ts, ok := ln.LastForwardTS[ch.ChannelId] + if ok { + daysNoFlow = int(currentTime.Sub(time.Unix(ts, 0)).Hours() / 24) + } channelList = append(channelList, &ln.AutoFeeStatus{ Enabled: ln.AutoFeeEnabled[ch.ChannelId], @@ -870,6 +876,7 @@ func afHandler(w http.ResponseWriter, r *http.Request) { FeeRate: outboundFeeRates[ch.ChannelId], InboundRate: inboundFeeRates[ch.ChannelId], ChannelId: ch.ChannelId, + DaysNoFlow: daysNoFlow, }) if ch.ChannelId == channelId { diff --git a/cmd/psweb/ln/cln.go b/cmd/psweb/ln/cln.go index e005893..43aab0f 100644 --- a/cmd/psweb/ln/cln.go +++ b/cmd/psweb/ln/cln.go @@ -421,7 +421,7 @@ func CacheForwards() { forwardsIn[chIn] = append(forwardsIn[chIn], f) forwardsOut[chOut] = append(forwardsOut[chOut], f) // save for autofees - lastForwardTS[chOut] = int64(f.ResolvedTime) + LastForwardTS[chOut] = int64(f.ResolvedTime) } else { // catch not enough balance error if f.FailCode == 4103 { diff --git a/cmd/psweb/ln/common.go b/cmd/psweb/ln/common.go index 12f5d87..5853d97 100644 --- a/cmd/psweb/ln/common.go +++ b/cmd/psweb/ln/common.go @@ -85,6 +85,7 @@ type AutoFeeStatus struct { Custom bool FeeRate int64 InboundRate int64 + DaysNoFlow int } type AutoFeeParams struct { @@ -161,7 +162,7 @@ var ( } // track timestamp of the last outbound forward per channel - lastForwardTS = make(map[uint64]int64) + LastForwardTS = make(map[uint64]int64) // prevents starting another fee update while the first still running autoFeeIsRunning = false @@ -283,7 +284,7 @@ func calculateAutoFee(channelId uint64, params *AutoFeeParams, liqPct int, oldFe // see if cool-off period has passed if lastUpdate < time.Now().Add(-time.Duration(params.CoolOffHours)*time.Hour).Unix() { // check the inactivity period - if lastForwardTS[channelId] < time.Now().AddDate(0, 0, -params.InactivityDays).Unix() { + if LastForwardTS[channelId] < time.Now().AddDate(0, 0, -params.InactivityDays).Unix() { // decrease the fee newFee -= params.InactivityDropPPM newFee = newFee * (100 - params.InactivityDropPct) / 100 diff --git a/cmd/psweb/ln/lnd.go b/cmd/psweb/ln/lnd.go index e01c9f5..0981e9b 100644 --- a/cmd/psweb/ln/lnd.go +++ b/cmd/psweb/ln/lnd.go @@ -774,7 +774,7 @@ func downloadForwards(client lnrpc.LightningClient) { 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) + LastForwardTS[event.ChanIdOut] = int64(event.TimestampNs / 1_000_000_000) } } @@ -988,7 +988,7 @@ func subscribeForwards(ctx context.Context, client routerrpc.RouterClient) error // 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) + LastForwardTS[htlc.forwardingEvent.ChanIdOut] = int64(htlc.forwardingEvent.TimestampNs / 1_000_000_000) // execute autofee client, cleanup, err := GetClient() diff --git a/cmd/psweb/templates/af.gohtml b/cmd/psweb/templates/af.gohtml index 1df52ca..88b9678 100644 --- a/cmd/psweb/templates/af.gohtml +++ b/cmd/psweb/templates/af.gohtml @@ -297,6 +297,7 @@ % Out In + Flow Rule @@ -316,6 +317,13 @@ {{end}}{{end}}">{{fmt .LocalPct}} {{fs .FeeRate}} {{fs .InboundRate}} + {{.DaysNoFlow}} {{if .Enabled}}{{if .Custom}}*{{end}}{{.Rule}}{{end}} From f9a1da98e6bfa48e40a91a3203c796d9bf271160 Mon Sep 17 00:00:00 2001 From: Impa10r Date: Mon, 1 Jul 2024 14:51:10 +0200 Subject: [PATCH 5/8] Shrink width --- CHANGELOG.md | 1 + cmd/psweb/static/styles.css | 5 +++++ cmd/psweb/templates/af.gohtml | 16 ++++++++-------- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f44b291..5d7d16a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## 1.5.9 - Add get BTC receiving address and send with coin selection +- AutoFee: add column with days from the last outbound flow ## 1.5.8 diff --git a/cmd/psweb/static/styles.css b/cmd/psweb/static/styles.css index 0853c7f..e08c728 100644 --- a/cmd/psweb/static/styles.css +++ b/cmd/psweb/static/styles.css @@ -184,6 +184,11 @@ input[type=checkbox] { .input { padding: 0.5em; /* reduce padding inside input cells */ } + + th, td { + padding-left: 1px; + padding-right: 1px; + } } /* Style for the tooltip */ diff --git a/cmd/psweb/templates/af.gohtml b/cmd/psweb/templates/af.gohtml index 88b9678..37add98 100644 --- a/cmd/psweb/templates/af.gohtml +++ b/cmd/psweb/templates/af.gohtml @@ -91,7 +91,7 @@
- +
@@ -113,7 +113,7 @@
- +
@@ -135,7 +135,7 @@
- +
@@ -157,7 +157,7 @@
- +
@@ -179,7 +179,7 @@
- +
@@ -201,7 +201,7 @@ - +
@@ -293,9 +293,9 @@ Peer - Cap + Cap % - Out + Out In Flow 101 { - if config.Config.PeginClaimScript != "" { + if confs > 0 { + if config.Config.PeginClaimScript == "" { + log.Println("BTC withdrawal complete") + telegramSendMessage("BTC withdrawal complete") + } else if confs > 101 { // claim pegin failed := false proof := "" diff --git a/cmd/psweb/templates/af.gohtml b/cmd/psweb/templates/af.gohtml index 37add98..800144a 100644 --- a/cmd/psweb/templates/af.gohtml +++ b/cmd/psweb/templates/af.gohtml @@ -293,7 +293,7 @@ Peer - Cap + Cap % Out In From 5a216e5ad50f56eedca099be3300f05dcfb92da8 Mon Sep 17 00:00:00 2001 From: Impa10r Date: Wed, 3 Jul 2024 14:26:24 +0200 Subject: [PATCH 7/8] Fix pegin claim --- cmd/psweb/main.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/psweb/main.go b/cmd/psweb/main.go index 32a0ef1..7b5c841 100644 --- a/cmd/psweb/main.go +++ b/cmd/psweb/main.go @@ -1090,6 +1090,8 @@ func checkPegin() { log.Println("Peg-in success! Liquid TxId:", txid) telegramSendMessage("💸 Peg-in success!") } + } else { + return } // stop trying after one attempt From f088e6c531735ce5395bdd9965467691538dd298 Mon Sep 17 00:00:00 2001 From: Impa10r Date: Wed, 3 Jul 2024 17:15:11 +0200 Subject: [PATCH 8/8] Update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d7d16a..04a15f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,9 @@ ## 1.5.9 -- Add get BTC receiving address and send with coin selection +- Add get BTC receiving address and send BTC with coin selection - AutoFee: add column with days from the last outbound flow +- AutoFee: fix live outbound payments not registering for LND ## 1.5.8