@@ -19,7 +19,6 @@ import (
19
19
"peerswap-web/cmd/psweb/bitcoin"
20
20
"peerswap-web/cmd/psweb/config"
21
21
"peerswap-web/cmd/psweb/db"
22
- "peerswap-web/cmd/psweb/internet"
23
22
"peerswap-web/cmd/psweb/liquid"
24
23
"peerswap-web/cmd/psweb/ln"
25
24
"peerswap-web/cmd/psweb/ps"
@@ -486,6 +485,13 @@ func bitcoinHandler(w http.ResponseWriter, r *http.Request) {
486
485
popupMessage = keys [0 ]
487
486
}
488
487
488
+ // newly genetated address
489
+ addr := ""
490
+ keys , ok = r .URL .Query ()["addr" ]
491
+ if ok && len (keys [0 ]) > 0 {
492
+ addr = keys [0 ]
493
+ }
494
+
489
495
var utxos []ln.UTXO
490
496
cl , clean , er := ln .GetClient ()
491
497
if er != nil {
@@ -502,6 +508,7 @@ func bitcoinHandler(w http.ResponseWriter, r *http.Request) {
502
508
BitcoinBalance uint64
503
509
Outputs * []ln.UTXO
504
510
PeginTxId string
511
+ IsPegin bool // false for ordinary BTC withdrawal
505
512
PeginAmount uint64
506
513
BitcoinApi string
507
514
Confirmations int32
@@ -515,6 +522,7 @@ func bitcoinHandler(w http.ResponseWriter, r *http.Request) {
515
522
CanBump bool
516
523
CanRBF bool
517
524
IsCLN bool
525
+ BitcoinAddress string
518
526
}
519
527
520
528
btcBalance := ln .ConfirmedWalletBalance (cl )
@@ -536,8 +544,8 @@ func bitcoinHandler(w http.ResponseWriter, r *http.Request) {
536
544
fee = fee + fee / 2
537
545
}
538
546
}
539
- if fee < config .Config .PeginFeeRate + 1 {
540
- fee = config .Config .PeginFeeRate + 1 // min increment
547
+ if fee < config .Config .PeginFeeRate + 2 {
548
+ fee = config .Config .PeginFeeRate + 2 // min increment
541
549
}
542
550
}
543
551
}
@@ -554,6 +562,7 @@ func bitcoinHandler(w http.ResponseWriter, r *http.Request) {
554
562
BitcoinBalance : uint64 (btcBalance ),
555
563
Outputs : & utxos ,
556
564
PeginTxId : config .Config .PeginTxId ,
565
+ IsPegin : config .Config .PeginClaimScript != "" ,
557
566
PeginAmount : uint64 (config .Config .PeginAmount ),
558
567
BitcoinApi : config .Config .BitcoinApi ,
559
568
Confirmations : confs ,
@@ -563,16 +572,18 @@ func bitcoinHandler(w http.ResponseWriter, r *http.Request) {
563
572
MempoolFeeRate : mempoolFeeRate ,
564
573
LiquidFeeRate : liquid .EstimateFee (),
565
574
SuggestedFeeRate : fee ,
566
- MinBumpFeeRate : config .Config .PeginFeeRate + 1 ,
575
+ MinBumpFeeRate : config .Config .PeginFeeRate + 2 ,
567
576
CanBump : canBump ,
568
577
CanRBF : ln .CanRBF (),
569
578
IsCLN : ln .Implementation == "CLN" ,
579
+ BitcoinAddress : addr ,
570
580
}
571
581
572
582
// executing template named "bitcoin"
573
583
executeTemplate (w , "bitcoin" , data )
574
584
}
575
585
586
+ // handles Liquid pegin and Bitcoin send form
576
587
func peginHandler (w http.ResponseWriter , r * http.Request ) {
577
588
if r .Method == http .MethodPost {
578
589
// Parse the form data
@@ -595,6 +606,7 @@ func peginHandler(w http.ResponseWriter, r *http.Request) {
595
606
596
607
selectedOutputs := r .Form ["selected_outputs[]" ]
597
608
subtractFeeFromAmount := r .FormValue ("subtractfee" ) == "on"
609
+ isPegin := r .FormValue ("isPegin" ) == "true"
598
610
599
611
totalAmount := int64 (0 )
600
612
@@ -638,69 +650,79 @@ func peginHandler(w http.ResponseWriter, r *http.Request) {
638
650
return
639
651
}
640
652
641
- // test on pre-existing tx that bitcon core can complete the peg
642
- tx := "b61ec844027ce18fd3eb91fa7bed8abaa6809c4d3f6cf4952b8ebaa7cd46583a"
643
- if config .Config .Chain == "testnet" {
644
- tx = "2c7ec5043fe8ee3cb4ce623212c0e52087d3151c9e882a04073cce1688d6fc1e"
645
- }
653
+ address := ""
654
+ claimScript := ""
655
+
656
+ if isPegin {
657
+ // test on pre-existing tx that bitcon core can complete the peg
658
+ tx := "b61ec844027ce18fd3eb91fa7bed8abaa6809c4d3f6cf4952b8ebaa7cd46583a"
659
+ if config .Config .Chain == "testnet" {
660
+ tx = "2c7ec5043fe8ee3cb4ce623212c0e52087d3151c9e882a04073cce1688d6fc1e"
661
+ }
646
662
647
- _ , err = bitcoin .GetTxOutProof (tx )
648
- if err != nil {
649
- // automatic fallback to getblock.io
650
- config .Config .BitcoinHost = config .GetBlockIoHost ()
651
- config .Config .BitcoinUser = ""
652
- config .Config .BitcoinPass = ""
653
663
_ , err = bitcoin .GetTxOutProof (tx )
654
664
if err != nil {
655
- redirectWithError (w , r , "/bitcoin?" , errors .New ("GetTxOutProof failed, check BitcoinHost in Config" ))
656
- return
657
- } else {
658
- // use getblock.io endpoint going forward
659
- log .Println ("Switching to getblock.io bitcoin host endpoint" )
660
- if err := config .Save (); err != nil {
661
- log .Println ("Error saving config file:" , err )
662
- redirectWithError (w , r , "/bitcoin?" , err )
665
+ // automatic fallback to getblock.io
666
+ config .Config .BitcoinHost = config .GetBlockIoHost ()
667
+ config .Config .BitcoinUser = ""
668
+ config .Config .BitcoinPass = ""
669
+ _ , err = bitcoin .GetTxOutProof (tx )
670
+ if err != nil {
671
+ redirectWithError (w , r , "/bitcoin?" , errors .New ("GetTxOutProof failed, check BitcoinHost in Config" ))
663
672
return
673
+ } else {
674
+ // use getblock.io endpoint going forward
675
+ log .Println ("Switching to getblock.io bitcoin host endpoint" )
676
+ if err := config .Save (); err != nil {
677
+ redirectWithError (w , r , "/bitcoin?" , err )
678
+ return
679
+ }
664
680
}
665
681
}
666
- }
667
682
668
- var addr liquid.PeginAddress
683
+ var addr liquid.PeginAddress
669
684
670
- err = liquid .GetPeginAddress (& addr )
671
- if err != nil {
672
- redirectWithError (w , r , "/bitcoin?" , err )
673
- return
685
+ err = liquid .GetPeginAddress (& addr )
686
+ if err != nil {
687
+ redirectWithError (w , r , "/bitcoin?" , err )
688
+ return
689
+ }
690
+
691
+ address = addr .MainChainAddress
692
+ claimScript = addr .ClaimScript
693
+ } else {
694
+ address = r .FormValue ("sendAddress" )
695
+ claimScript = ""
674
696
}
675
697
676
- res , err := ln .SendCoinsWithUtxos (& selectedOutputs , addr . MainChainAddress , amount , fee , subtractFeeFromAmount )
698
+ res , err := ln .SendCoinsWithUtxos (& selectedOutputs , address , amount , fee , subtractFeeFromAmount )
677
699
if err != nil {
678
700
redirectWithError (w , r , "/bitcoin?" , err )
679
701
return
680
702
}
681
703
682
- // to speed things up, also broadcast it to mempool.space
683
- internet .SendRawTransaction (res .RawHex )
684
-
685
- log .Println ("Peg-in TxId:" , res .TxId , "RawHex:" , res .RawHex , "Claim script:" , addr .ClaimScript )
686
- duration := time .Duration (1020 ) * time .Minute
687
- formattedDuration := time.Time {}.Add (duration ).Format ("15h 04m" )
704
+ if isPegin {
705
+ log .Println ("Peg-in TxId:" , res .TxId , "RawHex:" , res .RawHex , "Claim script:" , claimScript )
706
+ duration := time .Duration (1020 ) * time .Minute
707
+ formattedDuration := time.Time {}.Add (duration ).Format ("15h 04m" )
708
+ telegramSendMessage ("⏰ Started peg-in " + formatWithThousandSeparators (uint64 (res .AmountSat )) + " sats. Time left: " + formattedDuration )
709
+ } else {
710
+ log .Println ("BTC withdrawal TxId:" , res .TxId , "RawHex:" , res .RawHex )
711
+ telegramSendMessage ("BTC withdrawal pending: " + formatWithThousandSeparators (uint64 (res .AmountSat )) + " sats." )
712
+ }
688
713
689
- config .Config .PeginClaimScript = addr . ClaimScript
690
- config .Config .PeginAddress = addr . MainChainAddress
714
+ config .Config .PeginClaimScript = claimScript
715
+ config .Config .PeginAddress = address
691
716
config .Config .PeginAmount = res .AmountSat
692
717
config .Config .PeginTxId = res .TxId
693
718
config .Config .PeginReplacedTxId = ""
694
719
config .Config .PeginFeeRate = uint32 (fee )
695
720
696
721
if err := config .Save (); err != nil {
697
- log .Println ("Error saving config file:" , err )
698
722
redirectWithError (w , r , "/bitcoin?" , err )
699
723
return
700
724
}
701
725
702
- telegramSendMessage ("⏰ Started peg-in " + formatWithThousandSeparators (uint64 (res .AmountSat )) + " sats. Time left: " + formattedDuration )
703
-
704
726
// Redirect to bitcoin page to follow the pegin progress
705
727
http .Redirect (w , r , "/bitcoin" , http .StatusSeeOther )
706
728
} else {
@@ -748,9 +770,6 @@ func bumpfeeHandler(w http.ResponseWriter, r *http.Request) {
748
770
}
749
771
750
772
if ln .CanRBF () {
751
- // to speed things up, also broadcast it to mempool.space
752
- internet .SendRawTransaction (res .RawHex )
753
-
754
773
log .Println ("RBF TxId:" , res .TxId )
755
774
config .Config .PeginReplacedTxId = config .Config .PeginTxId
756
775
config .Config .PeginAmount = res .AmountSat
@@ -764,7 +783,6 @@ func bumpfeeHandler(w http.ResponseWriter, r *http.Request) {
764
783
config .Config .PeginFeeRate = uint32 (fee )
765
784
766
785
if err := config .Save (); err != nil {
767
- log .Println ("Error saving config file:" , err )
768
786
redirectWithError (w , r , "/bitcoin?" , err )
769
787
return
770
788
}
@@ -833,13 +851,19 @@ func afHandler(w http.ResponseWriter, r *http.Request) {
833
851
localPct := uint64 (0 )
834
852
feeRate := outboundFeeRates [channelId ]
835
853
inboundRate := inboundFeeRates [channelId ]
854
+ currentTime := time .Now ()
836
855
837
856
for _ , peer := range res .GetPeers () {
838
857
alias := getNodeAlias (peer .NodeId )
839
858
for _ , ch := range peer .Channels {
840
859
rule , custom := ln .AutoFeeRatesSummary (ch .ChannelId )
841
860
af , _ := ln .AutoFeeRule (ch .ChannelId )
842
861
peerNodeId [ch .ChannelId ] = peer .NodeId
862
+ daysNoFlow := 999
863
+ ts , ok := ln .LastForwardTS [ch .ChannelId ]
864
+ if ok {
865
+ daysNoFlow = int (currentTime .Sub (time .Unix (ts , 0 )).Hours () / 24 )
866
+ }
843
867
844
868
channelList = append (channelList , & ln.AutoFeeStatus {
845
869
Enabled : ln .AutoFeeEnabled [ch .ChannelId ],
@@ -852,6 +876,7 @@ func afHandler(w http.ResponseWriter, r *http.Request) {
852
876
FeeRate : outboundFeeRates [ch .ChannelId ],
853
877
InboundRate : inboundFeeRates [ch .ChannelId ],
854
878
ChannelId : ch .ChannelId ,
879
+ DaysNoFlow : daysNoFlow ,
855
880
})
856
881
857
882
if ch .ChannelId == channelId {
@@ -1444,6 +1469,17 @@ func submitHandler(w http.ResponseWriter, r *http.Request) {
1444
1469
defer cleanup ()
1445
1470
1446
1471
switch action {
1472
+ case "deleteTxId" :
1473
+ // acknowledges BTC withdrawal
1474
+ config .Config .PeginTxId = ""
1475
+ if err := config .Save (); err != nil {
1476
+ redirectWithError (w , r , "/bitcoin?" , err )
1477
+ return
1478
+ }
1479
+
1480
+ // all done
1481
+ http .Redirect (w , r , "/" , http .StatusSeeOther )
1482
+ return
1447
1483
case "saveAutoFee" :
1448
1484
channelId , err := strconv .ParseUint (r .FormValue ("channelId" ), 10 , 64 )
1449
1485
if err != nil {
@@ -1845,7 +1881,6 @@ func submitHandler(w http.ResponseWriter, r *http.Request) {
1845
1881
1846
1882
// Save config
1847
1883
if err := config .Save (); err != nil {
1848
- log .Println ("Error saving config file:" , err )
1849
1884
redirectWithError (w , r , "/liquid?" , err )
1850
1885
return
1851
1886
}
@@ -1854,6 +1889,18 @@ func submitHandler(w http.ResponseWriter, r *http.Request) {
1854
1889
http .Redirect (w , r , "/liquid?msg=" + msg , http .StatusSeeOther )
1855
1890
return
1856
1891
1892
+ case "newBitcoinAddress" :
1893
+ addr , err := ln .NewAddress ()
1894
+ if err != nil {
1895
+ log .Printf ("unable to connect to RPC server: %v" , err )
1896
+ redirectWithError (w , r , "/bitcoin?" , err )
1897
+ return
1898
+ }
1899
+
1900
+ // Redirect to bitcoin page with new address
1901
+ http .Redirect (w , r , "/bitcoin?addr=" + addr , http .StatusSeeOther )
1902
+ return
1903
+
1857
1904
case "newAddress" :
1858
1905
res , err := ps .LiquidGetAddress (client )
1859
1906
if err != nil {
@@ -2012,7 +2059,10 @@ func saveConfigHandler(w http.ResponseWriter, r *http.Request) {
2012
2059
// display CA certificate installation instructions
2013
2060
if secureConnection && ! config .Config .SecureConnection {
2014
2061
config .Config .ServerIPs = r .FormValue ("serverIPs" )
2015
- config .Save ()
2062
+ if err := config .Save (); err != nil {
2063
+ redirectWithError (w , r , "/config?" , err )
2064
+ return
2065
+ }
2016
2066
http .Redirect (w , r , "/ca" , http .StatusSeeOther )
2017
2067
return
2018
2068
}
@@ -2105,15 +2155,13 @@ func saveConfigHandler(w http.ResponseWriter, r *http.Request) {
2105
2155
}
2106
2156
2107
2157
if err := config .Save (); err != nil {
2108
- log .Println ("Error saving config file:" , err )
2109
2158
redirectWithError (w , r , "/config?" , err )
2110
2159
return
2111
2160
}
2112
2161
2113
2162
if mustRestart {
2114
2163
// show progress bar and log
2115
2164
go http .Redirect (w , r , "/loading" , http .StatusSeeOther )
2116
- config .SavePS ()
2117
2165
ps .Stop ()
2118
2166
} else if clientIsDown { // configs did not work, try again
2119
2167
redirectWithError (w , r , "/config?" , err )
0 commit comments