Add voting wallet status to admin page
This commit is contained in:
parent
da410b5060
commit
1c351d02ec
@ -155,3 +155,12 @@ func (c *WalletRPC) AddTicketForVoting(votingWIF, blockHash, txHex string) error
|
||||
func (c *WalletRPC) SetVoteChoice(agenda, choice, ticketHash string) error {
|
||||
return c.Call(c.ctx, "setvotechoice", nil, agenda, choice, ticketHash)
|
||||
}
|
||||
|
||||
func (c *WalletRPC) GetBestBlockHeight() (int64, error) {
|
||||
var block dcrdtypes.GetBestBlockResult
|
||||
err := c.Call(c.ctx, "getbestblock", &block)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return block.Height, nil
|
||||
}
|
||||
|
||||
@ -3,14 +3,64 @@ package webapi
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/decred/vspd/rpc"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/sessions"
|
||||
)
|
||||
|
||||
// WalletStatus describes the current status of a single voting wallet.
|
||||
type WalletStatus struct {
|
||||
Connected bool
|
||||
InfoError bool
|
||||
DaemonConnected bool
|
||||
VoteVersion uint32
|
||||
Unlocked bool
|
||||
Voting bool
|
||||
BestBlockError bool
|
||||
BestBlockHeight int64
|
||||
}
|
||||
|
||||
func walletStatus(c *gin.Context) map[string]WalletStatus {
|
||||
walletClients := c.MustGet("WalletClients").([]*rpc.WalletRPC)
|
||||
failedWalletClients := c.MustGet("FailedWalletClients").([]string)
|
||||
|
||||
walletStatus := make(map[string]WalletStatus)
|
||||
for _, v := range walletClients {
|
||||
ws := WalletStatus{Connected: true}
|
||||
|
||||
walletInfo, err := v.WalletInfo()
|
||||
if err != nil {
|
||||
log.Errorf("dcrwallet.WalletInfo error (wallet=%s): %v", v.String(), err)
|
||||
ws.InfoError = true
|
||||
} else {
|
||||
ws.DaemonConnected = walletInfo.DaemonConnected
|
||||
ws.VoteVersion = walletInfo.VoteVersion
|
||||
ws.Unlocked = walletInfo.Unlocked
|
||||
ws.Voting = walletInfo.Voting
|
||||
}
|
||||
|
||||
height, err := v.GetBestBlockHeight()
|
||||
if err != nil {
|
||||
log.Errorf("dcrwallet.GetBestBlockHeight error (wallet=%s): %v", v.String(), err)
|
||||
ws.BestBlockError = true
|
||||
} else {
|
||||
ws.BestBlockHeight = height
|
||||
}
|
||||
|
||||
walletStatus[v.String()] = ws
|
||||
}
|
||||
for _, v := range failedWalletClients {
|
||||
ws := WalletStatus{Connected: false}
|
||||
walletStatus[v] = ws
|
||||
}
|
||||
return walletStatus
|
||||
}
|
||||
|
||||
// adminPage is the handler for "GET /admin".
|
||||
func adminPage(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "admin.html", gin.H{
|
||||
"VspStats": getVSPStats(),
|
||||
"VspStats": getVSPStats(),
|
||||
"WalletStatus": walletStatus(c),
|
||||
})
|
||||
}
|
||||
|
||||
@ -32,7 +82,8 @@ func ticketSearch(c *gin.Context) {
|
||||
"Found": found,
|
||||
"Ticket": ticket,
|
||||
},
|
||||
"VspStats": getVSPStats(),
|
||||
"VspStats": getVSPStats(),
|
||||
"WalletStatus": walletStatus(c),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -105,6 +105,7 @@ func withWalletClients(wallets rpc.WalletConnect) gin.HandlerFunc {
|
||||
len(failedConnections), len(clients))
|
||||
}
|
||||
c.Set("WalletClients", clients)
|
||||
c.Set("FailedWalletClients", failedConnections)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -103,7 +103,8 @@ footer .code {
|
||||
.block__content th {
|
||||
font-weight: normal;
|
||||
padding-right: 15px;
|
||||
text-align: right;
|
||||
color: #495057;
|
||||
background-color: #e9ecef;
|
||||
}
|
||||
|
||||
.block__content table td {
|
||||
@ -115,3 +116,22 @@ footer .code {
|
||||
vertical-align: top;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
td.status-good{
|
||||
background-color: #C4ECCA;
|
||||
}
|
||||
td.status-bad{
|
||||
background-color: #FEB8A5;
|
||||
}
|
||||
|
||||
.ticket-table th {
|
||||
text-align: right;
|
||||
}
|
||||
.ticket-table td {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.status-table th,
|
||||
.status-table td {
|
||||
text-align: center;
|
||||
}
|
||||
@ -22,14 +22,70 @@
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-12 p-3">
|
||||
<div class="block__content">
|
||||
<h1>Voting Wallet Status</h1>
|
||||
|
||||
<table class="table status-table mb-0" width="100%">
|
||||
<tr>
|
||||
<th>URL</th>
|
||||
<th>Best Block Height</th>
|
||||
<th>Daemon Connected</th>
|
||||
<th>Unlocked</th>
|
||||
<th>Voting</th>
|
||||
<th>Vote Version</th>
|
||||
</tr>
|
||||
{{ range $host, $status := .WalletStatus }}
|
||||
<tr>
|
||||
<td>{{ $host }}</td>
|
||||
|
||||
{{ if $status.Connected }}
|
||||
|
||||
{{ if $status.BestBlockError }}
|
||||
<td class="status-bad">Error</td>
|
||||
{{ else }}
|
||||
<td>{{ $status.BestBlockHeight }}</td>
|
||||
{{ end }}
|
||||
|
||||
{{ if $status.InfoError }}
|
||||
<td class="status-bad" colspan="4">Error</td>
|
||||
{{ else }}
|
||||
<td class="{{ if $status.DaemonConnected }}status-good{{else}}status-bad{{end}}"
|
||||
>{{ $status.DaemonConnected }}</td>
|
||||
|
||||
|
||||
<td class="{{ if $status.Unlocked }}status-good{{else}}status-bad{{end}}"
|
||||
>{{ $status.Unlocked }}</td>
|
||||
|
||||
|
||||
<td class="{{ if $status.Voting }}status-good{{else}}status-bad{{end}}"
|
||||
>{{ $status.Voting }}</td>
|
||||
|
||||
<td>{{ $status.VoteVersion }}</td>
|
||||
{{ end }}
|
||||
|
||||
{{else}}
|
||||
<td class="status-bad" colspan="4">Cannot connect to wallet</td>
|
||||
{{end}}
|
||||
</tr>
|
||||
{{end}}
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-12 p-3">
|
||||
<div class="block__content">
|
||||
<h1>Ticket Search</h1>
|
||||
|
||||
|
||||
<form class="my-2" action="/admin/ticket" method="post">
|
||||
<input type="text" name="hash" size="64" minlength="64" maxlength="64" required placeholder="Ticket hash" autocomplete="off">
|
||||
<button class="ml-3 btn btn-primary" type="submit">Search</button>
|
||||
@ -38,7 +94,7 @@
|
||||
{{ with .SearchResult }}
|
||||
{{ if .Found }}
|
||||
{{ with .Ticket }}
|
||||
<table class="table mt-4 mb-0">
|
||||
<table class="table ticket-table mt-4 mb-0">
|
||||
<tr>
|
||||
<th>Hash</th>
|
||||
<td>{{ .Hash }}</td>
|
||||
@ -104,7 +160,6 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{{ template "footer" . }}
|
||||
|
||||
@ -205,7 +205,7 @@ func router(debugMode bool, cookieSecret []byte, dcrd rpc.DcrdConnect, wallets r
|
||||
login.POST("", adminLogin)
|
||||
|
||||
admin := router.Group("/admin").Use(
|
||||
withSession(cookieStore), requireAdmin(),
|
||||
withWalletClients(wallets), withSession(cookieStore), requireAdmin(),
|
||||
)
|
||||
admin.GET("", adminPage)
|
||||
admin.POST("/ticket", ticketSearch)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user