mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-11-13 04:41:24 +00:00
Terra luna (#1197)
* Add separate view for finbrain for crypto curreny sentiment analysis * Move json with symbols to separate directory, little refactoring, update readme * Add screenshot of finbrain for PolkaDot * add dataframe helper denomination method, add terramoney_fcd model * add account growth function, goverment proposals function * add staking ratio and returns for terra: * Refactor terra model, add terramoney_fcd_view with 2 methods * Add terramoney_fdc_model views * add plots for terra fcd views * add terra fcd to defi controller * add hugo docs, refactor defi controller * change export parameters, refactor chart tickers, fix --descend flag in validators command, add multiline formatted string for terra staking report, change tabulate to rich, add terra adress validator
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import re
|
||||
from typing import Union, Any
|
||||
from typing import Union, Any, Optional
|
||||
import textwrap
|
||||
import pandas as pd
|
||||
from gamestonk_terminal.helper_funcs import long_number_format
|
||||
@@ -137,3 +137,46 @@ def prettify_column_names(columns: list) -> list:
|
||||
list with reformatted columns
|
||||
"""
|
||||
return [" ".join(re.findall(".[^A-Z]*", val)).capitalize() for val in columns]
|
||||
|
||||
|
||||
def denominate_number(
|
||||
number: Any, divider: int = 1000000, round_digits: Optional[int] = 4
|
||||
) -> float:
|
||||
"""Denominate numbers base on provided divider and round number by provided digit
|
||||
|
||||
Parameters
|
||||
----------
|
||||
number: Any
|
||||
value to round
|
||||
divider: int
|
||||
divide by value
|
||||
round_digits:
|
||||
round number to n digits
|
||||
Returns
|
||||
-------
|
||||
float:
|
||||
denominated number
|
||||
"""
|
||||
|
||||
if round_digits:
|
||||
return round(float(number) / divider, round_digits)
|
||||
return round(float(number) / divider)
|
||||
|
||||
|
||||
def replace_unicode(x: Any) -> Any:
|
||||
"""Replace unicode characters to ?
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x: Any
|
||||
value to replace unicode chars
|
||||
|
||||
Returns
|
||||
-------
|
||||
Any
|
||||
replaced value
|
||||
"""
|
||||
|
||||
if isinstance(x, str):
|
||||
return x.encode("ascii", "replace").decode()
|
||||
return x
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
"""Defi Controller Module"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
# pylint: disable=C0302
|
||||
|
||||
import argparse
|
||||
|
||||
from typing import List
|
||||
@@ -11,6 +13,8 @@ from gamestonk_terminal.cryptocurrency.defi import (
|
||||
coindix_model,
|
||||
terraengineer_model,
|
||||
terraengineer_view,
|
||||
terramoney_fcd_view,
|
||||
terramoney_fcd_model,
|
||||
)
|
||||
from gamestonk_terminal.parent_classes import BaseController
|
||||
from gamestonk_terminal import feature_flags as gtff
|
||||
@@ -18,6 +22,7 @@ from gamestonk_terminal.menu import session
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
parse_known_args_and_warn,
|
||||
check_positive,
|
||||
check_terra_address_format,
|
||||
EXPORT_ONLY_RAW_DATA_ALLOWED,
|
||||
EXPORT_BOTH_RAW_DATA_AND_FIGURES,
|
||||
)
|
||||
@@ -54,6 +59,12 @@ class DefiController(BaseController):
|
||||
"vaults",
|
||||
"ayr",
|
||||
"aterra",
|
||||
"sinfo",
|
||||
"validators",
|
||||
"govp",
|
||||
"gacc",
|
||||
"sratio",
|
||||
"sreturn",
|
||||
]
|
||||
|
||||
PATH = "/crypto/defi/"
|
||||
@@ -75,6 +86,14 @@ class DefiController(BaseController):
|
||||
choices["vaults"]["-k"] = {c: {} for c in coindix_model.VAULT_KINDS}
|
||||
choices["vaults"]["-c"] = {c: {} for c in coindix_model.CHAINS}
|
||||
choices["vaults"]["-p"] = {c: {} for c in coindix_model.PROTOCOLS}
|
||||
choices["govp"]["-s"] = {c: {} for c in terramoney_fcd_model.GOV_COLUMNS}
|
||||
choices["govp"]["--status"] = {
|
||||
c: {} for c in terramoney_fcd_model.GOV_STATUSES
|
||||
}
|
||||
choices["validators"]["-s"] = {
|
||||
c: {} for c in terramoney_fcd_model.VALIDATORS_COLUMNS
|
||||
}
|
||||
|
||||
self.completer = NestedCompleter.from_nested_dict(choices)
|
||||
|
||||
def print_help(self):
|
||||
@@ -95,12 +114,19 @@ class DefiController(BaseController):
|
||||
swaps Recent swaps done on Uniswap
|
||||
[src][Defi Llama][/src]
|
||||
ldapps Lists dApps
|
||||
gdapps Display top DeFi dApps grouped by chain
|
||||
stvl Display historical values of the total sum of TVLs from all dApps
|
||||
dtvl Display historical total value locked (TVL) by dApp
|
||||
gdapps Displays top DeFi dApps grouped by chain
|
||||
stvl Displays historical values of the total sum of TVLs from all dApps
|
||||
dtvl Displays historical total value locked (TVL) by dApp
|
||||
[src][Terra Engineer][/src]
|
||||
aterra Displays 30-day history of specified asset in terra address
|
||||
ayr Displays 30-day history of anchor yield reserve[/cmds]
|
||||
aterra Displays 30-day history of specified asset in terra address [src][Terra Engineer][/src]
|
||||
ayr Displays 30-day history of anchor yield reserve [src][Terra Engineer][/src]
|
||||
[src][Terra FCD][/src]
|
||||
sinfo Displays staking info for provided terra account address
|
||||
validators Displays information about terra blockchain validators
|
||||
govp Displays terra blockchain governance proposals list
|
||||
gacc Displays terra blockchain account growth history
|
||||
sratio Displays terra blockchain staking ratio history
|
||||
sreturn Displays terra blockchain staking returns history[/cmds]
|
||||
"""
|
||||
console.print(text=help_text, menu="Cryptocurrency - Decentralized Finance")
|
||||
|
||||
@@ -125,7 +151,7 @@ class DefiController(BaseController):
|
||||
parser.add_argument(
|
||||
"--address",
|
||||
dest="address",
|
||||
type=str,
|
||||
type=check_terra_address_format,
|
||||
help="Terra address. Valid terra addresses start with 'terra'",
|
||||
required=True,
|
||||
)
|
||||
@@ -167,6 +193,265 @@ class DefiController(BaseController):
|
||||
if ns_parser:
|
||||
terraengineer_view.display_anchor_yield_reserve(export=ns_parser.export)
|
||||
|
||||
def call_sinfo(self, other_args: List[str]):
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
prog="sinfo",
|
||||
description="""
|
||||
Displays staking info of a certain terra address.
|
||||
[Source: https://fcd.terra.dev/swagger]
|
||||
""",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-a",
|
||||
"--address",
|
||||
dest="address",
|
||||
type=check_terra_address_format,
|
||||
help="Terra address. Valid terra addresses start with 'terra'",
|
||||
required="-h" not in other_args,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-l",
|
||||
"--limit",
|
||||
dest="limit",
|
||||
type=check_positive,
|
||||
help="Number of delegations",
|
||||
default=10,
|
||||
)
|
||||
|
||||
if other_args and not other_args[0][0] == "-":
|
||||
other_args.insert(0, "-a")
|
||||
|
||||
ns_parser = parse_known_args_and_warn(
|
||||
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
|
||||
)
|
||||
|
||||
if ns_parser:
|
||||
terramoney_fcd_view.display_account_staking_info(
|
||||
export=ns_parser.export, address=ns_parser.address, top=ns_parser.limit
|
||||
)
|
||||
|
||||
def call_validators(self, other_args: List[str]):
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
prog="validators",
|
||||
description="""
|
||||
Displays information about terra validators.
|
||||
[Source: https://fcd.terra.dev/swagger]
|
||||
""",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-l",
|
||||
"--limit",
|
||||
dest="limit",
|
||||
type=check_positive,
|
||||
help="Number of validators to show",
|
||||
default=10,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-s",
|
||||
"--sort",
|
||||
dest="sortby",
|
||||
type=str,
|
||||
help="Sort by given column. Default: votingPower",
|
||||
default="votingPower",
|
||||
choices=[
|
||||
"validatorName",
|
||||
"tokensAmount",
|
||||
"votingPower",
|
||||
"commissionRate",
|
||||
"status",
|
||||
"uptime",
|
||||
],
|
||||
)
|
||||
parser.add_argument(
|
||||
"--descend",
|
||||
action="store_true",
|
||||
help="Flag to sort in descending order (lowest first)",
|
||||
dest="descend",
|
||||
default=False,
|
||||
)
|
||||
|
||||
ns_parser = parse_known_args_and_warn(
|
||||
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
|
||||
)
|
||||
|
||||
if ns_parser:
|
||||
terramoney_fcd_view.display_validators(
|
||||
export=ns_parser.export,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
top=ns_parser.limit,
|
||||
)
|
||||
|
||||
def call_govp(self, other_args: List[str]):
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
prog="govp",
|
||||
description="""
|
||||
Displays terra blockchain governance proposals list.
|
||||
[Source: https://fcd.terra.dev/swagger]
|
||||
""",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-l",
|
||||
"--limit",
|
||||
dest="limit",
|
||||
type=check_positive,
|
||||
help="Number of proposals to show",
|
||||
default=10,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-s",
|
||||
"--sort",
|
||||
dest="sortby",
|
||||
type=str,
|
||||
help="Sort by given column. Default: id",
|
||||
default="id",
|
||||
choices=terramoney_fcd_model.GOV_COLUMNS,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--status",
|
||||
dest="status",
|
||||
type=str,
|
||||
help="Status of proposal. Default: all",
|
||||
default="all",
|
||||
choices=terramoney_fcd_model.GOV_STATUSES,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--descend",
|
||||
action="store_false",
|
||||
help="Flag to sort in descending order (lowest first)",
|
||||
dest="descend",
|
||||
default=False,
|
||||
)
|
||||
|
||||
ns_parser = parse_known_args_and_warn(
|
||||
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
|
||||
)
|
||||
|
||||
if ns_parser:
|
||||
terramoney_fcd_view.display_gov_proposals(
|
||||
status=ns_parser.status,
|
||||
export=ns_parser.export,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
top=ns_parser.limit,
|
||||
)
|
||||
|
||||
def call_gacc(self, other_args: List[str]):
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
prog="gacc",
|
||||
description="""
|
||||
Displays terra blockchain account growth history.
|
||||
[Source: https://fcd.terra.dev/swagger]
|
||||
""",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-l",
|
||||
"--limit",
|
||||
dest="limit",
|
||||
type=check_positive,
|
||||
help="Number of days to show",
|
||||
default=90,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--cumulative",
|
||||
action="store_false",
|
||||
help="Show cumulative or discrete values. For active accounts only discrete value are available",
|
||||
dest="cumulative",
|
||||
default=True,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-k",
|
||||
"--kind",
|
||||
dest="kind",
|
||||
type=str,
|
||||
help="Total account count or active account count. Default: total",
|
||||
default="total",
|
||||
choices=["active", "total"],
|
||||
)
|
||||
parser.add_argument(
|
||||
"--descend",
|
||||
action="store_false",
|
||||
help="Flag to sort in descending order (lowest first)",
|
||||
dest="descend",
|
||||
default=False,
|
||||
)
|
||||
|
||||
ns_parser = parse_known_args_and_warn(
|
||||
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
|
||||
)
|
||||
|
||||
if ns_parser:
|
||||
terramoney_fcd_view.display_account_growth(
|
||||
kind=ns_parser.kind,
|
||||
export=ns_parser.export,
|
||||
cumulative=ns_parser.cumulative,
|
||||
top=ns_parser.limit,
|
||||
)
|
||||
|
||||
def call_sratio(self, other_args: List[str]):
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
prog="sratio",
|
||||
description="""
|
||||
Displays terra blockchain staking ratio history.
|
||||
[Source: https://fcd.terra.dev/swagger]
|
||||
""",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-l",
|
||||
"--limit",
|
||||
dest="limit",
|
||||
type=check_positive,
|
||||
help="Number of days to show",
|
||||
default=90,
|
||||
)
|
||||
|
||||
ns_parser = parse_known_args_and_warn(
|
||||
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
|
||||
)
|
||||
|
||||
if ns_parser:
|
||||
terramoney_fcd_view.display_staking_ratio_history(
|
||||
export=ns_parser.export, top=ns_parser.limit
|
||||
)
|
||||
|
||||
def call_sreturn(self, other_args: List[str]):
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
prog="sreturn",
|
||||
description="""
|
||||
Displays terra blockchain staking returns history.
|
||||
[Source: https://fcd.terra.dev/swagger]
|
||||
""",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-l",
|
||||
"--limit",
|
||||
dest="limit",
|
||||
type=check_positive,
|
||||
help="Number of days to show",
|
||||
default=90,
|
||||
)
|
||||
|
||||
ns_parser = parse_known_args_and_warn(
|
||||
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
|
||||
)
|
||||
|
||||
if ns_parser:
|
||||
terramoney_fcd_view.display_staking_returns_history(
|
||||
export=ns_parser.export, top=ns_parser.limit
|
||||
)
|
||||
|
||||
def call_dpi(self, other_args: List[str]):
|
||||
"""Process dpi command"""
|
||||
parser = argparse.ArgumentParser(
|
||||
|
||||
273
gamestonk_terminal/cryptocurrency/defi/terramoney_fcd_model.py
Normal file
273
gamestonk_terminal/cryptocurrency/defi/terramoney_fcd_model.py
Normal file
@@ -0,0 +1,273 @@
|
||||
"""Terra Money FCD model"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import textwrap
|
||||
from typing import Any, Tuple
|
||||
from datetime import datetime
|
||||
import requests
|
||||
import pandas as pd
|
||||
from gamestonk_terminal.cryptocurrency.dataframe_helpers import (
|
||||
denominate_number,
|
||||
prettify_column_names,
|
||||
replace_unicode,
|
||||
)
|
||||
|
||||
GOV_COLUMNS = [
|
||||
"submitTime",
|
||||
"id",
|
||||
"depositEndTime",
|
||||
"status",
|
||||
"type",
|
||||
"title",
|
||||
"Yes",
|
||||
"No",
|
||||
]
|
||||
GOV_STATUSES = ["voting", "deposit", "passed", "rejected", "all"]
|
||||
VALIDATORS_COLUMNS = [
|
||||
"validatorName",
|
||||
"tokensAmount",
|
||||
"votingPower",
|
||||
"commissionRate",
|
||||
"status",
|
||||
"uptime",
|
||||
]
|
||||
|
||||
|
||||
def _make_request(endpoint: str) -> dict:
|
||||
"""Helper method handles terra fcd api requests. [Source: https://fcd.terra.dev/v1]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
endpoint: str
|
||||
endpoint url
|
||||
Returns
|
||||
-------
|
||||
dict:
|
||||
dictionary with response data
|
||||
"""
|
||||
|
||||
url = f"https://fcd.terra.dev/v1/{endpoint}"
|
||||
response = requests.get(
|
||||
url, headers={"Accept": "application/json", "User-Agent": "GST"}
|
||||
)
|
||||
if not 200 <= response.status_code < 300:
|
||||
raise Exception(f"fcd terra api exception: {response.text}")
|
||||
try:
|
||||
return response.json()
|
||||
except Exception as e:
|
||||
raise ValueError(f"Invalid Response: {response.text}") from e
|
||||
|
||||
|
||||
def _adjust_delegation_info(delegation: dict) -> dict:
|
||||
"""Helper method which removes redundant fields from delegation info dictionary,
|
||||
and denominate value fields. [Source: https://fcd.terra.dev/v1]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
delegation:
|
||||
dictionary object with delegation data e.g.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict
|
||||
adjusted dictionary with delegation data
|
||||
"""
|
||||
|
||||
delegation_info = {}
|
||||
for key, value in delegation.items():
|
||||
if key in ["amountDelegated", "totalReward"]:
|
||||
delegation_info[key] = denominate_number(value)
|
||||
elif key in ["validatorAddress", "rewards"]:
|
||||
continue
|
||||
else:
|
||||
delegation_info[key] = value
|
||||
return delegation_info
|
||||
|
||||
|
||||
def get_staking_account_info(address: str = "") -> Tuple[pd.DataFrame, str]:
|
||||
"""Get staking info for provided terra account [Source: https://fcd.terra.dev/swagger]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
address: str
|
||||
terra blockchain address e.g. terra1jvwelvs7rdk6j3mqdztq5tya99w8lxk6l9hcqg
|
||||
Returns
|
||||
-------
|
||||
Tuple[pd.DataFrame, str]:
|
||||
luna delegations and summary report for given address
|
||||
"""
|
||||
|
||||
response = _make_request(f"staking/{address}")
|
||||
results: dict[str, Any] = {"myDelegations": []}
|
||||
|
||||
for field in ["availableLuna", "delegationTotal"]:
|
||||
results[field] = denominate_number(response.get(field, 0))
|
||||
|
||||
my_delegations = response.get("myDelegations")
|
||||
if my_delegations:
|
||||
for delegation in my_delegations:
|
||||
validator = _adjust_delegation_info(delegation)
|
||||
results["myDelegations"].append(validator)
|
||||
|
||||
df = pd.DataFrame(results["myDelegations"])
|
||||
|
||||
try:
|
||||
df["validatorName"] = df["validatorName"].apply(lambda x: replace_unicode(x))
|
||||
df.columns = prettify_column_names(list(df.columns))
|
||||
except KeyError:
|
||||
df = pd.DataFrame()
|
||||
|
||||
results["totalRewards"] = denominate_number(
|
||||
response.get("rewards", {}).get("total", 0)
|
||||
)
|
||||
|
||||
report = f"""Overview:
|
||||
Address: {address}
|
||||
Available Luna: {results['availableLuna']}
|
||||
Delegated Luna: {results['delegationTotal']}
|
||||
Total Rewards: {results['totalRewards']}\n"""
|
||||
report += "\nDelegations: " if not df.empty else "\nNo delegations found\n"
|
||||
|
||||
return df, report
|
||||
|
||||
|
||||
def get_validators() -> pd.DataFrame:
|
||||
"""Get information about terra validators [Source: https://fcd.terra.dev/swagger]
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
terra validators details
|
||||
"""
|
||||
|
||||
response = _make_request("staking")["validators"]
|
||||
results = []
|
||||
for validator in response:
|
||||
results.append(
|
||||
{
|
||||
"accountAddress": validator["accountAddress"],
|
||||
"validatorName": validator["description"].get("moniker"),
|
||||
"tokensAmount": denominate_number(validator["tokens"]),
|
||||
"votingPower": round(
|
||||
(float(validator["votingPower"].get("weight")) * 100), 2
|
||||
),
|
||||
"commissionRate": round(
|
||||
(float(validator["commissionInfo"].get("rate", 0)) * 100), 2
|
||||
),
|
||||
"status": validator["status"],
|
||||
"uptime": round((float(validator.get("upTime", 0)) * 100), 2),
|
||||
}
|
||||
)
|
||||
|
||||
return pd.DataFrame(results).sort_values(by="votingPower")
|
||||
|
||||
|
||||
def get_proposals(status: str = "") -> pd.DataFrame:
|
||||
"""Get terra blockchain governance proposals list [Source: https://fcd.terra.dev/swagger]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
status: str
|
||||
status of proposal, one from list: ['Voting','Deposit','Passed','Rejected']
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
Terra blockchain governance proposals list
|
||||
"""
|
||||
|
||||
statuses = ["Voting", "Deposit", "Passed", "Rejected"]
|
||||
response = _make_request("gov/proposals")["proposals"]
|
||||
results = []
|
||||
votes_options = ["Yes", "Abstain", "No", "NoWithVeto"]
|
||||
for proposal in response:
|
||||
deposit = proposal.pop("deposit")
|
||||
proposal["depositEndTime"] = deposit.get("depositEndTime")
|
||||
vote = proposal.pop("vote")
|
||||
proposal.pop("proposer")
|
||||
for opt in votes_options:
|
||||
proposal[opt] = vote["count"].get(opt)
|
||||
|
||||
results.append(proposal)
|
||||
columns = [
|
||||
"id",
|
||||
"submitTime",
|
||||
"depositEndTime",
|
||||
"status",
|
||||
"type",
|
||||
"title",
|
||||
"Yes",
|
||||
"No",
|
||||
"Abstain",
|
||||
"NoWithVeto",
|
||||
]
|
||||
df = pd.DataFrame(results)[columns]
|
||||
df[["id", "Yes", "No", "Abstain", "NoWithVeto"]] = df[
|
||||
["id", "Yes", "No", "Abstain", "NoWithVeto"]
|
||||
].astype(int, errors="ignore")
|
||||
df["title"] = df["title"].apply(
|
||||
lambda x: "\n".join(textwrap.wrap(x, width=40)) if isinstance(x, str) else x
|
||||
)
|
||||
|
||||
for col in ["submitTime", "depositEndTime"]:
|
||||
df[col] = df[col].apply(lambda x: pd.to_datetime(x).strftime("%Y-%m-%d %H:%M"))
|
||||
|
||||
if status.title() in statuses:
|
||||
df = df[df["status"] == status.title()]
|
||||
return df
|
||||
|
||||
|
||||
def get_account_growth(cumulative: bool = True) -> pd.DataFrame:
|
||||
"""Get terra blockchain account growth history [Source: https://fcd.terra.dev/swagger]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
cumulative: bool
|
||||
distinguish between periodical and cumulative account growth data
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
historical data of accounts growth
|
||||
"""
|
||||
|
||||
response = _make_request("dashboard/account_growth")
|
||||
kind = "cumulative" if cumulative else "periodic"
|
||||
df = pd.DataFrame(response[kind])
|
||||
df["date"] = df["datetime"].apply(lambda x: datetime.fromtimestamp(x / 1000).date())
|
||||
df = df[["date", "totalAccountCount", "activeAccountCount"]]
|
||||
df.columns = ["date", "Total accounts", "Active accounts"]
|
||||
return df
|
||||
|
||||
|
||||
def get_staking_ratio_history():
|
||||
"""Get terra blockchain staking ratio history [Source: https://fcd.terra.dev/swagger]
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
historical staking ratio
|
||||
"""
|
||||
|
||||
response = _make_request("dashboard/staking_ratio")
|
||||
df = pd.DataFrame(response)
|
||||
df["date"] = df["datetime"].apply(lambda x: datetime.fromtimestamp(x / 1000).date())
|
||||
df["stakingRatio"] = df["stakingRatio"].apply(lambda x: round(float(x) * 100, 2))
|
||||
return df[["date", "stakingRatio"]]
|
||||
|
||||
|
||||
def get_staking_returns_history():
|
||||
"""Get terra blockchain staking returns history [Source: https://fcd.terra.dev/v1]
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
historical staking returns
|
||||
"""
|
||||
|
||||
response = _make_request("dashboard/staking_return")
|
||||
df = pd.DataFrame(response)
|
||||
df["date"] = df["datetime"].apply(lambda x: datetime.fromtimestamp(x / 1000).date())
|
||||
df["annualizedReturn"] = df["annualizedReturn"].apply(
|
||||
lambda x: round(float(x) * 100, 2)
|
||||
)
|
||||
return df[["date", "annualizedReturn"]]
|
||||
299
gamestonk_terminal/cryptocurrency/defi/terramoney_fcd_view.py
Normal file
299
gamestonk_terminal/cryptocurrency/defi/terramoney_fcd_view.py
Normal file
@@ -0,0 +1,299 @@
|
||||
"""Terra Money FCD view"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import os
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib import ticker, dates as mdates
|
||||
from gamestonk_terminal.cryptocurrency.defi import terramoney_fcd_model
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
export_data,
|
||||
long_number_format,
|
||||
plot_autoscale,
|
||||
rich_table_from_df,
|
||||
)
|
||||
from gamestonk_terminal.cryptocurrency.dataframe_helpers import (
|
||||
prettify_column_names,
|
||||
very_long_number_formatter,
|
||||
)
|
||||
from gamestonk_terminal import feature_flags as gtff
|
||||
from gamestonk_terminal.config_plot import PLOT_DPI
|
||||
from gamestonk_terminal.rich_config import console
|
||||
|
||||
|
||||
def display_account_staking_info(
|
||||
address: str = "", top: int = 10, export: str = ""
|
||||
) -> None:
|
||||
"""Display staking info for provided terra account address [Source: https://fcd.terra.dev/swagger]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
address: str
|
||||
terra blockchain address e.g. terra1jvwelvs7rdk6j3mqdztq5tya99w8lxk6l9hcqg
|
||||
top: int
|
||||
Number of records to display
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df, report = terramoney_fcd_model.get_staking_account_info(address)
|
||||
console.print(report)
|
||||
if not df.empty:
|
||||
if gtff.USE_TABULATE_DF:
|
||||
console.print(
|
||||
rich_table_from_df(
|
||||
df.head(top),
|
||||
headers=list(df.columns),
|
||||
floatfmt=".2f",
|
||||
show_index=False,
|
||||
),
|
||||
"\n",
|
||||
)
|
||||
else:
|
||||
console.print(df.to_string, "\n")
|
||||
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"sinfo",
|
||||
df,
|
||||
)
|
||||
|
||||
|
||||
def display_validators(
|
||||
top: int = 10, sortby: str = "votingPower", descend: bool = False, export: str = ""
|
||||
) -> None:
|
||||
"""Display information about terra validators [Source: https://fcd.terra.dev/swagger]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
top: int
|
||||
Number of records to display
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
descend: bool
|
||||
Flag to sort data descending
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = terramoney_fcd_model.get_validators()
|
||||
df_data = df.copy()
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
df["tokensAmount"] = df["tokensAmount"].apply(
|
||||
lambda x: very_long_number_formatter(x)
|
||||
)
|
||||
df.columns = [
|
||||
x if x not in ["Voting power", "Commission rate", "Uptime"] else f"{x} %"
|
||||
for x in prettify_column_names(df.columns)
|
||||
]
|
||||
|
||||
if gtff.USE_TABULATE_DF:
|
||||
console.print(
|
||||
rich_table_from_df(
|
||||
df.head(top),
|
||||
headers=list(df.columns),
|
||||
floatfmt=".2f",
|
||||
show_index=False,
|
||||
),
|
||||
"\n",
|
||||
)
|
||||
else:
|
||||
console.print(df.to_string, "\n")
|
||||
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"validators",
|
||||
df_data,
|
||||
)
|
||||
|
||||
|
||||
def display_gov_proposals(
|
||||
top: int = 10,
|
||||
status: str = "all",
|
||||
sortby: str = "id",
|
||||
descend: bool = False,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Display terra blockchain governance proposals list [Source: https://fcd.terra.dev/swagger]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
top: int
|
||||
Number of records to display
|
||||
status: str
|
||||
status of proposal, one from list: ['Voting','Deposit','Passed','Rejected']
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
descend: bool
|
||||
Flag to sort data descending
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = terramoney_fcd_model.get_proposals(status)
|
||||
df_data = df.copy()
|
||||
df = df.sort_values(by=sortby, ascending=descend).head(top)
|
||||
df.columns = prettify_column_names(df.columns)
|
||||
|
||||
if gtff.USE_TABULATE_DF:
|
||||
console.print(
|
||||
rich_table_from_df(
|
||||
df,
|
||||
headers=list(df.columns),
|
||||
floatfmt=".2f",
|
||||
show_index=False,
|
||||
),
|
||||
"\n",
|
||||
)
|
||||
else:
|
||||
console.print(df.to_string, "\n")
|
||||
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"govp",
|
||||
df_data,
|
||||
)
|
||||
|
||||
|
||||
def display_account_growth(
|
||||
kind: str = "total", cumulative: bool = False, top: int = 90, export: str = ""
|
||||
) -> None:
|
||||
"""Display terra blockchain account growth history [Source: https://fcd.terra.dev/swagger]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
top: int
|
||||
Number of records to display
|
||||
kind: str
|
||||
display total account count or active account count. One from list [active, total]
|
||||
cumulative: bool
|
||||
Flag to show cumulative or discrete values. For active accounts only discrete value are available.
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = terramoney_fcd_model.get_account_growth(cumulative)
|
||||
if kind not in ["active", "total"]:
|
||||
kind = "total"
|
||||
options = {"total": "Total accounts", "active": "Active accounts"}
|
||||
|
||||
opt = options[kind]
|
||||
label = "Cumulative" if cumulative and opt == "total" else "Daily"
|
||||
|
||||
fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
|
||||
df = df.sort_values("date", ascending=False).head(top)
|
||||
df = df.set_index("date")
|
||||
|
||||
start, end = df.index[-1], df.index[0]
|
||||
if cumulative:
|
||||
ax.plot(df[opt], label=df[opt])
|
||||
else:
|
||||
ax.bar(x=df.index, height=df[opt], label=df[opt])
|
||||
|
||||
ax.set_ylabel(f"{opt}")
|
||||
ax.set_xlabel("Date")
|
||||
dateFmt = mdates.DateFormatter("%m/%d/%Y")
|
||||
ax.xaxis.set_major_formatter(dateFmt)
|
||||
|
||||
ax.get_yaxis().set_major_formatter(
|
||||
ticker.FuncFormatter(lambda x, _: long_number_format(x))
|
||||
)
|
||||
fig.tight_layout(pad=8)
|
||||
ax.set_title(f"{label} number of {opt.lower()} in period from {start} to {end}")
|
||||
ax.grid(alpha=0.5)
|
||||
ax.tick_params(axis="x", labelrotation=45)
|
||||
if gtff.USE_ION:
|
||||
plt.ion()
|
||||
plt.show()
|
||||
print("")
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"gacc",
|
||||
df,
|
||||
)
|
||||
|
||||
|
||||
def display_staking_ratio_history(top: int = 90, export: str = "") -> None:
|
||||
"""Display terra blockchain staking ratio history [Source: https://fcd.terra.dev/v1]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
top: int
|
||||
Number of records to display
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = terramoney_fcd_model.get_staking_ratio_history()
|
||||
|
||||
fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
df = df.sort_values("date", ascending=False).head(top)
|
||||
df = df.set_index("date")
|
||||
|
||||
start, end = df.index[-1], df.index[0]
|
||||
|
||||
ax.plot(df, label=df["stakingRatio"])
|
||||
ax.set_ylabel("Staking ratio [%]")
|
||||
ax.set_xlabel("Date")
|
||||
dateFmt = mdates.DateFormatter("%m/%d/%Y")
|
||||
ax.xaxis.set_major_formatter(dateFmt)
|
||||
|
||||
fig.tight_layout(pad=8)
|
||||
ax.set_title(f"Staking ratio in period from {start} to {end}")
|
||||
ax.grid(alpha=0.5)
|
||||
ax.tick_params(axis="x", labelrotation=45)
|
||||
if gtff.USE_ION:
|
||||
plt.ion()
|
||||
plt.show()
|
||||
print("")
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"sratio",
|
||||
df,
|
||||
)
|
||||
|
||||
|
||||
def display_staking_returns_history(top: int = 90, export: str = "") -> None:
|
||||
"""Display terra blockchain staking returns history [Source: https://fcd.terra.dev/swagger]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
top: int
|
||||
Number of records to display
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = terramoney_fcd_model.get_staking_returns_history()
|
||||
|
||||
fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
df = df.sort_values("date", ascending=False).head(top)
|
||||
df = df.set_index("date")
|
||||
|
||||
start, end = df.index[-1], df.index[0]
|
||||
|
||||
ax.plot(df, label=df["annualizedReturn"])
|
||||
ax.set_ylabel("Staking returns [%]")
|
||||
ax.set_xlabel("Date")
|
||||
dateFmt = mdates.DateFormatter("%m/%d/%Y")
|
||||
ax.xaxis.set_major_formatter(dateFmt)
|
||||
|
||||
fig.tight_layout(pad=8)
|
||||
ax.set_title(f"Staking returns in period from {start} to {end}")
|
||||
ax.grid(alpha=0.5)
|
||||
ax.tick_params(axis="x", labelrotation=45)
|
||||
if gtff.USE_ION:
|
||||
plt.ion()
|
||||
plt.show()
|
||||
print("")
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"sreturn",
|
||||
df,
|
||||
)
|
||||
@@ -161,6 +161,27 @@ def check_non_negative(value) -> int:
|
||||
return new_value
|
||||
|
||||
|
||||
def check_terra_address_format(address: str) -> str:
|
||||
"""Validate if terra account address has proper format: ^terra1[a-z0-9]{38}$
|
||||
|
||||
Parameters
|
||||
----------
|
||||
address: str
|
||||
terra blockchain account address
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
Terra blockchain address or raise argparse exception
|
||||
"""
|
||||
|
||||
pattern = re.compile(r"^terra1[a-z0-9]{38}$")
|
||||
if not pattern.match(address):
|
||||
raise argparse.ArgumentTypeError(
|
||||
f"Terra address: {address} has invalid format. Valid format: ^terra1[a-z0-9]{{38}}$"
|
||||
)
|
||||
return address
|
||||
|
||||
|
||||
def check_non_negative_float(value) -> float:
|
||||
"""Argparse type to check non negative int"""
|
||||
new_value = float(value)
|
||||
|
||||
17
website/content/cryptocurrency/defi/gacc/_index.md
vendored
Normal file
17
website/content/cryptocurrency/defi/gacc/_index.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
```
|
||||
usage: gacc [-l LIMIT] [--cumulative] [-k {active,total}] [--descend] [-h] [--export {csv,json,xlsx}]
|
||||
```
|
||||
Displays terra blockchain account growth history. [Source: https://fcd.terra.dev/swagger]
|
||||
|
||||
```
|
||||
optional arguments:
|
||||
-l LIMIT, --limit LIMIT
|
||||
Number of days to show (default: 90)
|
||||
--cumulative Show cumulative or discrete values. For active accounts only discrete value are available (default: True)
|
||||
-k {active,total}, --kind {active,total}
|
||||
Total account count or active account count. Default: total (default: total)
|
||||
--descend Flag to sort in descending order (lowest first) (default: False)
|
||||
-h, --help show this help message (default: False)
|
||||
--export {csv,json,xlsx}
|
||||
Export raw data into csv, json, xlsx (default: )
|
||||
```
|
||||
17
website/content/cryptocurrency/defi/govp/_index.md
vendored
Normal file
17
website/content/cryptocurrency/defi/govp/_index.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
```
|
||||
usage: govp [-l LIMIT] [-s {submitTime,id,depositEndTime,status,type,title,Yes,No}] [--status {voting,deposit,passed,rejected,all}] [--descend] [-h] [--export {csv,json,xlsx}]
|
||||
```
|
||||
Displays terra blockchain governance proposals list. [Source: https://fcd.terra.dev/swagger]
|
||||
```
|
||||
optional arguments:
|
||||
-l LIMIT, --limit LIMIT
|
||||
Number of proposals to show (default: 10)
|
||||
-s {submitTime,id,depositEndTime,status,type,title,Yes,No}, --sort {submitTime,id,depositEndTime,status,type,title,Yes,No}
|
||||
Sort by given column. Default: id (default: id)
|
||||
--status {voting,deposit,passed,rejected,all}
|
||||
Status of proposal. Default: all (default: all)
|
||||
--descend Flag to sort in descending order (lowest first) (default: False)
|
||||
-h, --help show this help message (default: False)
|
||||
--export {csv,json,xlsx}
|
||||
Export raw data into csv, json, xlsx (default: )
|
||||
```
|
||||
15
website/content/cryptocurrency/defi/sinfo/_index.md
vendored
Normal file
15
website/content/cryptocurrency/defi/sinfo/_index.md
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
```
|
||||
usage: sinfo [-a ADDRESS] [-l LIMIT] [-h] [--export {csv,json,xlsx}]
|
||||
```
|
||||
Displays staking info of a certain terra address. [Source: https://fcd.terra.dev/swagger]
|
||||
|
||||
```
|
||||
optional arguments:
|
||||
-a ADDRESS, --address ADDRESS
|
||||
Terra address. Valid terra addresses start with 'terra' (default: None)
|
||||
-l LIMIT, --limit LIMIT
|
||||
Number of delegations (default: 10)
|
||||
-h, --help show this help message (default: False)
|
||||
--export {csv,json,xlsx}
|
||||
Export raw data into csv, json, xlsx (default: )
|
||||
```
|
||||
12
website/content/cryptocurrency/defi/sratio/_index.md
vendored
Normal file
12
website/content/cryptocurrency/defi/sratio/_index.md
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
```
|
||||
usage: sratio [-l LIMIT] [-h] [--export {csv,json,xlsx}]
|
||||
```
|
||||
Displays terra blockchain staking ratio history. [Source: https://fcd.terra.dev/swagger]
|
||||
```
|
||||
optional arguments:
|
||||
-l LIMIT, --limit LIMIT
|
||||
Number of days to show (default: 90)
|
||||
-h, --help show this help message (default: False)
|
||||
--export {csv,json,xlsx}
|
||||
Export raw data into csv, json, xlsx (default: )
|
||||
```
|
||||
13
website/content/cryptocurrency/defi/sreturn/_index.md
vendored
Normal file
13
website/content/cryptocurrency/defi/sreturn/_index.md
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
```
|
||||
usage: sreturn [-l LIMIT] [-h] [--export {csv,json,xlsx}]
|
||||
```
|
||||
Displays terra blockchain staking returns history. [Source: https://fcd.terra.dev/swagger]
|
||||
|
||||
```
|
||||
optional arguments:
|
||||
-l LIMIT, --limit LIMIT
|
||||
Number of days to show (default: 90)
|
||||
-h, --help show this help message (default: False)
|
||||
--export {csv,json,xlsx}
|
||||
Export raw data into csv, json, xlsx (default: )
|
||||
```
|
||||
16
website/content/cryptocurrency/defi/validators/_index.md
vendored
Normal file
16
website/content/cryptocurrency/defi/validators/_index.md
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
```
|
||||
usage: validators [-l LIMIT] [-s {validatorName,tokensAmount,votingPower,commissionRate,status,uptime}] [--descend] [-h] [--export {csv,json,xlsx}]
|
||||
```
|
||||
Displays information about terra validators. [Source: https://fcd.terra.dev/swagger]
|
||||
|
||||
```
|
||||
optional arguments:
|
||||
-l LIMIT, --limit LIMIT
|
||||
Number of validators to show (default: 10)
|
||||
-s {validatorName,tokensAmount,votingPower,commissionRate,status,uptime}, --sort {validatorName,tokensAmount,votingPower,commissionRate,status,uptime}
|
||||
Sort by given column. Default: votingPower (default: votingPower)
|
||||
--descend Flag to sort in descending order (lowest first) (default: False)
|
||||
-h, --help show this help message (default: False)
|
||||
--export {csv,json,xlsx}
|
||||
Export raw data into csv, json, xlsx (default: )
|
||||
```
|
||||
12
website/data/menu/main.yml
vendored
12
website/data/menu/main.yml
vendored
@@ -903,6 +903,18 @@ main:
|
||||
ref: "/cryptocurrency/defi/pools"
|
||||
- name: swaps
|
||||
ref: "/cryptocurrency/defi/swaps"
|
||||
- name: sinfo
|
||||
ref: "/cryptocurrency/defi/sinfo"
|
||||
- name: govp
|
||||
ref: "/cryptocurrency/defi/govp"
|
||||
- name: gacc
|
||||
ref: "/cryptocurrency/defi/gacc"
|
||||
- name: validators
|
||||
ref: "/cryptocurrency/defi/validators"
|
||||
- name: sratio
|
||||
ref: "/cryptocurrency/defi/sratio"
|
||||
- name: sreturn
|
||||
ref: "/cryptocurrency/defi/sreturn"
|
||||
- name: economy
|
||||
ref: "/economy"
|
||||
sub:
|
||||
|
||||
Reference in New Issue
Block a user