From bcc8de476396359a423a562df1c3859c3e0c2cf8 Mon Sep 17 00:00:00 2001 From: Martin Boehm Date: Wed, 7 Feb 2018 19:59:09 +0100 Subject: [PATCH] Implement Bitcore socket.io method estimateSmartFee --- bchain/bitcoinrpc.go | 41 +++++++++++++++++++++ server/socketio.go | 82 ++++++++++++++++++++++++++++++++++------- server/static/test.html | 31 ++++++++++++++++ 3 files changed, 141 insertions(+), 13 deletions(-) diff --git a/bchain/bitcoinrpc.go b/bchain/bitcoinrpc.go index 4494eec7..7459a9a8 100644 --- a/bchain/bitcoinrpc.go +++ b/bchain/bitcoinrpc.go @@ -132,6 +132,24 @@ type resGetRawTransactionVerbose struct { Result Tx `json:"result"` } +// estimatesmartfee + +type cmdEstimateSmartFee struct { + Method string `json:"method"` + Params struct { + ConfTarget int `json:"conf_target"` + EstimateMode string `json:"estimate_mode"` + } `json:"params"` +} + +type resEstimateSmartFee struct { + Error *RPCError `json:"error"` + Result struct { + Feerate float64 `json:"feerate"` + Blocks int `json:"blocks"` + } `json:"result"` +} + type BlockParser interface { ParseBlock(b []byte) (*Block, error) } @@ -355,6 +373,29 @@ func (b *BitcoinRPC) GetTransaction(txid string) (*Tx, error) { return &res.Result, nil } +// EstimateSmartFee returns fee estimation. +func (b *BitcoinRPC) EstimateSmartFee(blocks int, conservative bool) (float64, error) { + glog.V(1).Info("rpc: estimatesmartfee ", blocks) + + res := resEstimateSmartFee{} + req := cmdEstimateSmartFee{Method: "estimatesmartfee"} + req.Params.ConfTarget = blocks + if conservative { + req.Params.EstimateMode = "CONSERVATIVE" + } else { + req.Params.EstimateMode = "ECONOMICAL" + } + err := b.call(&req, &res) + + if err != nil { + return 0, err + } + if res.Error != nil { + return 0, res.Error + } + return res.Result.Feerate, nil +} + func (b *BitcoinRPC) call(req interface{}, res interface{}) error { httpData, err := json.Marshal(req) if err != nil { diff --git a/server/socketio.go b/server/socketio.go index 11f5b087..b9be0957 100644 --- a/server/socketio.go +++ b/server/socketio.go @@ -103,21 +103,38 @@ type reqRange struct { To int `json:"to"` } +var onMessageHandlers = map[string]func(*SocketIoServer, json.RawMessage) (interface{}, error){ + "\"getAddressTxids\"": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) { + addr, rr, err := unmarshalGetAddressTxids(params) + if err == nil { + rv, err = s.getAddressTxids(addr, &rr) + } + return + }, + "\"getBlockHeader\"": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) { + height, hash, err := unmarshalGetBlockHeader(params) + if err == nil { + rv, err = s.getBlockHeader(height, hash) + } + return + }, + "\"estimateSmartFee\"": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) { + blocks, conservative, err := unmarshalEstimateSmartFee(params) + if err == nil { + rv, err = s.estimateSmartFee(blocks, conservative) + } + return + }, +} + func (s *SocketIoServer) onMessage(c *gosocketio.Channel, req map[string]json.RawMessage) interface{} { var err error var rv interface{} method := string(req["method"]) params := req["params"] - if method == "\"getAddressTxids\"" { - addr, rr, err := unmarshalGetAddressTxids(params) - if err == nil { - rv, err = s.getAddressTxids(addr, &rr) - } - } else if method == "\"getBlockHeader\"" { - height, hash, err := unmarshalGetBlockHeader(params) - if err == nil { - rv, err = s.getBlockHeader(height, hash) - } + f, ok := onMessageHandlers[method] + if ok { + rv, err = f(s, params) } else { err = errors.New("unknown method") } @@ -184,16 +201,23 @@ func (s *SocketIoServer) getAddressTxids(addr []string, rr *reqRange) ([]string, return txids, nil } -func unmarshalGetBlockHeader(params []byte) (height uint32, hash string, err error) { - var p []interface{} +func unmarshalArray(params []byte, np int) (p []interface{}, err error) { err = json.Unmarshal(params, &p) if err != nil { return } - if len(p) != 1 { + if len(p) != np { err = errors.New("incorrect number of parameters") return } + return +} + +func unmarshalGetBlockHeader(params []byte) (height uint32, hash string, err error) { + p, err := unmarshalArray(params, 1) + if err != nil { + return + } fheight, ok := p[0].(float64) if ok { return uint32(fheight), "", nil @@ -248,6 +272,38 @@ func (s *SocketIoServer) getBlockHeader(height uint32, hash string) (res resultG return } +func unmarshalEstimateSmartFee(params []byte) (blocks int, conservative bool, err error) { + p, err := unmarshalArray(params, 2) + if err != nil { + return + } + fblocks, ok := p[0].(float64) + if !ok { + err = errors.New("Invalid parameter blocks") + return + } + blocks = int(fblocks) + conservative, ok = p[1].(bool) + if !ok { + err = errors.New("Invalid parameter conservative") + return + } + return +} + +type resultEstimateSmartFee struct { + Result float64 `json:"result"` +} + +func (s *SocketIoServer) estimateSmartFee(blocks int, conservative bool) (res resultEstimateSmartFee, err error) { + fee, err := s.chain.EstimateSmartFee(blocks, conservative) + if err != nil { + return + } + res.Result = fee + return +} + func (s *SocketIoServer) onSubscribe(c *gosocketio.Channel, req map[string]json.RawMessage) interface{} { glog.Info(c.Id(), " onSubscribe ", req) return nil diff --git a/server/static/test.html b/server/static/test.html index 475e9b4e..5eee039a 100644 --- a/server/static/test.html +++ b/server/static/test.html @@ -66,6 +66,21 @@ return socket.send({ method, params }, f); } + function estimateSmartFee() { + var blocks = document.getElementById('estimateSmartFeeBlocks').value; + var conservative = document.getElementById("estimateSmartFeeConservative").checked; + estimateSmartTxFee(parseInt(blocks), conservative, function (result) { + console.log('estimateSmartFee sent successfully'); + console.log(result); + document.getElementById('estimateSmartFeeResult').innerText = JSON.stringify(result).replace(/,/g, ", "); + }); + } + + function estimateSmartTxFee(blocks, conservative, f) { + const method = 'estimateSmartFee'; + const params = [blocks, conservative]; + return socket.send({ method, params }, f); + } @@ -115,6 +130,22 @@
+
+
+ +
+
+ +
+
+   + +
+
+
+
+
+