Merge pull request #25 from asymmetric-research/provider-interface
Static tests
This commit is contained in:
commit
f1e948fb3b
|
@ -72,15 +72,19 @@ func NewSolanaCollector(rpcAddr string) *solanaCollector {
|
|||
func (c *solanaCollector) Describe(ch chan<- *prometheus.Desc) {
|
||||
ch <- c.totalValidatorsDesc
|
||||
ch <- c.solanaVersion
|
||||
ch <- c.validatorActivatedStake
|
||||
ch <- c.validatorLastVote
|
||||
ch <- c.validatorRootSlot
|
||||
ch <- c.validatorDelinquent
|
||||
}
|
||||
|
||||
func (c *solanaCollector) mustEmitMetrics(ch chan<- prometheus.Metric, response *rpc.GetVoteAccountsResponse) {
|
||||
func (c *solanaCollector) mustEmitMetrics(ch chan<- prometheus.Metric, response *rpc.VoteAccounts) {
|
||||
ch <- prometheus.MustNewConstMetric(c.totalValidatorsDesc, prometheus.GaugeValue,
|
||||
float64(len(response.Result.Delinquent)), "delinquent")
|
||||
float64(len(response.Delinquent)), "delinquent")
|
||||
ch <- prometheus.MustNewConstMetric(c.totalValidatorsDesc, prometheus.GaugeValue,
|
||||
float64(len(response.Result.Current)), "current")
|
||||
float64(len(response.Current)), "current")
|
||||
|
||||
for _, account := range append(response.Result.Current, response.Result.Delinquent...) {
|
||||
for _, account := range append(response.Current, response.Delinquent...) {
|
||||
ch <- prometheus.MustNewConstMetric(c.validatorActivatedStake, prometheus.GaugeValue,
|
||||
float64(account.ActivatedStake), account.VotePubkey, account.NodePubkey)
|
||||
ch <- prometheus.MustNewConstMetric(c.validatorLastVote, prometheus.GaugeValue,
|
||||
|
@ -88,11 +92,11 @@ func (c *solanaCollector) mustEmitMetrics(ch chan<- prometheus.Metric, response
|
|||
ch <- prometheus.MustNewConstMetric(c.validatorRootSlot, prometheus.GaugeValue,
|
||||
float64(account.RootSlot), account.VotePubkey, account.NodePubkey)
|
||||
}
|
||||
for _, account := range response.Result.Current {
|
||||
for _, account := range response.Current {
|
||||
ch <- prometheus.MustNewConstMetric(c.validatorDelinquent, prometheus.GaugeValue,
|
||||
0, account.VotePubkey, account.NodePubkey)
|
||||
}
|
||||
for _, account := range response.Result.Delinquent {
|
||||
for _, account := range response.Delinquent {
|
||||
ch <- prometheus.MustNewConstMetric(c.validatorDelinquent, prometheus.GaugeValue,
|
||||
1, account.VotePubkey, account.NodePubkey)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,163 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var staticCollector = createSolanaCollector(&staticRPCClient{})
|
||||
|
||||
func TestSolanaCollector_Collect(t *testing.T) {
|
||||
prometheus.NewPedanticRegistry().MustRegister(staticCollector)
|
||||
|
||||
testCases := map[string]string{
|
||||
"solana_active_validators": `
|
||||
# HELP solana_active_validators Total number of active validators by state
|
||||
# TYPE solana_active_validators gauge
|
||||
solana_active_validators{state="current"} 2
|
||||
solana_active_validators{state="delinquent"} 1
|
||||
`,
|
||||
"solana_validator_activated_stake": `
|
||||
# HELP solana_validator_activated_stake Activated stake per validator
|
||||
# TYPE solana_validator_activated_stake gauge
|
||||
solana_validator_activated_stake{nodekey="4MUdt8D2CadJKeJ8Fv2sz4jXU9xv4t2aBPpTf6TN8bae",pubkey="xKUz6fZ79SXnjGYaYhhYTYQBoRUBoCyuDMkBa1tL3zU"} 49
|
||||
solana_validator_activated_stake{nodekey="B97CCUW3AEZFGy6uUg6zUdnNYvnVq5VG8PUtb2HayTDD",pubkey="3ZT31jkAGhUaw8jsy4bTknwBMP8i4Eueh52By4zXcsVw"} 42
|
||||
solana_validator_activated_stake{nodekey="C97CCUW3AEZFGy6uUg6zUdnNYvnVq5VG8PUtb2HayTDD",pubkey="4ZT31jkAGhUaw8jsy4bTknwBMP8i4Eueh52By4zXcsVw"} 43
|
||||
`,
|
||||
"solana_validator_last_vote": `
|
||||
# HELP solana_validator_last_vote Last voted slot per validator
|
||||
# TYPE solana_validator_last_vote gauge
|
||||
solana_validator_last_vote{nodekey="4MUdt8D2CadJKeJ8Fv2sz4jXU9xv4t2aBPpTf6TN8bae",pubkey="xKUz6fZ79SXnjGYaYhhYTYQBoRUBoCyuDMkBa1tL3zU"} 92
|
||||
solana_validator_last_vote{nodekey="B97CCUW3AEZFGy6uUg6zUdnNYvnVq5VG8PUtb2HayTDD",pubkey="3ZT31jkAGhUaw8jsy4bTknwBMP8i4Eueh52By4zXcsVw"} 147
|
||||
solana_validator_last_vote{nodekey="C97CCUW3AEZFGy6uUg6zUdnNYvnVq5VG8PUtb2HayTDD",pubkey="4ZT31jkAGhUaw8jsy4bTknwBMP8i4Eueh52By4zXcsVw"} 148
|
||||
`,
|
||||
"solana_validator_root_slot": `
|
||||
# HELP solana_validator_root_slot Root slot per validator
|
||||
# TYPE solana_validator_root_slot gauge
|
||||
solana_validator_root_slot{nodekey="4MUdt8D2CadJKeJ8Fv2sz4jXU9xv4t2aBPpTf6TN8bae",pubkey="xKUz6fZ79SXnjGYaYhhYTYQBoRUBoCyuDMkBa1tL3zU"} 3
|
||||
solana_validator_root_slot{nodekey="B97CCUW3AEZFGy6uUg6zUdnNYvnVq5VG8PUtb2HayTDD",pubkey="3ZT31jkAGhUaw8jsy4bTknwBMP8i4Eueh52By4zXcsVw"} 18
|
||||
solana_validator_root_slot{nodekey="C97CCUW3AEZFGy6uUg6zUdnNYvnVq5VG8PUtb2HayTDD",pubkey="4ZT31jkAGhUaw8jsy4bTknwBMP8i4Eueh52By4zXcsVw"} 19
|
||||
`,
|
||||
"solana_validator_delinquent": `
|
||||
# HELP solana_validator_delinquent Whether a validator is delinquent
|
||||
# TYPE solana_validator_delinquent gauge
|
||||
solana_validator_delinquent{nodekey="4MUdt8D2CadJKeJ8Fv2sz4jXU9xv4t2aBPpTf6TN8bae",pubkey="xKUz6fZ79SXnjGYaYhhYTYQBoRUBoCyuDMkBa1tL3zU"} 1
|
||||
solana_validator_delinquent{nodekey="B97CCUW3AEZFGy6uUg6zUdnNYvnVq5VG8PUtb2HayTDD",pubkey="3ZT31jkAGhUaw8jsy4bTknwBMP8i4Eueh52By4zXcsVw"} 0
|
||||
solana_validator_delinquent{nodekey="C97CCUW3AEZFGy6uUg6zUdnNYvnVq5VG8PUtb2HayTDD",pubkey="4ZT31jkAGhUaw8jsy4bTknwBMP8i4Eueh52By4zXcsVw"} 0
|
||||
`,
|
||||
"solana_node_version": `
|
||||
# HELP solana_node_version Node version of solana
|
||||
# TYPE solana_node_version gauge
|
||||
solana_node_version{version="1.16.7"} 1
|
||||
`,
|
||||
}
|
||||
|
||||
for testName, expectedValue := range testCases {
|
||||
t.Run(
|
||||
testName,
|
||||
func(t *testing.T) {
|
||||
if err := testutil.CollectAndCompare(
|
||||
staticCollector,
|
||||
bytes.NewBufferString(expectedValue),
|
||||
testName,
|
||||
); err != nil {
|
||||
t.Errorf("unexpected collecting result for %s: \n%s", testName, err)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSolanaCollector_WatchSlots(t *testing.T) {
|
||||
go staticCollector.WatchSlots()
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
tests := []struct {
|
||||
expectedValue float64
|
||||
metric prometheus.Gauge
|
||||
}{
|
||||
{
|
||||
expectedValue: float64(staticEpochInfo.AbsoluteSlot),
|
||||
metric: confirmedSlotHeight,
|
||||
},
|
||||
{
|
||||
expectedValue: float64(staticEpochInfo.TransactionCount),
|
||||
metric: totalTransactionsTotal,
|
||||
},
|
||||
{
|
||||
expectedValue: float64(staticEpochInfo.Epoch),
|
||||
metric: currentEpochNumber,
|
||||
},
|
||||
{
|
||||
expectedValue: float64(staticEpochInfo.AbsoluteSlot - staticEpochInfo.SlotIndex),
|
||||
metric: epochFirstSlot,
|
||||
},
|
||||
{
|
||||
expectedValue: float64(staticEpochInfo.AbsoluteSlot - staticEpochInfo.SlotIndex + staticEpochInfo.SlotsInEpoch),
|
||||
metric: epochLastSlot,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range tests {
|
||||
name := extractName(testCase.metric.Desc())
|
||||
t.Run(
|
||||
name,
|
||||
func(t *testing.T) {
|
||||
assert.Equal(t, testCase.expectedValue, testutil.ToFloat64(testCase.metric))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
hosts := []string{
|
||||
"B97CCUW3AEZFGy6uUg6zUdnNYvnVq5VG8PUtb2HayTDD",
|
||||
"C97CCUW3AEZFGy6uUg6zUdnNYvnVq5VG8PUtb2HayTDD",
|
||||
"4MUdt8D2CadJKeJ8Fv2sz4jXU9xv4t2aBPpTf6TN8bae",
|
||||
}
|
||||
metrics := map[string]*prometheus.CounterVec{
|
||||
"solana_leader_slots_total": leaderSlotsTotal,
|
||||
"solana_leader_slots_by_epoch": leaderSlotsByEpoch,
|
||||
}
|
||||
statuses := []string{"valid", "skipped"}
|
||||
for name, metric := range metrics {
|
||||
// subtest for each metric:
|
||||
t.Run(name, func(t *testing.T) {
|
||||
for _, status := range statuses {
|
||||
// sub subtest for each status (as each one requires a different calc)
|
||||
t.Run(status, func(t *testing.T) {
|
||||
for _, host := range hosts {
|
||||
testBlockProductionMetric(t, metric, host, status)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testBlockProductionMetric(
|
||||
t *testing.T,
|
||||
metric *prometheus.CounterVec,
|
||||
host string,
|
||||
status string,
|
||||
) {
|
||||
hostInfo := staticBlockProduction.Hosts[host]
|
||||
// get expected value depending on status:
|
||||
var expectedValue float64
|
||||
switch status {
|
||||
case "valid":
|
||||
expectedValue = float64(hostInfo.BlocksProduced)
|
||||
case "skipped":
|
||||
expectedValue = float64(hostInfo.LeaderSlots - hostInfo.BlocksProduced)
|
||||
}
|
||||
// get labels (leaderSlotsByEpoch requires an extra one)
|
||||
labels := []string{status, host}
|
||||
if metric == leaderSlotsByEpoch {
|
||||
labels = append(labels, fmt.Sprintf("%d", staticEpochInfo.Epoch))
|
||||
}
|
||||
// now we can do the assertion:
|
||||
assert.Equal(t, expectedValue, testutil.ToFloat64(metric.WithLabelValues(labels...)))
|
||||
}
|
|
@ -74,11 +74,21 @@ func (c *solanaCollector) WatchSlots() {
|
|||
}
|
||||
cancel()
|
||||
|
||||
totalTransactionsTotal.Set(float64(info.TransactionCount))
|
||||
confirmedSlotHeight.Set(float64(info.AbsoluteSlot))
|
||||
|
||||
// watermark is the last slot number we generated ticks for. Set it to the current offset on startup (we do not backfill slots we missed at startup)
|
||||
watermark := info.AbsoluteSlot
|
||||
currentEpoch, firstSlot, lastSlot := getEpochBounds(info)
|
||||
currentEpochNumber.Set(float64(currentEpoch))
|
||||
epochFirstSlot.Set(float64(firstSlot))
|
||||
epochLastSlot.Set(float64(lastSlot))
|
||||
|
||||
klog.Infof("Starting at slot %d in epoch %d (%d-%d)", firstSlot, currentEpoch, firstSlot, lastSlot)
|
||||
_, err = updateCounters(c.rpcClient, currentEpoch, watermark, &lastSlot)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
}
|
||||
ticker := time.NewTicker(slotPacerSchedule)
|
||||
|
||||
for {
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/certusone/solana_exporter/pkg/rpc"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type (
|
||||
staticRPCClient struct{}
|
||||
// TODO: create dynamicRPCClient + according tests!
|
||||
)
|
||||
|
||||
var (
|
||||
staticEpochInfo = rpc.EpochInfo{
|
||||
AbsoluteSlot: 166598,
|
||||
BlockHeight: 166500,
|
||||
Epoch: 27,
|
||||
SlotIndex: 2790,
|
||||
SlotsInEpoch: 8192,
|
||||
TransactionCount: 22661093,
|
||||
}
|
||||
staticBlockProduction = rpc.BlockProduction{
|
||||
FirstSlot: 1000,
|
||||
LastSlot: 2000,
|
||||
Hosts: map[string]rpc.BlockProductionPerHost{
|
||||
"B97CCUW3AEZFGy6uUg6zUdnNYvnVq5VG8PUtb2HayTDD": {
|
||||
LeaderSlots: 400,
|
||||
BlocksProduced: 360,
|
||||
},
|
||||
"C97CCUW3AEZFGy6uUg6zUdnNYvnVq5VG8PUtb2HayTDD": {
|
||||
LeaderSlots: 300,
|
||||
BlocksProduced: 296,
|
||||
},
|
||||
"4MUdt8D2CadJKeJ8Fv2sz4jXU9xv4t2aBPpTf6TN8bae": {
|
||||
LeaderSlots: 300,
|
||||
BlocksProduced: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func (c *staticRPCClient) GetEpochInfo(ctx context.Context, commitment rpc.Commitment) (*rpc.EpochInfo, error) {
|
||||
return &staticEpochInfo, nil
|
||||
}
|
||||
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func (c *staticRPCClient) GetSlot(ctx context.Context) (int64, error) {
|
||||
return staticEpochInfo.AbsoluteSlot, nil
|
||||
}
|
||||
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func (c *staticRPCClient) GetVersion(ctx context.Context) (*string, error) {
|
||||
version := "1.16.7"
|
||||
return &version, nil
|
||||
}
|
||||
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func (c *staticRPCClient) GetVoteAccounts(
|
||||
ctx context.Context,
|
||||
params []interface{},
|
||||
) (*rpc.VoteAccounts, error) {
|
||||
voteAccounts := rpc.VoteAccounts{
|
||||
Current: []rpc.VoteAccount{
|
||||
{
|
||||
ActivatedStake: 42,
|
||||
Commission: 0,
|
||||
EpochCredits: [][]int{
|
||||
{1, 64, 0},
|
||||
{2, 192, 64},
|
||||
},
|
||||
EpochVoteAccount: true,
|
||||
LastVote: 147,
|
||||
NodePubkey: "B97CCUW3AEZFGy6uUg6zUdnNYvnVq5VG8PUtb2HayTDD",
|
||||
RootSlot: 18,
|
||||
VotePubkey: "3ZT31jkAGhUaw8jsy4bTknwBMP8i4Eueh52By4zXcsVw",
|
||||
},
|
||||
{
|
||||
ActivatedStake: 43,
|
||||
Commission: 1,
|
||||
EpochCredits: [][]int{
|
||||
{2, 65, 1},
|
||||
{3, 193, 65},
|
||||
},
|
||||
EpochVoteAccount: true,
|
||||
LastVote: 148,
|
||||
NodePubkey: "C97CCUW3AEZFGy6uUg6zUdnNYvnVq5VG8PUtb2HayTDD",
|
||||
RootSlot: 19,
|
||||
VotePubkey: "4ZT31jkAGhUaw8jsy4bTknwBMP8i4Eueh52By4zXcsVw",
|
||||
},
|
||||
},
|
||||
Delinquent: []rpc.VoteAccount{
|
||||
{
|
||||
ActivatedStake: 49,
|
||||
Commission: 2,
|
||||
EpochCredits: [][]int{
|
||||
{10, 594, 6},
|
||||
{9, 98, 4},
|
||||
},
|
||||
EpochVoteAccount: true,
|
||||
LastVote: 92,
|
||||
NodePubkey: "4MUdt8D2CadJKeJ8Fv2sz4jXU9xv4t2aBPpTf6TN8bae",
|
||||
RootSlot: 3,
|
||||
VotePubkey: "xKUz6fZ79SXnjGYaYhhYTYQBoRUBoCyuDMkBa1tL3zU",
|
||||
},
|
||||
},
|
||||
}
|
||||
return &voteAccounts, nil
|
||||
}
|
||||
|
||||
//goland:noinspection GoUnusedParameter
|
||||
func (c *staticRPCClient) GetBlockProduction(
|
||||
ctx context.Context,
|
||||
firstSlot *int64,
|
||||
lastSlot *int64,
|
||||
) (rpc.BlockProduction, error) {
|
||||
return staticBlockProduction, nil
|
||||
}
|
||||
|
||||
// extractName takes a Prometheus descriptor and returns its name
|
||||
func extractName(desc *prometheus.Desc) string {
|
||||
// Get the string representation of the descriptor
|
||||
descString := desc.String()
|
||||
|
||||
// Use regex to extract the metric name and help message from the descriptor string
|
||||
reName := regexp.MustCompile(`fqName: "([^"]+)"`)
|
||||
|
||||
nameMatch := reName.FindStringSubmatch(descString)
|
||||
|
||||
var name string
|
||||
if len(nameMatch) > 1 {
|
||||
name = nameMatch[1]
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
2
go.mod
2
go.mod
|
@ -4,5 +4,7 @@ go 1.13
|
|||
|
||||
require (
|
||||
github.com/prometheus/client_golang v1.4.0
|
||||
github.com/prometheus/common v0.9.1
|
||||
github.com/stretchr/testify v1.4.0
|
||||
k8s.io/klog/v2 v2.4.0
|
||||
)
|
||||
|
|
7
go.sum
7
go.sum
|
@ -9,6 +9,7 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
|||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
|
@ -31,8 +32,10 @@ github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
|
|||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
|
@ -43,6 +46,7 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
|
|||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
|
@ -65,6 +69,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
|||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
|
@ -84,10 +89,12 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IV
|
|||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ=
|
||||
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||
|
|
|
@ -32,7 +32,7 @@ type (
|
|||
Error rpcError2 `json:"error"`
|
||||
}
|
||||
|
||||
blockProductionPerHost struct {
|
||||
BlockProductionPerHost struct {
|
||||
LeaderSlots int64
|
||||
BlocksProduced int64
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ type (
|
|||
BlockProduction struct {
|
||||
FirstSlot int64
|
||||
LastSlot int64
|
||||
Hosts map[string]blockProductionPerHost
|
||||
Hosts map[string]BlockProductionPerHost
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -81,10 +81,10 @@ func (c *Client) GetBlockProduction(ctx context.Context, firstSlot *int64, lastS
|
|||
|
||||
ret.FirstSlot = resp.Result.Value.Range.FirstSlot
|
||||
ret.LastSlot = *resp.Result.Value.Range.LastSlot
|
||||
ret.Hosts = make(map[string]blockProductionPerHost)
|
||||
ret.Hosts = make(map[string]BlockProductionPerHost)
|
||||
|
||||
for id, arr := range resp.Result.Value.ByIdentity {
|
||||
ret.Hosts[id] = blockProductionPerHost{
|
||||
ret.Hosts[id] = BlockProductionPerHost{
|
||||
LeaderSlots: arr[0],
|
||||
BlocksProduced: arr[1],
|
||||
}
|
||||
|
|
|
@ -15,12 +15,12 @@ type (
|
|||
rpcAddr string
|
||||
}
|
||||
|
||||
rpcError struct {
|
||||
rpcError1 struct {
|
||||
Message string `json:"message"`
|
||||
Code int64 `json:"id"`
|
||||
}
|
||||
|
||||
rpcError2 struct {
|
||||
rpcError2 struct { // TODO: combine these error types into a single one
|
||||
Message string `json:"message"`
|
||||
Code int64 `json:"code"`
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ type Provider interface {
|
|||
// The method takes a context for cancellation and a slice of parameters to filter the vote accounts.
|
||||
// It returns a pointer to a GetVoteAccountsResponse struct containing the vote accounts details,
|
||||
// or an error if the operation fails.
|
||||
GetVoteAccounts(ctx context.Context, params []interface{}) (*GetVoteAccountsResponse, error)
|
||||
GetVoteAccounts(ctx context.Context, params []interface{}) (*VoteAccounts, error)
|
||||
|
||||
// GetVersion retrieves the version of the Solana node.
|
||||
// The method takes a context for cancellation.
|
||||
|
|
|
@ -25,7 +25,7 @@ type (
|
|||
|
||||
GetEpochInfoResponse struct {
|
||||
Result EpochInfo `json:"result"`
|
||||
Error rpcError `json:"error"`
|
||||
Error rpcError1 `json:"error"`
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
@ -19,17 +19,19 @@ type (
|
|||
VotePubkey string `json:"votePubkey"`
|
||||
}
|
||||
|
||||
VoteAccounts struct {
|
||||
Current []VoteAccount `json:"current"`
|
||||
Delinquent []VoteAccount `json:"delinquent"`
|
||||
}
|
||||
|
||||
GetVoteAccountsResponse struct {
|
||||
Result struct {
|
||||
Current []VoteAccount `json:"current"`
|
||||
Delinquent []VoteAccount `json:"delinquent"`
|
||||
} `json:"result"`
|
||||
Error rpcError `json:"error"`
|
||||
Result VoteAccounts `json:"result"`
|
||||
Error rpcError1 `json:"error"`
|
||||
}
|
||||
)
|
||||
|
||||
// https://docs.solana.com/developing/clients/jsonrpc-api#getvoteaccounts
|
||||
func (c *Client) GetVoteAccounts(ctx context.Context, params []interface{}) (*GetVoteAccountsResponse, error) {
|
||||
func (c *Client) GetVoteAccounts(ctx context.Context, params []interface{}) (*VoteAccounts, error) {
|
||||
body, err := c.rpcRequest(ctx, formatRPCRequest("getVoteAccounts", params))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("RPC call failed: %w", err)
|
||||
|
@ -46,5 +48,5 @@ func (c *Client) GetVoteAccounts(ctx context.Context, params []interface{}) (*Ge
|
|||
return nil, fmt.Errorf("RPC error: %d %v", resp.Error.Code, resp.Error.Message)
|
||||
}
|
||||
|
||||
return &resp, nil
|
||||
return &resp.Result, nil
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ type (
|
|||
Result struct {
|
||||
Version string `json:"solana-core"`
|
||||
} `json:"result"`
|
||||
Error rpcError `json:"error"`
|
||||
Error rpcError1 `json:"error"`
|
||||
}
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in New Issue