import sys import time import click import coin_info import marketcap LOG = logging.getLogger(__name__) OPTIONAL_KEYS = ("links", "notes", "wallet") ALLOWED_SUPPORT_STATUS = ("yes", "no", "planned", "soon") WALLETS = coin_info.load_json("wallets.json") OVERRIDES = coin_info.load_json("coins_details.override.json") VERSIONS = coin_info.latest_releases() # automatic wallet entries WALLET_SUITE = {"Trezor Suite": "https://suite.trezor.io"} WALLET_NEM = { "Nano Wallet": "https://nem.io/downloads/", "Magnum": "https://magnumwallet.co", } WALLETS_ETH_3RDPARTY = { "MyEtherWallet": "https://www.myetherwallet.com", "MyCrypto": "https://mycrypto.com", } TREZOR_KNOWN_URLS = ( "https://suite.trezor.io", "https://wallet.trezor.io",
def release( ctx, device: str, version, git_tag, release_missing, dry_run, soon, force, add_all, verbose, ): """Release a new Trezor firmware. Update support infos so that all coins have a clear support status. By default, marks duplicate tokens as unsupported, and all coins that either don't have support info, or they are supported "soon", are set to the released firmware version. Optionally tags the repository with the given version. `device` can be "1", "2", or a string matching `support.json` key. Version is autodetected by downloading a list of latest releases and incrementing micro version by one, or you can specify `--version` explicitly. Unless `--add-all` is specified, the tool will ask you to confirm each added coin. ERC20 tokens are added automatically. Use `--verbose` to see them. """ # check condition(s) if soon and git_tag: raise click.ClickException("Cannot git-tag a 'soon' revision") # process `device` if device.isnumeric(): device = f"trezor{device}" if not force and device not in coin_info.VERSIONED_SUPPORT_INFO: raise click.ClickException( f"Non-releasable device {device} (support info is not versioned). " "Use --force to proceed anyway.") if not soon: # guess `version` if not given if not version: versions = coin_info.latest_releases() latest_version = versions.get(device) if latest_version is None: raise click.ClickException( "Failed to guess version. " "Please use --version to specify it explicitly.") else: latest_version = list(latest_version) latest_version[-1] += 1 version = ".".join(str(n) for n in latest_version) # process `version` try: version_numbers = list(map(int, version.split("."))) expected_device = f"trezor{version_numbers[0]}" if not force and device != expected_device: raise click.ClickException( f"Device {device} should not be version {version}. " "Use --force to proceed anyway.") except ValueError as e: if not force: raise click.ClickException( f"Failed to parse '{version}' as a version. " "Use --force to proceed anyway.") from e if soon: version = "soon" print(f"Moving {device} missing infos to 'soon'") else: print(f"Releasing {device} firmware version {version}") defs, _ = coin_info.coin_info_with_duplicates() coins_dict = defs.as_dict() # Invoke data fixup as dry-run. That will modify data internally but won't write # changes. We will write changes at the end based on our own `dry_run` value. print("Fixing up data...") ctx.invoke(fix, dry_run=True) def maybe_add(coin, label): add = False if add_all: add = True else: text = f"Add {label} coin {coin['key']} ({coin['name']})?" add = click.confirm(text, default=True) if add: set_supported(device, coin["key"], version) # if we're releasing, process coins marked "soon" if not soon: supported, _ = support_dicts(device) soon_list = [ coins_dict[key] for key, val in supported.items() if val == "soon" and key in coins_dict ] for coin in soon_list: key = coin["key"] maybe_add(coin, "soon") # process missing (not listed) supportinfos if release_missing: missing_list = find_unsupported_coins(coins_dict)[device] tokens = [coin for coin in missing_list if coin_info.is_token(coin)] nontokens = [ coin for coin in missing_list if not coin_info.is_token(coin) ] for coin in tokens: key = coin["key"] # assert not coin.get("duplicate"), key if verbose: print(f"Adding missing {key} ({coin['name']})") set_supported(device, key, version) for coin in nontokens: maybe_add(coin, "missing") tagname = f"{device}-{version}" if git_tag: if dry_run: print(f"Would tag current commit with {tagname}") else: print(f"Tagging current commit with {tagname}") subprocess.check_call(["git", "tag", tagname]) if not dry_run: write_support_info() else: print("No changes written")
import json import logging import requests import sys import coin_info import click LOG = logging.getLogger(__name__) OPTIONAL_KEYS = ("links", "notes", "wallet") ALLOWED_SUPPORT_STATUS = ("yes", "no", "planned", "soon") WALLETS = coin_info.load_json("wallets.json") OVERRIDES = coin_info.load_json("coins_details.override.json") VERSIONS = coin_info.latest_releases() COINMAKETCAP_CACHE = os.path.join(os.path.dirname(__file__), "coinmarketcap.json") COINMARKETCAP_API_BASE = "https://pro-api.coinmarketcap.com/v1/" MARKET_CAPS = {} # automatic wallet entries WALLET_TREZOR = {"Trezor": "https://wallet.trezor.io"} WALLET_TREZOR_NEXT = {"Trezor Beta": "https://beta-wallet.trezor.io/next/"} WALLET_NEM = {"Nano Wallet": "https://nem.io/downloads/"} WALLETS_ETH_3RDPARTY = { "MyEtherWallet": "https://www.myetherwallet.com", "MyCrypto": "https://mycrypto.com", }
def release( ctx, device: str, version, git_tag, release_missing, dry_run, soon, force, add_all, verbose, ): """Release a new Trezor firmware. Update support infos so that all coins have a clear support status. By default, marks duplicate tokens as unsupported, and all coins that either don't have support info, or they are supported "soon", are set to the released firmware version. Optionally tags the repository with the given version. `device` can be "1", "2", or a string matching `support.json` key. Version is autodetected by downloading a list of latest releases and incrementing micro version by one, or you can specify `--version` explicitly. Unless `--add-all` is specified, the tool will ask you to confirm each added coin. ERC20 tokens are added automatically. Use `--verbose` to see them. """ # check condition(s) if soon and git_tag: raise click.ClickException("Cannot git-tag a 'soon' revision") # process `device` if device.isnumeric(): device = f"trezor{device}" if not force and device not in coin_info.VERSIONED_SUPPORT_INFO: raise click.ClickException( f"Non-releasable device {device} (support info is not versioned). " "Use --force to proceed anyway." ) if not soon: # guess `version` if not given if not version: versions = coin_info.latest_releases() latest_version = versions.get(device) if latest_version is None: raise click.ClickException( "Failed to guess version. " "Please use --version to specify it explicitly." ) else: latest_version = list(latest_version) latest_version[-1] += 1 version = ".".join(str(n) for n in latest_version) # process `version` try: version_numbers = list(map(int, version.split("."))) expected_device = f"trezor{version_numbers[0]}" if not force and device != expected_device: raise click.ClickException( f"Device {device} should not be version {version}. " "Use --force to proceed anyway." ) except ValueError as e: if not force: raise click.ClickException( f"Failed to parse '{version}' as a version. " "Use --force to proceed anyway." ) from e if soon: version = "soon" print(f"Moving {device} missing infos to 'soon'") else: print(f"Releasing {device} firmware version {version}") defs, _ = coin_info.coin_info_with_duplicates() coins_dict = defs.as_dict() # Invoke data fixup as dry-run. That will modify data internally but won't write # changes. We will write changes at the end based on our own `dry_run` value. print("Fixing up data...") ctx.invoke(fix, dry_run=True) def maybe_add(coin, label): add = False if add_all: add = True else: text = f"Add {label} coin {coin['key']} ({coin['name']})?" add = click.confirm(text, default=True) if add: set_supported(device, coin["key"], version) # if we're releasing, process coins marked "soon" if not soon: supported, _ = support_dicts(device) soon_list = [ coins_dict[key] for key, val in supported.items() if val == "soon" and key in coins_dict ] for coin in soon_list: key = coin["key"] maybe_add(coin, "soon") # process missing (not listed) supportinfos if release_missing: missing_list = find_unsupported_coins(coins_dict)[device] tokens = [coin for coin in missing_list if coin_info.is_token(coin)] nontokens = [coin for coin in missing_list if not coin_info.is_token(coin)] for coin in tokens: key = coin["key"] assert not coin.get("duplicate") if verbose: print(f"Adding missing {key} ({coin['name']})") set_supported(device, key, version) for coin in nontokens: maybe_add(coin, "missing") tagname = f"{device}-{version}" if git_tag: if dry_run: print(f"Would tag current commit with {tagname}") else: print(f"Tagging current commit with {tagname}") subprocess.check_call(["git", "tag", tagname]) if not dry_run: write_support_info() else: print("No changes written")
def release( ctx, v1, v2, dry_run, force, verbose, skip_testnets, ): """Release a new Trezor firmware. Update support infos so that all coins have a clear support status. By default, marks duplicate tokens and testnets as unsupported, and all coins that don't have support info are set to the released firmware version. The tool will ask you to confirm each added coin. ERC20 tokens are added automatically. Use `--verbose` to see them. """ latest_releases = coin_info.latest_releases() def bump_version(version_tuple): version_list = list(version_tuple) version_list[-1] += 1 return ".".join(str(n) for n in version_list) # guess `version` if not given if not v1: v1 = bump_version(latest_releases["trezor1"]) if not v2: v2 = bump_version(latest_releases["trezor2"]) versions = {"trezor1": v1, "trezor2": v2} for number in "1", "2": device = f"trezor{number}" version = versions[device] if not force and not version.startswith(number + "."): raise click.ClickException( f"Device trezor{device} should not be version {version}. " "Use --force to proceed anyway." ) print(f"Releasing {device} firmware version {version}") defs, _ = coin_info.coin_info_with_duplicates() coins_dict = defs.as_dict() # Invoke data fixup as dry-run. That will modify data internally but won't write # changes. We will write changes at the end based on our own `dry_run` value. print("Fixing up data...") ctx.invoke(fix, dry_run=True) def maybe_add(coin): add = click.confirm( f"Add missing coin {coin['key']} ({coin['name']})?", default=True ) if not add: unsupport_reason = click.prompt( "Enter reason for not supporting (blank to skip)", default="", show_default=False, ) if not unsupport_reason: return for device, version in versions.items(): if add: support_setdefault(device, coin["key"], version) else: support_setdefault(device, coin["key"], False, unsupport_reason) # process missing (not listed) supportinfos missing_list = [] unsupported = find_unsupported_coins(coins_dict) for val in unsupported.values(): for coin in val: if coin not in missing_list: missing_list.append(coin) tokens = [coin for coin in missing_list if coin_info.is_token(coin)] nontokens = [coin for coin in missing_list if not coin_info.is_token(coin)] for coin in tokens: key = coin["key"] # assert not coin.get("duplicate"), key if verbose: print(f"Adding missing {key} ({coin['name']})") for device, version in versions.items(): support_setdefault(device, key, version) for coin in nontokens: if skip_testnets and "testnet" in coin["name"].lower(): for device, version in versions.items(): support_setdefault(device, coin["key"], False, "(AUTO) exclude testnet") else: maybe_add(coin) if not dry_run: write_support_info() else: print("No changes written")