1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-04-28 04:59:01 +00:00

tools: unified retrieval of coin data, regenerated coins_details

This commit is contained in:
matejcik 2018-07-20 16:49:45 +02:00
parent cebeb81e8c
commit 288445cecc
3 changed files with 775 additions and 945 deletions

File diff suppressed because it is too large Load Diff

404
tools/coin_defs.py Executable file
View File

@ -0,0 +1,404 @@
#!/usr/bin/env python3
from binascii import unhexlify
from collections import defaultdict, OrderedDict
import re
import os
import json
import glob
import logging
try:
import requests
except ImportError:
requests = None
log = logging.getLogger(__name__)
DEFS_DIR = os.path.abspath(
os.environ.get("DEFS_DIR") or os.path.join(os.path.dirname(__file__), "..", "defs")
)
def load_json(*path):
if len(path) == 1 and path[0].startswith("/"):
filename = path[0]
else:
filename = os.path.join(DEFS_DIR, *path)
with open(filename) as f:
return json.load(f, object_pairs_hook=OrderedDict)
# ====== coin validation ======
def check_type(val, types, nullable=False, empty=False, regex=None, choice=None):
# check nullable
if val is None:
if nullable:
return
else:
raise ValueError("Missing required value")
# check type
if not isinstance(val, types):
raise TypeError("Wrong type (expected: {})".format(types))
# check empty
if isinstance(val, (list, dict)) and not empty and not val:
raise ValueError("Empty collection")
# check regex
if regex is not None:
if types is not str:
raise TypeError("Wrong type for regex check")
if not re.search(regex, val):
raise ValueError("Value does not match regex {}".format(regex))
# check choice
if choice is not None and val not in choice:
raise ValueError("Value not allowed, use one of: {}".format(", ".join(choice)))
def check_key(key, types, **kwargs):
def do_check(coin):
if not key in coin:
raise KeyError("{}: Missing key".format(key))
try:
check_type(coin[key], types, **kwargs)
except Exception as e:
raise ValueError("{}: {}".format(key, e)) from e
return do_check
COIN_CHECKS = [
check_key("coin_name", str, regex=r"^[A-Z]"),
check_key("coin_shortcut", str, regex=r"^t?[A-Z]{3,}$"),
check_key("coin_label", str, regex=r"^[A-Z]"),
check_key("website", str, regex=r"^http.*[^/]$"),
check_key("github", str, regex=r"^https://github.com/.*[^/]$"),
check_key("maintainer", str),
check_key(
"curve_name", str, choice=["secp256k1", "secp256k1_decred", "secp256k1_groestl"]
),
check_key("address_type", int),
check_key("address_type_p2sh", int),
check_key("maxfee_kb", int),
check_key("minfee_kb", int),
check_key("hash_genesis_block", str, regex=r"^[0-9a-f]{64}$"),
check_key("xprv_magic", int),
check_key("xpub_magic", int),
check_key("xpub_magic_segwit_p2sh", int, nullable=True),
check_key("xpub_magic_segwit_native", int, nullable=True),
check_key("slip44", int),
check_key("segwit", bool),
check_key("decred", bool),
check_key("fork_id", int, nullable=True),
check_key("force_bip143", bool),
check_key("bip115", bool),
check_key("version_group_id", int, nullable=True),
check_key("default_fee_b", dict),
check_key("dust_limit", int),
check_key("blocktime_seconds", int),
check_key("signed_message_header", str),
check_key("address_prefix", str, regex=r":$"),
check_key("min_address_length", int),
check_key("max_address_length", int),
check_key("bech32_prefix", str, nullable=True),
check_key("cashaddr_prefix", str, nullable=True),
check_key("bitcore", list, empty=True),
check_key("blockbook", list, empty=True),
]
def validate_coin(coin):
errors = []
for check in COIN_CHECKS:
try:
check(coin)
except Exception as e:
errors.append(str(e))
magics = [
coin[k]
for k in (
"xprv_magic",
"xpub_magic",
"xpub_magic_segwit_p2sh",
"xpub_magic_segwit_native",
)
if coin[k] is not None
]
# each of those must be unique
# therefore length of list == length of set of unique values
if len(magics) != len(set(magics)):
errors.append("XPUB/XPRV magic numbers must be unique")
if coin["address_type"] == coin["address_type_p2sh"]:
errors.append("address_type must be distinct from address_type_p2sh")
if not coin["maxfee_kb"] >= coin["minfee_kb"]:
errors.append("max fee must not be smaller than min fee")
if not coin["max_address_length"] >= coin["min_address_length"]:
errors.append("max address length must not be smaller than min address length")
for bc in coin["bitcore"] + coin["blockbook"]:
if bc.endswith("/"):
errors.append("make sure URLs don't end with '/'")
return errors
# ======= Coin json loaders =======
def get_coins():
coins = []
for filename in glob.glob(os.path.join(DEFS_DIR, "coins", "*.json")):
coin = load_json(filename)
coin.update(
name=coin["coin_name"],
shortcut=coin["coin_shortcut"],
key="btc:{}".format(coin["coin_shortcut"]),
)
coins.append(coin)
return coins
def get_ethereum_networks():
networks = load_json("ethereum", "networks.json")
for network in networks:
network.update(key="eth:{}".format(network["shortcut"]))
return networks
def get_erc20_tokens():
networks = get_ethereum_networks()
tokens = []
for network in networks:
if network["name"].startswith("Ethereum Testnet "):
idx = len("Ethereum Testnet ")
chain = network["name"][idx : idx + 3]
else:
chain = network["shortcut"]
chain = chain.lower()
if not chain:
continue
chain_path = os.path.join(DEFS_DIR, "ethereum", "tokens", "tokens", chain)
for filename in glob.glob(os.path.join(chain_path, "*.json")):
token = load_json(filename)
token.update(
chain=chain,
chain_id=network["chain_id"],
address_bytes=unhexlify(token["address"][2:]),
shortcut=token["symbol"],
key="erc20:{}:{}".format(chain, token["symbol"]),
)
tokens.append(token)
return tokens
def get_nem_mosaics():
mosaics = load_json("nem", "nem_mosaics.json")
for mosaic in mosaics:
shortcut = mosaic["ticker"].strip()
mosaic.update(shortcut=shortcut, key="nem:{}".format(shortcut))
return mosaics
def get_others():
others = load_json("others.json")
for other in others:
other.update(key="network:{}".format(other["shortcut"]))
return others
# ====== support info ======
RELEASES_URL = "https://wallet.trezor.io/data/firmware/{}/releases.json"
ETHEREUM_TOKENS = {
"1": "https://raw.githubusercontent.com/trezor/trezor-mcu/v{}/firmware/ethereum_tokens.c",
"2": "https://raw.githubusercontent.com/trezor/trezor-core/v{}/src/apps/ethereum/tokens.py",
}
TOKEN_MATCH = {
"1": re.compile(r'\{.*" ([^"]+)".*\},'),
"2": re.compile(r'\(.*["\']([^"\']+)["\'].*\),'),
}
def latest_releases():
if not requests:
raise RuntimeError("requests library is required for getting release info")
latest = {}
for v in ("1", "2"):
releases = requests.get(RELEASES_URL.format(v)).json()
latest[v] = max(tuple(r["version"]) for r in releases)
return latest
def support_info_erc20(coins, versions):
supported_tokens = {}
for trezor, version in versions.items():
tokens = set()
version_str = ".".join(map(str, version))
token_file = requests.get(ETHEREUM_TOKENS[trezor].format(version_str)).text
token_match = TOKEN_MATCH[trezor]
for line in token_file.split("\n"):
m = token_match.search(line)
if m:
tokens.add(m.group(1))
supported_tokens[trezor] = tokens
support = {}
for coin in coins:
key = coin["key"]
if not key.startswith("erc20:"):
continue
support[key] = dict(
trezor1="yes" if coin["shortcut"] in supported_tokens["1"] else "soon",
trezor2="yes" if coin["shortcut"] in supported_tokens["2"] else "soon",
)
return support
def support_info(coins, erc20_versions=None):
support_data = load_json("support.json")
support = {}
for coin in coins:
key = coin["key"]
typ = key.split(":", maxsplit=1)[0]
if key in support_data:
support[key] = support_data[key]
elif typ in ("nem", "eth"):
support[key] = dict(trezor1="yes", trezor2="yes")
elif typ == "erc20":
# you must call a separate function to get that
continue
else:
log.warning("support info missing for {}".format(key))
support[key] = {}
if erc20_versions:
erc20 = support_info_erc20(coins, erc20_versions)
erc20.update(support)
return erc20
else:
return support
# ====== data cleanup functions ======
def find_address_collisions(coins):
slip44 = defaultdict(list)
at_p2pkh = defaultdict(list)
at_p2sh = defaultdict(list)
for name, coin in coins.items():
s = coin["slip44"]
# ignore m/1 testnets
if not (name.endswith("Testnet") and s == 1):
slip44[s].append(s)
# skip address types on cashaddr currencies
if coin["cashaddr_prefix"]:
continue
at_p2pkh[coin["address_type"]].append(name)
at_p2sh[coin["address_type_p2sh"]].append(name)
def prune(d):
ret = d.copy()
for key in d.keys():
if len(d[key]) < 2:
del ret[key]
return ret
return dict(
slip44=prune(slip44),
address_type=prune(at_p2pkh),
address_type_p2sh=prune(at_p2sh),
)
def ensure_mandatory_values(coins):
for coin in coins:
if not all(coin.get(k) for k in ("name", "shortcut", "key")):
raise ValueError(coin)
def filter_duplicate_shortcuts(coins):
dup_keys = set()
retained_coins = OrderedDict()
for coin in coins:
key = coin["shortcut"]
if key in dup_keys:
pass
elif key in retained_coins:
dup_keys.add(key)
del retained_coins[key]
else:
retained_coins[key] = coin
# modify original list
coins[:] = retained_coins.values()
# return duplicates
return dup_keys
def _btc_sort_key(coin):
if coin["name"] in ("Bitcoin", "Testnet"):
return "000000" + coin["name"]
else:
return coin["name"]
def get_all():
all_coins = dict(
btc=get_coins(),
eth=get_ethereum_networks(),
erc20=get_erc20_tokens(),
nem=get_nem_mosaics(),
other=get_others(),
)
for k, coins in all_coins.items():
if k == "btc":
coins.sort(key=_btc_sort_key)
else:
coins.sort(key=lambda c: c["key"].upper())
ensure_mandatory_values(coins)
if k != "eth":
dup_keys = filter_duplicate_shortcuts(coins)
if dup_keys:
log.warning(
"{}: removing duplicate symbols: {}".format(k, ", ".join(dup_keys))
)
return all_coins
def get_list():
all_coins = get_all()
return sum(all_coins.values(), [])
def get_dict():
return {coin["key"]: coin for coin in get_list()}

View File

@ -2,26 +2,39 @@
"""Fetch information about coins and tokens supported by Trezor and update it in coins_details.json.""" """Fetch information about coins and tokens supported by Trezor and update it in coins_details.json."""
import time import time
import json import json
import logging
import requests import requests
import ethereum_tokens_gen import coin_defs
import build_coins
from distutils.version import LooseVersion
T1_LATEST='1.6.2' OPTIONAL_KEYS = ("links", "notes", "wallet")
T2_LATEST='2.0.7' OVERRIDES = coin_defs.load_json("coins_details.override.json")
VERSIONS = coin_defs.latest_releases()
COINS = {} COINS = {}
log = logging.getLogger(__name__)
def coinmarketcap_init(): def coinmarketcap_init():
global COINS global COINS
try: try:
COINS = json.load(open('coinmarketcap.json', 'r')) marketcap_json = json.load(open("coinmarketcap.json", "r"))
except FileNotFoundError: except FileNotFoundError:
pass pass
else: else:
if COINS["1"]["last_updated"] > time.time() - 3600: pass
print("Using local cache of coinmarketcap") # if COINS["1"]["last_updated"] > time.time() - 3600:
# print("Using local cache of coinmarketcap")
# return
for coin in marketcap_json.values():
slug = coin["website_slug"]
market_cap = coin["quotes"]["USD"]["market_cap"]
if market_cap is not None:
COINS[slug] = int(float(market_cap))
return return
print("Updating coins from coinmarketcap") print("Updating coins from coinmarketcap")
@ -29,333 +42,303 @@ def coinmarketcap_init():
COINS = {} COINS = {}
while total is None or len(COINS) < total: while total is None or len(COINS) < total:
url = 'https://api.coinmarketcap.com/v2/ticker/?start=%d&convert=USD&limit=100' % (len(COINS)) url = (
"https://api.coinmarketcap.com/v2/ticker/?start=%d&convert=USD&limit=100"
% (len(COINS) + 1)
)
data = requests.get(url).json() data = requests.get(url).json()
COINS.update(data['data']) COINS.update(data["data"])
if total is None: if total is None:
total = data['metadata']['num_cryptocurrencies'] total = data["metadata"]["num_cryptocurrencies"]
print("Fetched %d of %d coins" % (len(COINS), total)) print("Fetched %d of %d coins" % (len(COINS), total))
time.sleep(1) time.sleep(1)
json.dump(COINS, open('coinmarketcap.json', 'w'), sort_keys=True, indent=4) json.dump(COINS, open("coinmarketcap.json", "w"), sort_keys=True, indent=4)
def coinmarketcap_info(shortcut): def marketcap(coin):
global COINS cap = None
shortcut = shortcut.replace(' ', '-').lower()
for _id in COINS: if "coinmarketcap_alias" in coin:
coin = COINS[_id] cap = COINS.get(coin["coinmarketcap_alias"])
# print(shortcut, coin['website_slug'])
if shortcut == coin['website_slug']: if not cap:
# print(coin) slug = coin["name"].replace(" ", "-").lower()
return coin cap = COINS.get(slug)
if not cap:
cap = COINS.get(coin["shortcut"].lower())
return cap
def update_marketcap(obj, *shortcuts): def update_marketcap(coins):
for sym in shortcuts: for coin in coins.values():
try: cap = marketcap(coin)
obj['marketcap_usd'] = int(float(coinmarketcap_info(sym)['quotes']['USD']['market_cap'])) if cap:
return coin["marketcap_usd"] = cap
except:
pass
# print("Marketcap info not found for", shortcut)
def coinmarketcap_global(): def coinmarketcap_global():
url = 'https://api.coinmarketcap.com/v2/global' url = "https://api.coinmarketcap.com/v2/global"
ret = requests.get(url) ret = requests.get(url)
data = ret.json() data = ret.json()
return data return data
def set_default(obj, key, default_value):
obj[key] = obj.setdefault(key, default_value)
def update_info(details): def update_info(details):
details['info']['updated_at'] = int(time.time()) details["info"]["updated_at"] = int(time.time())
details['info']['updated_at_readable'] = time.asctime() details["info"]["updated_at_readable"] = time.asctime()
details['info']['t1_coins'] = len([True for _, c in details['coins'].items() if c.get('t1_enabled') == 'yes' and not c.get('hidden', False)]) details["info"]["t1_coins"] = len(
details['info']['t2_coins'] = len([True for _, c in details['coins'].items() if c.get('t2_enabled') == 'yes' and not c.get('hidden', False)]) [
True
for _, c in details["coins"].items()
if c.get("t1_enabled") == "yes" and not c.get("hidden", False)
]
)
details["info"]["t2_coins"] = len(
[
True
for _, c in details["coins"].items()
if c.get("t2_enabled") == "yes" and not c.get("hidden", False)
]
)
try: try:
details['info']['total_marketcap_usd'] = int(coinmarketcap_global()['data']['quotes']['USD']['total_market_cap']) details["info"]["total_marketcap_usd"] = int(
coinmarketcap_global()["data"]["quotes"]["USD"]["total_market_cap"]
)
except: except:
pass pass
marketcap = 0 marketcap = 0
for k, c in details['coins'].items(): for k, c in details["coins"].items():
if c['t1_enabled'] == 'yes' or c['t2_enabled'] == 'yes': if c["t1_enabled"] == "yes" or c["t2_enabled"] == "yes":
marketcap += details['coins'][k].setdefault('marketcap_usd', 0) marketcap += details["coins"][k].setdefault("marketcap_usd", 0)
details['info']['marketcap_usd'] = marketcap details["info"]["marketcap_usd"] = marketcap
def check_unsupported(details, prefix, supported): def check_unsupported(details, prefix, supported):
for k in details['coins'].keys(): for k in details["coins"].keys():
if not k.startswith(prefix): if not k.startswith(prefix):
continue continue
if k not in supported: if k not in supported:
print("%s not supported by Trezor? (Possible manual entry)" % k) print("%s not supported by Trezor? (Possible manual entry)" % k)
def update_coins(details): def _is_supported(support, trezor_version):
(coins, _) = build_coins.process(None) version = VERSIONS[str(trezor_version)]
firmware = json.load(open('../defs/support.json', 'r')) nominal = support.get("trezor" + str(trezor_version))
if nominal is None:
return "no"
elif isinstance(nominal, bool):
return "yes" if nominal else "no"
supported = [] try:
for key, coin in coins.items(): nominal_version = tuple(map(int, nominal.split(".")))
return "yes" if nominal_version <= version else "soon"
except ValueError:
return nominal
t1_enabled = 'no'
if key in firmware['trezor1']: def _webwallet_support(coin, support):
if LooseVersion(firmware['trezor1'][key]) <= LooseVersion(T1_LATEST): """Check the "webwallet" support property.
t1_enabled = 'yes' If set, check that at least one of the backends run on trezor.io.
If yes, assume we support the coin in our wallet.
Otherwise it's probably working with a custom backend, which means don't
link to our wallet.
"""
if not support.get("webwallet"):
return False
return any(".trezor.io" in url for url in coin["blockbook"] + coin["bitcore"])
def update_coins(coins, support_info):
res = {}
for coin in coins:
key = coin["key"]
support = support_info[key]
details = dict(
type="coin",
shortcut=coin["shortcut"],
name=coin["coin_label"],
links=dict(Homepage=coin["website"], Github=coin["github"]),
t1_enabled=_is_supported(support, 1),
t2_enabled=_is_supported(support, 2),
wallet={},
)
if _webwallet_support(coin, support):
details["wallet"]["Trezor"] = "https://wallet.trezor.io"
if support.get("other"):
details["wallet"].update(support["other"])
# XXX get rid of this in favor of res[key]
res["coin:{}".format(coin["shortcut"])] = details
return res
def update_erc20(coins, support_info):
# TODO skip disabled networks?
res = {}
for coin in coins:
key = coin["key"]
support = support_info[key]
details = dict(
type="erc20",
network=coin["chain"],
address=coin["address"],
shortcut=coin["shortcut"],
name=coin["name"],
links={},
wallet=dict(
MyCrypto="https://mycrypto.com",
MyEtherWallet="https://www.myetherwallet.com",
),
t1_enabled=support["trezor1"],
t2_enabled=support["trezor2"],
)
if coin.get("website"):
details["links"]["Homepage"] = coin["website"]
if coin.get("social", {}).get("github"):
details["links"]["Github"] = coin["social"]["github"]
res[key] = details
return res
def update_simple(coins, support_info, type):
res = {}
for coin in coins:
key = coin["key"]
support = support_info[key]
# XXX drop newkey
if type == "mosaic":
newkey = "mosaic:{}".format(coin["shortcut"])
else: else:
t1_enabled = 'soon' newkey = "coin2:{}".format(coin["shortcut"])
t2_enabled = 'no' details = dict(
if key in firmware['trezor2']: name=coin["name"],
if LooseVersion(firmware['trezor2'][key]) <= LooseVersion(T2_LATEST): shortcut=coin["shortcut"],
t2_enabled = 'yes' type=type,
else: t1_enabled=_is_supported(support, 1),
t2_enabled = 'soon' t2_enabled=_is_supported(support, 2),
)
for key in OPTIONAL_KEYS:
if key in coin:
details[key] = coin[key]
# print("Updating", coin['coin_label'], coin['coin_shortcut']) res[newkey] = details
key = "coin:%s" % coin['coin_shortcut']
supported.append(key)
out = details['coins'].setdefault(key, {})
out['type'] = 'coin'
out['t1_enabled'] = t1_enabled
out['t2_enabled'] = t2_enabled
set_default(out, 'shortcut', coin['coin_shortcut']) return res
set_default(out, 'name', coin['coin_label'])
set_default(out, 'links', {})
set_default(out['links'], 'Homepage', coin['website'])
set_default(out['links'], 'Github', coin['github'])
set_default(out, 'wallet', {})
update_marketcap(out, coin.get('coinmarketcap_alias', coin['coin_label']))
check_unsupported(details, 'coin:', supported)
def update_erc20(details): def update_ethereum_networks(coins, support_info):
networks = [x[0] for x in ethereum_tokens_gen.networks] res = update_simple(coins, support_info, "coin")
for coin in coins:
LATEST_T1 = 'https://raw.githubusercontent.com/trezor/trezor-mcu/v%s/firmware/ethereum_tokens.c' % T1_LATEST newkey = "coin2:{}".format(coin["shortcut"])
LATEST_T2 = 'https://raw.githubusercontent.com/trezor/trezor-core/v%s/src/apps/ethereum/tokens.py' % T2_LATEST res[newkey]["wallet"] = dict(
MyCrypto="https://mycrypto.com",
tokens = ethereum_tokens_gen.get_tokens() MyEtherWallet="https://www.myetherwallet.com",
tokens_t1 = requests.get(LATEST_T1).text )
tokens_t2 = requests.get(LATEST_T2).text res[newkey]["links"] = dict(Homepage=coin.get("url"))
return res
supported = []
for t in tokens:
# print('Updating', t['symbol'])
if t['chain'] not in networks:
print('Skipping, %s is disabled' % t['chain'])
continue
key = "erc20:%s:%s" % (t['chain'], t['symbol'])
supported.append(key)
out = details['coins'].setdefault(key, {})
out['type'] = 'erc20'
out['network'] = t['chain']
out['address'] = t['address']
set_default(out, 'shortcut', t['symbol'])
set_default(out, 'name', t['name'])
set_default(out, 'links', {})
set_default(out, 'wallet', {})
if "\" %s\"" % t['symbol'] in tokens_t1:
out['t1_enabled'] = 'yes'
else:
out['t1_enabled'] = 'soon'
if "'%s'" % t['symbol'] in tokens_t2:
out['t2_enabled'] = 'yes'
else:
out['t2_enabled'] = 'soon'
out['wallet']['MyCrypto'] = 'https://mycrypto.com'
out['wallet']['MyEtherWallet'] = 'https://www.myetherwallet.com'
if t.get('website'):
out['links']['Homepage'] = t['website']
if t.get('social', {}).get('github', None):
out['links']['Github'] = t['social']['github']
update_marketcap(out, out.get('coinmarketcap_alias'), t['name'], t['symbol'])
check_unsupported(details, 'erc20:', supported)
def update_ethereum(details):
out = details['coins'].setdefault('coin2:ETH', {})
out['type'] = 'coin'
set_default(out, 'shortcut', 'ETH')
set_default(out, 'name', 'Ethereum')
set_default(out, 't1_enabled', 'yes')
set_default(out, 't2_enabled', 'yes')
update_marketcap(out, 'ethereum')
out = details['coins'].setdefault('coin2:ETC', {})
out['type'] = 'coin'
set_default(out, 'shortcut', 'ETC')
set_default(out, 'name', 'Ethereum Classic')
set_default(out, 't1_enabled', 'yes')
set_default(out, 't2_enabled', 'yes')
update_marketcap(out, 'ethereum-classic')
out = details['coins'].setdefault('coin2:RSK', {})
out['type'] = 'coin'
set_default(out, 'shortcut', 'RSK')
set_default(out, 'name', 'Rootstock')
set_default(out, 't1_enabled', 'yes')
set_default(out, 't2_enabled', 'yes')
update_marketcap(out, 'rootstock')
out = details['coins'].setdefault('coin2:EXP', {})
out['type'] = 'coin'
set_default(out, 'shortcut', 'EXP')
set_default(out, 'name', 'Expanse')
set_default(out, 't1_enabled', 'yes')
set_default(out, 't2_enabled', 'yes')
update_marketcap(out, 'expanse')
out = details['coins'].setdefault('coin2:UBQ', {})
out['type'] = 'coin'
set_default(out, 'shortcut', 'UBQ')
set_default(out, 'name', 'Ubiq')
set_default(out, 't1_enabled', 'yes')
set_default(out, 't2_enabled', 'yes')
update_marketcap(out, 'ubiq')
out = details['coins'].setdefault('coin2:ELLA', {})
out['type'] = 'coin'
set_default(out, 'shortcut', 'ELLA')
set_default(out, 'name', 'Ellaism')
set_default(out, 't1_enabled', 'yes')
set_default(out, 't2_enabled', 'yes')
update_marketcap(out, 'ellaism')
out = details['coins'].setdefault('coin2:EGEM', {})
out['type'] = 'coin'
set_default(out, 'shortcut', 'EGEM')
set_default(out, 'name', 'EtherGem')
set_default(out, 't1_enabled', 'yes')
set_default(out, 't2_enabled', 'yes')
update_marketcap(out, 'egem')
out = details['coins'].setdefault('coin2:ETSC', {})
out['type'] = 'coin'
set_default(out, 'shortcut', 'ETSC')
set_default(out, 'name', 'Ethereum Social')
set_default(out, 't1_enabled', 'yes')
set_default(out, 't2_enabled', 'yes')
update_marketcap(out, 'etsc')
out = details['coins'].setdefault('coin2:EOSC', {})
out['type'] = 'coin'
set_default(out, 'shortcut', 'EOSC')
set_default(out, 'name', 'EOS Classic')
set_default(out, 't1_enabled', 'yes')
set_default(out, 't2_enabled', 'yes')
update_marketcap(out, 'eosc')
out = details['coins'].setdefault('coin2:ADA', {})
out['type'] = 'coin'
set_default(out, 'shortcut', 'ADA')
set_default(out, 'name', 'Cardano')
set_default(out, 't1_enabled', 'no')
set_default(out, 't2_enabled', 'soon')
update_marketcap(out, 'cardano')
out = details['coins'].setdefault('coin2:XTZ', {})
out['type'] = 'coin'
set_default(out, 'shortcut', 'XTZ')
set_default(out, 'name', 'Tezos')
set_default(out, 't1_enabled', 'no')
set_default(out, 't2_enabled', 'soon')
update_marketcap(out, 'tezos')
def update_mosaics(details):
d = json.load(open('../defs/nem/nem_mosaics.json'))
supported = []
for mosaic in d:
# print('Updating', mosaic['name'], mosaic['ticker'])
key = "mosaic:%s" % mosaic['ticker'].strip()
supported.append(key)
out = details['coins'].setdefault(key, {})
out['type'] = 'mosaic'
set_default(out, 'shortcut', mosaic['ticker'].strip())
set_default(out, 'name', mosaic['name'])
set_default(out, 't1_enabled', 'yes')
set_default(out, 't2_enabled', 'yes')
update_marketcap(out, out.get('coinmarketcap_alias', out['name']))
check_unsupported(details, 'mosaic:', supported)
def check_missing_details(details): def check_missing_details(details):
for k in details['coins'].keys(): for k in details["coins"].keys():
coin = details['coins'][k] coin = details["coins"][k]
hide = False hide = False
if 'links' not in coin: if "links" not in coin:
print("%s: Missing links" % k) print("%s: Missing links" % k)
hide = True hide = True
if 'Homepage' not in coin.get('links', {}): if "Homepage" not in coin.get("links", {}):
print("%s: Missing homepage" % k) print("%s: Missing homepage" % k)
hide = True hide = True
if coin['t1_enabled'] not in ('yes', 'no', 'planned', 'soon'): if coin["t1_enabled"] not in ("yes", "no", "planned", "soon"):
print("%s: Unknown t1_enabled" % k) print("%s: Unknown t1_enabled" % k)
hide = True hide = True
if coin['t2_enabled'] not in ('yes', 'no', 'planned', 'soon'): if coin["t2_enabled"] not in ("yes", "no", "planned", "soon"):
print("%s: Unknown t2_enabled" % k) print("%s: Unknown t2_enabled" % k)
hide = True hide = True
if 'Trezor' in coin.get('wallet', {}) and coin['wallet']['Trezor'] != 'https://wallet.trezor.io': if (
"Trezor" in coin.get("wallet", {})
and coin["wallet"]["Trezor"] != "https://wallet.trezor.io"
):
print("%s: Strange URL for Trezor Wallet" % k) print("%s: Strange URL for Trezor Wallet" % k)
hide = True hide = True
if len(coin.get('wallet', {})) == 0: if len(coin.get("wallet", {})) == 0:
print("%s: Missing wallet" % k) print("%s: Missing wallet" % k)
if "Testnet" in coin["name"]:
print("%s: Hiding testnet" % k)
hide = True
if hide: if hide:
if coin.get('hidden') != 1: if coin.get("hidden") != 1:
print("%s: HIDING COIN!" % k) print("%s: HIDING COIN!" % k)
# If any of important detail is missing, hide coin from list # If any of important detail is missing, hide coin from list
coin['hidden'] = 1 coin["hidden"] = 1
if not hide and coin.get('hidden'): if not hide and coin.get("hidden"):
print("%s: Details are OK, but coin is still hidden" % k) print("%s: Details are OK, but coin is still hidden" % k)
for k in details['coins'].keys(): for k in details["coins"].keys():
if details['coins'][k].get('hidden') == 1: if details["coins"][k].get("hidden") == 1:
print("%s: Coin is hidden" % k) print("%s: Coin is hidden" % k)
if __name__ == '__main__': def apply_overrides(coins):
try: for key, override in OVERRIDES.items():
details = json.load(open('../defs/coins_details.json', 'r')) if key not in coins:
except FileNotFoundError: log.warning("override without coin: {}".format(key))
details = {'coins': {}, 'info': {}} continue
def recursive_update(orig, new):
if isinstance(new, dict) and isinstance(orig, dict):
for k, v in new.items():
orig[k] = recursive_update(orig.get(k), v)
else:
return new
coin = coins[key]
recursive_update(coin, override)
if __name__ == "__main__":
# try:
# details = json.load(open('../defs/coins_details.json', 'r'))
# except FileNotFoundError:
# details = {'coins': {}, 'info': {}}
coinmarketcap_init() coinmarketcap_init()
update_coins(details)
update_erc20(details) defs = coin_defs.get_all()
update_ethereum(details) all_coins = sum(defs.values(), [])
update_mosaics(details) support_info = coin_defs.support_info(all_coins, erc20_versions=VERSIONS)
coins = {}
coins.update(update_coins(defs["btc"], support_info))
coins.update(update_erc20(defs["erc20"], support_info))
coins.update(update_ethereum_networks(defs["eth"], support_info))
coins.update(update_simple(defs["nem"], support_info, "mosaic"))
coins.update(update_simple(defs["other"], support_info, "coin"))
apply_overrides(coins)
update_marketcap(coins)
details = dict(coins=coins, info={})
update_info(details) update_info(details)
check_missing_details(details) check_missing_details(details)
print(json.dumps(details['info'], sort_keys=True, indent=4)) print(json.dumps(details["info"], sort_keys=True, indent=4))
json.dump(details, open('../defs/coins_details.json', 'w'), sort_keys=True, indent=4) json.dump(details, open("../defs/coins_details.json", "w"), sort_keys=True, indent=4)