Compare commits

...

16 Commits

Author SHA1 Message Date
serinko f270ff8655 syntax edits 2024-08-29 13:25:29 +02:00
serinko 39d053b51b finish initial draft of fair mixnet page 2024-08-29 12:38:02 +02:00
serinko f72a24608d finish fair-mixnet page initial draft 2024-08-12 16:05:57 +02:00
serinko a176c6e49b add calculation of stake target and documentation 2024-08-12 13:34:53 +02:00
serinko 2eff3d91d5 start fair mixnet detailed tokenomics chapter 2024-08-09 17:45:31 +02:00
serinko ede6d565f2 clarify only one active set for all 2024-08-08 17:41:52 +02:00
serinko 1b55078d7f add katex to install_mdbook_deps.sh 2024-08-08 16:24:22 +02:00
serinko 296ce96860 start explain reward logic step by step 2024-08-08 15:12:08 +02:00
serinko 37a32d21cd add ascii reward flow 2024-08-05 14:28:08 +02:00
serinko 3dbee66bc3 add ascii reward flow 2024-08-05 14:27:44 +02:00
serinko c30c08ff68 finish tokenomics overview page 2024-08-01 15:41:44 +02:00
serinko 3360de139f fix date formatting 2024-08-01 10:41:34 +02:00
serinko 6a4d803f8a add description values to api_targets column 2024-08-01 10:34:20 +02:00
serinko 33316dc250 add separator arg 2024-07-26 14:38:17 +02:00
serinko 0941efe48a nym token key points 2024-07-24 11:12:05 +02:00
serinko 1b1b7fc760 initialise tokenomics page 2024-07-19 15:14:16 +02:00
8 changed files with 535 additions and 39 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ set -o pipefail
# pinning minor version allows for updates but no breaking changes
MINOR_VERSION=0.4
# if a new plugin is added to the books it needs to be added here also
declare -a plugins=("admonish" "linkcheck" "last-changed" "theme" "variables" "cmdrun")
declare -a plugins=("admonish" "linkcheck" "last-changed" "theme" "variables" "cmdrun" "katex")
# install mdbook + plugins
install_mdbook_deps() {
+23 -2
View File
@@ -18,8 +18,8 @@ pagetoc = true
sidebar-width = "280px"
content-max-width = "80%"
root-font-size = "70%"
# if you need to change anything in the index.hbs file you need to turn this to `false`, rebuild the book,
# probably remove the additional `comment` that gets appended to the header, and then change this back to `true`.
# if you need to change anything in the index.hbs file you need to turn this to `false`, rebuild the book,
# probably remove the additional `comment` that gets appended to the header, and then change this back to `true`.
# this is because of a bug in the `mdbook-theme` plugin
turn-off = true
@@ -51,6 +51,27 @@ renderer = ["html"]
# [preprocessor.api-call]
# command = "$(tokens=$(curl -L https://api.nymtech.net/cosmos/staking/v1beta1/pool | jq 'values[\"pool\"][\"bonded_tokens\"]') && echo ${tokens:0:2},${tokens:2:2})"
[preprocessor.katex]
# a latex preprocesor, taken from https://github.com/lzanini/mdbook-katex
# docs with supported syntax https://katex.org/docs/supported.html
after = ["links"]
# KaTeX options.
output = "html"
leqno = false
fleqn = false
throw-on-error = true
error-color = "#cc0000"
min-rule-thickness = -1.0
max-size = "Infinity"
max-expand = 1000
trust = false
# Extra options.
no-css = false
include-src = false
block-delimiter = { left = "$$", right = "$$" }
inline-delimiter = { left = "$", right = "$" }
pre-render = true
#########
# BUILD #
#########
+3 -3
View File
@@ -47,9 +47,9 @@
# Token Economics
<!-- - [Fair Mixnet](tokenomics/fair-mixnet.md) -->
<!-- - [Mixnet: Nym Node Rewards](tokenomics/mixnet-rewards.md) -->
- [Nyx: Validator Rewards](tokenomics/validator-rewards.md)
- [Fair Mixnet](tokenomics/fair-mixnet.md)
- [Nym Operators Rewards](tokenomics/mixnet-rewards.md)
- [Nyx Validator Rewards](tokenomics/validator-rewards.md)
# FAQ
Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

@@ -0,0 +1,153 @@
# Fair Mixnet
```admonish info title="\*Important Info"
**The data on this page were last time updated on <!--cmdrun cd ../../../scripts/cmdrun && ./api_targets.py time_now-->. Every information labeled with `*` sign is corresponding to that time stamp.**
```
Nym Network is composed of two main elements, the Mixnet represented by [Nym Nodes](../nodes/nym-node.md) routing and mixing the data packets, and Nyx blockchain distributted accros [validator set](validator-rewards.md), using smart contracts (based on [cosmwasm](https://cosmwasm.com/)) to monitor and reward Nym Nodes by querying API endpoints and distributing NYM token to operators according to work done by their nodes. All Nym nodes and validators are run by decentralised community of operators.
* Nym tokenomics are based on the research paper [*Reward Sharing for Mixnets*](https://nymtech.net/nym-cryptoecon-paper.pdf)
* For a more comprehensive overview, live data and supply graphs, visit [*nymtech.net/about/token*](https://nymtech.net/about/token)
**Formulas and Examples Annotation**
To make it easier for the reader, we use a highlighting line on the left side, with a specific color:
```admonish tip title=""
$Green\ for\ formulas.$
```
```admonish example collapsible=true
$Purple\ collapsible\ for\ examples.$
```
## NYM Token: Incentivise Stability & Secure Reputation
Besides the Mixnet itself, Nym Network is secured by its own blockchain Nyx (IBC on Cosmos) with a native token NYM. NYM token key features are:
* **Incentives:** Distribute rewards to decentralised nodes based on mixing and routing (work). This dynamic ensures that the network is as robust as possible - the nodes are chosen every hour according to their performance.
* **Network take over defense:** Another decisive factor for a node to be chosen to the network active set is reputation. Reputation is a size of stake (delegation) where delegators earn proportional percentage of nodes rewards. Nodes without reputation are not chosen to take part in the network active set.
* **Centralisation defense:** Any node can only have a certain stake (called stake saturation) to earn maximum rewards, increasing stake level per node leads to decreasing rewards for the operator and all delegators. This feature makes it more difficult for whales to over-stake their nodes or to attract more delegators (stakers) as they would become dis-advantaged.
To learn more about rewards calculation and distribution, read the next page [*Nym Operators Rewards*](mixnet-rewards.md).
### Utility
*NYM token is a first and foremost a utility to secure Nym Network.*
![](../images/tokenomics/nym_token_flow.png)
Nyx blockchain's validators run API to monitor the network and node performance. Based on the live input the operators and stakers of the active nodes get rewarded. The network is adjusted and re-randomized in the beginning of each epoch (60 min) composing the best performing nodes with the highest reputation.
This creates an incentive for people to operate Nym nodes as quality and reliable service. The reputation system also works as a network defense against a large adversary take over or sybil attacks.
Node reputation is calculated by delegation. Delegation is a stake done by NYM token holders on top of nodes they want to support to join the network as it compensate the stakers with APR. Therefore there is an incetive for NYM holders to stake their token on top of nodes which they believe will perform well.
To prevent a whale takeover and centralisation, the revenue grows alongside nodes stake size only until a certain point, after which the rewards per staker start to decrease. We call this mark *node stake saturation*.
Thanks to Nyx blockchain API monitoring, the flow is dynamic and constantly optimized based on live metrics. Below is a detailed explanation and reckoning of Nym tokenomics logic.
## Tokenomics
### Summary in Numbers
Below is a table with Nyx chain data\* and token supply distribution.
<!--cmdrun cd ../../../scripts/cmdrun && ./api_targets.py v --api mainnet --endpoint circulating-supply --format markdown --separator _ -->
To get live data, visit [Nym token page](https://nymtech.net/about/token
) or see how to [query API endpoints](#query-tokenomics-api).
### Calculation & Explanation
To get a full comprehension of [node operators rewards](mixnet-rewards.md) calculation and [delegators APR height](https://nymtech.net/about/token), we need to understand some basic logic behind the numbers presented. This chapter covers some of the most essential variables in Nym tokenomics flow.
```ascii
┌───────────┐ staking ┌───────────┐ ┌───────────┐
│ │ supply │ │ sum of │ │
│circulating│ scale │ staking │ bonded │ stake │
│ supply │ factor │ target │ nym nodes │saturation │
│ ├────────────►│ ├────────────►│ │
└───────────┘ └───────────┘ └───────────┘
```
#### Supply
<b>Circulating supply\* is <!-- cmdrun cd ../../../scripts/cmdrun && ./api_targets.py v --api mainnet --endpoint circulating-supply --value circulating_supply amount --separator _ --> NYM.</b>
NYM token is capped at 1b. Visit [Nym token page](https://nymtech.net/about/token) to see live data and graphs.
#### Staking target
A number of aimed NYM tokens to be staked in the network. The staking target a is multiplier of staking supply scale factor and circulating supply.
```admonish tip title=""
$staking\ target = staking\ supply\ scale\ factor * circulating\ supply$
```
Staking supply scale factor is currently\* it's set to be <!--cmdrun cd ../../../scripts/cmdrun && ./api_targets.py v --api mainnet --endpoint epoch/reward_params --value interval staking_supply_scale_factor --format percent -->.
The value of this variable can be changed to optimize the metrics of the network. With a current circulating supply of <!--cmdrun cd ../../../scripts/cmdrun && ./api_targets.py v --api mainnet --endpoint circulating-supply --value circulating_supply amount --separator _ --> NYM and staking supply scale factor <!--cmdrun cd ../../../scripts/cmdrun && ./api_targets.py v --api mainnet --endpoint epoch/reward_params --value interval staking_supply_scale_factor --format percent -->, <b>the staking target is <!-- cmdrun cd ../../../scripts/cmdrun && ./api_targets.py c --staking_target --separator _ --> NYM.</b>
#### Stake saturation
Node reputation in a form of self bond or stakers delegation. Stake saturation is calculated as:
```admonish tip title=""
$stake\ saturation = circulating\ supply * staking\ target\ /\ total\ \#\ of\ nodes$
```
<!-- CODE AUTO COMPLETION:
- # of nodes in the network
- circulating supply * staking target
- staking target / # of nodes in the network
-->
With current\* circulating supply of <!-- cmdrun cd ../../../scripts/cmdrun && ./api_targets.py v --api mainnet --endpoint circulating-supply --value circulating_supply amount --separator _ --> NYM, staking target of <!-- cmdrun cd ../../../scripts/cmdrun && ./api_targets.py c --staking_target --separator _--> NYM, divided by the sum of [nodes bonded to the network](https://harbourmaster.nymtech.net), <b>the stake saturation level is <!-- cmdrun cd ../../../scripts/cmdrun && ./api_targets.py v --api mainnet --endpoint epoch/reward_params --value interval stake_saturation_point --separator _ --> NYM per node.</b>
#### Active set
Nym Network needs an optimised number of nodes to route and mix the packets. This healthy balance lies in between being too congested - which would detriment speed and user experience - on one side, and having too little traffic per node - which would could weaken anonymity - on the other. Currently\* <b>the active set is 240 nodes</b>, 120 with Gateway functionality (entry and exit layer) and 120 as Mixnode (2nd, 3rd and 4th mixing layer). The active set is chosen in the beginning of each epoch (60min). The best performing and reputated (stake saturation) nodes are chosen. Performance is much more ample as you can see in the formula below:
```admonish tip title=""
$$
active\ set\ selection\ probability = node\ performance^{20} * stake\ saturation
$$
```
To read more about rewards calculation, please see next page [*Nym Operators Rewards*](mixnet-rewards.md).
## Query Validator API
We have available API endpoints which can be accessed via [Swagger UI page](https://validator.nymtech.net/api/swagger/index.html). Or by querying the endpoints directly:
```sh
curl -X 'GET' \
'https://validator.nymtech.net/api/v1/circulating-supply' \
-H 'accept: application/json'sh
curl -X 'GET' \
'https://validator.nymtech.net/api/v1/circulating-supply/total-supply-value' \
-H 'accept: application/json'sh
curl -X 'GET' \
'https://validator.nymtech.net/api/v1/circulating-supply-value' \
-H 'accept: application/json'sh
curl -X 'GET' \
'https://validator.nymtech.net/api/v1/epoch/reward_params' \
-H 'accept: application/json'sh
```
> The unit of value is measured in `uNYM`.
```admonish tip title=""
$1 \ NYM = 1 \_ 000 \_ 000 \ uNYM$
```
@@ -1,22 +1,188 @@
<!-- THIS PAGE IS ALL COMMENTED FROM SUMMARY - NO NEED TO REVIEW YET!!! -->
# Nym Operators Rewards
<!-- DROPPING THIS FROM THE MAINTENANCE -->
```admonish info title="\* Important Info"
**The data on this page were last time updated on <!--cmdrun cd ../../../scripts/cmdrun && ./api_targets.py time_now-->. Every information labeled with `*` sign is corresponding to that time stamp.**
```
### Mix Node Reward Estimation API endpoint
* Nym tokenomics are based on the research paper [*Reward Sharing for Mixnets*](https://nymtech.net/nym-cryptoecon-paper.pdf)
* For a more comprehensive overview, live data and supply graphs, visit [*nymtech.net/about/token*](https://nymtech.net/about/token)
**Formulas and Examples Annotation**
To make it easier for the reader, we use a highlighting line on the left side, with a specific color:
```admonish tip title=""
$Green\ for\ formulas.$
```
```admonish example collapsible=true
$Purple\ collapsible\ for\ examples.$
```
## Overview
This is a quick summary, to understand the full picture, please see detailed [*Rewards Logic & Calculation*](#rewards-logic--calculation) chapter below.
* The operators of `nym-node` get rewarded from Mixmining pool, which emits around 6000 NYM per hour.
* An active set of `nym-nodes` selected for Nym network routing and mixing is 240 nodes in total and it's selected for each new epoch (60 min).
* The active set is composed of 120 Mixnodes and 120 Gateways.
* `nym-nodes` can run in mode `entry-gateway`, `exit-gateway` and `mixnode`, the active set selection of each mode is
| Nym node mode | Total in active set | Rationale |
| :--- | ---: | :--- |
| `mixnode` | 120 | Always 3 layers of 40 mixnodes |
| `entry-gateway` | 120 | Any Gateway can act as an entry |
| `exit-gateway` | max 120 | Any Gateway running `exit-gateway` mode from the same 120 |
* NymVPN can route through Nym Network two ways, both using the same active set:
- Mixnet: 5 layers routing and mixing - full privacy
- Wireguard: 2 layers routing, skipping 3 mixing layers - fast mode
* The reward distribution is per layer according to a [decision made by the operators](https://forum.nymtech.net/t/poll-what-should-be-the-split-of-mixmining-rewards-among-the-layers-of-the-nym-mixnet/407) as follows:
- 5-hop: 16%-16%-16%-16%-36%
- 2-hop: (In future) 33%-67%
- Currently Gateways earn rewards only from 5-hop mode. The operators can sign up to a grant program as a substitution for 2-hop routing.
* Each node is rewarded according to the layer in which it's positioned in the given epoch, divided uniformly between all nodes in that layer.
* Nodes are selected to the active set based on their performance and stake saturation (self bond + delegation)
* In future a ticket system will be implemented where nodes will be rewarded according to the work they perform, with a revenue for both 2-hop and 5-hop work. The uniform naive distribution is an intermediate step. See [*Roadmap*](#roadmap) chapter for more details.
## Rewards Logic & Calculation
**Note that in the current intermediate model we use one active set for both 2-hop and 5-hop routing Gateways. In reality it means that all nodes are rewarded within 5-hop reward scheme only. In the meantime, given that the 120 Gateways within the active set route traffic for 2-hop wireguard mode as well, without any extra rewards, the operators can get substitution in the form of grants.**
~~~admonish tip title="Nym network active set distribution"
```ascii
Network
layer: 1. 2. 3. 4. 5.
┌► mixnode ─┐ mixnode mixnode
│ │
Node entry │ │ exit
type: gateway ──┘ mixnode │ mixnode ┌─► mixnode ───► gateway
│ │
│ │
mixnode └─► mixnode ─┘ mixnode
Active set: 120 40 40 40 max 120
Rewards
distribution 16% 16% 16% 16% 36%
5-hop mode:
Future implementation:
Rewards
distribution 33% skip skip skip 67%
2-hop mode:
```
~~~
### Active Set Selection
*Performance matters!*
For a node to be rewarded, the node must be part of an active set in the first place. The active set is selected in the beginning of each epoch (every 60min) where total of 240 nodes - represented by 120 mixnodes and 120 gateways, are randomly allocated across the layers. Mixnodes only work within the given layer, while any Exit Gateway can be chosen by a client as an Entry Gateway, not vice versa.
The algorithm choosing nodes into the active set takes into account node's performance and [stake saturation](fair-mixnet.md#stake-saturation), both values being between 0 and 1.
```admonish tip title=""
$$
active\ set\ selection\ probability = node\ performance^{20} * stake\ saturation
$$
```
For a comparison we made an example with 5 nodes, where first number is node performance and second stake saturation:
```admonish example collapsible=true
$$
\begin{align}
\notag node_1 &= 1^{20} * 1 = 1 \\
\notag node_2 &= 1^{20} * 0.5 = 0.5 \\
\notag node_3 &= 0.99^{20} * 1 = 0.818 \\
\notag node_4 &= 0.95^{20} * 1 = 0.358 \\
\notag node_5 &= 0.9^{20} * 1 = 0.122 \\
\end{align}
$$
```
As you can see the performance (also known as *Routing score*) is much more important during the active set selection. A node with 100% performance but only 50% stake saturation has much bigger chance to be chosen than a node with 95% performance but full stake saturation and incomparably bigger chance than 90% performing node with 100% stake saturation.
### Layer Distribution
Once the active set of 120 Mixnodes and 120 Gateways is selected, the nodes can start to route and mix packets in the Nym Network. Each hour a total of 6000 NYM is distributed between the layers from Mixmining pool, following the ratio according to a [decision made by the operators](https://forum.nymtech.net/t/poll-what-should-be-the-split-of-mixmining-rewards-among-the-layers-of-the-nym-mixnet/407) as follows:
```admonish tip title=""
5-hop mixnet mode: <br>
$16\%; 16\%; 16\%; 16\%; 36\%$ <br>
<!-- COMMENTING OUT FOR NOW AS WE DON'T HAVE IT IMPLEMENTED
2-hop wireguard mode: $33\%; 67\%$
-->
```
In real numbers: If hourly revenue to all 240 nodes is 6000 NYM, the layer compartmentalisation is 960 NYM for Entry Gateway layer and each Mixnode layer and 2160 NYM for Exit Gateway layer. The calculation is in the example below:
```admonish example collapsible=true
5-hop mixnet mode: <br>
$0.16 * 6000 = 960; 0.16 * 6000 = 960; 0.16 * 6000 = 960; 0.16 * 6000 = 960; 0.36 * 6000 2160$ <br>
<!-- COMMENTING OUT AS WE DO NOT HAVE A CLEAR NUMBERS HERE
<br>
2-hop wireguard mode:<br>
$33\% - 67\%$
-->
```
### Node Rewards within Same Layer
### Operation Cost, Profit Margin & Delegation
### APR Calculation
## Roadmap
<!-- PUT FINAL TOKENOMIC SCHEME AND ALL STEPS TOWARDS IT IN HERE -->
## Stats
NYM token is capped at 1b. Below is a table with actual\* token supply distribution.
<!--cmdrun cd ../../../scripts/cdmrun && ./api_targets.py s --api mainnet --endpoint circulating-supply --format -->
<!-- ADD MIXNET STATS GRAPHS -->
<!-- DROPPING THIS FROM THE MAINTENANCE PAGE - NEEDS REWORK -->
## Mix Node Reward Estimation API endpoint
<!-- THIS NEEDS REDO -->
The Reward Estimation API endpoint allows Mix Node operators to estimate the rewards they could earn for running a Nym Mix Node with a specific `MIX_ID`.
> The `<MIX_ID>` can be found in the "Mix ID" column of the [Network Explorer](https://explorer.nymtech.net/network-components/mixnodes/active).
> The `<MIX_ID>` can be found in the "Mix ID" column of the [Harbourmaster](https://harbourmaster/nymtech.net).
<!--
The endpoint is a particularly common for Mix Node operators as it can provide an estimate of potential earnings based on factors such as the amount of traffic routed through the Mix Node, the quality of the Mix Node's performance, and the overall demand for Mix Nodes in the network. This information can be useful for Mix Node operators in deciding whether or not to run a Mix Node and in optimizing its operations for maximum profitability.
-->
Using this API endpoint returns information about the Reward Estimation:
We have available API endpoints which can be accessed via [Swagger UI page](https://validator.nymtech.net/api/swagger/index.html). Or by querying the endpoints directly:
```sh
/status/mixnode/<MIX_ID>/reward-estimation
curl -X 'GET' \
'https://validator.nymtech.net/api/v1/status/mixnode/<MIX_ID>/reward-estimation' \
-H 'accept: application/json'sh
```
Query Response:
Query response will look like this:
```sh
"estimation": {
@@ -29,6 +195,9 @@ Query Response:
> The unit of value is measured in `uNYM`.
```admonish tip title=""
$1 \ NYM = 1 \_ 000 \_ 000 \ uNYM$
```
- `estimated_total_node_reward` - An estimate of the total amount of rewards that a particular Mix Node can expect to receive during the current epoch. This value is calculated by the Nym Validator based on a number of factors, including the current state of the network, the number of Mix Nodes currently active in the network, and the amount of network traffic being processed by the Mix Node.
- `estimated_operator_reward` - An estimate of the amount of rewards that a particular Mix Node operator can expect to receive. This value is calculated by the Nym Validator based on a number of factors, including the amount of traffic being processed by the Mix Node, the quality of service provided by the Mix Node, and the operator's stake in the network.
@@ -38,9 +207,3 @@ Query Response:
- `estimated_node_profit` - An estimate of the profit that a particular Mix node operator can expect to earn. This value is calculated by subtracting the Mix Node operator's `operating_costs` from their `estimated_operator_reward` for the current epoch.
- `estimated_operator_cost` - An estimate of the total cost that a particular Mix Node operator can expect to incur for their participation. This value is calculated by the Nym Validator based on a number of factors, including the cost of running a Mix Node, such as server hosting fees, and other expenses associated with operating the Mix Node.
### Validator: Installing and configuring nginx for HTTPS
#### Setup
[Nginx](https://www.nginx.com/resources/glossary/nginx) is an open source software used for operating high-performance web servers. It allows us to set up reverse proxying on our validator server to improve performance and security.
Install `nginx` and allow the 'Nginx Full' rule in your firewall:
@@ -1,5 +1,9 @@
# Nyx Validator Rewards
```admonish info
**The data on this page were last time updated on <!--cmdrun cd ../../../scripts/cmdrun && ./api_targets.py time_now-->.**
```
## Summary
* Nyx Validators are rewarded in NYM tokens from the Nym mixmining pool and increasingly from apps that run on the Nym mixnet, the first of which is the NymVPN.
@@ -22,7 +26,7 @@ Validator rewards initially come from the Nym mixmining pool with additional rew
1. **From mixmining pool** - at a rate of 1000 NYM per hour, of which 2/3 are distributed for signing blocks and 1/3 for zk-nyms. These are stable in NYM, and therefore will fluctuate in their fiat value depending on exchange rate.
2. **From vpn user subscriptions** - the rate is tied to the growth of NymVPN subscriptions and will be stable in fiat, fluctuating in NYM depending on exchange rate. 1/3 will be distributed for signing blocks and 2/3 for zk-nyms.
2. **From vpn user subscriptions** - the rate is tied to the growth of NymVPN subscriptions and will be stable in fiat, fluctuating in NYM depending on exchange rate. 1/3 will be distributed for signing blocks and 2/3 for zk-nyms.
| Source | Signing blocks | Running NymAPI | Currency |
| :-- | --: | --: | :---: |
+174 -19
View File
@@ -1,3 +1,5 @@
#!/usr/bin/python3
import argparse
import os
import requests
@@ -5,12 +7,14 @@ import json
import sys
import pandas as pd
from collections import namedtuple
from time import gmtime, strftime
import time
############################################
############## GENERAL FNs #################
############################################
def get_url(args):
def get_url(args, **kwargs):
config_file = "./api_targets_config.json"
with open(config_file, "r") as f:
config = json.load(f)
@@ -28,18 +32,40 @@ def subparser_read(args):
response = r.json()
return response
def print_time_now(args):
#now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
#now = time.ctime()
day = strftime("%d", gmtime())
if day[0] == "0":
day = day[1]
if day == "1" or day == "21" or day == "31":
suffix = "st"
elif day == "2" or day == "22":
suffix = "nd"
elif day == "3" or day == "23":
suffix = "rd"
else:
suffix = "th"
now = strftime(f"%A, %B {day}{suffix} %Y, %X UTC", gmtime())
print(now)
############################################
########### NYX RELATED FNs ################
############################################
def convert_u_nym(unym):
unym = int(unym)
unym = float(unym)
nym = unym / 1000000
nym = int(nym)
return nym
def thousand_separator(n):
n = f'{n:_}'
def thousand_separator(n, separator):
if separator == " ":
n = f'{n:_}'
n = remove_underscore(n)
else:
n = f'{n:{separator}}'
return n
def remove_underscore(arg):
@@ -48,6 +74,7 @@ def remove_underscore(arg):
return string
def display_supply_table(response, args):
separator = args.separator
df = pd.DataFrame(response)
df = df.T
del df['denom']
@@ -56,23 +83,100 @@ def display_supply_table(response, args):
df = df.rename(columns={'index1': '**Item**', 'amount': '**Amount in NYM**'})
df['**Item**'] = df['**Item**'].apply(remove_underscore)
df['**Amount in NYM**'] = df['**Amount in NYM**'].apply(convert_u_nym)
df['**Amount in NYM**'] = df['**Amount in NYM**'].apply(thousand_separator)
table = df.to_markdown(index=False)
desc_column = _get_desc_column()
df.insert(1, '**Description**', desc_column, True)
stake_saturation = _get_stake_saturation()
df.loc[len(df.index)] = ['Stake Saturation', 'Optimal size of node self-bond + delegation', stake_saturation]
df['**Amount in NYM**'] = df['**Amount in NYM**'].apply(thousand_separator, args=(separator, ))
table = df.to_markdown(index=False,colalign=("left","left","right"))
print(table)
def _get_stake_saturation():
reward_params = get_api("https://validator.nymtech.net/api/v1/epoch/reward_params")
stake_saturation = get_dict_value(reward_params,["interval","stake_saturation_point"])
stake_saturation = convert_u_nym(stake_saturation)
return stake_saturation
def _get_desc_column():
supply = "Maximum amount of NYM token in existence"
reserve = "Tokens releasing for operators rewards"
vesting = "Tokens locked outside of cicrulation for future claim"
circulating = "Amount of unlocked tokens"
desc_column = [supply, reserve, vesting, circulating]
return desc_column
def read_supply(args):
separator = args.separator
response = subparser_read(args)
if args.endpoint == "circulating-supply":
if args.format:
if args.value:
value = get_nested_value(response, args)
value = convert_u_nym(value)
value = thousand_separator(value, separator)
print(value)
elif args.format == "markdown":
display_supply_table(response, args)
else:
print(response)
elif args.endpoint == "foo":
# placeholder for other endpoint args
pass
value = response
print(value)
elif args.endpoint == "epoch/reward_params":
value = get_reward_params(response, args, separator)
print(value)
def get_reward_params(response, args, separator):
value = get_nested_value(response, args)
if args.format == "percent":
value = _return_percent_annotation(value)
else:
# placeholder for other endpoint args
pass
value = convert_u_nym(value)
value = thousand_separator(value, separator)
return value
def get_nested_value(response, args):
value = response
for key in args.value:
value = value[key]
return value
def _return_percent_annotation(value):
value = float(value) * 100
value = f"{value}%"
return value
###########################################
############# CALCULATE FNs ###############
###########################################
def calculate(args):
separator = args.separator
reward_params = get_api("https://validator.nymtech.net/api/v1/epoch/reward_params")
circulating_supply = get_api("https://validator.nymtech.net/api/v1/circulating-supply")
if args.staking_target:
display_staking_target(args, reward_params, circulating_supply, separator)
def get_api(url):
r = requests.get(url)
response = r.json()
return response
def display_staking_target(args, reward_params, circulating_supply, separator):
keys = ["interval", "staking_supply_scale_factor"]
staking_supply_scale_factor = get_dict_value(reward_params, keys)
keys = ["circulating_supply", "amount"]
circulating_supply = get_dict_value(circulating_supply, keys)
staking_target = float(staking_supply_scale_factor) * float(circulating_supply)
staking_target = convert_u_nym(staking_target)
if args.separator:
staking_target = thousand_separator(staking_target, separator)
print(staking_target)
def get_dict_value(json, keys):
value = json
for key in keys:
value = value[key]
return value
###########################################
############ GH RELATED FNs ###############
@@ -114,9 +218,9 @@ def parser_main():
epilog=''
)
subparsers = parser.add_subparsers(help="")
parser_supply = subparsers.add_parser('supply',
help='reads API on supply',
aliases=['s','S']
parser_supply = subparsers.add_parser('validator',
help='Reads validaor API enpoints',
aliases=['v']
)
parser_supply.add_argument(
@@ -130,18 +234,66 @@ def parser_main():
type=str,
help="choose from: https://validator.nymtech.net/api/swagger/index.html"
)
parser_supply.add_argument(
"-v","--value",
type=str,
help="dictionary keys to get needed value separated by a space",
nargs = '+'
)
parser_supply.add_argument(
"-f","--format",
action="store_true",
help="format the output for documentation purpose (.md) - default: False (raw output)",
type=str,
help="'markdown' formats the output for documentation purpose; 'percent' returns a number with % annotation",
)
parser_supply.add_argument(
"-s", "--separator",
type=str,
default=" ",
help="Add custom thousand separator to --format flag (default is none)"
)
parser_supply.set_defaults(func=read_supply)
parser_calculate = subparsers.add_parser('calculate',
help='Calculate and print the values of optional args',
aliases=['c']
)
parser_calculate.add_argument(
"--staking_target",
action="store_true",
help="A multiplier of staking supply scale factor and circulating supply"
)
parser_calculate.add_argument(
"-s", "--separator",
type=str,
default=" ",
help="Add custom thousand separator to --format flag (default is none)"
)
# parser_calculate.add_argument(
# "--api",
# default="mainnet",
# )
parser_calculate.set_defaults(func=calculate)
parser_time_now = subparsers.add_parser('time_now',
help='Prints UTC time now',
aliases=['time', 't']
)
parser_time_now.set_defaults(func=print_time_now)
parser_nym_vpn = subparsers.add_parser('nym_vpn',
help='reads NymVPN latest version',
aliases=['n','N']
aliases=['n']
)
parser_nym_vpn.add_argument(
@@ -168,6 +320,9 @@ def parser_main():
parser_nym_vpn.set_defaults(func=get_nym_vpn_version)
args = parser.parse_args()
try:
args.func(args)