diff --git a/docs/api.md b/docs/api.md index ceea78d..0f102d3 100644 --- a/docs/api.md +++ b/docs/api.md @@ -54,6 +54,8 @@ when a VSP is closed will result in an error. "vspdversion":"1.0.0-pre", "voting":10, "voted":25, + "totalvotingwallets": 3, + "votingwalletsonline":3, "revoked":3, "blockheight":623212, "estimatednetworkproportion":0.048478414 diff --git a/webapi/cache.go b/webapi/cache.go index d88b66b..c74e6e4 100644 --- a/webapi/cache.go +++ b/webapi/cache.go @@ -20,15 +20,17 @@ import ( // apiCache is used to cache values which are commonly used by the API, so // repeated web requests don't repeatedly trigger DB or RPC calls. type apiCache struct { - UpdateTime string - PubKey string - DatabaseSize string - Voting int64 - Voted int64 - Revoked int64 - BlockHeight uint32 - NetworkProportion float32 - RevokedProportion float32 + UpdateTime string + PubKey string + DatabaseSize string + Voting int64 + Voted int64 + Revoked int64 + VotingWalletsOnline int64 + TotalVotingWallets int64 + BlockHeight uint32 + NetworkProportion float32 + RevokedProportion float32 } var cacheMtx sync.RWMutex @@ -55,7 +57,7 @@ func initCache() { // updateCache updates the dynamic values in the cache (ticket counts and best // block height). func updateCache(ctx context.Context, db *database.VspDatabase, - dcrd rpc.DcrdConnect, netParams *chaincfg.Params) error { + dcrd rpc.DcrdConnect, netParams *chaincfg.Params, wallets rpc.WalletConnect) error { dbSize, err := db.Size() if err != nil { @@ -83,6 +85,14 @@ func updateCache(ctx context.Context, db *database.VspDatabase, return errors.New("dcr node reports a network ticket pool size of zero") } + clients, failedConnections := wallets.Clients(ctx, cfg.NetParams) + if len(clients) == 0 { + log.Error("Could not connect to any wallets") + } else if len(failedConnections) > 0 { + log.Errorf("Failed to connect to %d wallet(s), proceeding with only %d", + len(failedConnections), len(clients)) + } + cacheMtx.Lock() defer cacheMtx.Unlock() @@ -90,6 +100,8 @@ func updateCache(ctx context.Context, db *database.VspDatabase, cache.DatabaseSize = humanize.Bytes(dbSize) cache.Voting = voting cache.Voted = voted + cache.TotalVotingWallets = int64(len(clients) + len(failedConnections)) + cache.VotingWalletsOnline = int64(len(clients)) cache.Revoked = revoked cache.BlockHeight = bestBlock.Height cache.NetworkProportion = float32(voting) / float32(bestBlock.PoolSize) diff --git a/webapi/types.go b/webapi/types.go index 7f0b359..1e8adc0 100644 --- a/webapi/types.go +++ b/webapi/types.go @@ -5,19 +5,21 @@ package webapi type vspInfoResponse struct { - APIVersions []int64 `json:"apiversions"` - Timestamp int64 `json:"timestamp"` - PubKey []byte `json:"pubkey"` - FeePercentage float64 `json:"feepercentage"` - VspClosed bool `json:"vspclosed"` - VspClosedMsg string `json:"vspclosedmsg"` - Network string `json:"network"` - VspdVersion string `json:"vspdversion"` - Voting int64 `json:"voting"` - Voted int64 `json:"voted"` - Revoked int64 `json:"revoked"` - BlockHeight uint32 `json:"blockheight"` - NetworkProportion float32 `json:"estimatednetworkproportion"` + APIVersions []int64 `json:"apiversions"` + Timestamp int64 `json:"timestamp"` + PubKey []byte `json:"pubkey"` + FeePercentage float64 `json:"feepercentage"` + VspClosed bool `json:"vspclosed"` + VspClosedMsg string `json:"vspclosedmsg"` + Network string `json:"network"` + VspdVersion string `json:"vspdversion"` + Voting int64 `json:"voting"` + Voted int64 `json:"voted"` + TotalVotingWallets int64 `json:"totalvotingwallets"` + VotingWalletsOnline int64 `json:"votingwalletsonline"` + Revoked int64 `json:"revoked"` + BlockHeight uint32 `json:"blockheight"` + NetworkProportion float32 `json:"estimatednetworkproportion"` } type feeAddressRequest struct { diff --git a/webapi/vspinfo.go b/webapi/vspinfo.go index 68e049f..b6b0f69 100644 --- a/webapi/vspinfo.go +++ b/webapi/vspinfo.go @@ -15,18 +15,20 @@ import ( func vspInfo(c *gin.Context) { cachedStats := getCache() sendJSONResponse(vspInfoResponse{ - APIVersions: []int64{3}, - Timestamp: time.Now().Unix(), - PubKey: signPubKey, - FeePercentage: cfg.VSPFee, - Network: cfg.NetParams.Name, - VspClosed: cfg.VspClosed, - VspClosedMsg: cfg.VspClosedMsg, - VspdVersion: version.String(), - Voting: cachedStats.Voting, - Voted: cachedStats.Voted, - Revoked: cachedStats.Revoked, - BlockHeight: cachedStats.BlockHeight, - NetworkProportion: cachedStats.NetworkProportion, + APIVersions: []int64{3}, + Timestamp: time.Now().Unix(), + PubKey: signPubKey, + FeePercentage: cfg.VSPFee, + Network: cfg.NetParams.Name, + VspClosed: cfg.VspClosed, + VspClosedMsg: cfg.VspClosedMsg, + VspdVersion: version.String(), + Voting: cachedStats.Voting, + Voted: cachedStats.Voted, + TotalVotingWallets: cachedStats.TotalVotingWallets, + VotingWalletsOnline: cachedStats.VotingWalletsOnline, + Revoked: cachedStats.Revoked, + BlockHeight: cachedStats.BlockHeight, + NetworkProportion: cachedStats.NetworkProportion, }, c) } diff --git a/webapi/webapi.go b/webapi/webapi.go index 92d6e61..ae9b212 100644 --- a/webapi/webapi.go +++ b/webapi/webapi.go @@ -85,7 +85,7 @@ func Start(ctx context.Context, requestShutdown func(), shutdownWg *sync.WaitGro // Populate cached VSP stats before starting webserver. initCache() - err = updateCache(ctx, vdb, dcrd, config.NetParams) + err = updateCache(ctx, vdb, dcrd, config.NetParams, wallets) if err != nil { log.Errorf("Could not initialize VSP stats cache: %v", err) } @@ -172,7 +172,7 @@ func Start(ctx context.Context, requestShutdown func(), shutdownWg *sync.WaitGro shutdownWg.Done() return case <-ticker.C: - err := updateCache(ctx, vdb, dcrd, config.NetParams) + err := updateCache(ctx, vdb, dcrd, config.NetParams, wallets) if err != nil { log.Errorf("Failed to update cached VSP stats: %v", err) }