refactor code organization
This commit is contained in:
parent
7f8b73055e
commit
b8172f06ab
|
@ -23,18 +23,45 @@ type metricInfo struct {
|
|||
// Exporter collect metrics from the helium blockchain api and exports them as prometheus metrics.
|
||||
type Exporter struct {
|
||||
Accounts []Account
|
||||
StartTime time.Time
|
||||
}
|
||||
|
||||
// NewExporter returns an initialized Exporter
|
||||
func NewExporter(accountAddress []string) (*Exporter, error) {
|
||||
accounts := make([]Account, 0)
|
||||
for _, accountAddress := range accountAddress {
|
||||
if accountAddress != "" {
|
||||
accounts = append(accounts, NewAccount(accountAddress))
|
||||
}
|
||||
}
|
||||
return &Exporter{
|
||||
Accounts: accounts,
|
||||
StartTime: time.Now(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Account represents a helium account
|
||||
type Account struct {
|
||||
hotspots []Hotspot
|
||||
hash string
|
||||
Address string
|
||||
Tx AccountTx
|
||||
}
|
||||
|
||||
// Hotspot represent a helium hotspot
|
||||
type Hotspot struct {
|
||||
name string
|
||||
hash string
|
||||
func NewAccount(address string) Account {
|
||||
return Account{
|
||||
Address: address,
|
||||
Tx: AccountTx{
|
||||
DepositTotal: 0,
|
||||
WithdrawalTotal: 0,
|
||||
LastUpdate: time.Now(),
|
||||
// LastUpdate: time.Time{},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type AccountTx struct {
|
||||
DepositTotal int
|
||||
WithdrawalTotal int
|
||||
LastUpdate time.Time
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -42,7 +69,24 @@ const (
|
|||
)
|
||||
|
||||
var (
|
||||
// lables
|
||||
// Activity classification
|
||||
accountDepositActivities = []string{
|
||||
"payment_v1", // if payee == account_address
|
||||
"payment_v2", // if payee == account_address
|
||||
"rewards_v1",
|
||||
"unstake_validator_v1",
|
||||
}
|
||||
accountWithdrawalActivities = []string{
|
||||
"add_gateway_v1",
|
||||
"assert_location_v1",
|
||||
"assert_location_v2",
|
||||
"payment_v1", // if payer == account_address
|
||||
"payment_v2", // if payer == account_address
|
||||
"stake_validator_v1",
|
||||
"token_burn_v1",
|
||||
}
|
||||
|
||||
// labels
|
||||
commonAccountLabels = []string{"account"}
|
||||
commonHotspotLabels = append(commonAccountLabels, "hotspot", "hotspot_name")
|
||||
|
||||
|
@ -61,43 +105,43 @@ var (
|
|||
// helium stats metrics
|
||||
statsValidators = metricInfo{
|
||||
prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "stats", "validators_total"),
|
||||
prometheus.BuildFQName(namespace, "stats", "validators"),
|
||||
"The total number of validators.",
|
||||
nil, nil,
|
||||
),
|
||||
prometheus.CounterValue,
|
||||
prometheus.GaugeValue,
|
||||
}
|
||||
statsOuis = metricInfo{
|
||||
prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "stats", "ouis_total"),
|
||||
prometheus.BuildFQName(namespace, "stats", "ouis"),
|
||||
"The total number of organization unique identifiers.",
|
||||
nil, nil,
|
||||
),
|
||||
prometheus.CounterValue,
|
||||
prometheus.GaugeValue,
|
||||
}
|
||||
statsHotspotsDataOnly = metricInfo{
|
||||
prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "stats", "hotspots_dataonly_total"),
|
||||
prometheus.BuildFQName(namespace, "stats", "hotspots_dataonly"),
|
||||
"The total number of data only hotspots.",
|
||||
nil, nil,
|
||||
),
|
||||
prometheus.CounterValue,
|
||||
prometheus.GaugeValue,
|
||||
}
|
||||
statsBlocks = metricInfo{
|
||||
prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "stats", "blocks_total"),
|
||||
prometheus.BuildFQName(namespace, "stats", "blocks"),
|
||||
"The total height/number of blocks in the blockchain.",
|
||||
nil, nil,
|
||||
),
|
||||
prometheus.CounterValue,
|
||||
prometheus.GaugeValue,
|
||||
}
|
||||
statsChallenges = metricInfo{
|
||||
prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "stats", "challenges_total"),
|
||||
prometheus.BuildFQName(namespace, "stats", "challenges"),
|
||||
"The total number of challenges.",
|
||||
nil, nil,
|
||||
),
|
||||
prometheus.CounterValue,
|
||||
prometheus.GaugeValue,
|
||||
}
|
||||
statsCities = metricInfo{
|
||||
prometheus.NewDesc(
|
||||
|
@ -109,7 +153,7 @@ var (
|
|||
}
|
||||
statsConsensusGroups = metricInfo{
|
||||
prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "stats", "consensus_groups_total"),
|
||||
prometheus.BuildFQName(namespace, "stats", "consensus_groups"),
|
||||
"The total number of consensus groups.",
|
||||
nil, nil,
|
||||
),
|
||||
|
@ -125,15 +169,15 @@ var (
|
|||
}
|
||||
statsHotspots = metricInfo{
|
||||
prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "stats", "hotspots_total"),
|
||||
prometheus.BuildFQName(namespace, "stats", "hotspots"),
|
||||
"The total number of hotspots.",
|
||||
nil, nil,
|
||||
),
|
||||
prometheus.CounterValue,
|
||||
prometheus.GaugeValue,
|
||||
}
|
||||
statsTokenSupply = metricInfo{
|
||||
prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "stats", "token_supply"),
|
||||
prometheus.BuildFQName(namespace, "stats", "token"),
|
||||
"The total supply of HNT tokens in circulation.",
|
||||
nil, nil,
|
||||
),
|
||||
|
@ -165,22 +209,22 @@ var (
|
|||
),
|
||||
prometheus.CounterValue,
|
||||
}
|
||||
// accountDepositsHnt = metricInfo{
|
||||
// prometheus.NewDesc(
|
||||
// prometheus.BuildFQName(namespace, "account", "deposits_hnt_total"),
|
||||
// "The number of HNT token deposited to this account.",
|
||||
// commonAccountLabels, nil,
|
||||
// ),
|
||||
// prometheus.CounterValue,
|
||||
// }
|
||||
// accountWithdrawalsHnt = metricInfo{
|
||||
// prometheus.NewDesc(
|
||||
// prometheus.BuildFQName(namespace, "account", "withdrawals_hnt_total"),
|
||||
// "The number of HNT token withdrawn from this account.",
|
||||
// commonAccountLabels, nil,
|
||||
// ),
|
||||
// prometheus.CounterValue,
|
||||
// }
|
||||
accountDepositsHnt = metricInfo{
|
||||
prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "account", "deposits_hnt_total"),
|
||||
"The number of HNT tokens deposited to this account.",
|
||||
commonAccountLabels, nil,
|
||||
),
|
||||
prometheus.CounterValue,
|
||||
}
|
||||
accountWithdrawalsHnt = metricInfo{
|
||||
prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "account", "withdrawals_hnt_total"),
|
||||
"The number of HNT tokens withdrawn from this account.",
|
||||
commonAccountLabels, nil,
|
||||
),
|
||||
prometheus.CounterValue,
|
||||
}
|
||||
|
||||
// helium hotspot metrics
|
||||
hotspotUp = metricInfo{
|
||||
|
@ -275,8 +319,8 @@ func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
|
|||
ch <- accountBalanceHnt.Desc
|
||||
ch <- accountActivity.Desc
|
||||
ch <- accountRewardsHnt.Desc
|
||||
// ch <- accountDepositsHnt.Desc
|
||||
// ch <- accountWithdrawalsHnt.Desc
|
||||
ch <- accountDepositsHnt.Desc
|
||||
ch <- accountWithdrawalsHnt.Desc
|
||||
|
||||
ch <- hotspotUp.Desc
|
||||
ch <- hotspotRelayed.Desc
|
||||
|
@ -354,19 +398,24 @@ func (e *Exporter) collectStatsMetrics(ch chan<- prometheus.Metric) {
|
|||
|
||||
// collectStatsMetrics collect metrics in the account group from the helium api
|
||||
func (e *Exporter) collectAccountMetrics(ch chan<- prometheus.Metric, account *Account) {
|
||||
accountForAddress, err := heliumapi.GetAccountForAddress(account.hash)
|
||||
accountForAddress, err := heliumapi.GetAccountForAddress(account.Address)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
accountActivityForAddress, err := heliumapi.GetActivityCountsForAccount(account.hash)
|
||||
accountActivityForAddress, err := heliumapi.GetActivityCountsForAccount(account.Address)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
accountRewardTotalsForAddress, err := heliumapi.GetRewardTotalsForAccount(account.hash, &time.Time{}, nil)
|
||||
accountRewardTotalsForAddress, err := heliumapi.GetRewardTotalsForAccount(account.Address, &e.StartTime, nil)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
tx, err := account.computeTransactions()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
|
@ -374,23 +423,31 @@ func (e *Exporter) collectAccountMetrics(ch chan<- prometheus.Metric, account *A
|
|||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
accountBalanceHnt.Desc, accountBalanceHnt.Type, float64(accountForAddress.Data.Balance),
|
||||
account.hash,
|
||||
account.Address,
|
||||
)
|
||||
for accType, count := range accountActivityForAddress.Data {
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
accountActivity.Desc, accountActivity.Type, float64(count),
|
||||
account.hash, accType,
|
||||
account.Address, accType,
|
||||
)
|
||||
}
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
accountRewardsHnt.Desc, accountRewardsHnt.Type, accountRewardTotalsForAddress.Data.Sum,
|
||||
account.hash,
|
||||
account.Address,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
accountDepositsHnt.Desc, accountDepositsHnt.Type, float64(tx.DepositTotal),
|
||||
account.Address,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
accountWithdrawalsHnt.Desc, accountWithdrawalsHnt.Type, float64(tx.WithdrawalTotal),
|
||||
account.Address,
|
||||
)
|
||||
}
|
||||
|
||||
// collectStatsMetrics collect metrics in the hotspot group from the helium api
|
||||
func (e *Exporter) collectHotspotMetrics(ch chan<- prometheus.Metric, account *Account) {
|
||||
hotspotsForAddress, err := heliumapi.GetHotspotsForAccount(account.hash)
|
||||
hotspotsForAddress, err := heliumapi.GetHotspotsForAccount(account.Address)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
|
@ -403,7 +460,7 @@ func (e *Exporter) collectHotspotMetrics(ch chan<- prometheus.Metric, account *A
|
|||
return
|
||||
}
|
||||
|
||||
hotspotRewardTotalsForAddress, err := heliumapi.GetRewardsTotalForHotspot(hotspotData.Address, &time.Time{}, nil)
|
||||
hotspotRewardTotalsForAddress, err := heliumapi.GetRewardsTotalForHotspot(hotspotData.Address, &e.StartTime, nil)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
|
@ -411,58 +468,52 @@ func (e *Exporter) collectHotspotMetrics(ch chan<- prometheus.Metric, account *A
|
|||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
hotspotUp.Desc, hotspotUp.Type, bool2Float64(hotspotData.Status.Online == "online"),
|
||||
account.hash, hotspotData.Address, hotspotData.Name,
|
||||
account.Address, hotspotData.Address, hotspotData.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
hotspotRelayed.Desc, hotspotRelayed.Type, bool2Float64(len(hotspotData.Status.ListenAddrs) > 0 && strings.HasPrefix(hotspotData.Status.ListenAddrs[0], "/p2p")),
|
||||
account.hash, hotspotData.Address, hotspotData.Name,
|
||||
account.Address, hotspotData.Address, hotspotData.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
hotspotBlocks.Desc, hotspotBlocks.Type, float64(hotspotData.Status.Height),
|
||||
account.hash, hotspotData.Address, hotspotData.Name,
|
||||
account.Address, hotspotData.Address, hotspotData.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
hotspotRewardsScale.Desc, hotspotRewardsScale.Type, float64(hotspotData.RewardScale),
|
||||
account.hash, hotspotData.Address, hotspotData.Name,
|
||||
account.Address, hotspotData.Address, hotspotData.Name,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
hotspotGeocodeInfo.Desc, hotspotGeocodeInfo.Type, 1.0,
|
||||
account.hash, hotspotData.Address, hotspotData.Name, strconv.FormatFloat(hotspotData.Lng, 'f', 6, 64), strconv.FormatFloat(hotspotData.Lat, 'f', 6, 64), hotspotData.Geocode.LongStreet, hotspotData.Geocode.LongState, hotspotData.Geocode.LongCountry, hotspotData.Geocode.LongCity,
|
||||
account.Address, hotspotData.Address, hotspotData.Name, strconv.FormatFloat(hotspotData.Lng, 'f', 6, 64), strconv.FormatFloat(hotspotData.Lat, 'f', 6, 64), hotspotData.Geocode.LongStreet, hotspotData.Geocode.LongState, hotspotData.Geocode.LongCountry, hotspotData.Geocode.LongCity,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
hotspotAntennaInfo.Desc, hotspotAntennaInfo.Type, 1.0,
|
||||
account.hash, hotspotData.Address, hotspotData.Name, strconv.Itoa(hotspotData.Gain), strconv.Itoa(hotspotData.Elevation),
|
||||
account.Address, hotspotData.Address, hotspotData.Name, strconv.Itoa(hotspotData.Gain), strconv.Itoa(hotspotData.Elevation),
|
||||
)
|
||||
for accType, count := range hotspotActivityForAddress.Data {
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
hotspotActivity.Desc, hotspotActivity.Type, float64(count),
|
||||
account.hash, hotspotData.Address, hotspotData.Name, accType,
|
||||
account.Address, hotspotData.Address, hotspotData.Name, accType,
|
||||
)
|
||||
}
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
hotspotRewardsHnt.Desc, hotspotRewardsHnt.Type, hotspotRewardTotalsForAddress.Data.Sum,
|
||||
account.hash, hotspotData.Address, hotspotData.Name,
|
||||
account.Address, hotspotData.Address, hotspotData.Name,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// NewExporter returns an initialized Exporter
|
||||
func NewExporter(accountHashs []string) (*Exporter, error) {
|
||||
accounts := make([]Account, 0)
|
||||
for _, accountHash := range accountHashs {
|
||||
if accountHash != "" {
|
||||
accounts = append(accounts, NewAccount(accountHash))
|
||||
}
|
||||
}
|
||||
return &Exporter{
|
||||
Accounts: accounts,
|
||||
}, nil
|
||||
func (a *Account) computeTransactions() (*AccountTx, error) {
|
||||
now := time.Now()
|
||||
_, err := heliumapi.GetActivityForAccount(a.Address, []string{}, &a.Tx.LastUpdate, &now)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func NewAccount(hash string) Account {
|
||||
return Account{
|
||||
hash: hash,
|
||||
}
|
||||
// fmt.Println(activities)
|
||||
|
||||
a.Tx.LastUpdate = now
|
||||
return &a.Tx, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
|
|
@ -4,61 +4,10 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/helium-blockchain-exporter/heliumapi/activity"
|
||||
)
|
||||
|
||||
type Account struct {
|
||||
Data struct {
|
||||
Address string `json:"address"`
|
||||
Balance int `json:"balance"`
|
||||
Block int `json:"block"`
|
||||
DCBalance int `json:"dc_balance"`
|
||||
DCNonce int `json:"dc_nonce"`
|
||||
SECBalance int `json:"sec_balance"`
|
||||
SECNonce int `json:"sec_nonce"`
|
||||
SpeculativeNonce int `json:"speculative_nonce"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
type AccountHotspots struct {
|
||||
Data []struct {
|
||||
Lng float64 `json:"lng"`
|
||||
Lat float64 `json:"lat"`
|
||||
TimestampAdded string `json:"timestamp_added"`
|
||||
Status struct {
|
||||
Timestamp string `json:"timestamp"`
|
||||
Online string `json:"online"`
|
||||
ListenAddrs []string `json:"listen_addrs"`
|
||||
Height int `json:"height"`
|
||||
} `json:"status"`
|
||||
RewardScale float64 `json:"reward_scale"`
|
||||
Payer string `json:"payer"`
|
||||
Owner string `json:"owner"`
|
||||
Nonce int `json:"nonce"`
|
||||
Name string `json:"name"`
|
||||
Mode string `json:"mode"`
|
||||
LocationHex string `json:"location_hex"`
|
||||
Location string `json:"location"`
|
||||
LastPocChallenge int `json:"last_poc_challenge"`
|
||||
LastChangeBlock int `json:"last_change_block"`
|
||||
Geocode struct {
|
||||
ShortStreet string `json:"short_street"`
|
||||
ShortState string `json:"short_state"`
|
||||
ShortCountry string `json:"short_country"`
|
||||
ShortCity string `json:"short_city"`
|
||||
LongStreet string `json:"long_street"`
|
||||
LongState string `json:"long_state"`
|
||||
LongCountry string `json:"long_country"`
|
||||
LongCity string `json:"long_city"`
|
||||
CityID string `json:"city_id"`
|
||||
} `json:"geocode"`
|
||||
Gain int `json:"gain"`
|
||||
Elevation int `json:"elevation"`
|
||||
BlockAdded int `json:"block_added"`
|
||||
Block int `json:"block"`
|
||||
Address string `json:"address"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
func GetAccountForAddress(account string) (*Account, error) {
|
||||
path := "/v1/accounts/" + account
|
||||
|
||||
|
@ -78,6 +27,36 @@ func GetAccountForAddress(account string) (*Account, error) {
|
|||
return &respobject, nil
|
||||
}
|
||||
|
||||
func GetActivityForAccount(account string, filterTypes []string, minTime *time.Time, maxTime *time.Time) (*activity.Activities, error) {
|
||||
path := "/v1/accounts/" + account + "/activity"
|
||||
params := map[string]string{}
|
||||
if minTime != nil {
|
||||
params["min_time"] = minTime.UTC().Format("2006-01-02T15:04:05Z")
|
||||
}
|
||||
if maxTime != nil {
|
||||
params["max_time"] = maxTime.UTC().Format("2006-01-02T15:04:05Z")
|
||||
}
|
||||
|
||||
// query the api
|
||||
resBodies, err := getHeliumApiWithCursor(path, ¶ms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// unmarshal the responses and merge them all together
|
||||
combinedResp := activity.ActivityResp{}
|
||||
for _, respBody := range resBodies {
|
||||
activityResp := activity.ActivityResp{}
|
||||
err = json.Unmarshal(respBody, &activityResp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal response from path %v: %v", path, err)
|
||||
}
|
||||
combinedResp.Data = append(combinedResp.Data, activityResp.Data...)
|
||||
}
|
||||
|
||||
return activity.NewActivities(combinedResp)
|
||||
}
|
||||
|
||||
func GetActivityCountsForAccount(account string) (*ActivityCounts, error) {
|
||||
path := "/v1/accounts/" + account + "/activity/count"
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
package activity
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ActivityResp struct {
|
||||
Data []json.RawMessage `json:"data"`
|
||||
}
|
||||
|
||||
type Activities struct{}
|
||||
|
||||
func NewActivities(resp ActivityResp) (*Activities, error) {
|
||||
type ActivityType struct {
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
activityType := ActivityType{}
|
||||
activities := Activities{}
|
||||
|
||||
for _, activityRaw := range resp.Data {
|
||||
if err := json.Unmarshal(activityRaw, &activityType); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal activity: %v", err)
|
||||
}
|
||||
fmt.Println(activityType.Type)
|
||||
switch activityType.Type {
|
||||
case "add_gateway_v1":
|
||||
case "assert_location_v1":
|
||||
case "assert_location_v2":
|
||||
case "payment_v1":
|
||||
case "payment_v2":
|
||||
case "rewards_v1":
|
||||
case "stake_validator_v1":
|
||||
case "token_burn_v1":
|
||||
case "unstake_validator_v1":
|
||||
default:
|
||||
fmt.Printf("unimplemented activy type: %v", activityType.Type)
|
||||
}
|
||||
}
|
||||
|
||||
return &activities, nil
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
package activity
|
|
@ -6,27 +6,6 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
type ActivityCounts struct {
|
||||
Data map[string]int
|
||||
}
|
||||
|
||||
type RewardTotal struct {
|
||||
Meta struct {
|
||||
MinTime string `json:"min_time"`
|
||||
MaxTime string `json:"max_time"`
|
||||
} `json:"meta"`
|
||||
|
||||
Data struct {
|
||||
Total float64 `json:"total"`
|
||||
Sum float64 `json:"sum"`
|
||||
Stddev float64 `json:"stddev"`
|
||||
Min float64 `json:"min"`
|
||||
Median float64 `json:"median"`
|
||||
Max float64 `json:"max"`
|
||||
Avg float64 `json:"avg"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
func GetHotspotActivityCount(hotspot string) (*ActivityCounts, error) {
|
||||
path := "/v1/hotspots/" + hotspot + "/activity/count"
|
||||
|
||||
|
|
|
@ -5,13 +5,6 @@ import (
|
|||
"fmt"
|
||||
)
|
||||
|
||||
type CurrentOraclePrice struct {
|
||||
Data struct {
|
||||
Price int `json:"price"`
|
||||
Block int `json:"block"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
func GetCurrentOraclePrice() (*CurrentOraclePrice, error) {
|
||||
const path = "/v1/oracle/prices/current"
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package heliumapi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
@ -14,7 +15,7 @@ var (
|
|||
client = &http.Client{}
|
||||
)
|
||||
|
||||
func getHeliumApi(path string, params *map[string]string) ([]byte, error) {
|
||||
func createGetRequest(path string, params map[string]string) (*http.Request, error) {
|
||||
req, err := http.NewRequest("GET", fmt.Sprintf("%s/%s", apiUrl, path), nil)
|
||||
|
||||
// setup headers
|
||||
|
@ -23,7 +24,7 @@ func getHeliumApi(path string, params *map[string]string) ([]byte, error) {
|
|||
// setup query param if there are any
|
||||
if params != nil {
|
||||
query := req.URL.Query()
|
||||
for k, v := range *params {
|
||||
for k, v := range params {
|
||||
query.Add(k, v)
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -32,6 +33,20 @@ func getHeliumApi(path string, params *map[string]string) ([]byte, error) {
|
|||
req.URL.RawQuery = query.Encode()
|
||||
}
|
||||
|
||||
return req, err
|
||||
}
|
||||
|
||||
func getHeliumApi(path string, params *map[string]string) ([]byte, error) {
|
||||
// if params is nil, set it to an empty map
|
||||
if params == nil {
|
||||
params = &map[string]string{}
|
||||
}
|
||||
|
||||
req, err := createGetRequest(path, *params)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create query request %v: %v", path, err)
|
||||
}
|
||||
|
||||
// query the api
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
|
@ -48,6 +63,56 @@ func getHeliumApi(path string, params *map[string]string) ([]byte, error) {
|
|||
return body, nil
|
||||
}
|
||||
|
||||
func getHeliumApiWithCursor(path string, params *map[string]string) ([]byte, error) {
|
||||
return nil, nil
|
||||
func getHeliumApiWithCursor(path string, params *map[string]string) ([][]byte, error) {
|
||||
// if params is nil, set it to an empty map
|
||||
if params == nil {
|
||||
params = &map[string]string{}
|
||||
}
|
||||
|
||||
type ResponseWithCursor struct {
|
||||
Cursor string `json:"cursor"`
|
||||
}
|
||||
|
||||
res := [][]byte{}
|
||||
respCursor := ResponseWithCursor{}
|
||||
req, err := createGetRequest(path, *params)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create query request %v: %v", path, err)
|
||||
}
|
||||
|
||||
for {
|
||||
// query the api
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to query path %v: %v", path, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// read the response body and add it to the result array
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read response body of path %v: %v", path, err)
|
||||
}
|
||||
res = append(res, body)
|
||||
|
||||
// parse the response body for a cursor
|
||||
respCursor.Cursor = ""
|
||||
err = json.Unmarshal(body, &respCursor)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal response from path %v: %v", path, err)
|
||||
}
|
||||
|
||||
// continue querying until there is no longer a cursor
|
||||
if respCursor.Cursor != "" {
|
||||
params = &map[string]string{"cursor": respCursor.Cursor}
|
||||
req, err = createGetRequest(path, *params)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create query request %v: %v", path, err)
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
|
|
@ -5,64 +5,6 @@ import (
|
|||
"fmt"
|
||||
)
|
||||
|
||||
type BlockchainStats struct {
|
||||
Data struct {
|
||||
BlockTime struct {
|
||||
LastDay struct {
|
||||
Avg float64 `json:"avg"`
|
||||
Stddev float64 `json:"stddev"`
|
||||
} `json:"last_day"`
|
||||
LastHour struct {
|
||||
Avg float64 `json:"avg"`
|
||||
Stddev float64 `json:"stddev"`
|
||||
} `json:"last_hour"`
|
||||
LastMonth struct {
|
||||
Avg float64 `json:"avg"`
|
||||
Stddev float64 `json:"stddev"`
|
||||
} `json:"last_month"`
|
||||
LastWeek struct {
|
||||
Avg float64 `json:"avg"`
|
||||
Stddev float64 `json:"stddev"`
|
||||
} `json:"last_week"`
|
||||
} `json:"block_times"`
|
||||
ChallengeCount struct {
|
||||
Active int `json:"active"`
|
||||
LastDay int `json:"last_day"`
|
||||
} `json:"challenge_counts"`
|
||||
Counts struct {
|
||||
Validators int `json:"validators"`
|
||||
Ouis int `json:"ouis"`
|
||||
HotspotsDataonly int `json:"hotspots_dataonly"`
|
||||
Blocks int `json:"blocks"`
|
||||
Challenges int `json:"challenges"`
|
||||
Cities int `json:"cities"`
|
||||
ConsensusGroups int `json:"consensus_groups"`
|
||||
Countries int `json:"countries"`
|
||||
Hotspots int `json:"hotspots"`
|
||||
Transactions int `json:"transactions"`
|
||||
} `json:"counts"`
|
||||
ElectionTimes struct {
|
||||
LastDay struct {
|
||||
Avg float64 `json:"avg"`
|
||||
Stddev float64 `json:"stddev"`
|
||||
} `json:"last_day"`
|
||||
LastHour struct {
|
||||
Avg float64 `json:"avg"`
|
||||
Stddev float64 `json:"stddev"`
|
||||
} `json:"last_hour"`
|
||||
LastMonth struct {
|
||||
Avg float64 `json:"avg"`
|
||||
Stddev float64 `json:"stddev"`
|
||||
} `json:"last_month"`
|
||||
LastWeek struct {
|
||||
Avg float64 `json:"avg"`
|
||||
Stddev float64 `json:"stddev"`
|
||||
} `json:"last_week"`
|
||||
} `json:"election_times"`
|
||||
TokenSupply float64 `json:"token_supply"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
func GetBlockchainStats() (*BlockchainStats, error) {
|
||||
const path = "/v1/stats"
|
||||
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
package heliumapi
|
||||
|
||||
type Account struct {
|
||||
Data struct {
|
||||
Address string `json:"address"`
|
||||
Balance int `json:"balance"`
|
||||
Block int `json:"block"`
|
||||
DCBalance int `json:"dc_balance"`
|
||||
DCNonce int `json:"dc_nonce"`
|
||||
SECBalance int `json:"sec_balance"`
|
||||
SECNonce int `json:"sec_nonce"`
|
||||
SpeculativeNonce int `json:"speculative_nonce"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// Time int `json:"time"`
|
||||
// StartEpoch int `json:"start_epoch"`
|
||||
// Height int `json:"height"`
|
||||
// Hash string `json:"hash"`
|
||||
// EndEpoch int `json:"end_epoch"`
|
||||
|
||||
type AccountHotspots struct {
|
||||
Data []struct {
|
||||
Lng float64 `json:"lng"`
|
||||
Lat float64 `json:"lat"`
|
||||
TimestampAdded string `json:"timestamp_added"`
|
||||
Status struct {
|
||||
Timestamp string `json:"timestamp"`
|
||||
Online string `json:"online"`
|
||||
ListenAddrs []string `json:"listen_addrs"`
|
||||
Height int `json:"height"`
|
||||
} `json:"status"`
|
||||
RewardScale float64 `json:"reward_scale"`
|
||||
Payer string `json:"payer"`
|
||||
Owner string `json:"owner"`
|
||||
Nonce int `json:"nonce"`
|
||||
Name string `json:"name"`
|
||||
Mode string `json:"mode"`
|
||||
LocationHex string `json:"location_hex"`
|
||||
Location string `json:"location"`
|
||||
LastPocChallenge int `json:"last_poc_challenge"`
|
||||
LastChangeBlock int `json:"last_change_block"`
|
||||
Geocode struct {
|
||||
ShortStreet string `json:"short_street"`
|
||||
ShortState string `json:"short_state"`
|
||||
ShortCountry string `json:"short_country"`
|
||||
ShortCity string `json:"short_city"`
|
||||
LongStreet string `json:"long_street"`
|
||||
LongState string `json:"long_state"`
|
||||
LongCountry string `json:"long_country"`
|
||||
LongCity string `json:"long_city"`
|
||||
CityID string `json:"city_id"`
|
||||
} `json:"geocode"`
|
||||
Gain int `json:"gain"`
|
||||
Elevation int `json:"elevation"`
|
||||
BlockAdded int `json:"block_added"`
|
||||
Block int `json:"block"`
|
||||
Address string `json:"address"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
type ActivityCounts struct {
|
||||
Data map[string]int
|
||||
}
|
||||
|
||||
type RewardTotal struct {
|
||||
Meta struct {
|
||||
MinTime string `json:"min_time"`
|
||||
MaxTime string `json:"max_time"`
|
||||
} `json:"meta"`
|
||||
|
||||
Data struct {
|
||||
Total float64 `json:"total"`
|
||||
Sum float64 `json:"sum"`
|
||||
Stddev float64 `json:"stddev"`
|
||||
Min float64 `json:"min"`
|
||||
Median float64 `json:"median"`
|
||||
Max float64 `json:"max"`
|
||||
Avg float64 `json:"avg"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
type CurrentOraclePrice struct {
|
||||
Data struct {
|
||||
Price int `json:"price"`
|
||||
Block int `json:"block"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
type BlockchainStats struct {
|
||||
Data struct {
|
||||
BlockTime struct {
|
||||
LastDay struct {
|
||||
Avg float64 `json:"avg"`
|
||||
Stddev float64 `json:"stddev"`
|
||||
} `json:"last_day"`
|
||||
LastHour struct {
|
||||
Avg float64 `json:"avg"`
|
||||
Stddev float64 `json:"stddev"`
|
||||
} `json:"last_hour"`
|
||||
LastMonth struct {
|
||||
Avg float64 `json:"avg"`
|
||||
Stddev float64 `json:"stddev"`
|
||||
} `json:"last_month"`
|
||||
LastWeek struct {
|
||||
Avg float64 `json:"avg"`
|
||||
Stddev float64 `json:"stddev"`
|
||||
} `json:"last_week"`
|
||||
} `json:"block_times"`
|
||||
ChallengeCount struct {
|
||||
Active int `json:"active"`
|
||||
LastDay int `json:"last_day"`
|
||||
} `json:"challenge_counts"`
|
||||
Counts struct {
|
||||
Validators int `json:"validators"`
|
||||
Ouis int `json:"ouis"`
|
||||
HotspotsDataonly int `json:"hotspots_dataonly"`
|
||||
Blocks int `json:"blocks"`
|
||||
Challenges int `json:"challenges"`
|
||||
Cities int `json:"cities"`
|
||||
ConsensusGroups int `json:"consensus_groups"`
|
||||
Countries int `json:"countries"`
|
||||
Hotspots int `json:"hotspots"`
|
||||
Transactions int `json:"transactions"`
|
||||
} `json:"counts"`
|
||||
ElectionTimes struct {
|
||||
LastDay struct {
|
||||
Avg float64 `json:"avg"`
|
||||
Stddev float64 `json:"stddev"`
|
||||
} `json:"last_day"`
|
||||
LastHour struct {
|
||||
Avg float64 `json:"avg"`
|
||||
Stddev float64 `json:"stddev"`
|
||||
} `json:"last_hour"`
|
||||
LastMonth struct {
|
||||
Avg float64 `json:"avg"`
|
||||
Stddev float64 `json:"stddev"`
|
||||
} `json:"last_month"`
|
||||
LastWeek struct {
|
||||
Avg float64 `json:"avg"`
|
||||
Stddev float64 `json:"stddev"`
|
||||
} `json:"last_week"`
|
||||
} `json:"election_times"`
|
||||
TokenSupply float64 `json:"token_supply"`
|
||||
} `json:"data"`
|
||||
}
|
Reference in New Issue