diff --git a/params.go b/params.go index 5fdf516d..56ff829a 100644 --- a/params.go +++ b/params.go @@ -12,22 +12,26 @@ type netParams struct { *chaincfg.Params DcrdRPCServerPort string WalletRPCServerPort string + BlockExplorerURL string } var mainNetParams = netParams{ Params: chaincfg.MainNetParams(), DcrdRPCServerPort: "9109", WalletRPCServerPort: "9110", + BlockExplorerURL: "https://dcrdata.decred.org", } var testNet3Params = netParams{ Params: chaincfg.TestNet3Params(), DcrdRPCServerPort: "19109", WalletRPCServerPort: "19110", + BlockExplorerURL: "https://testnet.dcrdata.org", } var simNetParams = netParams{ Params: chaincfg.SimNetParams(), DcrdRPCServerPort: "19556", WalletRPCServerPort: "19557", + BlockExplorerURL: "...", } diff --git a/vspd.go b/vspd.go index b667c3cc..b9ee11bd 100644 --- a/vspd.go +++ b/vspd.go @@ -87,6 +87,7 @@ func run(ctx context.Context) error { apiCfg := webapi.Config{ VSPFee: cfg.VSPFee, NetParams: cfg.netParams.Params, + BlockExplorerURL: cfg.netParams.BlockExplorerURL, SupportEmail: cfg.SupportEmail, VspClosed: cfg.VspClosed, AdminPass: cfg.AdminPass, diff --git a/webapi/admin.go b/webapi/admin.go index 9418e83f..291adb1f 100644 --- a/webapi/admin.go +++ b/webapi/admin.go @@ -7,6 +7,7 @@ package webapi import ( "net/http" + "github.com/decred/vspd/database" "github.com/decred/vspd/rpc" "github.com/gin-gonic/gin" "github.com/gorilla/sessions" @@ -26,6 +27,14 @@ type WalletStatus struct { BestBlockHeight int64 `json:"bestblockheight"` } +type searchResult struct { + Hash string + Found bool + Ticket database.Ticket + VoteChanges map[uint32]database.VoteChangeRecord + MaxVoteChanges int +} + func walletStatus(c *gin.Context) map[string]WalletStatus { walletClients := c.MustGet("WalletClients").([]*rpc.WalletRPC) failedWalletClients := c.MustGet("FailedWalletClients").([]string) @@ -113,12 +122,12 @@ func ticketSearch(c *gin.Context) { } c.HTML(http.StatusOK, "admin.html", gin.H{ - "SearchResult": gin.H{ - "Hash": hash, - "Found": found, - "Ticket": ticket, - "VoteChanges": voteChanges, - "MaxVoteChanges": cfg.MaxVoteChangeRecords, + "SearchResult": searchResult{ + Hash: hash, + Found: found, + Ticket: ticket, + VoteChanges: voteChanges, + MaxVoteChanges: cfg.MaxVoteChangeRecords, }, "VspStats": getVSPStats(), "WalletStatus": walletStatus(c), diff --git a/webapi/formatting.go b/webapi/formatting.go new file mode 100644 index 00000000..b3489c8e --- /dev/null +++ b/webapi/formatting.go @@ -0,0 +1,19 @@ +package webapi + +import "time" + +func addressURL(blockExplorerURL string) func(string) string { + return func(addr string) string { + return blockExplorerURL + "/address/" + addr + } +} + +func txURL(blockExplorerURL string) func(string) string { + return func(txID string) string { + return blockExplorerURL + "/tx/" + txID + } +} + +func dateTime(t int64) string { + return time.Unix(t, 0).Format("2 Jan 2006 15:04:05") +} diff --git a/webapi/homepage.go b/webapi/homepage.go index b3168f00..626f82b8 100644 --- a/webapi/homepage.go +++ b/webapi/homepage.go @@ -55,7 +55,7 @@ func updateVSPStats(db *database.VspDatabase, cfg Config) error { Revoked: revoked, VSPFee: cfg.VSPFee, Network: cfg.NetParams.Name, - UpdateTime: time.Now().Format("Mon Jan _2 15:04:05 2006"), + UpdateTime: dateTime(time.Now().Unix()), SupportEmail: cfg.SupportEmail, VspClosed: cfg.VspClosed, Debug: cfg.Debug, diff --git a/webapi/templates/admin.html b/webapi/templates/admin.html index 0a9c6a4b..d7f71915 100644 --- a/webapi/templates/admin.html +++ b/webapi/templates/admin.html @@ -97,7 +97,11 @@

Search Result

- + @@ -109,7 +113,11 @@

Search Result

- + @@ -117,7 +125,7 @@

Search Result

- + @@ -173,12 +181,16 @@

Search Result

- - + + - - + + diff --git a/webapi/webapi.go b/webapi/webapi.go index 3f9e03c5..9aecd3b0 100644 --- a/webapi/webapi.go +++ b/webapi/webapi.go @@ -11,6 +11,7 @@ import ( "encoding/json" "errors" "fmt" + "html/template" "net" "net/http" "sync" @@ -26,6 +27,7 @@ import ( type Config struct { VSPFee float64 NetParams *chaincfg.Params + BlockExplorerURL string FeeAccountName string SupportEmail string VspClosed bool @@ -173,6 +175,14 @@ func router(debugMode bool, cookieSecret []byte, dcrd rpc.DcrdConnect, wallets r } router := gin.New() + + // Add custom functions for use in templates. + router.SetFuncMap(template.FuncMap{ + "txURL": txURL(cfg.BlockExplorerURL), + "addressURL": addressURL(cfg.BlockExplorerURL), + "dateTime": dateTime, + }) + router.LoadHTMLGlob("webapi/templates/*.html") // Recovery middleware handles any go panics generated while processing web
Hash{{ .Ticket.Hash }} + + {{ .Ticket.Hash }} + +
Commitment Address
Fee Address{{ .Ticket.FeeAddress }} + + {{ .Ticket.FeeAddress }} + +
Fee Amount
Fee Expiration{{ .Ticket.FeeExpiration }}{{ .Ticket.FeeExpiration }} ({{ dateTime .Ticket.FeeExpiration }})
Confirmed {{ .Ticket.VotingWIF }}
Fee Tx{{ .Ticket.FeeTxHex }}Fee Tx Hash + + {{ .Ticket.FeeTxHash }} + +
Fee Tx Hash{{ .Ticket.FeeTxHash }}Fee Tx{{ .Ticket.FeeTxHex }}
Fee Tx Status