webapi: Display decoded fee tx, not just raw bytes

When searching for a ticket in the admin interface, use GetRawTransaction RPC to get the decoded transaction and display it as formatted JSON.
This commit is contained in:
jholdstock 2023-06-26 14:35:53 +01:00 committed by Jamie Holdstock
parent 4dc2cc4d8d
commit a88c261cb1
4 changed files with 65 additions and 1 deletions

View File

@ -150,6 +150,17 @@ func (c *DcrdRPC) GetRawTransaction(txHash string) (*dcrdtypes.TxRawResult, erro
return &resp, nil return &resp, nil
} }
// DecodeRawTransaction uses decoderawtransaction RPC to decode raw transaction bytes.
func (c *DcrdRPC) DecodeRawTransaction(txHex string) (*dcrdtypes.TxRawDecodeResult, error) {
var resp dcrdtypes.TxRawDecodeResult
err := c.Call(c.ctx, "decoderawtransaction", &resp, txHex)
if err != nil {
return nil, err
}
return &resp, nil
}
// SendRawTransaction uses sendrawtransaction RPC to broadcast a transaction to // SendRawTransaction uses sendrawtransaction RPC to broadcast a transaction to
// the network. It ignores errors caused by duplicate transactions. // the network. It ignores errors caused by duplicate transactions.
func (c *DcrdRPC) SendRawTransaction(txHex string) error { func (c *DcrdRPC) SendRawTransaction(txHex string) error {

View File

@ -5,6 +5,7 @@
package webapi package webapi
import ( import (
"encoding/json"
"net/http" "net/http"
"github.com/decred/vspd/database" "github.com/decred/vspd/database"
@ -41,6 +42,7 @@ type searchResult struct {
Hash string Hash string
Found bool Found bool
Ticket database.Ticket Ticket database.Ticket
FeeTxDecoded string
AltSignAddrData *database.AltSignAddrData AltSignAddrData *database.AltSignAddrData
VoteChanges map[uint32]database.VoteChangeRecord VoteChanges map[uint32]database.VoteChangeRecord
MaxVoteChanges int MaxVoteChanges int
@ -176,11 +178,42 @@ func (s *Server) ticketSearch(c *gin.Context) {
return return
} }
// Decode the fee tx so it can be displayed human-readable. Fee tx hex may
// be null because it is removed from the DB if the tx is already mined and
// confirmed.
var feeTxDecoded string
if ticket.FeeTxHex != "" {
dcrdClient := c.MustGet(dcrdKey).(*rpc.DcrdRPC)
dcrdErr := c.MustGet(dcrdErrorKey)
if dcrdErr != nil {
s.log.Errorf("Could not get dcrd client: %v", dcrdErr.(error))
c.String(http.StatusInternalServerError, "Could not get dcrd client")
return
}
resp, err := dcrdClient.DecodeRawTransaction(ticket.FeeTxHex)
if err != nil {
s.log.Errorf("dcrd.DecodeRawTransaction error: %w", err)
c.String(http.StatusInternalServerError, "Error decoding fee transaction")
return
}
decoded, err := json.Marshal(resp)
if err != nil {
s.log.Errorf("Unmarshal fee tx error: %w", err)
c.String(http.StatusInternalServerError, "Error unmarshalling fee tx")
return
}
feeTxDecoded = string(decoded)
}
c.HTML(http.StatusOK, "admin.html", gin.H{ c.HTML(http.StatusOK, "admin.html", gin.H{
"SearchResult": searchResult{ "SearchResult": searchResult{
Hash: hash, Hash: hash,
Found: found, Found: found,
Ticket: ticket, Ticket: ticket,
FeeTxDecoded: feeTxDecoded,
AltSignAddrData: altSignAddrData, AltSignAddrData: altSignAddrData,
VoteChanges: voteChanges, VoteChanges: voteChanges,
MaxVoteChanges: s.cfg.MaxVoteChangeRecords, MaxVoteChanges: s.cfg.MaxVoteChangeRecords,

View File

@ -158,6 +158,11 @@ footer .code {
font-size: 12px; font-size: 12px;
} }
#ticket-table .small-text {
padding: 10px 16px;
font-size: 12px;
}
#ticket-table pre { #ticket-table pre {
color: #3D5873; color: #3D5873;
font-size: 12px; font-size: 12px;

View File

@ -75,7 +75,22 @@
</tr> </tr>
<tr> <tr>
<th>Fee Tx</th> <th>Fee Tx</th>
<td>{{ .Ticket.FeeTxHex }}</td> <td>
{{ if .Ticket.FeeTxHex }}
<details>
<summary>Raw Bytes</summary>
<div class="small-text">
{{ .Ticket.FeeTxHex }}
</div>
</details>
<details>
<summary>Decoded</summary>
<div class="small-text">
<pre>{{ indentJSON .FeeTxDecoded }}</pre>
</div>
</details>
{{ end }}
</td>
</tr> </tr>
<tr> <tr>
<th>Fee Tx Status</th> <th>Fee Tx Status</th>