Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add MultiversX chain #44

Merged
merged 1 commit into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ NOTE: You can get your API Key by signing up [here](https://www.validators.app/u
18. [Sui](https://sui.io/)
19. [Pulsechain](https://pulsechain.com/)
20. [Celestia](https://celestia.org/)
21. [MultiversX](https://multiversx.com/)

### Notes

Expand Down
7 changes: 6 additions & 1 deletion core/chains/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const (
AVAX Token = "AVAX"
BLD Token = "BLD"
BNB Token = "BNB"
EGLD Token = "EGLD"
ETH2 Token = "ETH2"
GRT Token = "GRT"
HBAR Token = "HBAR"
Expand Down Expand Up @@ -52,6 +53,8 @@ func (t Token) ChainName() string {
return "Agoric"
case BNB:
return "Binance"
case EGLD:
return "MultiversX"
case ETH2:
return "Ethereum Proof-of-Stake"
case GRT:
Expand Down Expand Up @@ -87,7 +90,7 @@ func (t Token) ChainName() string {
}
}

var Tokens = []Token{ATOM, AVAX, BLD, BNB, ETH2, GRT, HBAR, JUNO, MATIC, MINA, NEAR, OSMO, PLS, REGEN, RUNE, SOL, STARS, SUI, TIA}
var Tokens = []Token{ATOM, AVAX, BLD, BNB, EGLD, ETH2, GRT, HBAR, JUNO, MATIC, MINA, NEAR, OSMO, PLS, REGEN, RUNE, SOL, STARS, SUI, TIA}

// NewState returns a new fresh state.
func NewState() ChainState {
Expand Down Expand Up @@ -129,6 +132,8 @@ func newValues(token Token) (int, error) {
currVal, err = Agoric()
case BNB:
currVal, err = Binance()
case EGLD:
currVal, err = MultiversX()
case ETH2:
currVal, err = Eth2()
case GRT:
Expand Down
112 changes: 112 additions & 0 deletions core/chains/multiversx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package chains

import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"sort"

"github.com/xenowits/nakamoto-coefficient-calculator/core/utils"
)

const totalValidatorsUrl = "https://api.multiversx.com/stake"
const identitiesUrl = "https://api.multiversx.com/identities"

type MultiversXTotalValidatorsResponse struct {
TotalValidators int64 `json:"totalValidators"`
}

type MultiversXIdentitiesResponse []struct {
Locked string `json:"locked"`
NumValidators int64 `json:"validators"`
}

func MultiversX() (int, error) {
numValidatorsPerIdentity := make([]int64, 0)

totalNumberOfValidators, err := getTotalValidatorsNumber()
if err != nil {
return 0, err
}

identities, err := getIdentities()
if err != nil {
return 0, err
}

for _, identity := range identities {
if identity.Locked == "0" {
continue
}
numValidatorsPerIdentity = append(numValidatorsPerIdentity, identity.NumValidators)
}

sort.Slice(numValidatorsPerIdentity, func(i, j int) bool {
return numValidatorsPerIdentity[i] > numValidatorsPerIdentity[j]
})

fmt.Println("Total voting power:", totalNumberOfValidators)

// there is a fixed number of validator seats in MultiversX - currently 3200
// the Nakamoto coefficient can be computed by counting the identities (node operators)
// that control more than 33% of the total number of validators
nakamotoCoefficient := utils.CalcNakamotoCoefficient(totalNumberOfValidators, numValidatorsPerIdentity)
fmt.Println("The Nakamoto coefficient for MultiversX is", nakamotoCoefficient)

return nakamotoCoefficient, nil
}

func getTotalValidatorsNumber() (int64, error) {
resp, err := http.Get(totalValidatorsUrl)
if err != nil {
return 0, err
}

defer closeBody(resp)

body, err := io.ReadAll(resp.Body)
if err != nil {
return 0, err
}

var response MultiversXTotalValidatorsResponse
err = json.Unmarshal(body, &response)
if err != nil {
return 0, err
}

return response.TotalValidators, nil
}

func getIdentities() (MultiversXIdentitiesResponse, error) {
resp, err := http.Get(identitiesUrl)
if err != nil {
return nil, err
}

defer closeBody(resp)

body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

var response MultiversXIdentitiesResponse
err = json.Unmarshal(body, &response)
if err != nil {
return nil, err
}

return response, nil
}

func closeBody(resp *http.Response) {
if resp == nil || resp.Body == nil {
return
}
if closeErr := resp.Body.Close(); closeErr != nil {
log.Printf("failed to close response body: %s", closeErr)
}
}