Ethplorer (#814)

* 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 ethplorer model and view

* Onchain controller

* Add webbrowser
for etherscan and ethplorer

* Add very long number formatter

* Add hugo docs

* Change names, remove prints from model, help as one string

* Add key for ethplorer, convert values based of token decimals number, apply changes from PR

* fix docs

* fix docs

* Add address command that load ethereum address

* Adjust hugo-docs
This commit is contained in:
jp
2021-10-22 01:22:48 +02:00
committed by GitHub
parent acf9c87573
commit ab15583f2d
18 changed files with 1727 additions and 23 deletions

2
README.md vendored
View File

@@ -268,6 +268,7 @@ These are the ones where a key is necessary:
* Twitter: https://developer.twitter.com
* Coinbase Pro API: https://docs.pro.coinbase.com/
* Whale Alert API: https://docs.whale-alert.io/
* Ethplorer API: https://github.com/EverexIO/Ethplorer/wiki/Ethplorer-API
When these are obtained, don't forget to update [config_terminal.py](/gamestonk_terminal/config_terminal.py).
@@ -292,6 +293,7 @@ Alternatively, you can also set them to the following environment variables:
| [Twitter](https://developer.twitter.com) | GT_API_TWITTER_KEY <br/> GT_API_TWITTER_SECRET_KEY <br/> GT_API_TWITTER_BEARER_TOKEN |
| [Coinbase](https://docs.pro.coinbase.com/) | GT_API_COINBASE_KEY <br/> GT_API_COINBASE_SECRET <br/> GT_API_COINBASE_PASS_PHRASE |
| [Whale Alert](https://docs.whale-alert.io/) | GT_API_WHALE_ALERT_KEY |
| [Ethplorer](https://github.com/EverexIO/Ethplorer/wiki/Ethplorer-API) | GT_API_ETHPLORER_KEY |
Example:
```

View File

@@ -96,3 +96,6 @@ API_COINBASE_PASS_PHRASE = os.getenv("GT_API_COINBASE_PASS_PHRASE") or "REPLACE_
# https://docs.whale-alert.io/
API_WHALE_ALERT_KEY = os.getenv("GT_API_WHALE_ALERT_KEY") or "REPLACE_ME"
# https://github.com/EverexIO/Ethplorer/wiki/Ethplorer-API
API_ETHPLORER_KEY = os.getenv("GT_API_ETHPLORER_KEY") or "freekey"

View File

@@ -76,7 +76,6 @@ def long_number_format_with_type_check(x: Union[int, float]) -> Union[str, Any]:
Returns
-------
Union[str, Any]
"""
if isinstance(x, (int, float)) and x < 10 ** 18:
@@ -86,3 +85,36 @@ def long_number_format_with_type_check(x: Union[int, float]) -> Union[str, Any]:
def replace_underscores_in_column_names(string: str) -> str:
return string.title().replace("_", " ")
def very_long_number_formatter(num: Union[str, int, float]) -> str:
"""Apply nice string format for very big numbers like Trillions, Quadrillions, Billions etc.
Parameters
----------
num: Union[str, int, float]
number to format
Returns
-------
str:
formatted number
"""
if isinstance(num, str):
try:
num = float(num)
except (TypeError, ValueError):
return str(num)
if isinstance(num, (int, float)):
num = int(num)
magnitude = 0
while abs(num) >= 1000 and magnitude <= 3:
magnitude += 1
num /= 1000.0
num = round(num, 1)
return "{}{}".format(
f"{num:f}".rstrip("0").rstrip("."),
["", "K", "M", "B", "T"][magnitude],
)
return num

View File

@@ -0,0 +1,457 @@
"""Ethplorer model"""
__docformat__ = "numpy"
import textwrap
from datetime import datetime
from typing import Any, Optional
from time import sleep
import pandas as pd
import requests
from gamestonk_terminal.cryptocurrency.dataframe_helpers import create_df_index
import gamestonk_terminal.config_terminal as cfg
def split_cols_with_dot(column: str) -> str:
"""Split column name in data frame columns whenever there is a dot between 2 words.
E.g. price.availableSupply -> priceAvailableSupply.
Parameters
----------
column: str
Pandas dataframe column value
Returns
-------
str:
Value of column with replaced format.
"""
def replace(string: str, char: str, index: int) -> str:
"""Helper method which replaces values with dot as a separator and converts it to camelCase format
Parameters
----------
string: str
String in which we remove dots and convert it to camelcase format.
char: str
First letter of given word.
index:
Index of string element.
Returns
-------
str:
Camel case string with removed dots. E.g. price.availableSupply -> priceAvailableSupply.
"""
return string[:index] + char + string[index + 1 :]
if "." in column:
part1, part2 = column.split(".")
part2 = replace(part2, part2[0].upper(), 0)
return part1 + part2
return column
def enrich_social_media(dct: dict) -> None:
"""Searching inside dictionary if there are any information about twitter, reddit or coingecko. If yes it
updates dictionary with url to given social media site.
Parameters
----------
dct: dict
Dictionary in which we search for coingecko, twitter or reddit url.
"""
social_media = {
"twitter": "https://www.twitter.com/",
"reddit": "https://www.reddit.com/r/",
"coingecko": "https://www.coingecko.com/en/coins/",
}
for k, v in social_media.items():
if k in dct:
dct[k] = v + dct[k]
def make_request(endpoint: str, address: Optional[str] = None, **kwargs: Any) -> dict:
"""Helper method that handles request for Ethplorer API [Source: https://ethplorer.io/]
Parameters
----------
endpoint: str
endpoint which we want to query e.g. https://api.ethplorer.io/<endpoint><arg>?=apiKey=freekey
address: str
balance argument for given endpoint. In most cases it's tx hash, or eth balance.
kwargs: Any
Additional keywords arguments e.g. limit of transactions
Returns
-------
dict
dictionary with response data
"""
base_url = "https://api.ethplorer.io/"
url = f"{base_url}{endpoint}"
if address:
url = url + "/" + address
url += f"?apiKey={cfg.API_ETHPLORER_KEY}"
if "limit" in kwargs:
url += f"&limit={kwargs['limit']}"
sleep(0.5) # Limit is 2 API calls per 1 sec.
response = requests.get(url).json()
if "error" in response:
raise Exception(
f"Error: {response['error']['code']}. Message: {response['error']['message']}\n",
)
return response
def get_token_decimals(address: str) -> Optional[int]:
"""Helper methods that gets token decimals number. [Source: Ethplorer]
Parameters
----------
address: str
Blockchain balance e.g. 0x1f9840a85d5af5bf1d1762f925bdaddc4201f984
Returns
-------
pd.DataFrame:
DataFrame with list of tokens and their balances.
"""
response = make_request("getTokenInfo", address)
if response and "decimals" in response:
return 10 ** int(response["decimals"])
return None
def get_address_info(address: str) -> pd.DataFrame:
"""Get info about tokens on you ethereum blockchain balance. Eth balance, balance of all tokens which
have name and symbol. [Source: Ethplorer]
Parameters
----------
address: str
Blockchain balance e.g. 0x3cD751E6b0078Be393132286c442345e5DC49699
Returns
-------
pd.DataFrame:
DataFrame with list of tokens and their balances.
"""
response = make_request("getAddressInfo", address)
if "tokens" in response:
tokens = response.pop("tokens")
for token in tokens:
token_info = token.pop("tokenInfo")
token.update(
{
"tokenName": token_info.get("name"),
"tokenSymbol": token_info.get("symbol"),
"tokenAddress": token_info.get("balance"),
"balance": token.get("balance")
/ (10 ** int(token_info.get("decimals"))),
}
)
else:
token_info = response.get("tokenInfo") or {}
tokens = [
{
"tokenName": token_info.get("name"),
"tokenSymbol": token_info.get("symbol"),
"tokenAddress": token_info.get("balance"),
"balance": token_info.get("balance")
/ (10 ** int(token_info.get("decimals"))),
}
]
eth = response["ETH"] or {}
eth_balance = eth.get("balance")
eth_row = [
"Ethereum",
"ETH",
"0x0000000000000000000000000000000000000000",
eth_balance,
]
cols = [
"tokenName",
"tokenSymbol",
"tokenAddress",
"balance",
]
df = pd.DataFrame(tokens)[cols]
eth_row_df = pd.DataFrame([eth_row], columns=cols)
df = pd.concat([eth_row_df, df], ignore_index=True)
df = df[df["tokenName"].notna()]
create_df_index(df, "index")
return df
def get_top_tokens() -> pd.DataFrame:
"""Get top 50 tokens. [Source: Ethplorer]
Returns
-------
pd.DataFrame:
DataFrame with list of top 50 tokens.
"""
response = make_request("getTopTokens")
tokens = response["tokens"]
df = pd.DataFrame(tokens)[
[
"name",
"symbol",
"price",
"txsCount",
"transfersCount",
"holdersCount",
"twitter",
"coingecko",
]
]
df["price"] = df["price"].apply(lambda x: x["rate"] if x and "rate" in x else None)
create_df_index(df, "rank")
return df
def get_top_token_holders(address) -> pd.DataFrame:
"""Get info about top token holders. [Source: Ethplorer]
Parameters
----------
address: str
Token balance e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984
Returns
-------
pd.DataFrame:
DataFrame with list of top token holders.
"""
response = make_request("getTopTokenHolders", address, limit=100)
df = pd.DataFrame(response["holders"])
sleep(0.5)
token_decimals_divider = get_token_decimals(address)
if token_decimals_divider:
df["balance"] = df["balance"] / token_decimals_divider
return df
def get_address_history(address) -> pd.DataFrame:
"""Get information about balance historical transactions. [Source: Ethplorer]
Parameters
----------
address: str
Blockchain balance e.g. 0x3cD751E6b0078Be393132286c442345e5DC49699
Returns
-------
pd.DataFrame:
DataFrame with balance historical transactions (last 100)
"""
response = make_request("getAddressHistory", address, limit=100)
operations = response.pop("operations")
if operations:
for operation in operations:
token = operation.pop("tokenInfo")
if token:
operation["token"] = token["name"]
operation["tokenAddress"] = token["address"]
operation["decimals"] = int(token["decimals"])
operation["timestamp"] = datetime.fromtimestamp(operation["timestamp"])
df = pd.DataFrame(operations)
cols = ["timestamp", "transactionHash", "token", "value"]
df["value"] = df["value"].astype(float) / (10 ** df["decimals"])
if df.empty:
return pd.DataFrame(columns=cols)
return df[cols]
def get_token_info(address) -> pd.DataFrame:
"""Get info about ERC20 token. [Source: Ethplorer]
Parameters
----------
address: str
Token balance e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984
Returns
-------
pd.DataFrame:
DataFrame with information about provided ERC20 token.
"""
response = make_request("getTokenInfo", address)
decimals = response.pop("decimals") if "decimals" in response else None
for name in [
"issuancesCount",
"lastUpdated",
"image",
"transfersCount",
"ethTransfersCount",
]:
try:
response.pop(name)
except KeyError:
continue
enrich_social_media(response)
df = pd.json_normalize(response)
df.columns = [split_cols_with_dot(x) for x in df.columns.tolist()]
if "priceTs" in df:
df.drop("priceTs", axis=1, inplace=True)
for col in [
"owner",
"slot",
"facebook",
"priceDiff",
"priceDiff7d",
"priceDiff30d",
"priceVolDiff1",
"priceVolDiff7",
"priceVolDiff30",
"priceCurrency",
]:
if col in df.columns:
df.drop(col, axis=1, inplace=True)
df["totalSupply"] = df["totalSupply"].astype(float) / (10 ** int(decimals))
df = df.T.reset_index()
df.columns = ["Metric", "Value"]
df["Value"] = df["Value"].apply(
lambda x: "\n".join(textwrap.wrap(x, width=70)) if isinstance(x, str) else x
)
return df
def get_tx_info(tx_hash) -> pd.DataFrame:
"""Get info about transaction. [Source: Ethplorer]
Parameters
----------
tx_hash: str
Transaction hash e.g. 0x9dc7b43ad4288c624fdd236b2ecb9f2b81c93e706b2ffd1d19b112c1df7849e6
Returns
-------
pd.DataFrame:
DataFrame with information about ERC20 token transaction.
"""
decimals = None
response = make_request("getTxInfo", tx_hash)
try:
response.pop("logs")
operations = response.pop("operations")[0]
if operations:
operations.pop("addresses")
token = operations.pop("tokenInfo")
decimals = token.get("decimals")
if token:
operations["token"] = token["name"]
operations["tokenAddress"] = token["address"]
operations["timestamp"] = datetime.fromtimestamp(operations["timestamp"])
response.update(operations)
response.pop("input")
df = pd.Series(response)
if decimals:
for col in ["intValue", "value"]:
df[col] = float(df[col]) // (10 ** int(decimals))
df = df.to_frame().reset_index()
df.columns = ["Metric", "Value"]
except KeyError:
return pd.DataFrame()
return df
def get_token_history(address) -> pd.DataFrame:
"""Get info about token historical transactions. [Source: Ethplorer]
Parameters
----------
address: str
Token e.g. 0xf3db5fa2c66b7af3eb0c0b782510816cbe4813b8
Returns
-------
pd.DataFrame:
DataFrame with token historical transactions.
"""
response = make_request("getTokenHistory", address, limit=1000)
all_operations = []
operations = response["operations"]
try:
first_row = operations[0]["tokenInfo"]
name, symbol, _ = (
first_row.get("name"),
first_row.get("symbol"),
first_row.get("balance"),
)
decimals = first_row.get("decimals")
except Exception:
name, symbol = "", ""
decimals = None
for operation in operations:
operation.pop("type")
operation.pop("tokenInfo")
operation["timestamp"] = datetime.fromtimestamp(operation["timestamp"])
all_operations.append(operation)
df = pd.DataFrame(all_operations)
if df.empty:
return df
df[["name", "symbol"]] = name, symbol
df["value"] = df["value"].astype(float) / (10 ** int(decimals))
return df[["timestamp", "name", "symbol", "value", "from", "to", "transactionHash"]]
def get_token_historical_price(address) -> pd.DataFrame:
"""Get token historical prices with volume and market cap, and average price. [Source: Ethplorer]
Parameters
----------
address: str
Token e.g. 0xf3db5fa2c66b7af3eb0c0b782510816cbe4813b8
Returns
-------
pd.DataFrame:
DataFrame with token historical prices.
"""
response = make_request("getTokenPriceHistoryGrouped", address)
data = response["history"]
data.pop("current")
prices = data.get("prices")
if not prices:
return pd.DataFrame()
prices_df = pd.DataFrame(prices)
prices_df["ts"] = prices_df["ts"].apply(lambda x: datetime.fromtimestamp(x))
prices_df.drop("tmp", axis=1, inplace=True)
return prices_df[
["date", "open", "close", "high", "low", "volumeConverted", "cap", "average"]
]

View File

@@ -0,0 +1,423 @@
"""Ethplorer view"""
__docformat__ = "numpy"
import os
from tabulate import tabulate
from gamestonk_terminal.helper_funcs import export_data
from gamestonk_terminal.cryptocurrency.dataframe_helpers import (
very_long_number_formatter,
)
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.cryptocurrency.onchain import ethplorer_model
def display_address_info(
address: str,
top: int = 15,
sortby: str = "index",
descend: bool = True,
export: str = "",
) -> None:
"""Display info about tokens for given ethereum blockchain balance e.g. ETH balance, balance of all tokens with
name and symbol. [Source: Ethplorer]
Parameters
----------
address: str
Ethereum balance.
top: int
Limit of transactions. Maximum 100
sortby: str
Key to sort by.
descend: str
Sort in descending order.
export : str
Export dataframe data to csv,json,xlsx file
"""
df = ethplorer_model.get_address_info(address)
df_data = df.copy()
df = df.sort_values(by=sortby, ascending=descend)
df["balance"] = df["balance"].apply(
lambda x: very_long_number_formatter(x) if x >= 10000 else round(float(x), 4)
)
if gtff.USE_TABULATE_DF:
print(
tabulate(
df.head(top),
headers=df.columns,
floatfmt=".2f",
showindex=False,
tablefmt="fancy_grid",
),
"\n",
)
else:
print(df.to_string, "\n")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"balance",
df_data,
)
def display_top_tokens(
top: int = 15,
sortby: str = "rank",
descend: bool = True,
export: str = "",
) -> None:
"""Display top ERC20 tokens [Source: Ethplorer]
Parameters
----------
top: int
Limit of transactions. Maximum 100
sortby: str
Key to sort by.
descend: str
Sort in descending order.
export : str
Export dataframe data to csv,json,xlsx file
"""
df = ethplorer_model.get_top_tokens()
df_data = df.copy()
df.fillna("", inplace=True)
df = df.sort_values(by=sortby, ascending=descend)
for col in ["txsCount", "transfersCount", "holdersCount"]:
if col in df.columns:
df[col] = df[col].apply(lambda x: very_long_number_formatter(x))
if gtff.USE_TABULATE_DF:
print(
tabulate(
df.head(top),
headers=df.columns,
floatfmt=".2f",
showindex=False,
tablefmt="fancy_grid",
),
"\n",
)
else:
print(df.to_string, "\n")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"top",
df_data,
)
def display_top_token_holders(
address: str,
top: int = 10,
sortby: str = "balance",
descend: bool = False,
export: str = "",
) -> None:
"""Display info about top ERC20 token holders. [Source: Ethplorer]
Parameters
----------
address: str
Token balance e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984
top: int
Limit of transactions. Maximum 100
sortby: str
Key to sort by.
descend: str
Sort in descending order.
export : str
Export dataframe data to csv,json,xlsx file
"""
df = ethplorer_model.get_top_token_holders(address)
df_data = df.copy()
df = df.sort_values(by=sortby, ascending=descend)
df["balance"] = df["balance"].apply(lambda x: very_long_number_formatter(x))
if gtff.USE_TABULATE_DF:
print(
tabulate(
df.head(top),
headers=df.columns,
floatfmt=".2f",
showindex=False,
tablefmt="fancy_grid",
),
"\n",
)
else:
print(df.to_string, "\n")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"holders",
df_data,
)
def display_address_history(
address: str,
top: int = 10,
sortby: str = "timestamp",
descend: bool = False,
export: str = "",
) -> None:
"""Display information about balance historical transactions. [Source: Ethplorer]
Parameters
----------
address: str
Ethereum nlockchain balance e.g. 0x3cD751E6b0078Be393132286c442345e5DC49699
top: int
Limit of transactions. Maximum 100
sortby: str
Key to sort by.
descend: str
Sort in descending order.
export : str
Export dataframe data to csv,json,xlsx file
"""
df = ethplorer_model.get_address_history(address)
df_data = df.copy()
df = df.sort_values(by=sortby, ascending=descend)
df["value"] = df["value"].apply(
lambda x: very_long_number_formatter(x) if x >= 10000 else round(float(x), 4)
)
if gtff.USE_TABULATE_DF:
print(
tabulate(
df.head(top),
headers=df.columns,
floatfmt=".0f",
showindex=False,
tablefmt="fancy_grid",
),
"\n",
)
else:
print(df.to_string, "\n")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"hist",
df_data,
)
def display_token_info(
address: str,
social: bool = False,
export: str = "",
) -> None:
"""Display info about ERC20 token. [Source: Ethplorer]
Parameters
----------
address: str
Token balance e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984
social: bool
Flag to display social media links
export : str
Export dataframe data to csv,json,xlsx file
"""
df = ethplorer_model.get_token_info(address)
df_data = df.copy()
df["Value"] = df["Value"].apply(lambda x: very_long_number_formatter(x))
socials = ["website", "telegram", "reddit", "twitter", "coingecko"]
if social:
df = df[df["Metric"].isin(["balance", "name", "symbol"] + socials)]
else:
df = df[~df["Metric"].isin(socials)]
if gtff.USE_TABULATE_DF:
print(
tabulate(
df,
headers=df.columns,
floatfmt=".0f",
showindex=False,
tablefmt="fancy_grid",
),
"\n",
)
else:
print(df.to_string, "\n")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"info",
df_data,
)
def display_tx_info(
tx_hash: str,
export: str = "",
) -> None:
"""Display info about transaction. [Source: Ethplorer]
Parameters
----------
tx_hash: str
Transaction hash e.g. 0x9dc7b43ad4288c624fdd236b2ecb9f2b81c93e706b2ffd1d19b112c1df7849e6
export : str
Export dataframe data to csv,json,xlsx file
"""
df = ethplorer_model.get_tx_info(tx_hash)
df_data = df.copy()
if gtff.USE_TABULATE_DF:
print(
tabulate(
df,
headers=df.columns,
floatfmt=".0f",
showindex=False,
tablefmt="fancy_grid",
),
"\n",
)
else:
print(df.to_string, "\n")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"tx",
df_data,
)
def display_token_history(
address: str,
top: int = 10,
sortby: str = "timestamp",
hash_: bool = False,
descend: bool = False,
export: str = "",
) -> None:
"""Display info about token history. [Source: Ethplorer]
Parameters
----------
address: str
Token balance e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984
top: int
Limit of transactions. Maximum 100
sortby: str
Key to sort by.
descend: str
Sort in descending order.
hash_: bool,
Flag to show transaction hash.
export : str
Export dataframe data to csv,json,xlsx file
"""
df = ethplorer_model.get_token_history(address)
df_data = df.copy()
if df.empty:
print(f"No results found for balance: {address}\n")
return
df["value"] = df["value"].apply(lambda x: very_long_number_formatter(x))
df = df.sort_values(by=sortby, ascending=descend)
if hash_:
df.drop(["from", "to"], axis=1, inplace=True)
else:
df.drop("transactionHash", inplace=True, axis=1)
if gtff.USE_TABULATE_DF:
print(
tabulate(
df.head(top),
headers=df.columns,
floatfmt=".2f",
showindex=False,
tablefmt="fancy_grid",
),
"\n",
)
else:
print(df.to_string, "\n")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"th",
df_data,
)
def display_token_historical_prices(
address: str,
top: int = 30,
sortby: str = "date",
descend: bool = False,
export: str = "",
) -> None:
"""Display token historical prices with volume and market cap, and average price. [Source: Ethplorer]
Parameters
----------
address: str
Token balance e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984
top: int
Limit of transactions. Maximum 100
sortby: str
Key to sort by.
descend: str
Sort in descending order.
export : str
Export dataframe data to csv,json,xlsx file
"""
df = ethplorer_model.get_token_historical_price(address)
df_data = df.copy()
if df.empty:
print(f"No results found for balance: {address}\n")
return
df["volumeConverted"] = df["volumeConverted"].apply(
lambda x: very_long_number_formatter(x)
)
df["cap"] = df["cap"].apply(lambda x: very_long_number_formatter(x))
df = df.sort_values(by=sortby, ascending=descend)
if gtff.USE_TABULATE_DF:
print(
tabulate(
df.head(top),
headers=df.columns,
floatfmt=".2f",
showindex=False,
tablefmt="fancy_grid",
),
"\n",
)
else:
print(df.to_string, "\n")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"prices",
df_data,
)

View File

@@ -4,6 +4,7 @@ __docformat__ = "numpy"
import os
import argparse
from typing import List
from prompt_toolkit.completion import NestedCompleter
from gamestonk_terminal import feature_flags as gtff
@@ -18,6 +19,7 @@ from gamestonk_terminal.helper_funcs import (
from gamestonk_terminal.cryptocurrency.onchain import (
ethgasstation_view,
whale_alert_view,
ethplorer_view,
)
# pylint: disable=R1732
@@ -34,7 +36,33 @@ class OnchainController:
"quit",
]
CHOICES_COMMANDS = ["gwei", "whales"]
SPECIFIC_CHOICES = {
"account": [
"balance",
"hist",
],
"token": [
"info",
"th",
"prices",
"holders",
],
"tx": ["tx"],
}
CHOICES_COMMANDS = [
"gwei",
"whales",
"balance",
"top",
"holders",
"tx",
"hist",
"info",
"th",
"prices",
"address",
]
CHOICES += CHOICES_COMMANDS
@@ -45,6 +73,8 @@ class OnchainController:
"cmd",
choices=self.CHOICES,
)
self.address = None
self.address_type = None
def switch(self, an_input: str):
"""Process and dispatch input
@@ -73,7 +103,7 @@ class OnchainController:
# Help menu again
if known_args.cmd == "?":
print_help()
self.print_help()
return None
# Clear screen
@@ -87,7 +117,7 @@ class OnchainController:
def call_help(self, *_):
"""Process Help command"""
print_help()
self.print_help()
def call_q(self, _):
"""Process Q command - quit the menu"""
@@ -186,8 +216,8 @@ class OnchainController:
parser.add_argument(
"-a",
"--address",
dest="address",
"--balance",
dest="balance",
action="store_true",
help="Flag to show addresses of transaction",
default=False,
@@ -220,18 +250,631 @@ class OnchainController:
except Exception as e:
print(e)
def call_address(self, other_args: List[str]):
"""Process address command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="address",
description="""
Load address for further analysis. You can analyze account address, token address or transaction hash.
[Source: Ethplorer]
""",
)
def print_help():
"""Print help"""
print("\nOnchain:")
print(" cls clear screen")
print(" ?/help show this menu again")
print(" q quit this menu, and shows back to main menu")
print(" quit quit to abandon program")
print("")
print(" gwei check current eth gas fees")
print(" whales check crypto wales transactions")
print("")
parser.add_argument(
"-a",
action="store_true",
help="Account address",
dest="account",
default=False,
)
parser.add_argument(
"-t",
action="store_true",
help="ERC20 token address",
dest="token",
default=False,
)
parser.add_argument(
"-tx",
action="store_true",
help="Transaction hash",
dest="transaction",
default=False,
)
parser.add_argument(
"--address",
dest="address",
help="Ethereum address",
default=False,
type=str,
required="-h" not in other_args,
)
try:
if other_args:
if not other_args[0][0] == "-":
other_args.insert(0, "--address")
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
if len(ns_parser.address) not in [42, 66]:
print(
f"Couldn't load address {ns_parser.address}. "
f"Token or account address should be 42 characters long. "
f"Transaction hash should be 66 characters long\n"
)
return
if ns_parser.account:
address_type = "account"
elif ns_parser.token:
address_type = "token"
elif ns_parser.transaction:
address_type = "tx"
else:
address_type = "account"
if len(ns_parser.address) == 66:
address_type = "tx"
self.address = ns_parser.address
self.address_type = address_type
print(f"Address loaded {self.address}\n")
except Exception as e:
print(e)
def call_balance(self, other_args: List[str]):
"""Process balance command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="balance",
description="""
Display info about tokens on given ethereum blockchain balance.
[Source: Ethplorer]
""",
)
parser.add_argument(
"-t",
"--top",
dest="top",
type=check_positive,
help="top N number records",
default=10,
)
parser.add_argument(
"-s",
"--sort",
dest="sortby",
type=str,
help="Sort by given column. Default: index",
default="index",
choices=[
"index",
"balance",
"tokenName",
"tokenSymbol",
],
)
parser.add_argument(
"--descend",
action="store_false",
help="Flag to sort in descending order (lowest first)",
dest="descend",
default=True,
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser or not self.address:
return
ethplorer_view.display_address_info(
top=ns_parser.top,
sortby=ns_parser.sortby,
descend=ns_parser.descend,
address=self.address,
export=ns_parser.export,
)
except Exception as e:
print(e)
def call_hist(self, other_args: List[str]):
"""Process hist command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="hist",
description="""
Display history for given ethereum blockchain balance.
e.g. 0x3cD751E6b0078Be393132286c442345e5DC49699
[Source: Ethplorer]
""",
)
parser.add_argument(
"-t",
"--top",
dest="top",
type=check_positive,
help="top N number records",
default=10,
)
parser.add_argument(
"-s",
"--sort",
dest="sortby",
type=str,
help="Sort by given column. Default: timestamp",
default="timestamp",
choices=["timestamp", "transactionHash", "token", "value"],
)
parser.add_argument(
"--descend",
action="store_false",
help="Flag to sort in descending order (lowest first)",
dest="descend",
default=True,
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser or not self.address:
return
ethplorer_view.display_address_history(
top=ns_parser.top,
sortby=ns_parser.sortby,
descend=ns_parser.descend,
address=self.address,
export=ns_parser.export,
)
except Exception as e:
print(e)
def call_holders(self, other_args: List[str]):
"""Process holders command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="holders",
description="""
Display top ERC20 token holders: e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984
[Source: Ethplorer]
""",
)
parser.add_argument(
"-t",
"--top",
dest="top",
type=check_positive,
help="top N number records",
default=10,
)
parser.add_argument(
"-s",
"--sort",
dest="sortby",
type=str,
help="Sort by given column. Default: share",
default="share",
choices=[
"balance",
"balance",
"share",
],
)
parser.add_argument(
"--descend",
action="store_false",
help="Flag to sort in descending order (lowest first)",
dest="descend",
default=False,
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser or not self.address:
return
ethplorer_view.display_top_token_holders(
top=ns_parser.top,
sortby=ns_parser.sortby,
descend=ns_parser.descend,
address=self.address,
export=ns_parser.export,
)
except Exception as e:
print(e)
def call_top(self, other_args: List[str]):
"""Process top command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="top",
description="""
Display top ERC20 tokens.
[Source: Ethplorer]
""",
)
parser.add_argument(
"-t",
"--top",
dest="top",
type=check_positive,
help="top N number records",
default=10,
)
parser.add_argument(
"-s",
"--sort",
dest="sortby",
type=str,
help="Sort by given column. Default: rank",
default="rank",
choices=[
"rank",
"name",
"symbol",
"price",
"txsCount",
"transfersCount",
"holdersCount",
],
)
parser.add_argument(
"--descend",
action="store_false",
help="Flag to sort in descending order (lowest first)",
dest="descend",
default=True,
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
ethplorer_view.display_top_tokens(
top=ns_parser.top,
sortby=ns_parser.sortby,
descend=ns_parser.descend,
export=ns_parser.export,
)
except Exception as e:
print(e)
def call_info(self, other_args: List[str]):
"""Process info command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="info",
description="""
Display info about ERC20 token. e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984
[Source: Ethplorer]
""",
)
parser.add_argument(
"--social",
action="store_false",
help="Flag to show social media links",
dest="social",
default=False,
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser or not self.address:
return
ethplorer_view.display_token_info(
social=ns_parser.social,
address=self.address,
export=ns_parser.export,
)
except Exception as e:
print(e)
def call_th(self, other_args: List[str]):
"""Process th command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="th",
description="""
Displays info about token history.
e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984
[Source: Ethplorer]
""",
)
parser.add_argument(
"-t",
"--top",
dest="top",
type=check_positive,
help="top N number records",
default=10,
)
parser.add_argument(
"-s",
"--sort",
dest="sortby",
type=str,
help="Sort by given column. Default: value",
default="value",
choices=[
"value",
],
)
parser.add_argument(
"--descend",
action="store_false",
help="Flag to sort in descending order (lowest first)",
dest="descend",
default=True,
)
parser.add_argument(
"--hash",
action="store_false",
help="Flag to show transaction hash",
dest="hash",
default=True,
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser or not self.address:
return
ethplorer_view.display_token_history(
top=ns_parser.top,
hash_=ns_parser.hash,
sortby=ns_parser.sortby,
descend=ns_parser.descend,
address=self.address,
export=ns_parser.export,
)
except Exception as e:
print(e)
def call_tx(self, other_args: List[str]):
"""Process tx command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="tx",
description="""
Display info ERC20 token transaction on ethereum blockchain.
e.g. 0x9dc7b43ad4288c624fdd236b2ecb9f2b81c93e706b2ffd1d19b112c1df7849e6
[Source: Ethplorer]
""",
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser or not self.address:
return
ethplorer_view.display_tx_info(
tx_hash=self.address,
export=ns_parser.export,
)
except Exception as e:
print(e)
def call_prices(self, other_args: List[str]):
"""Process prices command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="prices",
description="""
"Display token historical prices. e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984
[Source: Ethplorer]
""",
)
parser.add_argument(
"-t",
"--top",
dest="top",
type=check_positive,
help="top N number records",
default=10,
)
parser.add_argument(
"-s",
"--sort",
dest="sortby",
type=str,
help="Sort by given column. Default: date",
default="date",
choices=[
"date",
"cap",
"volumeConverted",
"open",
"high",
"close",
"low",
],
)
parser.add_argument(
"--descend",
action="store_false",
help="Flag to sort in descending order (lowest first)",
dest="descend",
default=False,
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser or not self.address:
return
ethplorer_view.display_token_historical_prices(
top=ns_parser.top,
sortby=ns_parser.sortby,
descend=ns_parser.descend,
address=self.address,
export=ns_parser.export,
)
except Exception as e:
print(e)
def print_help(self):
"""Print help"""
help_text = """
Onchain:
cls clear screen
?/help show this menu again
q quit this menu, and shows back to main menu
quit quit to abandon the program
gwei check current eth gas fees
whales check crypto wales transactions
"""
help_text += f"\nEthereum address: {self.address if self.address else '?'}"
help_text += (
f"\nAddress type: {self.address_type if self.address_type else '?'}\n"
)
help_text += """
Ethereum:
address load ethereum address of token, account or transaction
top top ERC20 tokens"""
if self.address_type == "account":
help_text += """
balance check ethereum balance balance
hist ethereum balance history (transactions)"""
if self.address_type == "token":
help_text += """
info ERC20 token info
holders top ERC20 token holders
th ERC20 token history
prices ERC20 token historical prices"""
if self.address_type == "tx":
help_text += """
tx ethereum blockchain transaction info"""
print(help_text, "\n")
def menu():

View File

@@ -74,7 +74,7 @@ def get_whales_transactions(min_value: int = 800000, limit: int = 100) -> pd.Dat
)
data["date"] = pd.to_datetime(data["timestamp"], unit="s")
data.columns = [col.replace(".address", "") for col in data.columns]
data.columns = [col.replace(".balance", "") for col in data.columns]
data["to_address"] = data["to"].apply(
lambda x: "\n".join(textwrap.wrap(x, width=45)) if isinstance(x, str) else x
)

View File

@@ -310,7 +310,7 @@ def get_contract_platform(platform_id: str = "eth-ethereum") -> pd.DataFrame:
Returns
-------
pandas.DataFrame
id, type, active, address
id, type, active, balance
"""
session = PaprikaSession()
@@ -318,4 +318,4 @@ def get_contract_platform(platform_id: str = "eth-ethereum") -> pd.DataFrame:
session.ENDPOINTS["contract_platform_addresses"].format(platform_id)
)
return pd.DataFrame(contract_platforms)[["id", "type", "active", "address"]]
return pd.DataFrame(contract_platforms)[["id", "type", "active", "balance"]]

View File

@@ -1458,11 +1458,11 @@ Coinbase:
description="""Gets all contract addresses for given platform.
Provide platform id with -p/--platform parameter
You can display only top N number of smart contracts with --top parameter.
You can sort data by id, type, active, address --sort parameter
You can sort data by id, type, active, balance --sort parameter
and also with --descend flag to sort descending.
Displays:
id, type, active, address
id, type, active, balance
""",
)
@@ -1492,7 +1492,7 @@ Coinbase:
type=str,
help="Sort by given column",
default="id",
choices=["id", "type", "active", "address"],
choices=["id", "type", "active", "balance"],
)
parser.add_argument(

View File

@@ -0,0 +1,14 @@
```
usage: address [-a] [-t] [-tx] [--address ADDRESS] [-h]
```
Load address for further analysis. You can analyze account address, token address or transaction hash. [Source: Ethplorer]
```
optional arguments:
-a Account address (default: False)
-t ERC20 token address (default: False)
-tx Transaction hash (default: False)
--address ADDRESS Ethereum address (default: False)
-h, --help show this help message (default: False)
```

View File

@@ -0,0 +1,18 @@
```
usage: balance [-t TOP] [-s {index,balance,tokenName,tokenSymbol}] [--descend] [--export {csv,json,xlsx}] [-h]
```
Display info about tokens on given ethereum blockchain address. [Source:
Ethplorer]
```
optional arguments:
-t TOP, --top TOP top N number records (default: 10)
-s {index,balance,tokenName,tokenSymbol}, --sort {index,balance,tokenName,tokenSymbol}
Sort by given column. Default: index (default: index)
--descend Flag to sort in descending order (lowest first) (default: True)
--export {csv,json,xlsx}
Export dataframe data to csv,json,xlsx file (default: )
-h, --help show this help message (default: False)
```

View File

@@ -0,0 +1,18 @@
```
usage: hist [-t TOP] [-s {timestamp,transactionHash,token,value}] [--descend] [--export {csv,json,xlsx}] [-h]
```
Display history for given ethereum blockchain address. e.g.
0x3cD751E6b0078Be393132286c442345e5DC49699 [Source: Ethplorer]
```
optional arguments:
-t TOP, --top TOP top N number records (default: 10)
-s {timestamp,transactionHash,token,value}, --sort {timestamp,transactionHash,token,value}
Sort by given column. Default: timestamp (default: timestamp)
--descend Flag to sort in descending order (lowest first) (default: True)
--export {csv,json,xlsx}
Export dataframe data to csv,json,xlsx file (default: )
-h, --help show this help message (default: False)
```

View File

@@ -0,0 +1,16 @@
```
usage: holders [-t TOP] [-s {balance,balance,share}] [--descend] [--export {csv,json,xlsx}] [-h]
```
Display top ERC20 token holders: e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984 [Source: Ethplorer]
```
optional arguments:
-t TOP, --top TOP top N number records (default: 10)
-s {balance,balance,share}, --sort {balance,balance,share}
Sort by given column. Default: share (default: share)
--descend Flag to sort in descending order (lowest first) (default: False)
--export {csv,json,xlsx}
Export dataframe data to csv,json,xlsx file (default: )
-h, --help show this help message (default: False)
```

View File

@@ -0,0 +1,13 @@
```
usage: info [--social] [--export {csv,json,xlsx}] [-h]
```
Display info about ERC20 token. e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984 [Source: Ethplorer]
```
optional arguments:
--social Flag to show social media links (default: False)
--export {csv,json,xlsx}
Export dataframe data to csv,json,xlsx file (default: )
-h, --help show this help message (default: False)
```

View File

@@ -0,0 +1,16 @@
```
usage: prices [-t TOP] [-s {date,cap,volumeConverted,open,high,close,low}] [--descend] [--export {csv,json,xlsx}] [-h]
```
Display token historical prices. e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984 [Source: Ethplorer]
```
optional arguments:
-t TOP, --top TOP top N number records (default: 10)
-s {date,cap,volumeConverted,open,high,close,low}, --sort {date,cap,volumeConverted,open,high,close,low}
Sort by given column. Default: date (default: date)
--descend Flag to sort in descending order (lowest first) (default: False)
--export {csv,json,xlsx}
Export dataframe data to csv,json,xlsx file (default: )
-h, --help show this help message (default: False)
```

View File

@@ -0,0 +1,17 @@
```
usage: th [-t TOP] [-s {value}] [--descend] [--hash] [--export {csv,json,xlsx}] [-h]
```
Displays info about token history. e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984 [Source: Ethplorer]
```
optional arguments:
-t TOP, --top TOP top N number records (default: 10)
-s {value}, --sort {value}
Sort by given column. Default: value (default: value)
--descend Flag to sort in descending order (lowest first) (default: True)
--hash Flag to show transaction hash (default: True)
--export {csv,json,xlsx}
Export dataframe data to csv,json,xlsx file (default: )
-h, --help show this help message (default: False)
```

View File

@@ -0,0 +1,20 @@
```
usage: top [-t TOP]
[-s {rank,name,symbol,price,txsCount,transfersCount,holdersCount,address}]
[--descend] [--export {csv,json,xlsx}] [-h]
```
Display top ERC20 tokens. [Source: Ethplorer]
```
optional arguments:
-t TOP, --top TOP top N number records (default: 10)
-s {rank,name,symbol,price,txsCount,transfersCount,holdersCount,address}, --sort {rank,name,symbol,price,txsCount,transfersCount,holdersCount,address}
Sort by given column. Default: rank (default: rank)
--descend Flag to sort in descending order (lowest first)
(default: True)
--export {csv,json,xlsx}
Export dataframe data to csv,json,xlsx file (default:
)
-h, --help show this help message (default: False)
```

View File

@@ -0,0 +1,12 @@
```
usage: tx [--export {csv,json,xlsx}] [-h]
```
Display info ERC20 token transaction on ethereum blockchain. e.g. 0x9dc7b43ad4288c624fdd236b2ecb9f2b81c93e706b2ffd1d19b112c1df7849e6 [Source: Ethplorer]
```
optional arguments:
--export {csv,json,xlsx}
Export dataframe data to csv,json,xlsx file (default: )
-h, --help show this help message (default: False)
```