Skip to content

Commit

Permalink
add near protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
xenowits committed Feb 12, 2022
1 parent 6141aaf commit baa688c
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 19 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
web/node_modules/
web/.cache/
web/public/
.idea
1 change: 1 addition & 0 deletions core/chains/avalanche.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type AvalancheErrorResponse struct {
Error string `json:"error"`
}

// Avalanche calculates nakamoto coefficient for the `Avalanche` C-Chain
// In AVAX, stake amounts are already multiplied by 10^9
// So, we need to deal with big numbers here.
// Else, if we divide each value with 10^9, we have to deal with fractional numbers which is worse.
Expand Down
94 changes: 94 additions & 0 deletions core/chains/near.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package chains

import (
"bytes"
"encoding/json"
"fmt"
"github.com/xenowits/nakamoto-coefficient-calculator/core/utils"
"io/ioutil"
"log"
"math/big"
"net/http"
"sort"
)

type NearResponse struct {
Jsonrpc string `json:"jsonrpc"`
Id int `json:"id"`
Result struct {
Validators []struct {
AccountId string `json:"account_id"`
Stake string `json:"stake"`
} `json:"current_validators"`
} `json:"result"`
}

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

url := fmt.Sprintf("https://rpc.mainnet.near.org")
jsonReqData := []byte(`{"jsonrpc": "2.0","method": "validators","params":[null],"id":1}`)

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

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

if resp != nil {
// Need to close body when redirection occurs
// In redirection, response is not empty
defer func() {
if err := resp.Body.Close(); err != nil {
log.Printf("failed to close response body")
}
}()
}

if err != nil {
return -1, err
}

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

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

// loop through the validators voting powers
for _, ele := range response.Result.Validators {
n, ok := new(big.Int).SetString(ele.Stake, 10)
if !ok {
return -1, fmt.Errorf("failed to parse string %s", ele.Stake)
}
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 nakamoto coefficient
nakamotoCoefficient := utils.CalcNakamotoCoefficientBigNums(totalVotingPower, votingPowers)
fmt.Println("The Nakamoto coefficient for near protocol is", nakamotoCoefficient)

return nakamotoCoefficient, nil
}
47 changes: 28 additions & 19 deletions core/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,26 @@ func main() {
var err error
conn, err = pgx.Connect(context.Background(), os.Getenv("DATABASE_URL"))
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to connect to database: %v\n", err)
fmt.Fprintln(os.Stderr, "Unable to connect to database", err)
os.Exit(1)
}
defer conn.Close(context.Background())

networks := []string{"BNB", "ATOM", "OSMO", "MATIC", "MINA", "SOL", "AVAX", "LUNA", "GRT", "RUNE"}
defer func() {
if err := conn.Close(context.Background()); err != nil {
log.Println("failed to close database connection", err)
}
}()

networks := []string{"BNB", "ATOM", "OSMO", "MATIC", "MINA", "SOL", "AVAX", "LUNA", "GRT", "RUNE", "NEAR"}
for _, n := range networks {
UpdateChainInfo(n)
}
}

func UpdateChainInfo(chain_token string) {
prevVal, currVal := GetPrevVal(chain_token), 0
func UpdateChainInfo(chainToken string) {
prevVal, currVal := getPrevVal(chainToken), 0
var err error
switch chain_token {
switch chainToken {
case "BNB":
currVal, err = chains.Binance()
case "ATOM":
Expand All @@ -52,33 +56,38 @@ func UpdateChainInfo(chain_token string) {
currVal, err = chains.Graph()
case "RUNE":
currVal, err = chains.Thorchain()
case "NEAR":
currVal, err = chains.Near()
}

if err != nil {
log.Println("Error occurred for", chain_token, err)
} else {
SaveUpdatedVals(currVal, prevVal, chain_token)
log.Println("failed to update chain info", chainToken, err)
}

if err := saveUpdatedVals(currVal, prevVal, chainToken); err != nil {
log.Println("failed to save updated values to database", chainToken, err)
}
}

// Query the database to get the previous (prior to updating it now) value of nakamoto coefficient for the given chain
func GetPrevVal(chain_token string) int {
// GetPrevVal queries the database to get the previous (prior to updating it now) value of nakamoto coefficient for the given chain
// Assumes row for chain already exists in the table
func getPrevVal(chainToken string) int {
queryStmt := `SELECT naka_co_curr_val from naka_coefficients WHERE chain_token=$1`
var naka_co_prev_val int
if err := conn.QueryRow(context.Background(), queryStmt, chain_token).Scan(&naka_co_prev_val); err == nil {
var nakaCoeffPrevVal int
if err := conn.QueryRow(context.Background(), queryStmt, chainToken).Scan(&nakaCoeffPrevVal); err == nil {
} else {
fmt.Println("Read unsuccessful for "+chain_token, err)
fmt.Println("Read unsuccessful", chainToken, err)
return -1
}
return naka_co_prev_val
return nakaCoeffPrevVal
}

// Save the recently calculated values back to the database
func SaveUpdatedVals(curr_val int, prev_val int, chain_token string) error {
// SaveUpdatedVals saves the recently calculated values back to the database
func saveUpdatedVals(currVal int, prevVal int, chainToken string) error {
queryStmt := `UPDATE naka_coefficients SET naka_co_curr_val=$1, naka_co_prev_val=$2 WHERE chain_token=$3`
_, err := conn.Exec(context.Background(), queryStmt, curr_val, prev_val, chain_token)
_, err := conn.Exec(context.Background(), queryStmt, currVal, prevVal, chainToken)
if err != nil {
fmt.Println("Write unsuccessful for "+chain_token, err)
fmt.Println("Write unsuccessful for "+chainToken, err)
}
return err
}
2 changes: 2 additions & 0 deletions db/postgres_script.sql
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,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 ('Thorchain', 'RUNE', -1, 10);

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

select * from naka_coefficients;

\q
Expand Down

0 comments on commit baa688c

Please sign in to comment.