Skip to content

Commit

Permalink
add support for juno & fix mina
Browse files Browse the repository at this point in the history
  • Loading branch information
xenowits committed Mar 5, 2022
1 parent baa688c commit 2011109
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 12 deletions.
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ Golang
2. Also, install [postgresql](https://www.postgresql.org/download/) and make sure it is running in the background
3. After postgres is installed, copy the commands in `db/postgres_script.sql` into the terminal
4. Add following to your `~/.bashrc` or `~/.zshrc`:
1. `export SOLANA_API_KEY=api_key`
2. `export DATABASE_URL=postgres://username:password@localhost:5432/postgres`
4. In a separate terminal, run `go run core/main.go`. This will start the core logic of calculating the nakamoto coefficients.
5. If you want to start the server, run `go run server/main.go` in another terminal.
1. `export SOLANA_API_KEY=api_key`
2. `export DATABASE_URL=postgres://username:password@localhost:5432/postgres`
5. In a separate terminal, run `go run core/main.go`. This will start the core logic of calculating the nakamoto coefficients.
6. If you want to start the server, run `go run server/main.go` in another terminal.

### Chains currently supported

Expand All @@ -33,11 +33,13 @@ Golang
8. [Terra](https://www.terra.money/)
9. [Graph Protocol](https://thegraph.com/)
10. [Thorchain](https://www.thorchain.com/)
11. [Near](https://near.org/)
12. [Juno](https://www.junonetwork.io/)

### Notes

1. The actual logic is present inside `/core`. So, ideally a cron job would be run after every `JOB_INTERVAL` which would save/refresh the nakamoto-coefficients `database`.
3. The server code resides inside `/server`. It is a simple server which would only respond to `GET /nakamoto-coefficients`. It basically queries the database and returns the values.
2. The server code resides inside `/server`. It is a simple server which would only respond to `GET /nakamoto-coefficients`. It basically queries the database and returns the values.

### Future Work

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

import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"strings"

"math/big"
"net/http"
"sort"

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

type JunoResponse struct {
Data struct {
Validators []struct {
ValidatorVotingPowers []struct {
VotingPower uint64 `json:"votingPower"`
} `json:"validatorVotingPowers"`
} `json:"validator"`
} `json:"data"`
}

type JunoErrorResponse struct {
Id int `json:"id"`
Jsonrpc string `json:"jsonrpc"`
Error string `json:"error"`
}

func Juno() (int, error) {
votingPowers := make([]big.Int, 0, 1000)

url := fmt.Sprintf("https://hasura.junoscan.com/v1/graphql")
jsonReqData := "{\"query\":\"query { validator { validatorVotingPowers: validator_voting_powers(order_by: { voting_power: desc }) { votingPower: voting_power } }}\",\"variables\":{}}"

// Create a new request using http
req, err := http.NewRequest("POST", url, strings.NewReader(jsonReqData))
if err != nil {
return -1, err
}
req.Header.Add("Content-Type", "application/json")

// Send req using http Client
client := &http.Client{}
resp, err := client.Do(req)

if err != nil {
errBody, _ := ioutil.ReadAll(resp.Body)
var errResp JunoErrorResponse
json.Unmarshal(errBody, &errResp)
log.Println(errResp.Error)
return -1, err
}
defer resp.Body.Close()

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

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

// loop through the validators voting powers
for _, ele := range response.Data.Validators {
if len(ele.ValidatorVotingPowers) > 0 {
n := new(big.Int).SetUint64(ele.ValidatorVotingPowers[0].VotingPower)
votingPowers = append(votingPowers, *n)
}
}

// 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
})

totalVotingPower := utils.CalculateTotalVotingPowerBigNums(votingPowers)
fmt.Println("Total voting power:", totalVotingPower)

// now we're ready to calculate the nakomoto coefficient
nakamotoCoefficient := utils.CalcNakamotoCoefficientBigNums(totalVotingPower, votingPowers)
fmt.Println("The Nakamoto coefficient for juno is", nakamotoCoefficient)

return nakamotoCoefficient, nil
}
10 changes: 4 additions & 6 deletions core/chains/mina.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,17 @@ func reverse(numbers []float64) {
}

func Mina() (int, error) {
votingPowers := make([]float64, 0, 200)
votingPowers := make([]float64, 0, 1000)
pageNo, entriesPerPage := 0, 50
url := ""
for true {
// Check the most active url in the network logs here: https://mina.staketab.com/validators/stake
// Sometimes it changes, like once it changed from mina.staketab.com to t-mina.staketab.com
url = fmt.Sprintf("https://t-mina.staketab.com:8181/api/validator/all/?page=%d&size=%d&sortBy=canonical_block&findStr=&orderBy=DESC", pageNo, entriesPerPage)
// Once, it was https://mina.staketab.com:8181/api/validator/all/
url = fmt.Sprintf("https://mina.staketab.com/mainnet/api/api/validators/?page=%d&size=%d&sortBy=canonical_block&findStr=&orderBy=DESC", pageNo, entriesPerPage)
resp, err := http.Get(url)
if err != nil {
errBody, _ := ioutil.ReadAll(resp.Body)
var errResp MinaErrorResponse
json.Unmarshal(errBody, &errResp)
log.Println(errResp.Error)
log.Println(err)
return -1, err
}
defer resp.Body.Close()
Expand Down
4 changes: 3 additions & 1 deletion core/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func main() {
}
}()

networks := []string{"BNB", "ATOM", "OSMO", "MATIC", "MINA", "SOL", "AVAX", "LUNA", "GRT", "RUNE", "NEAR"}
networks := []string{"BNB", "ATOM", "OSMO", "MATIC", "MINA", "SOL", "AVAX", "LUNA", "GRT", "RUNE", "NEAR", "JUNO"}
for _, n := range networks {
UpdateChainInfo(n)
}
Expand Down Expand Up @@ -58,6 +58,8 @@ func UpdateChainInfo(chainToken string) {
currVal, err = chains.Thorchain()
case "NEAR":
currVal, err = chains.Near()
case "JUNO":
currVal, err = chains.Juno()
}

if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions db/postgres_script.sql
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ INSERT INTO naka_coefficients (chain_name, chain_token, naka_co_prev_val, naka_c

INSERT INTO naka_coefficients (chain_name, chain_token, naka_co_prev_val, naka_co_curr_val) VALUES ('Near', 'NEAR', -1, 6);

INSERT INTO naka_coefficients (chain_name, chain_token, naka_co_prev_val, naka_co_curr_val) VALUES ('Juno', 'JUNO', -1, 2);

select * from naka_coefficients;

\q
Expand Down

0 comments on commit 2011109

Please sign in to comment.