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 Cardano chain #43

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ we simply calculate:
nakamoto-coefficient: no of validators controlling 33% of the total network stake
```

Note that the threshold may be different for some blockchains, for example, 50%.
So, I would suggest users to understand the context, cross-verify and examine the results. For any feedback, please join this [discord](https://discord.gg/Una8qmFg).

### Programming Languages
Expand Down Expand Up @@ -61,6 +62,7 @@ NOTE: You can get your API Key by signing up [here](https://www.validators.app/u
20. [MultiversX](https://multiversx.com/)
21. [Polkadot](https://polkadot.network/)
22. [Aptos](https://aptosfoundation.org/)
23. [Cardano](https://cardano.org/)

### Notes

Expand Down
75 changes: 75 additions & 0 deletions core/chains/cardano.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package chains

import (
"encoding/json"
"fmt"
"log"
"math/big"
"net/http"
"sort"

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

type CardanoResponse struct {
Label string `json:"label"`
Class string `json:"class"`
Epoch int `json:"epoch"`
Stake float64 `json:"stake"`
}

func Cardano() (int, error) {
url := "https://www.balanceanalytics.io/api/mavdata.json"

req, err := http.NewRequest("GET", url, nil)
if err != nil {
log.Println("Error creating request:", err)
return 0, err
}

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Println("Error making request:", err)
return 0, err
}
defer resp.Body.Close()

var responseData []struct {
CardanoResponse []CardanoResponse `json:"mav_data"`
}
err = json.NewDecoder(resp.Body).Decode(&responseData)
if err != nil {
log.Println("Error decoding JSON:", err)
return 0, err
}

var votingPowers []big.Int
for _, data := range responseData {
for _, mavData := range data.CardanoResponse {
stakeInt := big.NewInt(int64(mavData.Stake))
votingPowers = append(votingPowers, *stakeInt)
}
}

// need to sort the powers in descending order since they are in random order
sort.Slice(votingPowers, func(i, j int) bool {
res := (&votingPowers[i]).Cmp(&votingPowers[j])
if res == 1 {
return true
}
return false
})

// Calculate total voting power
totalVotingPower := utils.CalculateTotalVotingPowerBigNums(votingPowers)

// Calculate Nakamoto coefficient
nakamotoCoefficient := utils.CalcNakamotoCoefficientBigNums51(totalVotingPower, votingPowers)

fmt.Println("Total voting power:", totalVotingPower)
fmt.Println("The Nakamoto coefficient for Cardano is", nakamotoCoefficient)

// Return Nakamoto coefficient
return nakamotoCoefficient, nil
}
7 changes: 6 additions & 1 deletion core/chains/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type ChainState map[Token]Chain

// Append new chains in alphabetical order only.
const (
ADA Token = "ADA"
ALGO Token = "ALGO"
APT Token = "APT"
ATOM Token = "ATOM"
Expand Down Expand Up @@ -48,6 +49,8 @@ const (
// ChainName returns the name of the chain given the token name.
func (t Token) ChainName() string {
switch t {
case ADA:
return "Cardano"
case ALGO:
return "Algo"
case APT:
Expand Down Expand Up @@ -97,7 +100,7 @@ func (t Token) ChainName() string {
}
}

var Tokens = []Token{ALGO, APT, ATOM, AVAX, BLD, BNB, DOT, EGLD, GRT, HBAR, JUNO, MATIC, MINA, NEAR, OSMO, PLS, REGEN, RUNE, SOL, STARS, SUI, TIA}
var Tokens = []Token{ADA, ALGO, APT, ATOM, AVAX, BLD, BNB, DOT, EGLD, 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 @@ -131,6 +134,8 @@ func newValues(token Token) (int, error) {
)

switch token {
case ADA:
currVal, err = Cardano()
case ALGO:
currVal, err = Algorand()
case APT:
Expand Down
18 changes: 18 additions & 0 deletions core/utils/calc_nakamoto_coefficient_big_nums.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,21 @@ func CalcNakamotoCoefficientBigNums(totalVotingPower *big.Int, votingPowers []bi

return nakamotoCoefficient
}

func CalcNakamotoCoefficientBigNums51(totalVotingPower *big.Int, votingPowers []big.Int) int {
thresholdPercent := big.NewFloat(0.50)
thresholdVal := new(big.Float).Mul(new(big.Float).SetInt(totalVotingPower), thresholdPercent)
cumulativeVal := big.NewFloat(0.00)
nakamotoCoefficient := 0

for _, vp := range votingPowers {
z := new(big.Float).Add(cumulativeVal, new(big.Float).SetInt(&vp))
cumulativeVal = z
nakamotoCoefficient += 1
if cumulativeVal.Cmp(thresholdVal) == +1 {
break
}
}

return nakamotoCoefficient
}