From 8140af1a69a6aec5408ac700f47e6c4a04da1f21 Mon Sep 17 00:00:00 2001 From: Martin Boehm Date: Tue, 16 Oct 2018 12:25:31 +0200 Subject: [PATCH] Show coin specific transaction data in explorer and api --- bchain/coins/blockchain.go | 5 +++++ bchain/coins/btc/bitcoinrpc.go | 19 ++++++++++++++----- bchain/coins/eth/ethrpc.go | 14 ++++++++++++++ bchain/types.go | 1 + server/public.go | 19 +++++++++++++++++++ static/css/main.css | 20 ++++++++++++++++++++ static/templates/tx.html | 29 ++++++++++++++++++++++++++--- 7 files changed, 99 insertions(+), 8 deletions(-) diff --git a/bchain/coins/blockchain.go b/bchain/coins/blockchain.go index a8d8c95a..90e011ff 100644 --- a/bchain/coins/blockchain.go +++ b/bchain/coins/blockchain.go @@ -180,6 +180,11 @@ func (c *blockChainWithMetrics) GetTransaction(txid string) (v *bchain.Tx, err e return c.b.GetTransaction(txid) } +func (c *blockChainWithMetrics) GetTransactionSpecific(txid string) (v json.RawMessage, err error) { + defer func(s time.Time) { c.observeRPCLatency("GetTransactionSpecific", s, err) }(time.Now()) + return c.b.GetTransactionSpecific(txid) +} + func (c *blockChainWithMetrics) GetTransactionForMempool(txid string) (v *bchain.Tx, err error) { defer func(s time.Time) { c.observeRPCLatency("GetTransactionForMempool", s, err) }(time.Now()) return c.b.GetTransactionForMempool(txid) diff --git a/bchain/coins/btc/bitcoinrpc.go b/bchain/coins/btc/bitcoinrpc.go index 4d15330e..dfecbf71 100644 --- a/bchain/coins/btc/bitcoinrpc.go +++ b/bchain/coins/btc/bitcoinrpc.go @@ -670,6 +670,19 @@ func (b *BitcoinRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) { // GetTransaction returns a transaction by the transaction ID. func (b *BitcoinRPC) GetTransaction(txid string) (*bchain.Tx, error) { + r, err := b.GetTransactionSpecific(txid) + if err != nil { + return nil, err + } + tx, err := b.Parser.ParseTxFromJson(r) + if err != nil { + return nil, errors.Annotatef(err, "txid %v", txid) + } + return tx, nil +} + +// GetTransactionSpecific returns json as returned by backend, with all coin specific data +func (b *BitcoinRPC) GetTransactionSpecific(txid string) (json.RawMessage, error) { glog.V(1).Info("rpc: getrawtransaction ", txid) res := ResGetRawTransaction{} @@ -684,11 +697,7 @@ func (b *BitcoinRPC) GetTransaction(txid string) (*bchain.Tx, error) { if res.Error != nil { return nil, errors.Annotatef(res.Error, "txid %v", txid) } - tx, err := b.Parser.ParseTxFromJson(res.Result) - if err != nil { - return nil, errors.Annotatef(err, "txid %v", txid) - } - return tx, nil + return res.Result, nil } // ResyncMempool gets mempool transactions and maps output scripts to transactions. diff --git a/bchain/coins/eth/ethrpc.go b/bchain/coins/eth/ethrpc.go index 6bdda516..ffdac499 100644 --- a/bchain/coins/eth/ethrpc.go +++ b/bchain/coins/eth/ethrpc.go @@ -491,6 +491,20 @@ func (b *EthereumRPC) GetTransaction(txid string) (*bchain.Tx, error) { return btx, nil } +// GetTransactionSpecific returns json as returned by backend, with all coin specific data +func (b *EthereumRPC) GetTransactionSpecific(txid string) (json.RawMessage, error) { + ctx, cancel := context.WithTimeout(context.Background(), b.timeout) + defer cancel() + var tx json.RawMessage + err := b.rpc.CallContext(ctx, &tx, "eth_getTransactionByHash", ethcommon.HexToHash(txid)) + if err != nil { + return nil, err + } else if tx == nil { + return nil, ethereum.NotFound + } + return tx, nil +} + type rpcMempoolBlock struct { Transactions []string `json:"transactions"` } diff --git a/bchain/types.go b/bchain/types.go index d7177a6f..749adde7 100644 --- a/bchain/types.go +++ b/bchain/types.go @@ -167,6 +167,7 @@ type BlockChain interface { GetMempool() ([]string, error) GetTransaction(txid string) (*Tx, error) GetTransactionForMempool(txid string) (*Tx, error) + GetTransactionSpecific(txid string) (json.RawMessage, error) EstimateSmartFee(blocks int, conservative bool) (big.Int, error) EstimateFee(blocks int) (big.Int, error) SendRawTransaction(tx string) (string, error) diff --git a/server/public.go b/server/public.go index 18642b86..c9bd7ee3 100644 --- a/server/public.go +++ b/server/public.go @@ -124,6 +124,7 @@ func (s *PublicServer) ConnectFullPublicInterface() { // API calls serveMux.HandleFunc(path+"api/block-index/", s.jsonHandler(s.apiBlockIndex)) serveMux.HandleFunc(path+"api/tx/", s.jsonHandler(s.apiTx)) + 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)) // socket.io interface @@ -318,6 +319,7 @@ type TemplateData struct { Address *api.Address AddrStr string Tx *api.Tx + TxSpecific json.RawMessage Error *api.ApiError Blocks *api.Blocks Block *api.Block @@ -370,6 +372,7 @@ func setTxToTemplateData(td *TemplateData, tx *api.Tx) *TemplateData { func (s *PublicServer) explorerTx(w http.ResponseWriter, r *http.Request) (tpl, *TemplateData, error) { var tx *api.Tx + var txSpecific json.RawMessage var err error s.metrics.ExplorerViews.With(common.Labels{"action": "tx"}).Inc() if i := strings.LastIndexByte(r.URL.Path, '/'); i > 0 { @@ -378,9 +381,14 @@ func (s *PublicServer) explorerTx(w http.ResponseWriter, r *http.Request) (tpl, if err != nil { return errorTpl, nil, err } + txSpecific, err = s.chain.GetTransactionSpecific(txid) + if err != nil { + return errorTpl, nil, err + } } data := s.newTemplateData() data.Tx = tx + data.TxSpecific = txSpecific return txTpl, data, nil } @@ -603,6 +611,17 @@ func (s *PublicServer) apiTx(r *http.Request) (interface{}, error) { return tx, err } +func (s *PublicServer) apiTxSpecific(r *http.Request) (interface{}, error) { + var tx json.RawMessage + var err error + s.metrics.ExplorerViews.With(common.Labels{"action": "api-tx-specific"}).Inc() + if i := strings.LastIndexByte(r.URL.Path, '/'); i > 0 { + txid := r.URL.Path[i+1:] + tx, err = s.chain.GetTransactionSpecific(txid) + } + return tx, err +} + func (s *PublicServer) apiAddress(r *http.Request) (interface{}, error) { var address *api.Address var err error diff --git a/static/css/main.css b/static/css/main.css index b18df624..28e7344e 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -271,4 +271,24 @@ h3 { .page-item.active .page-link { background-color: #428bca; +} + +#txSpecific { + margin: 0; +} + +.string { + color: darkgreen; +} + +.number, .boolean { + color: darkred; +} + +.null { + color: red; +} + +.key { + color: #333 ; } \ No newline at end of file diff --git a/static/templates/tx.html b/static/templates/tx.html index fc8ce1bb..b96f71e9 100644 --- a/static/templates/tx.html +++ b/static/templates/tx.html @@ -1,4 +1,4 @@ -{{define "specific"}}{{$cs := .CoinShortcut}}{{$tx := .Tx}} +{{define "specific"}}{{$cs := .CoinShortcut}}{{$tx := .Tx}}{{$txSpecific := .TxSpecific}}

Transaction

{{$tx.Txid}} @@ -42,9 +42,32 @@ {{template "txdetail" .}}
-
Hex
+
Transaction Data
- {{$tx.Hex}} +

     
+
{{end}} \ No newline at end of file