Implement REST interface to mempool transactions
This commit is contained in:
parent
1f36acc084
commit
2605f2fc1d
@ -121,9 +121,9 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var httpServer *server.HttpServer
|
var httpServer *server.HTTPServer
|
||||||
if *httpServerBinding != "" {
|
if *httpServerBinding != "" {
|
||||||
httpServer, err = server.New(*httpServerBinding, index)
|
httpServer, err = server.NewHTTPServer(*httpServerBinding, index, mempool)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Fatal("https: ", err)
|
glog.Fatal("https: ", err)
|
||||||
}
|
}
|
||||||
@ -248,7 +248,7 @@ func mqHandler(m *bchain.MQMessage) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func waitForSignalAndShutdown(s *server.HttpServer, mq *bchain.MQ, timeout time.Duration) {
|
func waitForSignalAndShutdown(s *server.HTTPServer, mq *bchain.MQ, timeout time.Duration) {
|
||||||
stop := make(chan os.Signal, 1)
|
stop := make(chan os.Signal, 1)
|
||||||
signal.Notify(stop, syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)
|
signal.Notify(stop, syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)
|
||||||
|
|
||||||
|
|||||||
110
server/https.go
110
server/https.go
@ -16,26 +16,31 @@ import (
|
|||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HttpServer struct {
|
// HTTPServer is handle to HttpServer
|
||||||
https *http.Server
|
type HTTPServer struct {
|
||||||
db *db.RocksDB
|
https *http.Server
|
||||||
|
db *db.RocksDB
|
||||||
|
mempool *bchain.Mempool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(httpServerBinding string, db *db.RocksDB) (*HttpServer, error) {
|
// NewHTTPServer creates new REST interface to blockbook and returns its handle
|
||||||
|
func NewHTTPServer(httpServerBinding string, db *db.RocksDB, mempool *bchain.Mempool) (*HTTPServer, error) {
|
||||||
https := &http.Server{
|
https := &http.Server{
|
||||||
Addr: httpServerBinding,
|
Addr: httpServerBinding,
|
||||||
}
|
}
|
||||||
s := &HttpServer{
|
s := &HTTPServer{
|
||||||
https: https,
|
https: https,
|
||||||
db: db,
|
db: db,
|
||||||
|
mempool: mempool,
|
||||||
}
|
}
|
||||||
|
|
||||||
r := mux.NewRouter()
|
r := mux.NewRouter()
|
||||||
|
|
||||||
r.HandleFunc("/", s.info)
|
r.HandleFunc("/", s.info)
|
||||||
r.HandleFunc("/bestBlockHash", s.bestBlockHash)
|
r.HandleFunc("/bestBlockHash", s.bestBlockHash)
|
||||||
r.HandleFunc("/blockHash/{height}", s.blockHash)
|
r.HandleFunc("/blockHash/{height}", s.blockHash)
|
||||||
r.HandleFunc("/transactions/{address}/{lower}/{higher}", s.transactions)
|
r.HandleFunc("/transactions/{address}/{lower}/{higher}", s.transactions)
|
||||||
|
r.HandleFunc("/confirmedTransactions/{address}/{lower}/{higher}", s.confirmedTransactions)
|
||||||
|
r.HandleFunc("/unconfirmedTransactions/{address}", s.unconfirmedTransactions)
|
||||||
|
|
||||||
var h http.Handler = r
|
var h http.Handler = r
|
||||||
h = handlers.LoggingHandler(os.Stderr, h)
|
h = handlers.LoggingHandler(os.Stderr, h)
|
||||||
@ -45,26 +50,26 @@ func New(httpServerBinding string, db *db.RocksDB) (*HttpServer, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run starts the server
|
// Run starts the server
|
||||||
func (s *HttpServer) Run() error {
|
func (s *HTTPServer) Run() error {
|
||||||
glog.Infof("http server starting to listen on %s", s.https.Addr)
|
glog.Infof("http server starting to listen on %s", s.https.Addr)
|
||||||
return s.https.ListenAndServe()
|
return s.https.ListenAndServe()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes the server
|
// Close closes the server
|
||||||
func (s *HttpServer) Close() error {
|
func (s *HTTPServer) Close() error {
|
||||||
glog.Infof("http server closing")
|
glog.Infof("http server closing")
|
||||||
return s.https.Close()
|
return s.https.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown shuts down the server
|
// Shutdown shuts down the server
|
||||||
func (s *HttpServer) Shutdown(ctx context.Context) error {
|
func (s *HTTPServer) Shutdown(ctx context.Context) error {
|
||||||
glog.Infof("http server shutdown")
|
glog.Infof("http server shutdown")
|
||||||
return s.https.Shutdown(ctx)
|
return s.https.Shutdown(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func respondError(w http.ResponseWriter, err error, context string) {
|
func respondError(w http.ResponseWriter, err error, context string) {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
glog.Errorf("http server %s error: %v", context, err)
|
glog.Errorf("http server (context %s) error: %v", context, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func respondHashData(w http.ResponseWriter, hash string) {
|
func respondHashData(w http.ResponseWriter, hash string) {
|
||||||
@ -76,7 +81,7 @@ func respondHashData(w http.ResponseWriter, hash string) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HttpServer) info(w http.ResponseWriter, r *http.Request) {
|
func (s *HTTPServer) info(w http.ResponseWriter, r *http.Request) {
|
||||||
type info struct {
|
type info struct {
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
BestBlockHeight uint32 `json:"bestBlockHeight"`
|
BestBlockHeight uint32 `json:"bestBlockHeight"`
|
||||||
@ -95,7 +100,7 @@ func (s *HttpServer) info(w http.ResponseWriter, r *http.Request) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HttpServer) bestBlockHash(w http.ResponseWriter, r *http.Request) {
|
func (s *HTTPServer) bestBlockHash(w http.ResponseWriter, r *http.Request) {
|
||||||
_, hash, err := s.db.GetBestBlock()
|
_, hash, err := s.db.GetBestBlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondError(w, err, "bestBlockHash")
|
respondError(w, err, "bestBlockHash")
|
||||||
@ -104,7 +109,7 @@ func (s *HttpServer) bestBlockHash(w http.ResponseWriter, r *http.Request) {
|
|||||||
respondHashData(w, hash)
|
respondHashData(w, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HttpServer) blockHash(w http.ResponseWriter, r *http.Request) {
|
func (s *HTTPServer) blockHash(w http.ResponseWriter, r *http.Request) {
|
||||||
heightString := mux.Vars(r)["height"]
|
heightString := mux.Vars(r)["height"]
|
||||||
var hash string
|
var hash string
|
||||||
height, err := strconv.ParseUint(heightString, 10, 32)
|
height, err := strconv.ParseUint(heightString, 10, 32)
|
||||||
@ -118,31 +123,78 @@ func (s *HttpServer) blockHash(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HttpServer) transactions(w http.ResponseWriter, r *http.Request) {
|
func getAddress(r *http.Request) (address string, script []byte, err error) {
|
||||||
type transactionList struct {
|
address = mux.Vars(r)["address"]
|
||||||
Txid []string `json:"txid"`
|
script, err = bchain.AddressToOutputScript(address)
|
||||||
}
|
return
|
||||||
address := mux.Vars(r)["address"]
|
}
|
||||||
higher, err := strconv.ParseUint(mux.Vars(r)["higher"], 10, 32)
|
|
||||||
|
func getAddressAndHeightRange(r *http.Request) (address string, script []byte, lower, higher uint32, err error) {
|
||||||
|
address, script, err = getAddress(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondError(w, err, fmt.Sprintf("address %s", address))
|
return
|
||||||
}
|
}
|
||||||
lower, err := strconv.ParseUint(mux.Vars(r)["lower"], 10, 32)
|
higher64, err := strconv.ParseUint(mux.Vars(r)["higher"], 10, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondError(w, err, fmt.Sprintf("address %s", address))
|
return
|
||||||
}
|
}
|
||||||
script, err := bchain.AddressToOutputScript(address)
|
lower64, err := strconv.ParseUint(mux.Vars(r)["lower"], 10, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondError(w, err, fmt.Sprintf("address %s", address))
|
return
|
||||||
|
}
|
||||||
|
return address, script, uint32(lower64), uint32(higher64), err
|
||||||
|
}
|
||||||
|
|
||||||
|
type transactionList struct {
|
||||||
|
Txid []string `json:"txid"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *HTTPServer) unconfirmedTransactions(w http.ResponseWriter, r *http.Request) {
|
||||||
|
address, script, err := getAddress(r)
|
||||||
|
if err != nil {
|
||||||
|
respondError(w, err, fmt.Sprint("unconfirmedTransactions for address", address))
|
||||||
|
}
|
||||||
|
txs, err := s.mempool.GetTransactions(script)
|
||||||
|
if err != nil {
|
||||||
|
respondError(w, err, fmt.Sprint("unconfirmedTransactions for address", address))
|
||||||
|
}
|
||||||
|
txList := transactionList{Txid: txs}
|
||||||
|
json.NewEncoder(w).Encode(txList)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *HTTPServer) confirmedTransactions(w http.ResponseWriter, r *http.Request) {
|
||||||
|
address, script, lower, higher, err := getAddressAndHeightRange(r)
|
||||||
|
if err != nil {
|
||||||
|
respondError(w, err, fmt.Sprint("confirmedTransactions for address", address))
|
||||||
}
|
}
|
||||||
txList := transactionList{}
|
txList := transactionList{}
|
||||||
err = s.db.GetTransactions(script, uint32(lower), uint32(higher), func(txid string) error {
|
err = s.db.GetTransactions(script, lower, higher, func(txid string) error {
|
||||||
txList.Txid = append(txList.Txid, txid)
|
txList.Txid = append(txList.Txid, txid)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondError(w, err, fmt.Sprintf("address %s", address))
|
respondError(w, err, fmt.Sprint("confirmedTransactions for address", address))
|
||||||
}
|
}
|
||||||
json.NewEncoder(w).Encode(txList)
|
json.NewEncoder(w).Encode(txList)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *HTTPServer) transactions(w http.ResponseWriter, r *http.Request) {
|
||||||
|
address, script, lower, higher, err := getAddressAndHeightRange(r)
|
||||||
|
if err != nil {
|
||||||
|
respondError(w, err, fmt.Sprint("transactions for address", address))
|
||||||
|
}
|
||||||
|
txList := transactionList{}
|
||||||
|
err = s.db.GetTransactions(script, lower, higher, func(txid string) error {
|
||||||
|
txList.Txid = append(txList.Txid, txid)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
respondError(w, err, fmt.Sprint("transactions for address", address))
|
||||||
|
}
|
||||||
|
txs, err := s.mempool.GetTransactions(script)
|
||||||
|
if err != nil {
|
||||||
|
respondError(w, err, fmt.Sprint("transactions for address", address))
|
||||||
|
}
|
||||||
|
txList.Txid = append(txList.Txid, txs...)
|
||||||
|
json.NewEncoder(w).Encode(txList)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user