refactor code organization
This commit is contained in:
parent
7f8b73055e
commit
b8172f06ab
|
@ -22,19 +22,46 @@ type metricInfo struct {
|
||||||
|
|
||||||
// Exporter collect metrics from the helium blockchain api and exports them as prometheus metrics.
|
// Exporter collect metrics from the helium blockchain api and exports them as prometheus metrics.
|
||||||
type Exporter struct {
|
type Exporter struct {
|
||||||
Accounts []Account
|
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
|
// Account represents a helium account
|
||||||
type Account struct {
|
type Account struct {
|
||||||
hotspots []Hotspot
|
Address string
|
||||||
hash string
|
Tx AccountTx
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hotspot represent a helium hotspot
|
func NewAccount(address string) Account {
|
||||||
type Hotspot struct {
|
return Account{
|
||||||
name string
|
Address: address,
|
||||||
hash string
|
Tx: AccountTx{
|
||||||
|
DepositTotal: 0,
|
||||||
|
WithdrawalTotal: 0,
|
||||||
|
LastUpdate: time.Now(),
|
||||||
|
// LastUpdate: time.Time{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type AccountTx struct {
|
||||||
|
DepositTotal int
|
||||||
|
WithdrawalTotal int
|
||||||
|
LastUpdate time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -42,7 +69,24 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
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"}
|
commonAccountLabels = []string{"account"}
|
||||||
commonHotspotLabels = append(commonAccountLabels, "hotspot", "hotspot_name")
|
commonHotspotLabels = append(commonAccountLabels, "hotspot", "hotspot_name")
|
||||||
|
|
||||||
|
@ -61,43 +105,43 @@ var (
|
||||||
// helium stats metrics
|
// helium stats metrics
|
||||||
statsValidators = metricInfo{
|
statsValidators = metricInfo{
|
||||||
prometheus.NewDesc(
|
prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, "stats", "validators_total"),
|
prometheus.BuildFQName(namespace, "stats", "validators"),
|
||||||
"The total number of validators.",
|
"The total number of validators.",
|
||||||
nil, nil,
|
nil, nil,
|
||||||
),
|
),
|
||||||
prometheus.CounterValue,
|
prometheus.GaugeValue,
|
||||||
}
|
}
|
||||||
statsOuis = metricInfo{
|
statsOuis = metricInfo{
|
||||||
prometheus.NewDesc(
|
prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, "stats", "ouis_total"),
|
prometheus.BuildFQName(namespace, "stats", "ouis"),
|
||||||
"The total number of organization unique identifiers.",
|
"The total number of organization unique identifiers.",
|
||||||
nil, nil,
|
nil, nil,
|
||||||
),
|
),
|
||||||
prometheus.CounterValue,
|
prometheus.GaugeValue,
|
||||||
}
|
}
|
||||||
statsHotspotsDataOnly = metricInfo{
|
statsHotspotsDataOnly = metricInfo{
|
||||||
prometheus.NewDesc(
|
prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, "stats", "hotspots_dataonly_total"),
|
prometheus.BuildFQName(namespace, "stats", "hotspots_dataonly"),
|
||||||
"The total number of data only hotspots.",
|
"The total number of data only hotspots.",
|
||||||
nil, nil,
|
nil, nil,
|
||||||
),
|
),
|
||||||
prometheus.CounterValue,
|
prometheus.GaugeValue,
|
||||||
}
|
}
|
||||||
statsBlocks = metricInfo{
|
statsBlocks = metricInfo{
|
||||||
prometheus.NewDesc(
|
prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, "stats", "blocks_total"),
|
prometheus.BuildFQName(namespace, "stats", "blocks"),
|
||||||
"The total height/number of blocks in the blockchain.",
|
"The total height/number of blocks in the blockchain.",
|
||||||
nil, nil,
|
nil, nil,
|
||||||
),
|
),
|
||||||
prometheus.CounterValue,
|
prometheus.GaugeValue,
|
||||||
}
|
}
|
||||||
statsChallenges = metricInfo{
|
statsChallenges = metricInfo{
|
||||||
prometheus.NewDesc(
|
prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, "stats", "challenges_total"),
|
prometheus.BuildFQName(namespace, "stats", "challenges"),
|
||||||
"The total number of challenges.",
|
"The total number of challenges.",
|
||||||
nil, nil,
|
nil, nil,
|
||||||
),
|
),
|
||||||
prometheus.CounterValue,
|
prometheus.GaugeValue,
|
||||||
}
|
}
|
||||||
statsCities = metricInfo{
|
statsCities = metricInfo{
|
||||||
prometheus.NewDesc(
|
prometheus.NewDesc(
|
||||||
|
@ -109,7 +153,7 @@ var (
|
||||||
}
|
}
|
||||||
statsConsensusGroups = metricInfo{
|
statsConsensusGroups = metricInfo{
|
||||||
prometheus.NewDesc(
|
prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, "stats", "consensus_groups_total"),
|
prometheus.BuildFQName(namespace, "stats", "consensus_groups"),
|
||||||
"The total number of consensus groups.",
|
"The total number of consensus groups.",
|
||||||
nil, nil,
|
nil, nil,
|
||||||
),
|
),
|
||||||
|
@ -125,15 +169,15 @@ var (
|
||||||
}
|
}
|
||||||
statsHotspots = metricInfo{
|
statsHotspots = metricInfo{
|
||||||
prometheus.NewDesc(
|
prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, "stats", "hotspots_total"),
|
prometheus.BuildFQName(namespace, "stats", "hotspots"),
|
||||||
"The total number of hotspots.",
|
"The total number of hotspots.",
|
||||||
nil, nil,
|
nil, nil,
|
||||||
),
|
),
|
||||||
prometheus.CounterValue,
|
prometheus.GaugeValue,
|
||||||
}
|
}
|
||||||
statsTokenSupply = metricInfo{
|
statsTokenSupply = metricInfo{
|
||||||
prometheus.NewDesc(
|
prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, "stats", "token_supply"),
|
prometheus.BuildFQName(namespace, "stats", "token"),
|
||||||
"The total supply of HNT tokens in circulation.",
|
"The total supply of HNT tokens in circulation.",
|
||||||
nil, nil,
|
nil, nil,
|
||||||
),
|
),
|
||||||
|
@ -165,22 +209,22 @@ var (
|
||||||
),
|
),
|
||||||
prometheus.CounterValue,
|
prometheus.CounterValue,
|
||||||
}
|
}
|
||||||
// accountDepositsHnt = metricInfo{
|
accountDepositsHnt = metricInfo{
|
||||||
// prometheus.NewDesc(
|
prometheus.NewDesc(
|
||||||
// prometheus.BuildFQName(namespace, "account", "deposits_hnt_total"),
|
prometheus.BuildFQName(namespace, "account", "deposits_hnt_total"),
|
||||||
// "The number of HNT token deposited to this account.",
|
"The number of HNT tokens deposited to this account.",
|
||||||
// commonAccountLabels, nil,
|
commonAccountLabels, nil,
|
||||||
// ),
|
),
|
||||||
// prometheus.CounterValue,
|
prometheus.CounterValue,
|
||||||
// }
|
}
|
||||||
// accountWithdrawalsHnt = metricInfo{
|
accountWithdrawalsHnt = metricInfo{
|
||||||
// prometheus.NewDesc(
|
prometheus.NewDesc(
|
||||||
// prometheus.BuildFQName(namespace, "account", "withdrawals_hnt_total"),
|
prometheus.BuildFQName(namespace, "account", "withdrawals_hnt_total"),
|
||||||
// "The number of HNT token withdrawn from this account.",
|
"The number of HNT tokens withdrawn from this account.",
|
||||||
// commonAccountLabels, nil,
|
commonAccountLabels, nil,
|
||||||
// ),
|
),
|
||||||
// prometheus.CounterValue,
|
prometheus.CounterValue,
|
||||||
// }
|
}
|
||||||
|
|
||||||
// helium hotspot metrics
|
// helium hotspot metrics
|
||||||
hotspotUp = metricInfo{
|
hotspotUp = metricInfo{
|
||||||
|
@ -275,8 +319,8 @@ func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
|
||||||
ch <- accountBalanceHnt.Desc
|
ch <- accountBalanceHnt.Desc
|
||||||
ch <- accountActivity.Desc
|
ch <- accountActivity.Desc
|
||||||
ch <- accountRewardsHnt.Desc
|
ch <- accountRewardsHnt.Desc
|
||||||
// ch <- accountDepositsHnt.Desc
|
ch <- accountDepositsHnt.Desc
|
||||||
// ch <- accountWithdrawalsHnt.Desc
|
ch <- accountWithdrawalsHnt.Desc
|
||||||
|
|
||||||
ch <- hotspotUp.Desc
|
ch <- hotspotUp.Desc
|
||||||
ch <- hotspotRelayed.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
|
// collectStatsMetrics collect metrics in the account group from the helium api
|
||||||
func (e *Exporter) collectAccountMetrics(ch chan<- prometheus.Metric, account *Account) {
|
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 {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
accountActivityForAddress, err := heliumapi.GetActivityCountsForAccount(account.hash)
|
accountActivityForAddress, err := heliumapi.GetActivityCountsForAccount(account.Address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return
|
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 {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return
|
return
|
||||||
|
@ -374,23 +423,31 @@ func (e *Exporter) collectAccountMetrics(ch chan<- prometheus.Metric, account *A
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
accountBalanceHnt.Desc, accountBalanceHnt.Type, float64(accountForAddress.Data.Balance),
|
accountBalanceHnt.Desc, accountBalanceHnt.Type, float64(accountForAddress.Data.Balance),
|
||||||
account.hash,
|
account.Address,
|
||||||
)
|
)
|
||||||
for accType, count := range accountActivityForAddress.Data {
|
for accType, count := range accountActivityForAddress.Data {
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
accountActivity.Desc, accountActivity.Type, float64(count),
|
accountActivity.Desc, accountActivity.Type, float64(count),
|
||||||
account.hash, accType,
|
account.Address, accType,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
accountRewardsHnt.Desc, accountRewardsHnt.Type, accountRewardTotalsForAddress.Data.Sum,
|
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
|
// collectStatsMetrics collect metrics in the hotspot group from the helium api
|
||||||
func (e *Exporter) collectHotspotMetrics(ch chan<- prometheus.Metric, account *Account) {
|
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 {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return
|
return
|
||||||
|
@ -403,7 +460,7 @@ func (e *Exporter) collectHotspotMetrics(ch chan<- prometheus.Metric, account *A
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
hotspotRewardTotalsForAddress, err := heliumapi.GetRewardsTotalForHotspot(hotspotData.Address, &time.Time{}, nil)
|
hotspotRewardTotalsForAddress, err := heliumapi.GetRewardsTotalForHotspot(hotspotData.Address, &e.StartTime, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return
|
return
|
||||||
|
@ -411,58 +468,52 @@ func (e *Exporter) collectHotspotMetrics(ch chan<- prometheus.Metric, account *A
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
hotspotUp.Desc, hotspotUp.Type, bool2Float64(hotspotData.Status.Online == "online"),
|
hotspotUp.Desc, hotspotUp.Type, bool2Float64(hotspotData.Status.Online == "online"),
|
||||||
account.hash, hotspotData.Address, hotspotData.Name,
|
account.Address, hotspotData.Address, hotspotData.Name,
|
||||||
)
|
)
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
hotspotRelayed.Desc, hotspotRelayed.Type, bool2Float64(len(hotspotData.Status.ListenAddrs) > 0 && strings.HasPrefix(hotspotData.Status.ListenAddrs[0], "/p2p")),
|
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(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
hotspotBlocks.Desc, hotspotBlocks.Type, float64(hotspotData.Status.Height),
|
hotspotBlocks.Desc, hotspotBlocks.Type, float64(hotspotData.Status.Height),
|
||||||
account.hash, hotspotData.Address, hotspotData.Name,
|
account.Address, hotspotData.Address, hotspotData.Name,
|
||||||
)
|
)
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
hotspotRewardsScale.Desc, hotspotRewardsScale.Type, float64(hotspotData.RewardScale),
|
hotspotRewardsScale.Desc, hotspotRewardsScale.Type, float64(hotspotData.RewardScale),
|
||||||
account.hash, hotspotData.Address, hotspotData.Name,
|
account.Address, hotspotData.Address, hotspotData.Name,
|
||||||
)
|
)
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
hotspotGeocodeInfo.Desc, hotspotGeocodeInfo.Type, 1.0,
|
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(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
hotspotAntennaInfo.Desc, hotspotAntennaInfo.Type, 1.0,
|
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 {
|
for accType, count := range hotspotActivityForAddress.Data {
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
hotspotActivity.Desc, hotspotActivity.Type, float64(count),
|
hotspotActivity.Desc, hotspotActivity.Type, float64(count),
|
||||||
account.hash, hotspotData.Address, hotspotData.Name, accType,
|
account.Address, hotspotData.Address, hotspotData.Name, accType,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
hotspotRewardsHnt.Desc, hotspotRewardsHnt.Type, hotspotRewardTotalsForAddress.Data.Sum,
|
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 (a *Account) computeTransactions() (*AccountTx, error) {
|
||||||
func NewExporter(accountHashs []string) (*Exporter, error) {
|
now := time.Now()
|
||||||
accounts := make([]Account, 0)
|
_, err := heliumapi.GetActivityForAccount(a.Address, []string{}, &a.Tx.LastUpdate, &now)
|
||||||
for _, accountHash := range accountHashs {
|
if err != nil {
|
||||||
if accountHash != "" {
|
return nil, err
|
||||||
accounts = append(accounts, NewAccount(accountHash))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return &Exporter{
|
|
||||||
Accounts: accounts,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewAccount(hash string) Account {
|
// fmt.Println(activities)
|
||||||
return Account{
|
|
||||||
hash: hash,
|
a.Tx.LastUpdate = now
|
||||||
}
|
return &a.Tx, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
|
@ -4,61 +4,10 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"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) {
|
func GetAccountForAddress(account string) (*Account, error) {
|
||||||
path := "/v1/accounts/" + account
|
path := "/v1/accounts/" + account
|
||||||
|
|
||||||
|
@ -78,6 +27,36 @@ func GetAccountForAddress(account string) (*Account, error) {
|
||||||
return &respobject, nil
|
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) {
|
func GetActivityCountsForAccount(account string) (*ActivityCounts, error) {
|
||||||
path := "/v1/accounts/" + account + "/activity/count"
|
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"
|
"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) {
|
func GetHotspotActivityCount(hotspot string) (*ActivityCounts, error) {
|
||||||
path := "/v1/hotspots/" + hotspot + "/activity/count"
|
path := "/v1/hotspots/" + hotspot + "/activity/count"
|
||||||
|
|
||||||
|
|
|
@ -5,13 +5,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CurrentOraclePrice struct {
|
|
||||||
Data struct {
|
|
||||||
Price int `json:"price"`
|
|
||||||
Block int `json:"block"`
|
|
||||||
} `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetCurrentOraclePrice() (*CurrentOraclePrice, error) {
|
func GetCurrentOraclePrice() (*CurrentOraclePrice, error) {
|
||||||
const path = "/v1/oracle/prices/current"
|
const path = "/v1/oracle/prices/current"
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package heliumapi
|
package heliumapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -14,7 +15,7 @@ var (
|
||||||
client = &http.Client{}
|
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)
|
req, err := http.NewRequest("GET", fmt.Sprintf("%s/%s", apiUrl, path), nil)
|
||||||
|
|
||||||
// setup headers
|
// setup headers
|
||||||
|
@ -23,7 +24,7 @@ func getHeliumApi(path string, params *map[string]string) ([]byte, error) {
|
||||||
// setup query param if there are any
|
// setup query param if there are any
|
||||||
if params != nil {
|
if params != nil {
|
||||||
query := req.URL.Query()
|
query := req.URL.Query()
|
||||||
for k, v := range *params {
|
for k, v := range params {
|
||||||
query.Add(k, v)
|
query.Add(k, v)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -32,6 +33,20 @@ func getHeliumApi(path string, params *map[string]string) ([]byte, error) {
|
||||||
req.URL.RawQuery = query.Encode()
|
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
|
// query the api
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -48,6 +63,56 @@ func getHeliumApi(path string, params *map[string]string) ([]byte, error) {
|
||||||
return body, nil
|
return body, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHeliumApiWithCursor(path string, params *map[string]string) ([]byte, error) {
|
func getHeliumApiWithCursor(path string, params *map[string]string) ([][]byte, error) {
|
||||||
return nil, nil
|
// 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"
|
"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) {
|
func GetBlockchainStats() (*BlockchainStats, error) {
|
||||||
const path = "/v1/stats"
|
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