github.com/decred/dcrlnd@v0.7.6/lntest/fee_service.go (about) 1 package lntest 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "io" 8 "net/http" 9 "sync" 10 11 "github.com/decred/dcrlnd/lnwallet/chainfee" 12 ) 13 14 const ( 15 // feeServiceTarget is the confirmation target for which a fee estimate 16 // is returned. Requests for higher confirmation targets will fall back 17 // to this. 18 feeServiceTarget = 1 19 ) 20 21 // feeService runs a web service that provides fee estimation information. 22 type feeService struct { 23 feeEstimates 24 25 srv *http.Server 26 wg sync.WaitGroup 27 28 url string 29 30 lock sync.Mutex 31 } 32 33 // feeEstimates contains the current fee estimates. 34 type feeEstimates struct { 35 Fees map[uint32]uint32 `json:"fee_by_block_target"` 36 } 37 38 // startFeeService spins up a go-routine to serve fee estimates. 39 func startFeeService() *feeService { 40 port := NextAvailablePort() 41 f := feeService{ 42 url: fmt.Sprintf("http://localhost:%v/fee-estimates.json", port), 43 } 44 45 // Initialize default fee estimate. 46 f.Fees = map[uint32]uint32{feeServiceTarget: 1e4} 47 48 listenAddr := fmt.Sprintf(":%v", port) 49 mux := http.NewServeMux() 50 mux.HandleFunc("/fee-estimates.json", f.handleRequest) 51 52 f.srv = &http.Server{ 53 Addr: listenAddr, 54 Handler: mux, 55 } 56 57 f.wg.Add(1) 58 go func() { 59 defer f.wg.Done() 60 61 if err := f.srv.ListenAndServe(); err != http.ErrServerClosed { 62 fmt.Printf("error: cannot start fee api: %v", err) 63 } 64 }() 65 66 return &f 67 } 68 69 // handleRequest handles a client request for fee estimates. 70 func (f *feeService) handleRequest(w http.ResponseWriter, r *http.Request) { 71 f.lock.Lock() 72 defer f.lock.Unlock() 73 74 bytes, err := json.Marshal(f.feeEstimates) 75 if err != nil { 76 fmt.Printf("error: cannot serialize "+ 77 "estimates: %v", err) 78 79 return 80 } 81 82 _, err = io.WriteString(w, string(bytes)) 83 if err != nil { 84 fmt.Printf("error: cannot send estimates: %v", 85 err) 86 } 87 } 88 89 // stop stops the web server. 90 func (f *feeService) stop() { 91 if err := f.srv.Shutdown(context.Background()); err != nil { 92 fmt.Printf("error: cannot stop fee api: %v", err) 93 } 94 95 f.wg.Wait() 96 } 97 98 // setFee changes the current fee estimate for the fixed confirmation target. 99 func (f *feeService) setFee(fee chainfee.AtomPerKByte) { 100 f.lock.Lock() 101 defer f.lock.Unlock() 102 103 f.Fees[feeServiceTarget] = uint32(fee) 104 } 105 106 // setFeeWithConf sets a fee for the given confirmation target. 107 func (f *feeService) setFeeWithConf(fee chainfee.AtomPerKByte, conf uint32) { 108 f.lock.Lock() 109 defer f.lock.Unlock() 110 111 f.Fees[conf] = uint32(fee) 112 }