def __init__(self, name="default", password=None, is_verbose=True): Wallet.__init__(self, name, password) file = wallet_file(name) cipher_suite = None self.is_created = False if self.password: if not os.path.exists(file): raise errors.Error(''' Password is set, but the wallet file does not exist: {} '''.format(file)) cipher_suite = Fernet(str.encode(password)) keys_ciphered = None try: with open(wallet_file(name), "r") as input: keys_ciphered = [key.rstrip('\n') for key in input] except Exception as e: raise errors.Error(str(e)) try: decrypt(keys_ciphered[0], cipher_suite) except: raise errors.Error(''' Wrong password. ''') if is_verbose: logger.OUT(''' Opened existing wallet: {} '''.format(name)) else: if os.path.exists(file): raise errors.Error(''' Cannot overwrite existing wallet file: {} '''.format(file)) key = Fernet.generate_key() cipher_suite = Fernet(key) self.password = key.decode("utf-8") try: with open(file, "w+") as out: out.write(encrypt(_manager_id, cipher_suite) + "\n") except Exception as e: raise errors.Error(str(e)) self.is_creted = True if is_verbose: logger.OUT(''' Created wallet: {} Save password to use in the future to unlock this wallet. Without password imported keys will not be retrievable. "{}" '''.format(name, self.password)) _open_wallets[name] = OpenWallet(name, cipher_suite) global _timer _timer = Timer(_timeout, lock_all) _timer.start()
def get_block_trx_data(block_num): block = GetBlock(block_num, is_verbose=False) trxs = block.json["transactions"] if not len(trxs): logger.OUT("No transactions in block {}.".format(block_num)) else: for trx in trxs: logger.OUT(trx["trx"]["transaction"]["actions"][0]["data"])
def lock_all(is_verbose=True): locked = [] for name, open_wallet in _open_wallets.items(): _open_wallets[name].cipher_suite = None locked.append(name) if is_verbose: if locked: logger.OUT("Locked: \n" + ", ".join(locked)) else: logger.OUT("Nothing to lock.")
def list(is_verbose=True): wallets = [] for name, open_wallet in _open_wallets.items(): if open_wallet: wallets.append("* " + name) else: wallets.append(name) if is_verbose: if wallets: logger.OUT(''' Open wallets. Starlet, if any, means 'unlocked':\n''' + "\n".join(wallets)) else: logger.OUT("There is not any wallet open.")
def table(account_object, table_name, scope="", binary=False, limit=10, key="", lower="", upper=""): logger.INFO(''' * Table ``{}`` for ``{}`` '''.format(table_name, scope)) result = cleos.GetTable(account_object, table_name, scope, binary, limit, key, lower, upper, is_verbose=False) try: account_map = manager.account_map() scope = account_map[str(scope)] except: pass logger.OUT(result.out_msg) return result
def print_stats(accounts, params, last_col="%s", col="%15s"): def find(element, json): try: keys = element.split('.') rv = json for key in keys: rv = rv[key] except: rv = "n/a" return rv jsons = [] for account in accounts: json = cleos.GetAccount(account, is_info=False, is_verbose=0).json json["account_object_name"] = account.account_object_name jsons.append(json) header = "" for json in jsons: header = header + col % (json["account_object_name"]) output = ".\n" + header + "\n" for param in params: for json in jsons: output = output + col % find(param, json) output = output + " " + last_col % (param) + "\n" logger.OUT(output, translate=False)
def unlock(wallet, password=None, is_verbose=True): name = wallet_arg(wallet) if not password and isinstance(wallet, Wallet): password = wallet.password if not is_open(name): raise errors.Error(''' The wallet '{}' is not open. '''.format(name)) _manager_id = None if not is_unlocked(name): try: _open_wallets[name].cipher_suite = Fernet(str.encode(password)) with open(wallet_file(name), "r") as input: keys_ciphered = [key.rstrip('\n') for key in input] _manager_id = decrypt(keys_ciphered[0], _open_wallets[name].cipher_suite) except Exception as e: raise errors.Error(''' Wrong password. ''') if is_verbose: logger.OUT("Unlocked: {}".format(name)) global _timer if _timer: _timer.cancel() _timer = Timer(_timeout, lock_all) _timer.start() return _manager_id
def set_contract(account_object, contract_dir, wast_file="", abi_file="", permission=None, expiration_sec=30, skip_signature=0, dont_broadcast=0, forceUnique=0, max_cpu_usage=0, max_net_usage=0, ref_block=None): result = cleos.SetContract(account_object, contract_dir, wast_file, abi_file, permission, expiration_sec, skip_signature, dont_broadcast, forceUnique, max_cpu_usage, max_net_usage, ref_block, is_verbose=False) logger.OUT(result) account_object.set_contract = result
def is_name_taken(self, account_object_name, account_name): '''Check whether the given name is available is a name of an account object. If the name points to an existing account, propese an action that may resolve the conflict. Args: account_object_name (str): The proposed name of a new account object. account_name (str): The EOSIO name of the account mapped with the new account object. Returns: bool: Whether the given name is available is a name of an account object. ''' while True: account_map_json = manager.account_map() if account_map_json is None: return False is_taken = False for name, object_name in account_map_json.items(): if object_name == account_object_name: if not name == account_name: logger.OUT(''' The given account object name ``{}`` points to an existing account, of the name {}, mapped in a file in directory: {} Cannot overwrite it. However, you can free the name by changing the mapping. Do you want to edit the file? '''.format(account_object_name, name, self.wallet_dir)) is_taken = True break if is_taken: temp = None if account_object_name in Wallet.globals: temp = Wallet.globals[account_object_name] del Wallet.globals[account_object_name] answer = input("y/n <<< ") if answer == "y": manager.edit_account_map() continue else: if temp: Wallet.globals[account_object_name] = temp raise errors.Error(''' Use the function 'manager.edit_account_map()' to edit the file. ''') else: break
def table( self, table_name, scope="", binary=False, limit=10, lower="", upper="", index="", key_type="", encode_type="", reverse=False, show_payer=False ): '''Retrieve the contents of a database table Args: table (str): The name of the table as specified by the contract abi. scope (str or .interface.Account): The scope within the account in which the table is found. binary (bool): Return the value as BINARY rather than using abi to interpret as JSON. Default is *False*. limit (int): The maximum number of rows to return. Default is 10. lower (str): JSON representation of lower bound value of key, defaults to first. upper (str): JSON representation of upper bound value value of key, defaults to last. index (int or str): Index number, 1 - primary (first), 2 - secondary index (in order defined by multi_index), 3 - third index, etc. Number or name of index can be specified, e.g. 'secondary' or '2'. key_type (str): The key type of --index, primary only supports (i64), all others support (i64, i128, i256, float64, float128, ripemd160, sha256). Special type 'name' indicates an account name. encode_type (str): The encoding type of key_type (i64 , i128 , float64, float128) only support decimal encoding e.g. 'dec'i256 - supports both 'dec' and 'hex', ripemd160 and sha256 is 'hex' only. reverse (bool): Iterate in reverse order. show_payer (bool): Show RAM payer. Returns: :class:`.cleos_set.SetTable` object ''' stop_if_account_is_not_set(self) logger.INFO(''' * Table ``{}`` for ``{}`` '''.format(table_name, scope)) result = cleos_get.GetTable( self, table_name, scope, binary, limit, lower, upper, index, key_type, encode_type, reverse, show_payer, is_verbose=False) try: account_map = manager.account_map() scope = account_map[str(scope)] except: pass logger.OUT(result.out_msg) return result
def __init__(self, name=None, password="", verbosity=None, file=False): cleos.set_local_nodeos_address_if_none() if name is None: name = setup.wallet_default_name else: name = setup.file_prefix() + name if not self.wallet is None: raise errors.Error(''' It can be only one ``Wallet`` object in the script; there is one named ``{}``. '''.format(wallet.name)) return self.wallet_dir = manager.wallet_dir() logger.INFO(''' * Wallet name is ``{}``, wallet directory is {}. '''.format(name, self.wallet_dir)) if not password: # look for password: passwords = wallet_json_read() if name in passwords: password = passwords[name] logger.INFO( ''' The password is restored from the file: {} '''.format( os.path.join(self.wallet_dir, setup.password_map)), verbosity) cleos.WalletCreate.__init__(self, name, password, is_verbose=False) if self.is_created: # new password logger.INFO( ''' * Created wallet ``{}``. '''.format(self.name), verbosity) ############################################################################### # TO DO: detect live node!!!!!!!!!! if manager.is_local_testnet() or file or True: ############################################################################### password_map = wallet_json_read() password_map[name] = self.password wallet_json_write(password_map) logger.INFO( ''' * Password is saved to the file ``{}`` in the wallet directory. '''.format(setup.password_map), verbosity) else: logger.OUT(self.out_msg) else: logger.TRACE(''' Opened wallet ``{}`` '''.format(self.name))
def delete(wallet, is_verbose=True): name = wallet_arg(wallet) file = wallet_file(name) if os.path.isfile(file): try: os.remove(file) except Exception as e: raise errors.Error(str(e)) if is_verbose: logger.OUT("Deleted wallet: '{}'".format(name)) return True if is_verbose: logger.OUT(''' There is not any wallet file named '{}' '''.format(name)) return False
def printself(self, is_verbose=False): '''Print a message. Args: is_verbose (bool): If set, a message is printed. ''' if not hasattr(self, "is_verbose"): self.is_verbose = is_verbose if self.is_verbose: logger.OUT(self.__str__())
def stop(is_verbose=True): lock_all() _open_wallets = {} global _timer if _timer: _timer.cancel() if is_verbose: logger.OUT(''' All the wallet objects locked and removed from the list of open wallets.''' )
def lock(wallet, is_verbose=True): name = wallet_arg(wallet) if _open_wallets[name]: _open_wallets[name].cipher_suite = None else: raise errors.Error(''' The wallet '{}' is not open. '''.format(name)) if is_verbose: logger.OUT("Locked: {}".format(name))
def open_wallet(wallet, is_verbose=True): name = wallet_arg(wallet) wallets_ = wallets() if name + _file_ext in wallets_: _open_wallets[name] = OpenWallet(name) else: raise errors.Error(''' There is not any wallet file named {} '''.format((wallet_file(name)))) if is_verbose: logger.OUT("Opened: {}".format(name))
def code(self, code=None, abi=None, wasm=False): '''Retrieve the code and ABI Args: code (str): If set, the name of the file to save the contract WAST/WASM to. abi (str): If set, the name of the file to save the contract ABI to. wasm (bool): Save contract as wasm. ''' result = cleos_get.GetCode(self, is_verbose=False) logger.INFO(''' * code() ''') logger.OUT(str(result))
def set_contract(self, contract_dir, wasm_file="", abi_file="", clear=False, permission=None, expiration_sec=None, skip_sign=0, dont_broadcast=0, force_unique=0, max_cpu_usage=0, max_net_usage=0, ref_block=None, delay_sec=0): '''Create or update the contract. Call *EOSIO cleos* with the *set contract* command. Store the result, which is an object of the class :class:`.cleos_set.SetContract`, as the value of the *set_contract* attribute. Args: contract_dir (str): A path to a directory. wasm_file (str): The WASM file relative to the contract_dir. abi_file (str): The ABI file for the contract, relative to the contract-dir. clear (bool): Remove contract on an account. Default is False. See definitions of the remaining parameters: \ :func:`.cleos.common_parameters`. ''' stop_if_account_is_not_set(self) result = cleos_set.SetContract(self, contract_dir, wasm_file, abi_file, clear, permission, expiration_sec, skip_sign, dont_broadcast, force_unique, max_cpu_usage, max_net_usage, ref_block, delay_sec, is_verbose=False, json=True) logger.OUT(result) self.set_contract = result
def remove_key(key, is_verbose=True): trash = [] for name, open_wallet in _open_wallets.items(): if not open_wallet.cipher_suite: continue owner_key_public = key_arg(key, is_owner_key=True, is_private_key=False) active_key_public = key_arg(key, is_owner_key=False, is_private_key=False) private_keys_ = private_keys(name, False) keys = Node(''' const ecc = require('eosjs-ecc'); ((keys) => { public_keys = [] for (i = 0; i < keys.length; i++) { pair = [] pair[0] = keys[i] pair[1] = ecc.privateToPublic(keys[i]) public_keys[i] = pair } console.log(JSON.stringify(public_keys)) })(%s) ''' % private_keys_).json for pair in keys: if pair[1] == owner_key_public or pair[1] == active_key_public: trash.append(pair[0]) if trash: remaining = [] for private_key in private_keys_: if not private_key in trash: remaining.append(private_key) with open(wallet_file(name), "w") as out: out.write("\n".join(remaining)) if is_verbose: if trash: logger.OUT("Removed keys from wallet '{}':\n".format(name) + "\n".join(trash))
def table(self, table_name, scope="", binary=False, limit=10, key="", lower="", upper=""): '''Retrieve the contents of a database table Args: scope (str or .interface.Account): The scope within the account in which the table is found. table (str): The name of the table as specified by the contract abi. binary (bool): Return the value as BINARY rather than using abi to interpret as JSON. Default is *False*. limit (int): The maximum number of rows to return. Default is 10. lower (str): JSON representation of lower bound value of key, defaults to first. upper (str): JSON representation of upper bound value value of key, defaults to last. Returns: :class:`.cleos_set.SetTable` object ''' logger.INFO(''' * Table ``{}`` for ``{}`` '''.format(table_name, scope)) result = cleos_get.GetTable(self, table_name, scope, binary, limit, key, lower, upper, is_verbose=False) try: account_map = manager.account_map() scope = account_map[str(scope)] except: pass logger.OUT(result.out_msg) return result
def push_action(account_object, action, data, permission=None, expiration_sec=30, skip_signature=0, dont_broadcast=0, forceUnique=0, max_cpu_usage=0, max_net_usage=0, ref_block=None, json=False): data = _data_json(data) result = cleos.PushAction(account_object, action, data, permission, expiration_sec, skip_signature, dont_broadcast, forceUnique, max_cpu_usage, max_net_usage, ref_block, is_verbose=False, json=True) logger.INFO(''' * Push action ``{}``: '''.format(action)) logger.INFO(''' {} '''.format(re.sub(' +', ' ', data))) account_object.action = result try: account_object._console = result.console logger.DEBUG(account_object._console) except: pass if json: logger.OUT(result.out_msg) account_object.action = result
def is_name_taken(self, account_object_name, account_name): while True: account_map_json = manager.account_map(self) if account_map_json is None: return False is_taken = False for name, object_name in account_map_json.items(): if object_name == account_object_name: if not name == account_name: logger.OUT(''' The given account object name ``{}`` points to an existing account, of the name {}, mapped in a file in directory: {} Cannot overwrite it. However, you can free the name by changing the mapping. Do you want to edit the file? '''.format(account_object_name, name, self.wallet_dir)) is_taken = True break if is_taken: temp = None if account_object_name in Wallet.globals: temp = Wallet.globals[account_object_name] del Wallet.globals[account_object_name] answer = input("y/n <<< ") if answer == "y": manager.edit_account_map() continue else: if temp: Wallet.globals[account_object_name] = temp raise errors.Error(''' Use the function 'manager.edit_account_map(text_editor="nano")' to edit the file. ''') else: break
def runInThread(): p = subprocess.run( command_line, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) err_msg = p.stderr.decode("ISO-8859-1") if "error" in err_msg and not "exit shutdown" in err_msg: raise errors.Error(err_msg) elif not err_msg or "exit shutdown" in err_msg: logger.OUT( ''' Just another instability incident of the ``nodeos`` executable. Rerun the script. ''' ) else: print(err_msg)
def private_keys(wallet=None, is_verbose=True): keys = [] for name, open_wallet in _open_wallets.items(): if wallet: if name != wallet_arg(wallet): continue is_open_and_unlocked(name) with open(wallet_file(name), "r") as input: keys_ciphered = [key.rstrip('\n') for key in input] for key in keys_ciphered: keys.append(decrypt(key, _open_wallets[name].cipher_suite)) if is_verbose: logger.OUT("Private keys in all unlocked wallets: \n".format(name) + "\n".join(keys)) return keys
def account_map(logger=None): '''Return json account map Attempt to open the account map file named ``setup.account_map``, located in the wallet directory ``config.keosd_wallet_dir()``, to return its json contents. If the file does not exist, return an empty json. If the file is corrupted, offer editing the file with the ``nano`` linux editor. Return ``None`` if the the offer is rejected. ''' wallet_dir_ = config.keosd_wallet_dir(raise_error=False) if not wallet_dir_: return {} path = os.path.join(wallet_dir_, setup.account_map) while True: try: # whether the setup map file exists: with open(path, "r") as input_file: return json.load(input_file) except Exception as e: if isinstance(e, FileNotFoundError): return {} else: logger.OUT(''' The account mapping file is misformed. The error message is: {} Do you want to edit the file? '''.format(str(e))) answer = input("y/n <<< ") if answer == "y": edit_account_map() continue else: raise errors.Error(''' Use the function 'efman.edit_account_map(text_editor="nano")' or the corresponding method of any object of the 'eosfactory.wallet.Wallet` class to edit the file. ''') return None
def keys(wallet=None, is_verbose=True, is_lock_checked=True): name = wallet_arg(wallet) private_keys_ = private_keys(wallet, False) public_keys = Node(''' const ecc = require('eosjs-ecc'); ((keys) => { var public_keys = [] for (i = 0; i < keys.length; i++) { public_keys[i] = ecc.privateToPublic(keys[i]) } console.log(JSON.stringify(public_keys)) })(%s) ''' % (private_keys_)).json if is_verbose: logger.OUT("keys in all unlocked wallets: \n".format(name) + "\n".join(public_keys)) return public_keys
def import_key(wallet, key, is_verbose=True): is_open_and_unlocked(wallet) name = wallet_arg(wallet) key_private = key_arg(key, is_owner_key=True, is_private_key=True) with open(wallet_file(name), "a") as out: out.write( encrypt(key_private, _open_wallets[name].cipher_suite) + "\n") key_public = Node(''' const ecc = require('eosjs-ecc'); ((private_key) => { public_key = {key_public: ecc.privateToPublic(private_key)} console.log(JSON.stringify(public_key)) })('%s') ''' % (key_private)).json["key_public"] if is_verbose: logger.OUT("Imported key to wallet '{}':\n{}".format(name, key_public)) return key_public
def stats(self, params, last_col="%s", col="%15s", to_string=False): def find(element, json): try: keys = element.split('.') rv = json for key in keys: rv = rv[key] except: rv = "n/a" return rv json = cleos.GetAccount(self, is_info=False, is_verbose=0).json json["account_object_name"] = self.account_object_name output = "" for param in params: output = output + col % find(param, json) output = output + " " + last_col % (param) + "\n" if to_string: return output else: logger.OUT(output, translate=False)
def index(self): ''' Lists opened wallets, * marks unlocked. Returns `cleos.WalletList` object ''' result = cleos.WalletList(is_verbose=0) logger.OUT(result.out_msg)
def printself(self, is_verbose=None): if not hasattr(self, "is_verbose"): self.is_verbose = is_verbose if self.is_verbose: logger.OUT(self.__str__())