You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
110 lines
2.3 KiB
110 lines
2.3 KiB
package lntest |
|
|
|
import ( |
|
"context" |
|
"encoding/json" |
|
"fmt" |
|
"io" |
|
"net/http" |
|
"sync" |
|
|
|
"github.com/lightningnetwork/lnd/lnwallet/chainfee" |
|
) |
|
|
|
const ( |
|
// feeServiceTarget is the confirmation target for which a fee estimate |
|
// is returned. Requests for higher confirmation targets will fall back |
|
// to this. |
|
feeServiceTarget = 1 |
|
) |
|
|
|
// feeService runs a web service that provides fee estimation information. |
|
type feeService struct { |
|
feeEstimates |
|
|
|
srv *http.Server |
|
wg sync.WaitGroup |
|
|
|
url string |
|
|
|
lock sync.Mutex |
|
} |
|
|
|
// feeEstimates contains the current fee estimates. |
|
type feeEstimates struct { |
|
Fees map[uint32]uint32 `json:"fee_by_block_target"` |
|
} |
|
|
|
// startFeeService spins up a go-routine to serve fee estimates. |
|
func startFeeService() *feeService { |
|
port := NextAvailablePort() |
|
f := feeService{ |
|
url: fmt.Sprintf("http://localhost:%v/fee-estimates.json", port), |
|
} |
|
|
|
// Initialize default fee estimate. |
|
f.Fees = map[uint32]uint32{feeServiceTarget: 50000} |
|
|
|
listenAddr := fmt.Sprintf(":%v", port) |
|
f.srv = &http.Server{ |
|
Addr: listenAddr, |
|
} |
|
|
|
http.HandleFunc("/fee-estimates.json", f.handleRequest) |
|
|
|
f.wg.Add(1) |
|
go func() { |
|
defer f.wg.Done() |
|
|
|
if err := f.srv.ListenAndServe(); err != http.ErrServerClosed { |
|
fmt.Printf("error: cannot start fee api: %v", err) |
|
} |
|
}() |
|
|
|
return &f |
|
} |
|
|
|
// handleRequest handles a client request for fee estimates. |
|
func (f *feeService) handleRequest(w http.ResponseWriter, r *http.Request) { |
|
f.lock.Lock() |
|
defer f.lock.Unlock() |
|
|
|
bytes, err := json.Marshal(f.feeEstimates) |
|
if err != nil { |
|
fmt.Printf("error: cannot serialize "+ |
|
"estimates: %v", err) |
|
|
|
return |
|
} |
|
|
|
_, err = io.WriteString(w, string(bytes)) |
|
if err != nil { |
|
fmt.Printf("error: cannot send estimates: %v", |
|
err) |
|
} |
|
} |
|
|
|
// stop stops the web server. |
|
func (f *feeService) stop() { |
|
if err := f.srv.Shutdown(context.Background()); err != nil { |
|
fmt.Printf("error: cannot stop fee api: %v", err) |
|
} |
|
|
|
f.wg.Wait() |
|
} |
|
|
|
// setFee changes the current fee estimate for the fixed confirmation target. |
|
func (f *feeService) setFee(fee chainfee.SatPerKWeight) { |
|
f.lock.Lock() |
|
defer f.lock.Unlock() |
|
|
|
f.Fees[feeServiceTarget] = uint32(fee.FeePerKVByte()) |
|
} |
|
|
|
// setFeeWithConf sets a fee for the given confirmation target. |
|
func (f *feeService) setFeeWithConf(fee chainfee.SatPerKWeight, conf uint32) { |
|
f.lock.Lock() |
|
defer f.lock.Unlock() |
|
|
|
f.Fees[conf] = uint32(fee.FeePerKVByte()) |
|
}
|
|
|