feat(common): add wallet info to cointool dump

pull/2303/head
grdddj 2 years ago committed by Jiří Musil
parent 08f463e5e8
commit 9261f2ffce

@ -123,5 +123,13 @@
},
"eth:WAN": {
"Wanchain Wallet": "https://www.wanchain.org/getstarted/"
},
"eth:AUX": {
"MyEtherWallet": null
},
"eth:XDC": {
"MyCrypto": null,
"MyEtherWallet": null,
"XDC Wallet": "https://wallet.xinfin.network"
}
}

@ -50,6 +50,9 @@ class SupportInfoItem(TypedDict):
SupportInfo = dict[str, SupportInfoItem]
WalletItems = dict[str, str]
WalletInfo = dict[str, WalletItems]
class Coin(TypedDict):
# Necessary fields for BTC - from BTC_CHECKS
@ -86,7 +89,7 @@ class Coin(TypedDict):
# Other fields optionally coming from JSON
links: dict[str, str]
wallet: dict[str, str]
wallet: WalletItems
curve: str
decimals: int
@ -540,6 +543,115 @@ def support_info(coins: Iterable[Coin] | CoinsInfo | dict[str, Coin]) -> Support
return support
# ====== wallet info ======
WALLET_SUITE = {"Trezor Suite": "https://suite.trezor.io"}
WALLET_NEM = {"Nano Wallet": "https://nemplatform.com/wallets/#desktop"}
WALLETS_ETH_3RDPARTY = {
"MyEtherWallet": "https://www.myetherwallet.com",
"MyCrypto": "https://mycrypto.com",
}
def get_wallet_data() -> WalletInfo:
"""Get wallet data from `wallets.json`."""
return load_json("wallets.json")
def _suite_support(coin: Coin, support: SupportInfoItem) -> bool:
"""Check the "suite" support property.
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["suite"]:
return False
return any(".trezor.io" in url for url in coin["blockbook"])
def wallet_info_single(
support_data: SupportInfo,
eth_networks_support_data: SupportInfo,
wallet_data: WalletInfo,
coin: Coin,
) -> WalletItems:
"""Adds together a dict of all wallets for a coin."""
wallets: WalletItems = {}
key = coin["key"]
# Add wallets from the coin itself
# (usually not there, only for the `misc` category)
wallets.update(coin.get("wallet", {}))
# Each coin category has different further logic
if key.startswith("bitcoin:"):
if _suite_support(coin, support_data[key]):
wallets.update(WALLET_SUITE)
elif key.startswith("eth:"):
if support_data[key]["suite"]:
wallets.update(WALLET_SUITE)
else:
wallets.update(WALLETS_ETH_3RDPARTY)
elif key.startswith("erc20:"):
if eth_networks_support_data[coin["chain"]]["suite"]:
wallets.update(WALLET_SUITE)
else:
wallets.update(WALLETS_ETH_3RDPARTY)
elif key.startswith("nem:"):
wallets.update(WALLET_NEM)
elif key.startswith("misc:"):
pass # no special logic here
else:
raise ValueError(f"Unknown coin category: {key}")
# Add wallets from `wallets.json`
# This must come last as it offers the ability to override existing wallets
# (for example with `"MyEtherWallet": null` we delete the MyEtherWallet from the coin)
wallets.update(wallet_data.get(key, {}))
# Removing potentially disabled wallets from the last step
wallets = {name: url for name, url in wallets.items() if url}
return wallets
def wallet_info(coins: Iterable[Coin] | CoinsInfo | dict[str, Coin]) -> WalletInfo:
"""Generate Trezor wallet information.
Takes a collection of coins and generates a WalletItems entry for each.
The WalletItems is a dict with keys being the names of the wallets and
values being the URLs to those - same format as in `wallets.json`.
The `coins` argument can be a `CoinsInfo` object, a list or a dict of
coin items.
Wallet information is taken from `wallets.json`.
"""
if isinstance(coins, CoinsInfo):
coins = coins.as_list()
elif isinstance(coins, dict):
coins = coins.values()
support_data = support_info(coins)
wallet_data = get_wallet_data()
# Needed to find out suitable wallets for all the erc20 coins (Suite vs 3rd party)
eth_networks = [coin for coin in coins if coin["key"].startswith("eth:")]
eth_networks_support_data = {
n["chain"]: support_data[n["key"]] for n in eth_networks
}
wallet: WalletInfo = {}
for coin in coins:
wallet[coin["key"]] = wallet_info_single(
support_data, eth_networks_support_data, wallet_data, coin
)
return wallet
# ====== data cleanup functions ======

@ -711,6 +711,7 @@ device_choice = click.Choice(["connect", "suite", "trezor1", "trezor2"])
# fmt: off
@click.option("-o", "--outfile", type=click.File(mode="w"), default="-")
@click.option("-s/-S", "--support/--no-support", default=True, help="Include support data for each coin")
@click.option("-w/-W", "--wallet/--no-wallet", default=True, help="Include wallet data for each coin")
@click.option("-p", "--pretty", is_flag=True, help="Generate nicely formatted JSON")
@click.option("-l", "--list", "flat_list", is_flag=True, help="Output a flat list of coins")
@click.option("-i", "--include", metavar="FIELD", multiple=True, help="Include only these fields (-i shortcut -i name)")
@ -726,6 +727,7 @@ device_choice = click.Choice(["connect", "suite", "trezor1", "trezor2"])
def dump(
outfile: TextIO,
support: bool,
wallet: bool,
pretty: bool,
flat_list: bool,
include: tuple[str, ...],
@ -770,6 +772,9 @@ def dump(
Also devices can be used as filters. For example to find out which coins are
supported in Suite and connect but not on Trezor 1, it is possible to say
'-d suite -d connect -D trezor1'.
Includes even the wallet data, unless turned off by '-W'.
These can be filtered by using '-f', for example `-f 'wallet=*exodus*'` (* are necessary)
"""
if exclude_tokens:
exclude_type += ("erc20",)
@ -786,6 +791,7 @@ def dump(
# getting initial info
coins = coin_info.coin_info()
support_info = coin_info.support_info(coins.as_list())
wallet_info = coin_info.wallet_info(coins)
# optionally adding support info
if support:
@ -793,6 +799,12 @@ def dump(
for coin in category:
coin["support"] = support_info[coin["key"]]
# optionally adding wallet info
if wallet:
for category in coins.values():
for coin in category:
coin["wallet"] = wallet_info[coin["key"]]
# filter types
if include_type:
coins_dict = {k: v for k, v in coins.items() if k in include_type}

Loading…
Cancel
Save