add deposit/withdraw
continuous-integration/drone Build is failing
Details
continuous-integration/drone Build is failing
Details
This commit is contained in:
parent
b8172f06ab
commit
ff8e8cc377
|
@ -0,0 +1 @@
|
|||
bin/
|
|
@ -0,0 +1,17 @@
|
|||
kind: pipeline
|
||||
type: kubernetes
|
||||
name: arm64
|
||||
|
||||
node_selector:
|
||||
beta.kubernetes.io/arch: arm64
|
||||
|
||||
steps:
|
||||
- name: docker
|
||||
image: plugins/docker
|
||||
settings:
|
||||
repo: badjware/nextcloud-tweak
|
||||
auto_tag: true
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
|
@ -0,0 +1,10 @@
|
|||
FROM golang:1.17-alpine as builder
|
||||
COPY . /app
|
||||
WORKDIR /app
|
||||
RUN apk add git make build-base \
|
||||
&& make dist
|
||||
|
||||
FROM gcr.io/distroless/base-debian10
|
||||
COPY --from=builder /app/bin/helium-blockchain-exporter /usr/bin/helium-blockchain-exporter
|
||||
EXPOSE 9865
|
||||
ENTRYPOINT [ "/usr/bin/helium-blockchain-exporter" ]
|
33
Makefile
33
Makefile
|
@ -33,19 +33,19 @@ all: build
|
|||
help:
|
||||
@echo "clean revert back to clean state"
|
||||
@echo "lint lint and format the code"
|
||||
@echo "run run without building"
|
||||
@echo "prepare prepare environment for build"
|
||||
@echo "test build and run short test suite"
|
||||
@echo "coverage build and run full test suite and generate coverage report"
|
||||
@echo "build build the binary"
|
||||
@echo "build-docker build the docker image"
|
||||
@echo "dist build the binary for release"
|
||||
@echo "docker build the docker image"
|
||||
|
||||
# clean: revert back to initial state
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(GOCLEAN)
|
||||
rm -r $(TARGET_DIR)
|
||||
rm -r $(TARGET_DIR) || true
|
||||
|
||||
# lint: lint and format the code
|
||||
|
||||
|
@ -53,17 +53,6 @@ clean:
|
|||
lint:
|
||||
$(GOFMT) ./...
|
||||
|
||||
# run: run without building with debug flags
|
||||
ifeq (run,$(firstword $(MAKECMDGOALS)))
|
||||
# use the rest as arguments for "run"
|
||||
RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
|
||||
# ...and turn them into do-nothing targets
|
||||
$(eval $(RUN_ARGS):;@:)
|
||||
endif
|
||||
.PHONY: run
|
||||
run: lint
|
||||
$(GORUN) . $(RUN_ARGS)
|
||||
|
||||
# prepare: prepare environment for build
|
||||
|
||||
$(TARGET_DIR):
|
||||
|
@ -90,18 +79,24 @@ $(COVER_REPORT): $(TARGET_DIR) $(COVER_PROFILE)
|
|||
coverage: lint $(COVER_REPORT)
|
||||
$(GOCOVER) -func=$(COVER_PROFILE)
|
||||
|
||||
# build: build the program for release
|
||||
# build: build the program
|
||||
|
||||
$(BIN): $(TARGET_DIR) $(SRC)
|
||||
$(GOBUILD) -o=$(BIN)
|
||||
$(GOBUILD) -o=$(BIN) -race
|
||||
|
||||
.PHONY: build
|
||||
build: lint $(BIN)
|
||||
|
||||
# build-docker: build the docker image
|
||||
# dist: build the program for release
|
||||
|
||||
.PHONY: build-docker
|
||||
build-docker: $(BIN)
|
||||
.PHONY: dist
|
||||
dist: $(TARGET_DIR) $(SRC)
|
||||
$(GOBUILD) -o=$(BIN) -a -ldflags "-linkmode external -extldflags -static"
|
||||
|
||||
# docker: build the docker image
|
||||
|
||||
.PHONY: docker
|
||||
docker: $(BIN)
|
||||
$(DOCKERBUILD) -t $(PROGRAM) .
|
||||
$(foreach tag,$(DOCKER_TAGS),$(DOCKERTAG) $(PROGRAM) $(tag);)
|
||||
|
||||
|
|
|
@ -53,7 +53,6 @@ func NewAccount(address string) Account {
|
|||
DepositTotal: 0,
|
||||
WithdrawalTotal: 0,
|
||||
LastUpdate: time.Now(),
|
||||
// LastUpdate: time.Time{},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -69,23 +68,6 @@ const (
|
|||
)
|
||||
|
||||
var (
|
||||
// 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")
|
||||
|
@ -415,7 +397,7 @@ func (e *Exporter) collectAccountMetrics(ch chan<- prometheus.Metric, account *A
|
|||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
tx, err := account.computeTransactions()
|
||||
err = account.collectTransactionMetrics(ch)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
|
@ -435,14 +417,6 @@ func (e *Exporter) collectAccountMetrics(ch chan<- prometheus.Metric, account *A
|
|||
accountRewardsHnt.Desc, accountRewardsHnt.Type, accountRewardTotalsForAddress.Data.Sum,
|
||||
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
|
||||
|
@ -503,24 +477,90 @@ func (e *Exporter) collectHotspotMetrics(ch chan<- prometheus.Metric, account *A
|
|||
}
|
||||
}
|
||||
|
||||
func (a *Account) computeTransactions() (*AccountTx, error) {
|
||||
func (a *Account) collectTransactionMetrics(ch chan<- prometheus.Metric) error {
|
||||
now := time.Now()
|
||||
_, err := heliumapi.GetActivityForAccount(a.Address, []string{}, &a.Tx.LastUpdate, &now)
|
||||
activities, err := heliumapi.GetActivityForAccount(a.Address, []string{}, &a.Tx.LastUpdate, &now)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// fmt.Println(activities)
|
||||
|
||||
// logic based on https://github.com/helium/hotspot-app/blob/918563fba84d1abf4554a43a4d42bb838d017bd3/src/features/wallet/root/useActivityItem.tsx#L336
|
||||
for _, activity := range activities.AddGatewayV1 {
|
||||
a.Tx.WithdrawalTotal += activity.StakingFee
|
||||
}
|
||||
for _, activity := range activities.AssertLocationV1 {
|
||||
a.Tx.WithdrawalTotal += activity.StakingFee
|
||||
}
|
||||
for _, activity := range activities.AssertLocationV2 {
|
||||
a.Tx.WithdrawalTotal += activity.StakingFee
|
||||
}
|
||||
for _, activity := range activities.PaymentV1 {
|
||||
if activity.Payer == a.Address {
|
||||
a.Tx.WithdrawalTotal += activity.Amount
|
||||
} else {
|
||||
a.Tx.DepositTotal += activity.Amount
|
||||
}
|
||||
}
|
||||
for _, activity := range activities.PaymentV2 {
|
||||
if activity.Payer == a.Address {
|
||||
paymentTotal := 0
|
||||
for _, payment := range activity.Payments {
|
||||
paymentTotal += payment.Amount
|
||||
}
|
||||
a.Tx.WithdrawalTotal += paymentTotal
|
||||
} else {
|
||||
for _, payment := range activity.Payments {
|
||||
if payment.Payee == a.Address {
|
||||
a.Tx.DepositTotal += payment.Amount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, activity := range activities.RewardsV1 {
|
||||
for _, reward := range activity.Rewards {
|
||||
a.Tx.DepositTotal += reward.Amount
|
||||
}
|
||||
}
|
||||
for _, activity := range activities.RewardsV2 {
|
||||
for _, reward := range activity.Rewards {
|
||||
a.Tx.DepositTotal += reward.Amount
|
||||
}
|
||||
}
|
||||
for _, activity := range activities.StakeValidatorV1 {
|
||||
a.Tx.WithdrawalTotal += activity.Stake
|
||||
}
|
||||
for _, activity := range activities.TokenBurnV1 {
|
||||
a.Tx.WithdrawalTotal += activity.Amount
|
||||
}
|
||||
for _, activity := range activities.TransferHotspotV1 {
|
||||
if activity.Buyer == a.Address {
|
||||
a.Tx.WithdrawalTotal += activity.AmountToSeller
|
||||
} else {
|
||||
a.Tx.DepositTotal += activity.AmountToSeller
|
||||
}
|
||||
}
|
||||
for _, activity := range activities.UnstakeValidatorV1 {
|
||||
a.Tx.WithdrawalTotal += activity.StakeAmount
|
||||
}
|
||||
a.Tx.LastUpdate = now
|
||||
return &a.Tx, nil
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
accountDepositsHnt.Desc, accountDepositsHnt.Type, float64(a.Tx.DepositTotal),
|
||||
a.Address,
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
accountWithdrawalsHnt.Desc, accountWithdrawalsHnt.Type, float64(a.Tx.WithdrawalTotal),
|
||||
a.Address,
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
fHeliumAccounts := flag.String("accounts", "", "A comma-delimited list of helium accounts to scrape.")
|
||||
fHeliumAccounts := flag.String("accounts", "", "A comma-delimited list of helium accounts to scrape (optional)")
|
||||
fMetricsPath := flag.String("metricpath", "/metrics", "The metrics path")
|
||||
fListenAddress := flag.String("listenAddress", "0.0.0.0", "The http server listen address")
|
||||
fListenPort := flag.String("listenPort", "9111", "The http server listen port")
|
||||
fListenPort := flag.String("listenPort", "9865", "The http server listen port")
|
||||
flag.Parse()
|
||||
|
||||
heliumAccounts := strings.Split(*fHeliumAccounts, ",")
|
|
@ -9,8 +9,6 @@ type ActivityResp struct {
|
|||
Data []json.RawMessage `json:"data"`
|
||||
}
|
||||
|
||||
type Activities struct{}
|
||||
|
||||
func NewActivities(resp ActivityResp) (*Activities, error) {
|
||||
type ActivityType struct {
|
||||
Type string `json:"type"`
|
||||
|
@ -26,16 +24,67 @@ func NewActivities(resp ActivityResp) (*Activities, error) {
|
|||
fmt.Println(activityType.Type)
|
||||
switch activityType.Type {
|
||||
case "add_gateway_v1":
|
||||
addGatewayV1 := AddGatewayV1{}
|
||||
if err := json.Unmarshal(activityRaw, &addGatewayV1); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal %v: %v", activityType.Type, err)
|
||||
}
|
||||
activities.AddGatewayV1 = append(activities.AddGatewayV1, addGatewayV1)
|
||||
case "assert_location_v1":
|
||||
assertLocationV1 := AssertLocationV1{}
|
||||
if err := json.Unmarshal(activityRaw, &assertLocationV1); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal %v: %v", activityType.Type, err)
|
||||
}
|
||||
activities.AssertLocationV1 = append(activities.AssertLocationV1, assertLocationV1)
|
||||
case "assert_location_v2":
|
||||
assertLocationV2 := AssertLocationV2{}
|
||||
if err := json.Unmarshal(activityRaw, &assertLocationV2); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal %v: %v", activityType.Type, err)
|
||||
}
|
||||
activities.AssertLocationV2 = append(activities.AssertLocationV2, assertLocationV2)
|
||||
case "payment_v1":
|
||||
paymentV1 := PaymentV1{}
|
||||
if err := json.Unmarshal(activityRaw, &paymentV1); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal %v: %v", activityType.Type, err)
|
||||
}
|
||||
activities.PaymentV1 = append(activities.PaymentV1, paymentV1)
|
||||
case "payment_v2":
|
||||
paymentV2 := PaymentV2{}
|
||||
if err := json.Unmarshal(activityRaw, &paymentV2); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal %v: %v", activityType.Type, err)
|
||||
}
|
||||
activities.PaymentV2 = append(activities.PaymentV2, paymentV2)
|
||||
case "rewards_v1":
|
||||
rewardV1 := RewardsV1{}
|
||||
if err := json.Unmarshal(activityRaw, &rewardV1); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal %v: %v", activityType.Type, err)
|
||||
}
|
||||
activities.RewardsV1 = append(activities.RewardsV1, rewardV1)
|
||||
case "rewards_v2":
|
||||
rewardV2 := RewardsV2{}
|
||||
if err := json.Unmarshal(activityRaw, &rewardV2); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal %v: %v", activityType.Type, err)
|
||||
}
|
||||
activities.RewardsV2 = append(activities.RewardsV2, rewardV2)
|
||||
case "stake_validator_v1":
|
||||
stakeValidatorV1 := StakeValidatorV1{}
|
||||
if err := json.Unmarshal(activityRaw, &stakeValidatorV1); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal %v: %v", activityType.Type, err)
|
||||
}
|
||||
activities.StakeValidatorV1 = append(activities.StakeValidatorV1, stakeValidatorV1)
|
||||
case "token_burn_v1":
|
||||
tokenBurnV1 := TokenBurnV1{}
|
||||
if err := json.Unmarshal(activityRaw, &activities.TokenBurnV1); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal %v: %v", activityType.Type, err)
|
||||
}
|
||||
activities.TokenBurnV1 = append(activities.TokenBurnV1, tokenBurnV1)
|
||||
case "unstake_validator_v1":
|
||||
unstakeValidatorV1 := UnstakeValidatorV1{}
|
||||
if err := json.Unmarshal(activityRaw, &activities.UnstakeValidatorV1); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal %v: %v", activityType.Type, err)
|
||||
}
|
||||
activities.UnstakeValidatorV1 = append(activities.UnstakeValidatorV1, unstakeValidatorV1)
|
||||
default:
|
||||
fmt.Printf("unimplemented activy type: %v", activityType.Type)
|
||||
fmt.Printf("ignoring unimplemented activy type: %v", activityType.Type)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1,129 @@
|
|||
package activity
|
||||
|
||||
type Activities struct {
|
||||
AddGatewayV1 []AddGatewayV1
|
||||
AssertLocationV1 []AssertLocationV1
|
||||
AssertLocationV2 []AssertLocationV2
|
||||
PaymentV1 []PaymentV1
|
||||
PaymentV2 []PaymentV2
|
||||
RewardsV1 []RewardsV1
|
||||
RewardsV2 []RewardsV2
|
||||
StakeValidatorV1 []StakeValidatorV1
|
||||
TokenBurnV1 []TokenBurnV1
|
||||
TransferHotspotV1 []TransferHotspotV1
|
||||
UnstakeValidatorV1 []UnstakeValidatorV1
|
||||
}
|
||||
|
||||
type AddGatewayV1 struct {
|
||||
Hash string `json:"hash"`
|
||||
Fee int `json:"fee"`
|
||||
Owner string `json:"owner"`
|
||||
Payer string `json:"payer"`
|
||||
Gateway string `json:"gateway"`
|
||||
StakingFee int `json:"staking_fee"`
|
||||
}
|
||||
|
||||
type AssertLocationV1 struct {
|
||||
Hash string `json:"hash"`
|
||||
Fee int `json:"fee"`
|
||||
Nonce int `json:"nonce"`
|
||||
Owner string `json:"owner"`
|
||||
Payer string `json:"payer,omitempty"`
|
||||
Gateway string `json:"gateway"`
|
||||
Location string `json:"location"`
|
||||
StakingFee int `json:"staking_fee"`
|
||||
}
|
||||
|
||||
type AssertLocationV2 struct {
|
||||
Hash string `json:"hash"`
|
||||
Fee int `json:"fee"`
|
||||
Gain int `json:"gain"`
|
||||
Nonce int `json:"nonce"`
|
||||
Owner string `json:"owner"`
|
||||
Payer string `json:"payer,omitempty"`
|
||||
Gateway string `json:"gateway"`
|
||||
Location string `json:"location"`
|
||||
Elevation int `json:"elevation"`
|
||||
StakingFee int `json:"staking_fee"`
|
||||
}
|
||||
|
||||
type PaymentV1 struct {
|
||||
Hash string `json:"hash"`
|
||||
Amount int `json:"amount"`
|
||||
Fee int `json:"fee"`
|
||||
Nonce int `json:"nonce"`
|
||||
Payer string `json:"payer"`
|
||||
Payee string `json:"payee"`
|
||||
}
|
||||
|
||||
type PaymentV2 struct {
|
||||
Hash string `json:"hash"`
|
||||
Fee int `json:"fee"`
|
||||
Nonce int `json:"nonce"`
|
||||
Payer string `json:"payer"`
|
||||
Payments []struct {
|
||||
Amount int `json:"amount"`
|
||||
Memo string `json:"memo"`
|
||||
Payee string `json:"payee"`
|
||||
}
|
||||
}
|
||||
|
||||
type reward struct {
|
||||
Account string `json:"account,omitempty"`
|
||||
Amount int `json:"amount"`
|
||||
Gateway string `json:"gateway,omitempty"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
type RewardsV1 struct {
|
||||
Hash string `json:"hash"`
|
||||
StartEpoch int `json:"start_epoch"`
|
||||
EndEpoch int `json:"end_epoch"`
|
||||
Rewards []reward `json:"rewards"`
|
||||
}
|
||||
|
||||
type RewardsV2 struct {
|
||||
Hash string `json:"hash"`
|
||||
StartEpoch int `json:"start_epoch"`
|
||||
EndEpoch int `json:"end_epoch"`
|
||||
Rewards []reward `json:"rewards"`
|
||||
}
|
||||
|
||||
type StakeValidatorV1 struct {
|
||||
Address string `json:"address"`
|
||||
Fee int `json:"fee"`
|
||||
Hash string `json:"hash"`
|
||||
Owner string `json:"owner"`
|
||||
Stake int `json:"stake"`
|
||||
OwnerSignature string `json:"owner_signature"`
|
||||
}
|
||||
|
||||
type TokenBurnV1 struct {
|
||||
Fee int `json:"fee"`
|
||||
Hash string `json:"hash"`
|
||||
Memo string `json:"memo"`
|
||||
Nonce int `json:"nonce"`
|
||||
Payer string `json:"payer"`
|
||||
Payee string `json:"payee"`
|
||||
Amount int `json:"amount"`
|
||||
}
|
||||
|
||||
type TransferHotspotV1 struct {
|
||||
Hash string `json:"hash"`
|
||||
Fee int `json:"fee"`
|
||||
Buyer string `json:"buyer"`
|
||||
Seller string `json:"seller"`
|
||||
Gateway string `json:"gateway"`
|
||||
BuyerNonce int `json:"buyer_nonce"`
|
||||
AmountToSeller int `json:"amount_to_seller"`
|
||||
}
|
||||
|
||||
type UnstakeValidatorV1 struct {
|
||||
Address string `json:"address"`
|
||||
Owner string `json:"owner"`
|
||||
OwnerSignature string `json:"owner_signature"`
|
||||
Fee int `json:"fee"`
|
||||
StakeAmount int `json:"stake_amount"`
|
||||
StakeReleaseHeight int `json:"stake_release_height"`
|
||||
Hash string `json:"hash"`
|
||||
}
|
||||
|
|
|
@ -13,12 +13,6 @@ type Account struct {
|
|||
} `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"`
|
||||
|
|
Reference in New Issue