Implement apiSendTx and apiEstimateFee
parent
db35a51dde
commit
d1176e17d1
|
@ -9,6 +9,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"runtime"
|
||||
|
@ -128,6 +129,8 @@ func (s *PublicServer) ConnectFullPublicInterface() {
|
|||
serveMux.HandleFunc(path+"api/tx-specific/", s.jsonHandler(s.apiTxSpecific))
|
||||
serveMux.HandleFunc(path+"api/address/", s.jsonHandler(s.apiAddress))
|
||||
serveMux.HandleFunc(path+"api/block/", s.jsonHandler(s.apiBlock))
|
||||
serveMux.HandleFunc(path+"api/sendtx/", s.jsonHandler(s.apiSendTx))
|
||||
serveMux.HandleFunc(path+"api/estimatefee/", s.jsonHandler(s.apiEstimateFee))
|
||||
// socket.io interface
|
||||
serveMux.Handle(path+"socket.io/", s.socketio.GetHandler())
|
||||
}
|
||||
|
@ -217,7 +220,11 @@ func (s *PublicServer) jsonHandler(handler func(r *http.Request) (interface{}, e
|
|||
glog.Error(getFunctionName(handler), " error: ", err)
|
||||
}
|
||||
if s.debug {
|
||||
data = jsonError{fmt.Sprintf("Internal server error: %v, data %+v", err, data)}
|
||||
if data != nil {
|
||||
data = jsonError{fmt.Sprintf("Internal server error: %v, data %+v", err, data)}
|
||||
} else {
|
||||
data = jsonError{fmt.Sprintf("Internal server error: %v", err)}
|
||||
}
|
||||
} else {
|
||||
data = jsonError{"Internal server error"}
|
||||
}
|
||||
|
@ -537,7 +544,7 @@ func (s *PublicServer) explorerSendTx(w http.ResponseWriter, r *http.Request) (t
|
|||
data.Error = &api.ApiError{Text: err.Error(), Public: true}
|
||||
return sendTransactionTpl, data, nil
|
||||
}
|
||||
data.Status = "Transaction sent " + res
|
||||
data.Status = "Transaction sent, result " + res
|
||||
}
|
||||
}
|
||||
return sendTransactionTpl, data, nil
|
||||
|
@ -677,3 +684,60 @@ func (s *PublicServer) apiBlock(r *http.Request) (interface{}, error) {
|
|||
}
|
||||
return block, err
|
||||
}
|
||||
|
||||
type resultSendTransaction struct {
|
||||
Result string `json:"result"`
|
||||
}
|
||||
|
||||
func (s *PublicServer) apiSendTx(r *http.Request) (interface{}, error) {
|
||||
var err error
|
||||
var res resultSendTransaction
|
||||
s.metrics.ExplorerViews.With(common.Labels{"action": "api-sendtx"}).Inc()
|
||||
if i := strings.LastIndexByte(r.URL.Path, '/'); i > 0 {
|
||||
hex := r.URL.Path[i+1:]
|
||||
if len(hex) > 0 {
|
||||
if len(hex) > 0 {
|
||||
res.Result, err = s.chain.SendRawTransaction(hex)
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, api.NewApiError("Missing tx blob", true)
|
||||
}
|
||||
|
||||
type resultEstimateFeeAsString struct {
|
||||
Result string `json:"result"`
|
||||
}
|
||||
|
||||
func (s *PublicServer) apiEstimateFee(r *http.Request) (interface{}, error) {
|
||||
var res resultEstimateFeeAsString
|
||||
s.metrics.ExplorerViews.With(common.Labels{"action": "api-estimatefee"}).Inc()
|
||||
if i := strings.LastIndexByte(r.URL.Path, '/'); i > 0 {
|
||||
b := r.URL.Path[i+1:]
|
||||
if len(b) > 0 {
|
||||
blocks, err := strconv.Atoi(b)
|
||||
if err != nil {
|
||||
return nil, api.NewApiError("Parameter 'number of blocks' is not a number", true)
|
||||
}
|
||||
conservative := true
|
||||
c := r.URL.Query().Get("conservative")
|
||||
if len(c) > 0 {
|
||||
conservative, err = strconv.ParseBool(c)
|
||||
if err != nil {
|
||||
return nil, api.NewApiError("Parameter 'conservative' cannot be converted to boolean", true)
|
||||
}
|
||||
}
|
||||
var fee big.Int
|
||||
fee, err = s.chain.EstimateSmartFee(blocks, conservative)
|
||||
if err != nil {
|
||||
fee, err = s.chain.EstimateFee(blocks)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
res.Result = s.chainParser.AmountToDecimalString(&fee)
|
||||
return res, nil
|
||||
}
|
||||
}
|
||||
return nil, api.NewApiError("Missing parameter 'number of blocks'", true)
|
||||
}
|
||||
|
|
|
@ -338,7 +338,7 @@ func httpTests(t *testing.T, ts *httptest.Server) {
|
|||
`<a href="/" class="nav-link">Fake Coin Explorer</a>`,
|
||||
`<h1>Send Raw Transaction</h1>`,
|
||||
`<textarea class="form-control" rows="8" name="hex">12341234</textarea>`,
|
||||
`<div class="alert alert-danger">Not implemented</div></div>`,
|
||||
`<div class="alert alert-danger">Invalid data</div>`,
|
||||
`</html>`,
|
||||
},
|
||||
},
|
||||
|
@ -400,12 +400,21 @@ func httpTests(t *testing.T, ts *httptest.Server) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "apiBlock",
|
||||
r: newGetRequest(ts.URL + "/api/block/225493"),
|
||||
name: "apiSendTx",
|
||||
r: newGetRequest(ts.URL + "/api/sendtx/123456"),
|
||||
status: http.StatusOK,
|
||||
contentType: "application/json; charset=utf-8",
|
||||
body: []string{
|
||||
`{"page":1,"totalPages":1,"itemsOnPage":1000,"hash":"0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997","previousblockhash":"","nextblockhash":"","height":225493,"confirmations":2,"size":1234567,"time":1534858021,"version":0,"merkleroot":"","nonce":0,"bits":"","difficulty":0,"TxCount":2,"txs":[{"txid":"00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840","vin":[],"vout":[{"value":"1","n":0,"scriptPubKey":{"hex":"","addresses":["mfcWp7DB6NuaZsExybTTXpVgWz559Np4Ti"]}},{"value":"0.00012345","n":1,"scriptPubKey":{"hex":"","addresses":["mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz"]}}],"blockhash":"0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997","blockheight":225493,"confirmations":2,"time":1534858021,"blocktime":1534858021,"valueOut":"1.00012345","valueIn":"0","fees":"0","hex":""},{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vin":[],"vout":[{"value":"12345.67890123","n":0,"scriptPubKey":{"hex":"","addresses":["mv9uLThosiEnGRbVPS7Vhyw6VssbVRsiAw"]}},{"value":"0.00000001","n":1,"scriptPubKey":{"hex":"","addresses":["2Mz1CYoppGGsLNUGF2YDhTif6J661JitALS"]}},{"value":"0.00009876","n":2,"scriptPubKey":{"hex":"","addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"]}}],"blockhash":"0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997","blockheight":225493,"confirmations":2,"time":1534858021,"blocktime":1534858021,"valueOut":"12345.679","valueIn":"0","fees":"0","hex":""}]}`,
|
||||
`{"result":"9876"}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "apiEstimateFee",
|
||||
r: newGetRequest(ts.URL + "/api/estimatefee/123?conservative=false"),
|
||||
status: http.StatusOK,
|
||||
contentType: "application/json; charset=utf-8",
|
||||
body: []string{
|
||||
`{"result":"0.00012299"}`,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -522,7 +531,7 @@ func socketioTests(t *testing.T, ts *httptest.Server) {
|
|||
{
|
||||
name: "sendTransaction",
|
||||
req: socketioReq{"sendTransaction", []interface{}{"010000000001019d64f0c72a0d206001decbffaa722eb1044534c"}},
|
||||
want: `{"error":{"message":"Not implemented"}}`,
|
||||
want: `{"error":{"message":"Invalid data"}}`,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -635,10 +635,6 @@ func (s *SocketIoServer) getDetailedTransaction(txid string) (res resultGetDetai
|
|||
return
|
||||
}
|
||||
|
||||
type resultSendTransaction struct {
|
||||
Result string `json:"result"`
|
||||
}
|
||||
|
||||
func (s *SocketIoServer) sendTransaction(tx string) (res resultSendTransaction, err error) {
|
||||
txid, err := s.chain.SendRawTransaction(tx)
|
||||
if err != nil {
|
||||
|
|
|
@ -158,7 +158,11 @@ func (c *fakeBlockChain) GetTransactionForMempool(txid string) (v *bchain.Tx, er
|
|||
}
|
||||
|
||||
func (c *fakeBlockChain) EstimateSmartFee(blocks int, conservative bool) (v big.Int, err error) {
|
||||
v.SetInt64(int64(blocks) * 100)
|
||||
if conservative == false {
|
||||
v.SetInt64(int64(blocks)*100 - 1)
|
||||
} else {
|
||||
v.SetInt64(int64(blocks) * 100)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -168,7 +172,10 @@ func (c *fakeBlockChain) EstimateFee(blocks int) (v big.Int, err error) {
|
|||
}
|
||||
|
||||
func (c *fakeBlockChain) SendRawTransaction(tx string) (v string, err error) {
|
||||
return "", errors.New("Not implemented")
|
||||
if tx == "123456" {
|
||||
return "9876", nil
|
||||
}
|
||||
return "", errors.New("Invalid data")
|
||||
}
|
||||
|
||||
func (c *fakeBlockChain) ResyncMempool(onNewTxAddr bchain.OnNewTxAddrFunc) (count int, err error) {
|
||||
|
|
Loading…
Reference in New Issue