mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-11-01 23:12:21 +00:00
* implement user and change is guest * replace User methods * move remaining functions to user * fix bug * portfolio test * fix tests * fix tests * uncomment skip * ruff * start credentials model implementation * change deault structure * refacto quandl * change default struct and file names * bug * start using global user * add comments * move update flair * change cfg references in keys model * reddit & fmp * refactore additional keys * remaing config keys * remove unsude imports and fix hub keys * ruff * fix line too long * unblock unittests * fix keys model tests * remove os patch * fix account controller tests * fix account controller tests * fix account model * account fixed * fix user tests * User Model * User Model * User Model * Move session folder * User Model : grouping the models * User Model : fix bugs * Config Plot + bug fix * User Model : Refactoring plots * Feature flags * Remove dup * clean comments a fix some vars * fix feature flags controller * refactor obbff from settings controller * refactor a bunch of obbff variables * fix bug blocking terminal * fix integration tests * refactor controllers with obbff * refactor remaining ffs * remove comments * log not started * mispelled variable * set current user on local model * User Model : moving files + updating * User Preferences * User : Refactor is_guest function + bug fix * User : refactor is_guest function * Fix conftest.py * remove lost obbffs * typo on fileoverwrite * Plot config: move variables and start plot dpi * User : tests * refactor plot dpi references * remove plot dpi imports * refactor some config terminal leftover * /account/sync : fix bug * remove configs reload * start path refactor * installation paths vs user paths * remove cfg_plot * Tests : User Refactoring * user prefix only for preferences * user prefix only for preferences * move user paths * remove comment * update apply remote configs * fix tz not updating * save some copys * small fix * create interface for credentials and preferences * wrong docstrings fixed * ruff core * fix some pref setting * login is better * ruff * ruff * remove Literal * add small comment * Tests : User Refactoring * Credentials Model : add DataBento * Fix helper_funcs * Fixing code * Tests : fixing * User Model : freezing the models * Fixed Income + Databento * Tests : fixing keys * black * ruff * Tests : user model * Tests : user model * Fix linting * Fix linting * Linting * Linting * Fixing code and tests * Fix tests * mypy * SDK * Clean ruff cache * Fix syntax issue * Update fred_view * Black * Linting * Update code * Update tests * Linting * Linting * Tests * Black * Linting * Linting * Mock os.listdir to avoid looking for file that doesnt exist * Mock options paths * lint * Tests : fix * Code : update * Tests + Linting * Tests * Ruff * Code : update * Tests * Code : update * Fix workflow * Code : update --------- Co-authored-by: Chavithra PARANA <chavithra@gmail.com> Co-authored-by: luqazino@gmail.com <luqazino@gmail.com> Co-authored-by: James Maslek <jmaslek11@gmail.com>
779 lines
24 KiB
Python
779 lines
24 KiB
Python
"""Messari model"""
|
|
__docformat__ = "numpy"
|
|
# flake8: noqa
|
|
# pylint: disable=C0301,C0302
|
|
|
|
import logging
|
|
import re
|
|
from datetime import datetime, timedelta
|
|
from typing import Any, Optional, Tuple
|
|
|
|
import pandas as pd
|
|
|
|
from openbb_terminal.cryptocurrency.dataframe_helpers import (
|
|
lambda_replace_underscores_in_column_names,
|
|
prettify_column_names,
|
|
)
|
|
from openbb_terminal.cryptocurrency.due_diligence.pycoingecko_model import (
|
|
get_coin_tokenomics,
|
|
)
|
|
from openbb_terminal.decorators import check_api_key, log_start_end
|
|
from openbb_terminal.helper_funcs import lambda_long_number_format, request
|
|
from openbb_terminal.rich_config import console
|
|
from openbb_terminal.core.session.current_user import get_current_user
|
|
|
|
# pylint: disable=unsupported-assignment-operation
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
INTERVALS_TIMESERIES = ["5m", "15m", "30m", "1h", "1d", "1w"]
|
|
# pylint: disable=unsupported-assignment-operation
|
|
|
|
|
|
@log_start_end(log=logger)
|
|
def get_available_timeseries(only_free: bool = True) -> pd.DataFrame:
|
|
"""Returns available messari timeseries
|
|
[Source: https://messari.io/]
|
|
|
|
Parameters
|
|
----------
|
|
only_free : bool
|
|
Display only timeseries available for free
|
|
|
|
Returns
|
|
-------
|
|
pd.DataFrame
|
|
available timeseries
|
|
"""
|
|
r = request("https://data.messari.io/api/v1/assets/metrics")
|
|
if r.status_code == 200:
|
|
data = r.json()
|
|
metrics = data["data"]["metrics"]
|
|
arr = []
|
|
for metric in metrics:
|
|
sources = ""
|
|
for source in metric["source_attribution"]:
|
|
sources += source["name"]
|
|
sources += ","
|
|
sources = sources.rstrip(",")
|
|
arr.append(
|
|
{
|
|
"id": metric["metric_id"],
|
|
"Title": metric["name"],
|
|
"Description": metric["description"],
|
|
"Requires Paid Key": "role_restriction" in metric,
|
|
"Sources": sources,
|
|
}
|
|
)
|
|
df = pd.DataFrame(arr)
|
|
df.set_index("id", inplace=True)
|
|
if only_free:
|
|
df = df.drop(df[df["Requires Paid Key"]].index)
|
|
return df
|
|
return pd.DataFrame()
|
|
|
|
|
|
base_url = "https://data.messari.io/api/v1/"
|
|
base_url2 = "https://data.messari.io/api/v2/"
|
|
|
|
|
|
@log_start_end(log=logger)
|
|
def get_marketcap_dominance(
|
|
symbol: str,
|
|
interval: str = "1d",
|
|
start_date: Optional[str] = None,
|
|
end_date: Optional[str] = None,
|
|
) -> pd.DataFrame:
|
|
"""Returns market dominance of a coin over time
|
|
[Source: https://messari.io/]
|
|
|
|
Parameters
|
|
----------
|
|
symbol : str
|
|
Crypto symbol to check market cap dominance
|
|
interval : str
|
|
Interval frequency (possible values are: 5m, 15m, 30m, 1h, 1d, 1w)
|
|
start_date : Optional[str]
|
|
Initial date like string (e.g., 2021-10-01)
|
|
end_date : Optional[str]
|
|
End date like string (e.g., 2021-10-01)
|
|
|
|
Returns
|
|
-------
|
|
pd.DataFrame
|
|
market dominance percentage over time
|
|
|
|
Examples
|
|
--------
|
|
>>> from openbb_terminal.sdk import openbb
|
|
>>> mcapdom_df = openbb.crypto.dd.mcapdom(symbol="BTC")
|
|
"""
|
|
|
|
if start_date is None:
|
|
start_date = (datetime.now() - timedelta(days=365)).strftime("%Y-%m-%d")
|
|
|
|
if end_date is None:
|
|
end_date = datetime.now().strftime("%Y-%m-%d")
|
|
|
|
messari_timeseries = get_messari_timeseries(
|
|
symbol=symbol,
|
|
end_date=end_date,
|
|
start_date=start_date,
|
|
interval=interval,
|
|
timeseries_id="mcap.dom",
|
|
)
|
|
df, _ = messari_timeseries if messari_timeseries else (pd.DataFrame(), "")
|
|
return df
|
|
|
|
|
|
@log_start_end(log=logger)
|
|
@check_api_key(["API_MESSARI_KEY"])
|
|
def get_messari_timeseries(
|
|
symbol: str,
|
|
timeseries_id: str,
|
|
interval: str = "1d",
|
|
start_date: Optional[str] = None,
|
|
end_date: Optional[str] = None,
|
|
) -> Tuple[pd.DataFrame, str]:
|
|
"""Returns messari timeseries
|
|
[Source: https://messari.io/]
|
|
|
|
Parameters
|
|
----------
|
|
symbol : str
|
|
Crypto symbol to check messari timeseries
|
|
timeseries_id : str
|
|
Messari timeserie id
|
|
interval : str
|
|
Interval frequency (possible values are: 5m, 15m, 30m, 1h, 1d, 1w)
|
|
start : Optional[str]
|
|
Initial date like string (e.g., 2021-10-01)
|
|
end : Optional[str]
|
|
End date like string (e.g., 2021-10-01)
|
|
|
|
Returns
|
|
-------
|
|
Tuple[pd.DataFrame, str]
|
|
Messari timeseries over time,
|
|
Timeseries title
|
|
"""
|
|
|
|
if start_date is None:
|
|
start_date = (datetime.now() - timedelta(days=365)).strftime("%Y-%m-%d")
|
|
|
|
if end_date is None:
|
|
end_date = datetime.now().strftime("%Y-%m-%d")
|
|
|
|
url = base_url + f"assets/{symbol}/metrics/{timeseries_id}/time-series"
|
|
|
|
headers = {"x-messari-api-key": get_current_user().credentials.API_MESSARI_KEY}
|
|
|
|
parameters = {
|
|
"start": start_date,
|
|
"end": end_date,
|
|
"interval": interval,
|
|
}
|
|
|
|
r = request(url, params=parameters, headers=headers)
|
|
|
|
df = pd.DataFrame()
|
|
title = ""
|
|
|
|
if r.status_code == 200:
|
|
data = r.json()["data"]
|
|
title = data["schema"]["name"]
|
|
df = pd.DataFrame(data["values"], columns=data["parameters"]["columns"])
|
|
|
|
if df.empty:
|
|
console.print(f"No data found for {symbol}.\n")
|
|
else:
|
|
df = df.set_index("timestamp")
|
|
df.index = pd.to_datetime(df.index, unit="ms")
|
|
elif r.status_code == 401:
|
|
if "requires a pro or enterprise subscription" in r.text:
|
|
console.print("[red]API Key not authorized for Premium Feature[/red]\n")
|
|
else:
|
|
console.print("[red]Invalid API Key[/red]\n")
|
|
else:
|
|
console.print(r.text)
|
|
return df, title
|
|
|
|
|
|
@log_start_end(log=logger)
|
|
@check_api_key(["API_MESSARI_KEY"])
|
|
def get_links(symbol: str) -> pd.DataFrame:
|
|
"""Returns asset's links
|
|
[Source: https://messari.io/]
|
|
|
|
Parameters
|
|
----------
|
|
symbol : str
|
|
Crypto symbol to check links
|
|
|
|
Returns
|
|
-------
|
|
pd.DataFrame
|
|
asset links
|
|
"""
|
|
|
|
url = base_url2 + f"assets/{symbol}/profile"
|
|
|
|
headers = {"x-messari-api-key": get_current_user().credentials.API_MESSARI_KEY}
|
|
|
|
params = {"fields": "profile/general/overview/official_links"}
|
|
|
|
r = request(url, headers=headers, params=params)
|
|
|
|
df = pd.DataFrame()
|
|
|
|
if r.status_code == 200:
|
|
data = r.json()["data"]
|
|
df = pd.DataFrame(data["profile"]["general"]["overview"]["official_links"])
|
|
df.columns = map(str.capitalize, df.columns)
|
|
return df
|
|
if r.status_code == 401:
|
|
print("[red]Invalid API Key[/red]\n")
|
|
else:
|
|
print(r.text)
|
|
return pd.DataFrame()
|
|
|
|
|
|
@log_start_end(log=logger)
|
|
@check_api_key(["API_MESSARI_KEY"])
|
|
def get_roadmap(symbol: str, ascend: bool = True) -> pd.DataFrame:
|
|
"""Returns coin roadmap
|
|
[Source: https://messari.io/]
|
|
|
|
Parameters
|
|
----------
|
|
symbol : str
|
|
Crypto symbol to check roadmap
|
|
ascend: bool
|
|
reverse order
|
|
|
|
Returns
|
|
-------
|
|
pd.DataFrame
|
|
roadmap
|
|
"""
|
|
|
|
url = base_url2 + f"assets/{symbol}/profile"
|
|
|
|
headers = {"x-messari-api-key": get_current_user().credentials.API_MESSARI_KEY}
|
|
|
|
params = {"fields": "profile/general/roadmap"}
|
|
|
|
r = request(url, headers=headers, params=params)
|
|
|
|
df = pd.DataFrame()
|
|
|
|
if r.status_code == 200:
|
|
data = r.json()["data"]
|
|
df = pd.DataFrame(data["profile"]["general"]["roadmap"])
|
|
df["date"] = pd.to_datetime(df["date"])
|
|
df.columns = map(str.capitalize, df.columns)
|
|
df = df.dropna(axis=1, how="all")
|
|
df["Date"] = df["Date"].dt.date
|
|
show_df = df
|
|
show_df = show_df.sort_values(by="Date", ascending=ascend)
|
|
show_df.fillna("Unknown", inplace=True)
|
|
elif r.status_code == 401:
|
|
console.print("[red]Invalid API Key[/red]\n")
|
|
else:
|
|
console.print(r.text)
|
|
|
|
return df
|
|
|
|
|
|
@log_start_end(log=logger)
|
|
@check_api_key(["API_MESSARI_KEY"])
|
|
def get_tokenomics(symbol: str, coingecko_id: str) -> Tuple[pd.DataFrame, pd.DataFrame]:
|
|
"""Returns coin tokenomics
|
|
[Source: https://messari.io/]
|
|
|
|
Parameters
|
|
----------
|
|
symbol : str
|
|
Crypto symbol to check tokenomics
|
|
coingecko_id : str
|
|
ID from coingecko
|
|
|
|
Returns
|
|
-------
|
|
Tuple[pd.DataFrame, pd.DataFrame]
|
|
Metric Value tokenomics,
|
|
Circulating supply overtime
|
|
"""
|
|
|
|
url = base_url2 + f"assets/{symbol}/profile"
|
|
|
|
headers = {"x-messari-api-key": ""}
|
|
|
|
params = {"fields": "profile/economics/consensus_and_emission"}
|
|
|
|
r = request(url, headers=headers, params=params)
|
|
|
|
df = pd.DataFrame()
|
|
circ_df = pd.DataFrame()
|
|
if r.status_code == 200:
|
|
data = r.json()["data"]
|
|
tokenomics_data = data["profile"]["economics"]["consensus_and_emission"]
|
|
df = pd.DataFrame(
|
|
{
|
|
"Metric": [
|
|
"Emission Type",
|
|
"Consensus Mechanism",
|
|
"Consensus Details",
|
|
"Mining Algorithm",
|
|
"Block Reward",
|
|
],
|
|
"Value": [
|
|
tokenomics_data["supply"]["general_emission_type"],
|
|
tokenomics_data["consensus"]["general_consensus_mechanism"],
|
|
tokenomics_data["consensus"]["consensus_details"],
|
|
tokenomics_data["consensus"]["mining_algorithm"],
|
|
tokenomics_data["consensus"]["block_reward"],
|
|
],
|
|
}
|
|
)
|
|
df["Value"] = df["Value"].str.replace("n/a", "-")
|
|
cg_df = get_coin_tokenomics(coingecko_id)
|
|
df = pd.concat([df, cg_df], ignore_index=True, sort=False)
|
|
df.fillna("-", inplace=True)
|
|
circ_df, _ = get_messari_timeseries(
|
|
symbol=symbol,
|
|
timeseries_id="sply.circ",
|
|
interval="1d",
|
|
start_date="",
|
|
end_date="",
|
|
)
|
|
elif r.status_code == 401:
|
|
console.print("[red]Invalid API Key[/red]\n")
|
|
else:
|
|
console.print(r.text)
|
|
|
|
return df, circ_df
|
|
|
|
|
|
@log_start_end(log=logger)
|
|
@check_api_key(["API_MESSARI_KEY"])
|
|
def get_project_product_info(
|
|
symbol: str,
|
|
) -> Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame, pd.DataFrame]:
|
|
"""Returns coin product info
|
|
[Source: https://messari.io/]
|
|
|
|
Parameters
|
|
----------
|
|
symbol : str
|
|
Crypto symbol to check product info
|
|
|
|
Returns
|
|
-------
|
|
Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame, pd.DataFrame]
|
|
Metric, Value with project and technology details,
|
|
Coin public repos,
|
|
Coin audits,
|
|
Coin known exploits/vulns
|
|
"""
|
|
|
|
url = base_url2 + f"assets/{symbol}/profile"
|
|
|
|
headers = {"x-messari-api-key": ""}
|
|
|
|
params = {"fields": "profile/general/overview/project_details,profile/technology"}
|
|
|
|
r = request(url, headers=headers, params=params)
|
|
|
|
df = pd.DataFrame()
|
|
if r.status_code == 200:
|
|
data = r.json()["data"]
|
|
project_details = data["profile"]["general"]["overview"]["project_details"]
|
|
technology_data = data["profile"]["technology"]
|
|
technology_details = technology_data["overview"]["technology_details"]
|
|
df_info = pd.DataFrame(
|
|
{
|
|
"Metric": ["Project Details", "Technology Details"],
|
|
"Value": [project_details, technology_details],
|
|
}
|
|
)
|
|
df_repos = pd.DataFrame(technology_data["overview"]["client_repositories"])
|
|
df_repos.columns = prettify_column_names(df_repos.columns)
|
|
df_repos.fillna("-", inplace=True)
|
|
df_audits = pd.DataFrame(technology_data["security"]["audits"])
|
|
df_audits.columns = prettify_column_names(df_audits.columns)
|
|
if not df_audits.empty:
|
|
df_audits["Date"] = pd.to_datetime(df_audits["Date"])
|
|
df_audits.fillna("-", inplace=True)
|
|
df_vulns = pd.DataFrame(
|
|
technology_data["security"]["known_exploits_and_vulnerabilities"]
|
|
)
|
|
df_vulns.columns = prettify_column_names(df_vulns.columns)
|
|
if not df_vulns.empty:
|
|
df_vulns["Date"] = pd.to_datetime(df_vulns["Date"])
|
|
df_vulns.fillna("-", inplace=True)
|
|
return df_info, df_repos, df_audits, df_vulns
|
|
if r.status_code == 401:
|
|
console.print("[red]Invalid API Key[/red]\n")
|
|
else:
|
|
console.print(r.text)
|
|
|
|
return df, df, df, df
|
|
|
|
|
|
@log_start_end(log=logger)
|
|
@check_api_key(["API_MESSARI_KEY"])
|
|
def get_team(symbol: str) -> Tuple[pd.DataFrame, pd.DataFrame]:
|
|
"""Returns coin team
|
|
[Source: https://messari.io/]
|
|
|
|
Parameters
|
|
----------
|
|
symbol : str
|
|
Crypto symbol to check team
|
|
|
|
Returns
|
|
-------
|
|
Tuple[pd.DataFrame, pd.DataFrame]
|
|
Individuals,
|
|
Organizations
|
|
"""
|
|
|
|
url = base_url2 + f"assets/{symbol}/profile"
|
|
|
|
headers = {"x-messari-api-key": get_current_user().credentials.API_MESSARI_KEY}
|
|
|
|
params = {"fields": "profile/contributors"}
|
|
|
|
r = request(url, headers=headers, params=params)
|
|
|
|
df = pd.DataFrame()
|
|
if r.status_code == 200:
|
|
data = r.json()["data"]
|
|
df_individual_contributors = pd.DataFrame(
|
|
data["profile"]["contributors"]["individuals"]
|
|
)
|
|
if not df_individual_contributors.empty:
|
|
df_individual_contributors.fillna("-", inplace=True)
|
|
df_individual_contributors.insert(
|
|
0,
|
|
"Name",
|
|
df_individual_contributors[["first_name", "last_name"]].apply(
|
|
lambda x: " ".join(x), axis=1
|
|
),
|
|
)
|
|
df_individual_contributors.drop(
|
|
["slug", "avatar_url", "first_name", "last_name"],
|
|
axis=1,
|
|
inplace=True,
|
|
errors="ignore",
|
|
)
|
|
df_individual_contributors.columns = map(
|
|
str.capitalize, df_individual_contributors.columns
|
|
)
|
|
df_individual_contributors.replace(
|
|
to_replace=[None], value="-", inplace=True
|
|
)
|
|
df_organizations_contributors = pd.DataFrame(
|
|
data["profile"]["contributors"]["organizations"]
|
|
)
|
|
if not df_organizations_contributors.empty:
|
|
df_organizations_contributors.drop(
|
|
["slug", "logo"], axis=1, inplace=True, errors="ignore"
|
|
)
|
|
df_organizations_contributors.columns = map(
|
|
str.capitalize, df_organizations_contributors.columns
|
|
)
|
|
df_organizations_contributors.replace(
|
|
to_replace=[None], value="-", inplace=True
|
|
)
|
|
return df_individual_contributors, df_organizations_contributors
|
|
if r.status_code == 401:
|
|
console.print("[red]Invalid API Key[/red]\n")
|
|
else:
|
|
console.print(r.text)
|
|
|
|
return df, df
|
|
|
|
|
|
@log_start_end(log=logger)
|
|
@check_api_key(["API_MESSARI_KEY"])
|
|
def get_investors(symbol: str) -> Tuple[pd.DataFrame, pd.DataFrame]:
|
|
"""Returns coin investors
|
|
[Source: https://messari.io/]
|
|
|
|
Parameters
|
|
----------
|
|
symbol : str
|
|
Crypto symbol to check investors
|
|
|
|
Returns
|
|
-------
|
|
Tuple[pd.DataFrame, pd.DataFrame]
|
|
Individuals,
|
|
Organizations
|
|
"""
|
|
|
|
url = base_url2 + f"assets/{symbol}/profile"
|
|
|
|
headers = {"x-messari-api-key": get_current_user().credentials.API_MESSARI_KEY}
|
|
|
|
params = {"fields": "profile/investors"}
|
|
|
|
r = request(url, headers=headers, params=params)
|
|
|
|
df = pd.DataFrame()
|
|
if r.status_code == 200:
|
|
data = r.json()["data"]
|
|
df_individual_investors = pd.DataFrame(
|
|
data["profile"]["investors"]["individuals"]
|
|
)
|
|
if not df_individual_investors.empty:
|
|
df_individual_investors.fillna("-", inplace=True)
|
|
df_individual_investors.insert(
|
|
0,
|
|
"Name",
|
|
df_individual_investors[["first_name", "last_name"]].apply(
|
|
lambda x: " ".join(x), axis=1
|
|
),
|
|
)
|
|
df_individual_investors.drop(
|
|
["slug", "avatar_url", "first_name", "last_name"],
|
|
axis=1,
|
|
inplace=True,
|
|
errors="ignore",
|
|
)
|
|
df_individual_investors.columns = map(
|
|
str.capitalize, df_individual_investors.columns
|
|
)
|
|
df_individual_investors.replace(to_replace=[None], value="-", inplace=True)
|
|
df_organizations_investors = pd.DataFrame(
|
|
data["profile"]["investors"]["organizations"]
|
|
)
|
|
if not df_organizations_investors.empty:
|
|
df_organizations_investors.drop(
|
|
["slug", "logo"], axis=1, inplace=True, errors="ignore"
|
|
)
|
|
df_organizations_investors.columns = map(
|
|
str.capitalize, df_organizations_investors.columns
|
|
)
|
|
df_organizations_investors.replace(
|
|
to_replace=[None], value="-", inplace=True
|
|
)
|
|
return df_individual_investors, df_organizations_investors
|
|
if r.status_code == 401:
|
|
console.print("[red]Invalid API Key[/red]\n")
|
|
else:
|
|
console.print(r.text)
|
|
|
|
return df, df
|
|
|
|
|
|
@log_start_end(log=logger)
|
|
@check_api_key(["API_MESSARI_KEY"])
|
|
def get_governance(symbol: str) -> Tuple[str, pd.DataFrame]:
|
|
"""Returns coin governance
|
|
[Source: https://messari.io/]
|
|
|
|
Parameters
|
|
----------
|
|
symbol : str
|
|
Crypto symbol to check governance
|
|
|
|
Returns
|
|
-------
|
|
Tuple[str, pd.DataFrame]
|
|
Governance summary,
|
|
Metric Value with governance details
|
|
"""
|
|
|
|
url = base_url2 + f"assets/{symbol}/profile"
|
|
|
|
headers = {"x-messari-api-key": get_current_user().credentials.API_MESSARI_KEY}
|
|
|
|
params = {"fields": "profile/governance"}
|
|
|
|
r = request(url, headers=headers, params=params)
|
|
|
|
df = pd.DataFrame()
|
|
if r.status_code == 200:
|
|
data = r.json()["data"]
|
|
governance_data = data["profile"]["governance"]
|
|
if (
|
|
governance_data["onchain_governance"]["onchain_governance_type"] is not None
|
|
and governance_data["onchain_governance"]["onchain_governance_details"]
|
|
is not None
|
|
):
|
|
return (
|
|
re.sub("<[^>]*>", "", governance_data["governance_details"]),
|
|
pd.DataFrame(
|
|
{
|
|
"Metric": ["Type", "Details"],
|
|
"Value": [
|
|
governance_data["onchain_governance"][
|
|
"onchain_governance_type"
|
|
],
|
|
governance_data["onchain_governance"][
|
|
"onchain_governance_details"
|
|
],
|
|
],
|
|
}
|
|
),
|
|
)
|
|
return (
|
|
re.sub("<[^>]*>", "", governance_data["governance_details"]),
|
|
df,
|
|
)
|
|
if r.status_code == 401:
|
|
console.print("[red]Invalid API Key[/red]\n")
|
|
else:
|
|
console.print(r.text)
|
|
|
|
return "", df
|
|
|
|
|
|
def format_addresses(x: Any):
|
|
final_str = ""
|
|
for address in x:
|
|
final_str += f"{address['name']}: {address['link']}"
|
|
return final_str
|
|
|
|
|
|
@log_start_end(log=logger)
|
|
@check_api_key(["API_MESSARI_KEY"])
|
|
def get_fundraising(
|
|
symbol: str,
|
|
) -> Tuple[str, pd.DataFrame, pd.DataFrame, pd.DataFrame]:
|
|
"""Returns coin fundraising
|
|
[Source: https://messari.io/]
|
|
|
|
Parameters
|
|
----------
|
|
symbol : str
|
|
Crypto symbol to check fundraising
|
|
|
|
Returns
|
|
-------
|
|
Tuple[str, pd.DataFrame, pd.DataFrame, pd.DataFrame]
|
|
Launch summary,
|
|
Sales rounds,
|
|
Treasury Accounts,
|
|
Metric Value launch details
|
|
|
|
Examples
|
|
--------
|
|
>>> from openbb_terminal.sdk import openbb
|
|
>>> fundraise = openbb.crypto.dd.fr(symbol="BTC")
|
|
"""
|
|
|
|
url = base_url2 + f"assets/{symbol}/profile"
|
|
|
|
headers = {"x-messari-api-key": get_current_user().credentials.API_MESSARI_KEY}
|
|
|
|
params = {"fields": "profile/economics/launch"}
|
|
|
|
r = request(url, headers=headers, params=params)
|
|
|
|
df = pd.DataFrame()
|
|
if r.status_code == 200:
|
|
data = r.json()["data"]
|
|
launch_data = data["profile"]["economics"]["launch"]
|
|
launch_details = launch_data["general"]["launch_details"]
|
|
launch_type = launch_data["general"]["launch_style"]
|
|
launch_fundraising_rounds = pd.DataFrame(
|
|
launch_data["fundraising"]["sales_rounds"]
|
|
)
|
|
if not launch_fundraising_rounds.empty:
|
|
launch_fundraising_rounds.fillna("-", inplace=True)
|
|
launch_fundraising_rounds.drop(
|
|
[
|
|
"details",
|
|
"asset_collected",
|
|
"price_per_token_in_asset",
|
|
"amount_collected_in_asset",
|
|
"is_kyc_required",
|
|
"restricted_jurisdictions",
|
|
],
|
|
axis=1,
|
|
inplace=True,
|
|
errors="ignore",
|
|
)
|
|
launch_fundraising_rounds.columns = [
|
|
lambda_replace_underscores_in_column_names(val)
|
|
for val in launch_fundraising_rounds.columns
|
|
]
|
|
launch_fundraising_rounds["Start Date"] = launch_fundraising_rounds.apply(
|
|
lambda x: x["Start Date"].split("T")[0], axis=1
|
|
)
|
|
launch_fundraising_rounds["End Date"] = launch_fundraising_rounds.apply(
|
|
lambda x: x["End Date"].split("T")[0], axis=1
|
|
)
|
|
launch_fundraising_rounds.rename(
|
|
columns={
|
|
"Native Tokens Allocated": "Tokens Allocated",
|
|
"Equivalent Price Per Token In Usd": "Price [$]",
|
|
"Amount Collected In Usd": "Amount Collected [$]",
|
|
},
|
|
inplace=True,
|
|
)
|
|
launch_fundraising_rounds.fillna("-", inplace=True)
|
|
|
|
launch_fundraising_accounts = pd.DataFrame(
|
|
launch_data["fundraising"]["sales_treasury_accounts"]
|
|
)
|
|
if not launch_fundraising_accounts.empty:
|
|
launch_fundraising_accounts.columns = [
|
|
lambda_replace_underscores_in_column_names(val)
|
|
for val in launch_fundraising_accounts.columns
|
|
]
|
|
launch_fundraising_accounts.drop(
|
|
["Asset Held", "Security"], inplace=True, axis=1
|
|
)
|
|
launch_fundraising_accounts["Addresses"] = launch_fundraising_accounts[
|
|
"Addresses"
|
|
].map(format_addresses)
|
|
launch_distribution = pd.DataFrame(
|
|
{
|
|
"Metric": [
|
|
"Genesis Date",
|
|
"Type",
|
|
"Total Supply",
|
|
"Investors [%]",
|
|
"Organization/Founders [%]",
|
|
"Rewards/Airdrops [%]",
|
|
],
|
|
"Value": [
|
|
launch_data["initial_distribution"]["genesis_block_date"].split(
|
|
"T"
|
|
)[0]
|
|
if launch_data["initial_distribution"]["genesis_block_date"]
|
|
else "-",
|
|
launch_type,
|
|
lambda_long_number_format(
|
|
launch_data["initial_distribution"]["initial_supply"]
|
|
),
|
|
launch_data["initial_distribution"]["initial_supply_repartition"][
|
|
"allocated_to_investors_percentage"
|
|
],
|
|
launch_data["initial_distribution"]["initial_supply_repartition"][
|
|
"allocated_to_organization_or_founders_percentage"
|
|
],
|
|
launch_data["initial_distribution"]["initial_supply_repartition"][
|
|
"allocated_to_premined_rewards_or_airdrops_percentage"
|
|
],
|
|
],
|
|
}
|
|
)
|
|
return (
|
|
launch_details,
|
|
launch_fundraising_rounds,
|
|
launch_fundraising_accounts,
|
|
launch_distribution,
|
|
)
|
|
if r.status_code == 401:
|
|
console.print("[red]Invalid API Key[/red]\n")
|
|
else:
|
|
console.print(r.text)
|
|
|
|
return "", df, df, df
|