Repository: trustwallet/blockatlas
Pull request #1430 (2021-03-04 10:27:01)

[Binance] Add bnb staking apr
* Add bnb staking apr 
* code cleanup

codecov[bot]: # [Codecov](https://codecov.io/gh/trustwallet/blockatlas/pull/1430?src=pr&el=h1) Report
> Merging [#1430](https://codecov.io/gh/trustwallet/blockatlas/pull/1430?src=pr&el=desc) (73d0476) into [master](https://codecov.io/gh/trustwallet/blockatlas/commit/03eb45473c870263a9cd63b232e0a9de12253449?el=desc) (03eb454) will **decrease** coverage by `0%`.
> The diff coverage is `5%`.

[![Impacted file tree graph](https://codecov.io/gh/trustwallet/blockatlas/pull/1430/graphs/tree.svg?width=650&height=150&src=pr&token=jnrjoEQAqv)](https://codecov.io/gh/trustwallet/blockatlas/pull/1430?src=pr&el=tree)

```diff
@@          Coverage Diff           @@
##           master   #1430   +/-   ##
======================================
- Coverage      43%     43%   -1%     
======================================
  Files         146     147    +1     
  Lines        4107    4138   +31     
======================================
+ Hits         1783    1784    +1     
- Misses       2154    2184   +30     
  Partials      170     170           
```


| [Impacted Files](https://codecov.io/gh/trustwallet/blockatlas/pull/1430?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/blockatlas/staking.go](https://codecov.io/gh/trustwallet/blockatlas/pull/1430/diff?src=pr&el=tree#diff-cGtnL2Jsb2NrYXRsYXMvc3Rha2luZy5nbw==) | `37% <0%> (-63%)` | :arrow_down: |
| [platform/binance/stake.go](https://codecov.io/gh/trustwallet/blockatlas/pull/1430/diff?src=pr&el=tree#diff-cGxhdGZvcm0vYmluYW5jZS9zdGFrZS5nbw==) | `0% <0%> (ø)` | |
| [platform/cosmos/stake.go](https://codecov.io/gh/trustwallet/blockatlas/pull/1430/diff?src=pr&el=tree#diff-cGxhdGZvcm0vY29zbW9zL3N0YWtlLmdv) | `27% <0%> (+<1%)` | :arrow_up: |
| [platform/binance/base.go](https://codecov.io/gh/trustwallet/blockatlas/pull/1430/diff?src=pr&el=tree#diff-cGxhdGZvcm0vYmluYW5jZS9iYXNlLmdv) | `80% <100%> (+5%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/trustwallet/blockatlas/pull/1430?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/trustwallet/blockatlas/pull/1430?src=pr&el=footer). Last update [03eb454...2845ab6](https://codecov.io/gh/trustwallet/blockatlas/pull/1430?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/config.yml b/config.yml
index 7e19127..fe8ff2c 100644
--- a/config.yml
+++ b/config.yml
@@ -33,7 +33,8 @@ consumer:
 # [BNB] Binance DEX: https://www.binance.org/
 binance:
   api: https://dex.binance.org
-  # key: ""
+  key: ""
+  staking_api: "https://api.binance.org"
 
 # [NIM] Nimiq: https://nimiq.com
 nimiq:
diff --git a/config/configuration.go b/config/configuration.go
index 6f109dc..f939973 100755
--- a/config/configuration.go
+++ b/config/configuration.go
@@ -36,8 +36,9 @@ type Configuration struct {
 		CollectionsKey string `mapstructure:"collections_api_key"`
 	} `mapstructure:"ethereum"`
 	Binance struct {
-		API string `mapstructure:"api"`
-		Key string `mapstructure:"key"`
+		API        string `mapstructure:"api"`
+		Key        string `mapstructure:"key"`
+		StakingAPI string `mapstructure:"staking_api"`
 	} `mapstructure:"binance"`
 	Ripple struct {
 		API string `mapstructure:"api"`
diff --git a/go.sum b/go.sum
index cf899d3..88c5d53 100644
--- a/go.sum
+++ b/go.sum
@@ -194,8 +194,7 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
 github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
-github.com/itchyny/timefmt-go v0.1.1 h1:rLpnm9xxb39PEEVzO0n4IRp0q6/RmBc7Dy/rE4HrA0U=
-github.com/itchyny/timefmt-go v0.1.1/go.mod h1:0osSSCQSASBJMsIZnhAaF1C2fCBTJZXrnj37mG8/c+A=
+github.com/itchyny/timefmt-go v0.1.2 h1:q0Xa4P5it6K6D7ISsbLAMwx1PnWlixDcJL6/sFs93Hs=
 github.com/itchyny/timefmt-go v0.1.2/go.mod h1:0osSSCQSASBJMsIZnhAaF1C2fCBTJZXrnj37mG8/c+A=
 github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
 github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
diff --git a/pkg/blockatlas/staking.go b/pkg/blockatlas/staking.go
index f8260ab..452eb15 100644
--- a/pkg/blockatlas/staking.go
+++ b/pkg/blockatlas/staking.go
@@ -12,7 +12,7 @@ const (
 	DelegationTypeAuto     DelegationType = "auto"
 	DelegationTypeDelegate DelegationType = "delegate"
 
-	DefaultAnnualReward = 0
+	DefaultAnnualReward = 0.0
 )
 
 type (
@@ -82,10 +82,20 @@ type (
 	}
 )
 
-func (sv StakeValidators) ToMap() ValidatorMap {
+func (s StakeValidators) ToMap() ValidatorMap {
 	validators := make(ValidatorMap)
-	for _, v := range sv {
+	for _, v := range s {
 		validators[v.ID] = v
 	}
 	return validators
 }
+
+func FindHightestAPR(validators []Validator) float64 {
+	var apr = 0.0
+	for _, v := range validators {
+		if apr < v.Details.Reward.Annual {
+			apr = v.Details.Reward.Annual
+		}
+	}
+	return apr
+}
diff --git a/platform/binance/base.go b/platform/binance/base.go
index f49c59b..c6042f6 100644
--- a/platform/binance/base.go
+++ b/platform/binance/base.go
@@ -1,16 +1,19 @@
 package binance
 
 import (
+	"github.com/trustwallet/blockatlas/platform/binance/staking"
 	"github.com/trustwallet/golibs/coin"
 )
 
 type Platform struct {
-	client Client
+	client        Client
+	stakingClient staking.Client
 }
 
-func Init(api, apiKey string) *Platform {
+func Init(api, apiKey, stakingApi string) *Platform {
 	p := Platform{
-		client: InitClient(api, apiKey),
+		client:        InitClient(api, apiKey),
+		stakingClient: staking.InitClient(stakingApi),
 	}
 	return &p
 }
diff --git a/platform/binance/stake.go b/platform/binance/stake.go
new file mode 100644
index 0000000..5a3b8a4
--- /dev/null
+++ b/platform/binance/stake.go
@@ -0,0 +1,62 @@
+package binance
+
+import (
+	"github.com/trustwallet/blockatlas/pkg/blockatlas"
+	"github.com/trustwallet/blockatlas/platform/binance/staking"
+)
+
+const (
+	lockTime      = 604800      // 7 days
+	minimumAmount = "100000000" // 1 BNB
+)
+
+func (p *Platform) GetActiveValidators() (blockatlas.StakeValidators, error) {
+	return blockatlas.StakeValidators{}, nil
+}
+
+func (p *Platform) GetValidators() (blockatlas.ValidatorPage, error) {
+	validators, err := p.stakingClient.GetValidators()
+	if err != nil {
+		return nil, err
+	}
+	result := make(blockatlas.ValidatorPage, 0)
+	for _, validator := range validators.Validators {
+		result = append(result, normalizeValidator(validator))
+	}
+	return result, nil
+}
+
+func (p *Platform) GetDetails() blockatlas.StakingDetails {
+	apr := blockatlas.DefaultAnnualReward
+	validators, err := p.GetValidators()
+	if err == nil {
+		apr = blockatlas.FindHightestAPR(validators)
+	}
+	return blockatlas.StakingDetails{
+		Reward:        blockatlas.StakingReward{Annual: apr},
+		MinimumAmount: minimumAmount,
+		LockTime:      lockTime,
+		Type:          blockatlas.DelegationTypeDelegate,
+	}
+}
+
+func (p *Platform) UndelegatedBalance(address string) (string, error) {
+	return "0", nil
+}
+
+func (p *Platform) GetDelegations(address string) (blockatlas.DelegationsPage, error) {
+	return blockatlas.DelegationsPage{}, nil
+}
+
+func normalizeValidator(v staking.Validator) blockatlas.Validator {
+	return blockatlas.Validator{
+		Status: v.Status == 0,
+		ID:     v.Validator,
+		Details: blockatlas.StakingDetails{
+			Reward:        blockatlas.StakingReward{Annual: v.APR},
+			MinimumAmount: minimumAmount,
+			LockTime:      lockTime,
+			Type:          blockatlas.DelegationTypeDelegate,
+		},
+	}
+}
diff --git a/platform/binance/staking/client.go b/platform/binance/staking/client.go
new file mode 100644
index 0000000..9ec27ea
--- /dev/null
+++ b/platform/binance/staking/client.go
@@ -0,0 +1,26 @@
+package staking
+
+import (
+	"net/url"
+
+	"github.com/trustwallet/golibs/client"
+	"github.com/trustwallet/golibs/network/middleware"
+)
+
+type Client struct {
+	client.Request
+}
+
+func InitClient(url string) Client {
+	c := Client{client.InitClient(url, middleware.SentryErrorHandler)}
+	return c
+}
+
+func (c *Client) GetValidators() (validators Validators, err error) {
+	params := url.Values{
+		"limit":  {"100"},
+		"offset": {"0"},
+	}
+	err = c.Get(&validators, "/v1/staking/chains/bsc/validators", params)
+	return
+}
diff --git a/platform/binance/staking/model.go b/platform/binance/staking/model.go
new file mode 100644
index 0000000..9df34a9
--- /dev/null
+++ b/platform/binance/staking/model.go
@@ -0,0 +1,12 @@
+package staking
+
+type Validators struct {
+	Total      int         `json:"total"`
+	Validators []Validator `json:"validators"`
+}
+
+type Validator struct {
+	Validator string  `json:"validator"`
+	Status    int     `json:"status"`
+	APR       float64 `json:"apr"`
+}
diff --git a/platform/cosmos/stake.go b/platform/cosmos/stake.go
index 7f15ca2..9b3cf49 100644
--- a/platform/cosmos/stake.go
+++ b/platform/cosmos/stake.go
@@ -55,33 +55,19 @@ func (p *Platform) GetValidators() (blockatlas.ValidatorPage, error) {
 }
 
 func (p *Platform) GetDetails() blockatlas.StakingDetails {
+	apr := blockatlas.DefaultAnnualReward
+	validators, err := p.GetValidators()
+	if err == nil {
+		apr = blockatlas.FindHightestAPR(validators)
+	}
 	return blockatlas.StakingDetails{
-		Reward: blockatlas.StakingReward{
-			Annual: p.GetMaxAPR(),
-		},
+		Reward:        blockatlas.StakingReward{Annual: apr},
 		MinimumAmount: minimumAmount,
 		LockTime:      lockTime,
 		Type:          blockatlas.DelegationTypeDelegate,
 	}
 }
 
-func (p *Platform) GetMaxAPR() float64 {
-	validators, err := p.GetValidators()
-	if err != nil {
-		return blockatlas.DefaultAnnualReward
-	}
-
-	var max = 0.0
-	for _, e := range validators {
-		v := e.Details.Reward.Annual
-		if v > max {
-			max = v
-		}
-	}
-
-	return max
-}
-
 func (p *Platform) GetDelegations(address string) (blockatlas.DelegationsPage, error) {
 	results := make(blockatlas.DelegationsPage, 0)
 	delegations, err := p.client.GetDelegations(address)
diff --git a/platform/harmony/client.go b/platform/harmony/client.go
index e54adfd..4a07495 100644
--- a/platform/harmony/client.go
+++ b/platform/harmony/client.go
@@ -4,7 +4,6 @@ import (
 	"fmt"
 	"strconv"
 
-	log "github.com/sirupsen/logrus"
 	"github.com/trustwallet/golibs/client"
 	"github.com/trustwallet/golibs/numbers"
 )
@@ -43,25 +42,6 @@ func (c *Client) GetBlockByNumber(num int64) (info BlockInfo, err error) {
 	return
 }
 
-func (c *Client) GetValidators() (validators Validators, err error) {
-	err = rpcCallStub(c, &validators.Validators, "hmy_getAllValidatorInformation", []interface{}{-1})
-
-	if err != nil {
-		log.Error(err, "Harmony: Failed to get all validator addresses")
-	}
-
-	return
-}
-
-func (c *Client) GetDelegations(address string) (delegations Delegations, err error) {
-	err = rpcCallStub(c, &delegations.List, "hmy_getDelegationsByDelegator", []interface{}{address})
-
-	if err != nil {
-		log.Error(err, "Harmony: Failed to get delegations for address")
-	}
-	return
-}
-
 func (c *Client) GetBalance(address string) (string, error) {
 	var result string
 	err := rpcCallStub(c, &result, "hmy_getBalance", []interface{}{address, "latest"})
diff --git a/platform/harmony/model.go b/platform/harmony/model.go
index a9db97b..a4134e2 100644
--- a/platform/harmony/model.go
+++ b/platform/harmony/model.go
@@ -26,31 +26,3 @@ type BlockInfo struct {
 	Number       string        `json:"number"`
 	Transactions []Transaction `json:"transactions"`
 }
-
-type ValidatorInfo struct {
-	Address string `json:"address"`
-}
-
-type LifetimeInfo struct {
-	Apr string `json:"apr"`
-}
-
-type Validator struct {
-	Info     ValidatorInfo `json:"validator"`
-	Active   bool          `json:"currently-in-committee"`
-	Lifetime LifetimeInfo  `json:"lifetime"`
-}
-
-type Validators struct {
-	Validators []Validator `json:"result"`
-}
-
-type Delegation struct {
-	DelegatorAddress string  `json:"delegator_address"`
-	ValidatorAddress string  `json:"validator_address"`
-	Amount           float64 `json:"amount"`
-}
-
-type Delegations struct {
-	List []Delegation `json:"result"`
-}
diff --git a/platform/harmony/stake.go b/platform/harmony/stake.go
deleted file mode 100644
index f694b34..0000000
--- a/platform/harmony/stake.go
+++ /dev/null
@@ -1,137 +0,0 @@
-package harmony
-
-import (
-	"math/big"
-	"strconv"
-
-	log "github.com/sirupsen/logrus"
-	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	"github.com/trustwallet/blockatlas/services/assets"
-	"github.com/trustwallet/golibs/types"
-)
-
-const (
-	lockTime = 604800 // in seconds (7 epochs or 7 days)
-)
-
-func (p *Platform) GetActiveValidators() (blockatlas.StakeValidators, error) {
-	validators, err := assets.GetValidatorsMap(p)
-	if err != nil {
-		return nil, err
-	}
-	result := make(blockatlas.StakeValidators, 0, len(validators))
-	for _, v := range validators {
-		result = append(result, v)
-	}
-	return result, nil
-}
-
-func (p *Platform) GetValidators() (blockatlas.ValidatorPage, error) {
-	results := make(blockatlas.ValidatorPage, 0)
-	validators, err := p.client.GetValidators()
-	if err != nil {
-		return results, err
-	}
-
-	for _, v := range validators.Validators {
-		var apr float64
-		if apr, err = strconv.ParseFloat(v.Lifetime.Apr, 64); err != nil {
-			apr = 0
-		}
-		results = append(results, normalizeValidator(v, apr))
-	}
-
-	return results, nil
-}
-
-func (p *Platform) GetDetails() blockatlas.StakingDetails {
-	apr := p.GetMaxAPR()
-	return getDetails(apr)
-}
-
-func (p *Platform) GetMaxAPR() float64 {
-	validators, err := p.client.GetValidators()
-	if err != nil {
-		return Annual
-	}
-
-	var max = 0.0
-	for _, e := range validators.Validators {
-		var apr float64
-		if apr, err = strconv.ParseFloat(e.Lifetime.Apr, 64); err != nil {
-			apr = 0.0
-		}
-
-		if apr > max {
-			max = apr
-		}
-	}
-
-	return max
-}
-
-func (p *Platform) GetDelegations(address string) (blockatlas.DelegationsPage, error) {
-	delegations, err := p.client.GetDelegations(address)
-	if err != nil {
-		return nil, err
-	}
-
-	validators, err := assets.GetValidatorsMap(p)
-	if err != nil {
-		return nil, err
-	}
-
-	return NormalizeDelegations(delegations.List, validators), nil
-}
-
-func (p *Platform) UndelegatedBalance(address string) (string, error) {
-	balance, err := p.client.GetBalance(address)
-	if err != nil {
-		return "0", err
-	}
-	return balance, nil
-}
-
-func NormalizeDelegations(delegations []Delegation, validators blockatlas.ValidatorMap) []blockatlas.Delegation {
-	results := make([]blockatlas.Delegation, 0)
-	for _, v := range delegations {
-		validator, ok := validators[v.ValidatorAddress]
-		if !ok {
-			log.WithFields(
-				log.Fields{"address": v.ValidatorAddress, "platform": "harmony", "delegation": v.DelegatorAddress},
-			).Error("Validator not found")
-			continue
-		}
-
-		bigval := new(big.Float)
-		bigval.SetFloat64(v.Amount)
-
-		result := new(big.Int)
-		bigval.Int(result) // store converted number in result
-
-		delegation := blockatlas.Delegation{
-			Delegator: validator,
-			Value:     result.String(), // v.Amount.String(),
-			Status:    blockatlas.DelegationStatusActive,
-		}
-		results = append(results, delegation)
-	}
-	return results
-}
-
-func getDetails(apr float64) blockatlas.StakingDetails {
-	return blockatlas.StakingDetails{
-		Reward:        blockatlas.StakingReward{Annual: apr},
-		MinimumAmount: types.Amount("1000"),
-		LockTime:      lockTime,
-		Type:          blockatlas.DelegationTypeDelegate,
-	}
-}
-
-func normalizeValidator(v Validator, apr float64) (validator blockatlas.Validator) {
-	return blockatlas.Validator{
-		Status:  v.Active,
-		ID:      v.Info.Address,
-		Details: getDetails(apr),
-	}
-}
diff --git a/platform/kava/stake.go b/platform/kava/stake.go
index 56e8cbc..fdce7f1 100644
--- a/platform/kava/stake.go
+++ b/platform/kava/stake.go
@@ -57,33 +57,19 @@ func (p *Platform) GetValidators() (blockatlas.ValidatorPage, error) {
 }
 
 func (p *Platform) GetDetails() blockatlas.StakingDetails {
+	apr := blockatlas.DefaultAnnualReward
+	validators, err := p.GetValidators()
+	if err == nil {
+		apr = blockatlas.FindHightestAPR(validators)
+	}
 	return blockatlas.StakingDetails{
-		Reward: blockatlas.StakingReward{
-			Annual: p.GetMaxAPR(),
-		},
+		Reward:        blockatlas.StakingReward{Annual: apr},
 		MinimumAmount: minimumAmount,
 		LockTime:      lockTime,
 		Type:          blockatlas.DelegationTypeDelegate,
 	}
 }
 
-func (p *Platform) GetMaxAPR() float64 {
-	validators, err := p.GetValidators()
-	if err != nil {
-		return blockatlas.DefaultAnnualReward
-	}
-
-	var max = 0.0
-	for _, e := range validators {
-		v := e.Details.Reward.Annual
-		if v > max {
-			max = v
-		}
-	}
-
-	return max
-}
-
 func (p *Platform) GetDelegations(address string) (blockatlas.DelegationsPage, error) {
 	results := make(blockatlas.DelegationsPage, 0)
 	delegations, err := p.client.GetDelegations(address)
diff --git a/platform/platform.go b/platform/platform.go
index 1a7f171..0602101 100644
--- a/platform/platform.go
+++ b/platform/platform.go
@@ -65,7 +65,7 @@ func getAllHandlers() blockatlas.Platforms {
 		coin.Aeternity().Handle:    aeternity.Init(config.Default.Aeternity.API),
 		coin.Solana().Handle:       solana.Init(config.Default.Solana.API),
 		coin.Tezos().Handle:        tezos.Init(config.Default.Tezos.API, config.Default.Tezos.RPC, config.Default.Tezos.Baker),
-		coin.Binance().Handle:      binance.Init(config.Default.Binance.API, config.Default.Binance.Key),
+		coin.Binance().Handle:      binance.Init(config.Default.Binance.API, config.Default.Binance.Key, config.Default.Binance.StakingAPI),
 		coin.Zilliqa().Handle:      zilliqa.Init(config.Default.Zilliqa.API, config.Default.Zilliqa.Key, config.Default.Zilliqa.RPC),
 		coin.Polkadot().Handle:     polkadot.Init(coin.POLKADOT, config.Default.Polkadot.API),
 		coin.Stellar().Handle:      stellar.Init(coin.STELLAR, config.Default.Stellar.API),


Test patch:
diff --git a/platform/binance/block_test.go b/platform/binance/block_test.go
index 4e1447d..c6f40dd 100644
--- a/platform/binance/block_test.go
+++ b/platform/binance/block_test.go
@@ -11,7 +11,7 @@ import (
 func TestPlatform_CurrentBlockNumber(t *testing.T) {
 	server := httptest.NewServer(createMockedAPI())
 	defer server.Close()
-	p := Init(server.URL, "")
+	p := Init(server.URL, "<key>", "<staing_api>")
 	number, err := p.CurrentBlockNumber()
 	assert.Nil(t, err)
 	assert.Equal(t, int64(104867535), number)
@@ -20,7 +20,7 @@ func TestPlatform_CurrentBlockNumber(t *testing.T) {
 func TestPlatform_GetBlockByNumber(t *testing.T) {
 	server := httptest.NewServer(createMockedAPI())
 	defer server.Close()
-	p := Init(server.URL, "")
+	p := Init(server.URL, "<key>", "<staing_api>")
 	block, err := p.GetBlockByNumber(104867508)
 	assert.Nil(t, err)
 	res, err := json.Marshal(block)
diff --git a/platform/binance/token_test.go b/platform/binance/token_test.go
index 98d0ce4..005997b 100644
--- a/platform/binance/token_test.go
+++ b/platform/binance/token_test.go
@@ -11,7 +11,7 @@ import (
 func TestPlatform_GetTokenListByAddress(t *testing.T) {
 	server := httptest.NewServer(createMockedAPI())
 	defer server.Close()
-	p := Init(server.URL, "")
+	p := Init(server.URL, "<key>", "<staing_api>")
 
 	tokens, err := p.GetTokenListByAddress("bnb1w7puzjxu05ktc5zvpnzkndt6tyl720nsutzvpg")
 	assert.Nil(t, err)
diff --git a/platform/binance/transaction_test.go b/platform/binance/transaction_test.go
index 4f78700..ffd81a4 100644
--- a/platform/binance/transaction_test.go
+++ b/platform/binance/transaction_test.go
@@ -11,7 +11,7 @@ import (
 func TestPlatform_GetTxsByAddress(t *testing.T) {
 	server := httptest.NewServer(createMockedAPI())
 	defer server.Close()
-	p := Init(server.URL, "")
+	p := Init(server.URL, "<key>", "<staing_api>")
 	txs, err := p.GetTxsByAddress("bnb136ns6lfw4zs5hg4n85vdthaad7hq5m4gtkgf23")
 	assert.Nil(t, err)
 	res, err := json.Marshal(txs)
@@ -22,7 +22,7 @@ func TestPlatform_GetTxsByAddress(t *testing.T) {
 func TestPlatform_GetTokenTxsByAddress(t *testing.T) {
 	server := httptest.NewServer(createMockedAPI())
 	defer server.Close()
-	p := Init(server.URL, "")
+	p := Init(server.URL, "<key>", "<staing_api>")
 	txs, err := p.GetTokenTxsByAddress("bnb1w7puzjxu05ktc5zvpnzkndt6tyl720nsutzvpg", "AVA-645")
 	assert.Nil(t, err)
 	res, err := json.Marshal(txs)
diff --git a/platform/harmony/stake_test.go b/platform/harmony/stake_test.go
deleted file mode 100644
index 2fad411..0000000
--- a/platform/harmony/stake_test.go
+++ /dev/null
@@ -1,182 +0,0 @@
-package harmony
-
-import (
-	"encoding/json"
-	"strconv"
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-	"github.com/trustwallet/blockatlas/pkg/blockatlas"
-	"github.com/trustwallet/golibs/mock"
-)
-
-var (
-	validatorSrc, _   = mock.JsonStringFromFilePath("mocks/" + "validator.json")
-	delegationsSrc, _ = mock.JsonStringFromFilePath("mocks/" + "delegation.json")
-	validatorMap      = blockatlas.ValidatorMap{
-		"one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy": validator1,
-	}
-	validator1 = blockatlas.StakeValidator{
-		ID:     "one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy",
-		Status: true,
-		Info: blockatlas.StakeValidatorInfo{
-			Name:        "Harmony One",
-			Description: "Stake and earn rewards with the most secure and stable validator. Operated by Harmony One Inc.",
-			Image:       "https://assets.trustwalletapp.com/blockchains/harmony/validators/assets/one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy/logo.png",
-			Website:     "https://harmony.one",
-		},
-		Details: blockatlas.StakingDetails{
-			Reward: blockatlas.StakingReward{
-				Annual: 10,
-			},
-			LockTime:      0,
-			MinimumAmount: "0",
-		},
-	}
-)
-
-func TestNormalizeValidator(t *testing.T) {
-	var v Validator
-	_ = json.Unmarshal([]byte(validatorSrc), &v)
-	expected := blockatlas.Validator{
-		Status: v.Active,
-		ID:     v.Info.Address,
-		Details: blockatlas.StakingDetails{
-			Reward:        blockatlas.StakingReward{Annual: 12.345},
-			LockTime:      lockTime,
-			MinimumAmount: "1000",
-			Type:          blockatlas.DelegationTypeDelegate,
-		},
-	}
-
-	var apr float64
-	var err error
-	if apr, err = strconv.ParseFloat(v.Lifetime.Apr, 64); err != nil {
-		apr = 0
-	}
-
-	result := normalizeValidator(v, apr)
-	assert.Equal(t, expected, result)
-}
-
-func TestNormalizeDelegations(t *testing.T) {
-	var delegations []Delegation
-	err := json.Unmarshal([]byte(delegationsSrc), &delegations)
-	assert.NoError(t, err)
-	assert.NotNil(t, delegations)
-
-	expected := []blockatlas.Delegation{
-		{
-			Delegator: validator1,
-			Value:     "12345678900000000000",
-			Status:    blockatlas.DelegationStatusActive,
-		},
-	}
-	result := NormalizeDelegations(delegations, validatorMap)
-	assert.Equal(t, expected, result)
-}
-
-func TestHexToInt(t *testing.T) {
-	result, _ := hexToInt("0x604800")
-
-	assert.Equal(t, uint64(6309888), result)
-}
-
-func TestGetDetails(t *testing.T) {
-	var expected = blockatlas.StakingDetails{
-		Reward:        blockatlas.StakingReward{Annual: 10},
-		LockTime:      lockTime,
-		MinimumAmount: "1000",
-		Type:          blockatlas.DelegationTypeDelegate,
-	}
-
-	result := getDetails(10)
-	assert.Equal(t, expected, result)
-}
-
-func TestGetValidators(t *testing.T) {
-	var c Client
-
-	p := Platform{
-		client: c,
-	}
-
-	var validators = []Validator{
-		{
-			Info: ValidatorInfo{
-				Address: "one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy",
-			},
-			Active:   true,
-			Lifetime: LifetimeInfo{Apr: "10"},
-		},
-	}
-
-	rpcCallStub = func(c *Client, result interface{}, method string, params interface{}) error {
-		jsonData, _ := json.Marshal(validators)
-		_ = json.Unmarshal(jsonData, result)
-		return nil
-	}
-
-	result, _ := p.GetValidators()
-	assert.Equal(t, lockTime, result[0].Details.LockTime)
-	assert.Equal(t, float64(10), result[0].Details.Reward.Annual)
-}
-
-func TestGetDelegation(t *testing.T) {
-	var c Client
-
-	p := Platform{
-		client: c,
-	}
-
-	var delegations = []Delegation{
-		{
-			DelegatorAddress: "one1a0au0p33zrns49h3qw7prn02s4wphu0ggcqrhm",
-			ValidatorAddress: "one1a0au0p33zrns49h3qw7prn02s4wphu0ggcqrhm",
-			Amount:           100,
-		},
-	}
-
-	var validators = []Validator{
-		{
-			Info: ValidatorInfo{
-				Address: "one1a0au0p33zrns49h3qw7prn02s4wphu0ggcqrhm",
-			},
-			Active:   true,
-			Lifetime: LifetimeInfo{Apr: "10"},
-		},
-	}
-
-	rpcCallStub = func(c *Client, result interface{}, method string, params interface{}) error {
-		if method == "hmy_getAllValidatorInformation" {
-			jsonData, _ := json.Marshal(validators)
-			_ = json.Unmarshal(jsonData, result)
-		} else {
-			jsonData, _ := json.Marshal(delegations)
-			_ = json.Unmarshal(jsonData, result)
-		}
-		return nil
-	}
-
-	result, _ := p.GetDelegations("one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy")
-	assert.Equal(t, delegations[0].DelegatorAddress, result[0].Delegator.ID)
-}
-
-func TestGeBalance(t *testing.T) {
-	var c Client
-
-	p := Platform{
-		client: c,
-	}
-
-	var balance = "0x100"
-
-	rpcCallStub = func(c *Client, result interface{}, method string, params interface{}) error {
-		jsonData, _ := json.Marshal(balance)
-		_ = json.Unmarshal(jsonData, result)
-		return nil
-	}
-
-	result, _ := p.UndelegatedBalance("one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy")
-	assert.Equal(t, "256", result)
-}