#!/usr/bin/env python3 import json import glob import re def check_type(val, types, nullable=False, empty=False, regex=None, choice=None): # check nullable if nullable and val is None: return True # check empty try: if not empty and len(val) == 0: return False except TypeError: pass # check regex if regex is not None: if types is not str: return False m = re.match(regex, val) if not m: return False # check choice if choice is not None: if val not in choice: return False # check type if isinstance(types, list): return True in [isinstance(val, t) for t in types] else: return isinstance(val, types) def validate_coin(coin): assert check_type(coin['coin_name'], str, regex=r'^[A-Z]') assert check_type(coin['coin_shortcut'], str, regex=r'^[A-Zt][A-Z][A-Z]+$') assert check_type(coin['coin_label'], str, regex=r'^[A-Z]') assert check_type(coin['website'], str, regex=r'^http.*[^/]$') assert check_type(coin['github'], str, regex=r'^https://github.com/.*[^/]$') assert check_type(coin['maintainer'], str) assert check_type(coin['curve_name'], str, choice=['secp256k1', 'secp256k1_decred', 'secp256k1_groestl']) assert check_type(coin['address_type'], int) assert check_type(coin['address_type_p2sh'], int) assert coin['address_type'] != coin['address_type_p2sh'] assert check_type(coin['maxfee_kb'], int) assert check_type(coin['minfee_kb'], int) assert coin['maxfee_kb'] >= coin['minfee_kb'] assert check_type(coin['hash_genesis_block'], str, regex=r'^[0-9a-f]{64}$') assert check_type(coin['xprv_magic'], str, regex=r'^[0-9a-f]{8}$') assert check_type(coin['xpub_magic'], str, regex=r'^[0-9a-f]{8}$') assert check_type(coin['xpub_magic_segwit_p2sh'], str, regex=r'^[0-9a-f]{8}$', nullable=True) assert coin['xprv_magic'] != coin['xpub_magic'] assert coin['xprv_magic'] != coin['xpub_magic_segwit_p2sh'] assert coin['xpub_magic'] != coin['xpub_magic_segwit_p2sh'] assert check_type(coin['slip44'], int) assert check_type(coin['segwit'], bool) assert check_type(coin['decred'], bool) assert check_type(coin['forkid'], int, nullable=True) assert check_type(coin['force_bip143'], bool) assert check_type(coin['default_fee_b'], dict) assert check_type(coin['dust_limit'], int) assert check_type(coin['blocktime_seconds'], int) assert check_type(coin['signed_message_header'], str) assert check_type(coin['address_prefix'], str, regex=r'^.*:$') assert check_type(coin['min_address_length'], int) assert check_type(coin['max_address_length'], int) assert coin['max_address_length'] >= coin['min_address_length'] assert check_type(coin['bech32_prefix'], str, nullable=True) assert check_type(coin['cashaddr_prefix'], str, nullable=True) assert check_type(coin['bitcore'], list, empty=True) for bc in coin['bitcore']: assert not bc.endswith('/') def process_json(fn): print(fn, end=' ... ') j = json.load(open(fn)) validate_coin(j) print('OK') return j coins = {} for fn in glob.glob('*.json'): c = process_json(fn) n = c['coin_name'] coins[n] = c json.dump(coins, open('../coins.json', 'w'), indent=4, sort_keys=True)