def parse_csv(): data = [] if args.csv is not None: with open(args.csv, 'r') as f: for row in csv.DictReader(f): raw_amount, raw_address = row['funded'].strip( ), row['validator address'].strip() if raw_address and raw_address.startswith( 'one1') and raw_amount: sys.stdout.write( f"\rLoading address: {raw_address} to funding candidate from CSV." ) sys.stdout.flush() try: cli.single_call( f"hmy utility bech32-to-addr {raw_address}") data.append({ 'amount': float(raw_amount.replace(',', '')), 'address': raw_address }) except Exception as e: # catch all to not halt script print( f"{util.Typgpy.FAIL}\nError when parsing CSV file (addr `{raw_address}`). {e}{util.Typgpy.ENDC}" ) print( f"{util.Typgpy.WARNING}Skipping...{util.Typgpy.ENDC}" ) return data
def add_bls_key_to_validator(val_info, bls_pub_keys, passphrase, endpoint): print(f"{Typgpy.HEADER}{val_info['validator-addr']} already in list of validators!{Typgpy.ENDC}") chain_val_info = json_load(cli.single_call(f"hmy --node={endpoint} blockchain " f"validator information {val_info['validator-addr']}"))["result"] bls_keys = chain_val_info["validator"]["bls-public-keys"] directory_lock.acquire() for k in bls_pub_keys: if k not in bls_keys: # Add imported BLS key to existing validator if needed print(f"{Typgpy.OKBLUE}adding bls key: {k} " f"to validator: {val_info['validator-addr']}{Typgpy.ENDC}") os.chdir("/root/bin") proc = cli.expect_call(f"hmy --node={endpoint} staking edit-validator " f"--validator-addr {val_info['validator-addr']} " f"--add-bls-key {k} --passphrase-file /.wallet_passphrase ") proc.expect("Enter the bls passphrase:\r\n") proc.sendline(passphrase) proc.expect(pexpect.EOF) print(f"\n{Typgpy.OKBLUE}Edit-validator transaction response: " f"{Typgpy.OKGREEN}{proc.before.decode()}{Typgpy.ENDC}") directory_lock.release() new_val_info = json_load(cli.single_call(f"hmy --node={endpoint} blockchain " f"validator information {val_info['validator-addr']}"))["result"] new_bls_keys = new_val_info["validator"]["bls-public-keys"] print(f"{Typgpy.OKBLUE}{val_info['validator-addr']} updated bls keys: {new_bls_keys}{Typgpy.ENDC}") verify_node_sync(endpoint) print()
def load(start, end): for j, file_name in enumerate(key_paths[start:end]): # STRONG assumption about imported key-files. if file_name.endswith(".key") or not file_name.startswith("."): file_path = f"{keystore_path}/{file_name}" account_name = f"{import_account_name_prefix}{name_prefix}{j + start}" if not cli.get_address(account_name): cli.remove_account( account_name ) # Just in-case there is a folder with nothing in it. Loggers.general.info( f"Adding key file: ({j + start}) {file_name}") if fast_load: keystore_acc_dir = f"{cli.get_account_keystore_path()}/{account_name}" os.makedirs(keystore_acc_dir, exist_ok=True) shutil.copy(file_path, f"{keystore_acc_dir}/{file_name}") else: cli.single_call( f"hmy keys import-ks {file_path} {account_name} " f"--passphrase={passphrase}") _loaded_passphrase[account_name] = passphrase accounts_added.append(account_name) _accounts_added.add(account_name) account_balances[account_name] = get_balances(account_name)
def test_update_keystore(): cli.single_call("hmy keys add test1") addrs = cli.get_accounts_keystore() assert "test1" in addrs.keys() check_addr = addrs["test1"] accounts_list = cli.get_accounts(check_addr) check_acc = accounts_list[0] assert check_acc == "test1" raw_cli_keys_list_print = cli.single_call("hmy keys list", timeout=2) assert check_addr in raw_cli_keys_list_print assert check_acc in raw_cli_keys_list_print assert addrs[check_acc] == check_addr cli.remove_address(check_addr) assert check_addr not in addrs.values() assert "test1" not in addrs.keys()
def create_account(account_name, exist_ok=True): """ This will create a single account with `account_name`. One can choose to continue if the account exists by setting `exist_ok` to true. """ # TODO: add caching try: cli.single_call(f"hmy keys add {account_name}") except RuntimeError as e: if not exist_ok: raise e get_balances(account_name) _accounts_added.add(account_name) _loaded_passphrase[ account_name] = '' # Default passphrase used by the CLI. return account_name
def save_log(): fund_log["block-height"] = json.loads( cli.single_call( f"hmy blockchain " f"latest-header -n {endpoints[0]}"))["result"]["blockNumber"] log_dir = f"{os.path.dirname(os.path.realpath(__file__))}/logs/{os.environ['HMY_PROFILE']}" file = f"{log_dir}/funding.json" with open(file, 'w') as f: json.dump(fund_log, f, indent=4)
def load_accounts(): accs_info = [] assert os.path.isfile(args.config), f"`{args.config}` is not a file" with open(args.config, 'r') as f: config = json.load(f) cli_dir = cli.get_account_keystore_path() for j, src_info in enumerate(config): sys.stdout.write(f"Key import progress: {j}/{len(config)} \r") sys.stdout.flush() # Passphrase parsing if "passphrase-file-path" in src_info.keys(): pw_path = src_info['passphrase-file-path'] assert os.path.isfile(pw_path), f"`{pw_path}` is not a file." with open(pw_path, 'r') as f: passphrase = f.read().strip() elif "passphrase" in src_info.keys(): passphrase = src_info['passphrase'] else: passphrase = '' # CLI default passphrase # Load key acc_name = f"{prefix}{j}" cli.remove_account(acc_name) if "keystore-file-path" in src_info.keys(): ks_path = src_info['keystore-file-path'] assert os.path.isfile(ks_path), f"`{ks_path}` is not a file." os.makedirs(f"{cli_dir}/{acc_name}") shutil.copy(ks_path, f"{cli_dir}/{acc_name}") address = cli.get_address(acc_name) if address is None: raise RuntimeError(f"Could not import key for config {j}") added_key_names.append(acc_name) elif "private-key" in src_info.keys(): cli.single_call( f"hmy keys import-private-key {src_info['private-key']} {acc_name}" ) address = cli.get_address(acc_name) if address is None: raise RuntimeError(f"Could not import key for config {j}") else: raise RuntimeError(f"No key to import for config {j}") accs_info.append({'address': address, 'passphrase': passphrase}) return accs_info
def transfer(self, from_address, to_address, amount, from_shard=0, to_shard=0): cli.set_binary(HmyClient._hmyBinaryDir) return cli.single_call( f'hmy transfer --node={HmyClient._networkUrl} --from {from_address} --to {to_address} --from-shard {from_shard} --to-shard {to_shard} --amount {amount}' )
def load_log(): global fund_log log_dir = f"{os.path.dirname(os.path.realpath(__file__))}/logs/{os.environ['HMY_PROFILE']}" file = f"{log_dir}/funding.json" if os.path.isfile(file): with open(file, 'r') as f: loaded_fund_log = json.load(f) curr_height = json.loads( cli.single_call( f"hmy blockchain " f"latest-header -n {endpoints[0]}"))["result"]["blockNumber"] if loaded_fund_log['block-height'] <= curr_height: fund_log = loaded_fund_log
def get_balance_from_node_ip(address, endpoint_list): """ Assumes that endpoints provided are ips and that the CLI only returns the balances for a specific shard. """ balances = [] for endpoint in endpoint_list: cli_bal = json.loads( cli.single_call(f"hmy --node={endpoint} balances {address}")) assert len( cli_bal ) == 1, f"Expect CLI to only return balances for 1 shard. Got: {cli_bal}" balances.append(cli_bal[0]) return balances
def send(self, endpoint, wait_for_confirm=None, chain_id="testnet"): """ This will send all transactions in the buffer of transaction **sequentially** using the CLI with the provided `endpoint` and `chain_id`. One can force EACH transaction to confirm by providing a max `wait_for_confirm` time. This will return a list of dictionaries that contain transaction information (and possibly errors) of all the transactions sent. """ if wait_for_confirm: assert isinstance(wait_for_confirm, (int, float)) if not self._transactions_buffer: return [] with open(self._file_name, 'w') as f: json.dump(self._transactions_buffer, f, indent=4) command = f"hmy --node={endpoint} transfer --file {self._file_name} --chain-id {chain_id} " command += f"--timeout {wait_for_confirm} " if wait_for_confirm else f"--timeout 0 " timeout = None if self.size is None else get_config( )["TXN_WAIT_TO_CONFIRM"] * self.size response = json_load( cli.single_call(command, error_ok=True, timeout=timeout)) for txn, sent_txn in zip(self._transactions_buffer, response): info = { # Cast elements to fit transaction logger convention. 'from': txn['from'], 'to': txn['to'], 'from-shard': int(txn['from-shard']), 'to-shard': int(txn['to-shard']), 'amount': float(txn['amount']), 'txn-fee': round(float(txn['gas-price']) * 1e-9 * float(txn['gas-limit']), 18), 'nonce': None, 'error': None, 'hash': None, 'send-time-utc': None, } if "nonce" in txn.keys(): info['nonce'] = int(txn['nonce']) if "transaction-hash" in sent_txn.keys(): info['hash'] = sent_txn['transaction-hash'] if "errors" in sent_txn.keys(): info['error'] = ', '.join(e for e in sent_txn['errors']) if "time-signed-utc" in sent_txn.keys(): info['send-time-utc'] = sent_txn['time-signed-utc'] info[ 'batched-extra-info'] = sent_txn # Keep track of returned info just in case. Loggers.transaction.info(json.dumps(info)) self._transactions_buffer.clear() return response
def consolidate(shard): if shard >= len(endpoints): return transactions = [] total_amt = 0 overhead = Decimal( args.gas_price * args.gas_limit) * Decimal(1e-18) + Decimal(1e-18) max_amount = float('inf') if args.amount is None else Decimal( args.amount) + overhead print( f"{util.Typgpy.HEADER}Consolidating funds for shard {shard} ({len(accounts_info)} transaction(s)){util.Typgpy.ENDC}" ) for acc in accounts_info: acc_bal = json.loads( cli.single_call( f"hmy --node={endpoints[shard]} balances {acc['address']}"))[0] assert acc_bal[ "shard"] == shard, f"balance for shard {shard} does not match endpoint" amount = round( Decimal(min(acc_bal["amount"], max_amount)) - overhead, 18) total_amt += amount transactions.append({ "from": acc['address'], "to": args.dest_address, "from-shard": str(shard), "to-shard": str(shard), "gas-price": str(args.gas_price), "gas-limit": str(args.gas_limit), "passphrase-string": acc['passphrase'], "amount": str(amount) }) filename = f"./{prefix}fund{shard}.json" with open(filename, 'w') as f: json.dump(transactions, f, indent=4) command = f"hmy --node={endpoints[shard]} transfer --file {filename} --chain-id {chain_id} --timeout 0" print( f"{util.Typgpy.HEADER}Transaction for shard {shard}:\n{util.Typgpy.OKGREEN}" f"{cli.single_call(command, timeout=int(args.timeout) * len(endpoints) * len(accounts_info))}" f"{util.Typgpy.ENDC}") return total_amt
def get_balances(account_name): """ This gets the balances for the address associated with the `account_name` (aka wallet-name) in the CLI's keystore. """ config = get_config() address = cli.get_address(account_name) if not address: return {} response = cli.single_call( f"hmy balances {address} --node={config['ENDPOINTS'][0]}", timeout=60) balances = eval( response ) # There is a chance that the CLI returns a malformed json array. info = { 'address': address, 'balances': balances, 'time-utc': str(datetime.datetime.utcnow()) } Loggers.balance.info(json.dumps(info)) account_balances[account_name] = balances return balances
def remove_accounts(accounts, backup=False): """ This will remove all `accounts`, where `accounts` is an iterable of accounts name. One can specify `backup` if one wishes to log the private keys of all removed accounts. """ for acc in accounts: address = cli.get_address(acc) private_key = "" if backup: try: private_key = cli.single_call( f"hmy keys export-private-key {address}").strip() except RuntimeError: Loggers.general.error( f"{address} ({acc}) was not imported via CLI, cannot backup" ) private_key = "NOT-IMPORTED-USING-CLI" cli.remove_account(acc) if acc in _accounts_added: _accounts_added.remove(acc) if acc in _loaded_passphrase: del _loaded_passphrase[acc] removed_account = {"address": address, "private-key": private_key} Loggers.general.info(f"Removed Account: {removed_account}")
def export_private_key(name): return cli.single_call(f"hmy keys export-private-key {cli.get_address(name)}")
def regiterNewUser(self, telegram_user_id): cli.set_binary(HmyClient._hmyBinaryDir) return cli.single_call(f'hmy keys add {telegram_user_id}')
item.split(".")[0] for item in os.listdir( "/root/go/src/github.com/harmony-one/harmony/.hmy/keystore") ] for key in keys: balance = account.get_balance(key) print("There are %d one in %s" % (balance, key)) #current block number cur_block_num = blockchain.get_block_number() #get balance at certain block account.get_balance_by_block(keys[-1], cur_block_num) #get balance on all shards account.get_balance_on_all_shards(keys[-1]) #restore keys[-1] from keystore by cli cli.single_call( "hmy keys import-ks /root/go/src/github.com/harmony-one/harmony/.hmy/keystore/%s.key" % key) balance_before = account.get_balance(keys[-1]) #send 2 one from keys[-1] to local_test_address cli.single_call( "hmy transfer --from %s --to %s --amount %d --from-shard %s --to-shard %s" % (key, local_test_address, 2, 0, 0)) balance_after = account.get_balance(keys[-1]) diff = balance_before - balance_after print("The difference between before and after is %d" % (diff))
def load_from_priv_keys(): for i, private_key in enumerate(import_keys): acc_name = f"LOAD_NET_IMPORTED_PRIVATE_{i}" cli.remove_account(acc_name) cli.single_call(f"hmy keys import-private-key {private_key} {acc_name}") tx_gen.account_balances[acc_name] = tx_gen.get_balances(acc_name) # Manually update the tx_gen acc bal
env = cli.download("./bin/test", replace=False) cli.environment.update(env) new_path = os.getcwd() + "/bin/test" cli.set_binary(new_path) print("The binary path is %s"%(cli.get_binary_path())) #get a dict of account names name_dict = cli.get_accounts_keystore() print(name_dict) #get keystore path print("Your accounts are store in %s"%(cli.get_account_keystore_path())) if "difeng" not in name_dict.keys(): #create a user cli.single_call("hmy keys add difeng") print("difeng has been successfully created") if "dfxx" not in name_dict.keys(): #create a user cli.single_call("hmy keys add dfxx") print("dfxx has been successfully created") if "test1" not in name_dict.keys(): #create a user cli.single_call("hmy keys add test1") #get address of account difeng_address = cli.get_address("difeng") dfxx_address = cli.get_address("dfxx")
def check_min_bal_on_s0(address, amount, endpoint=default_endpoint): balances = json_load(cli.single_call(f"hmy --node={endpoint} balances {address}")) for bal in balances: if bal['shard'] == 0: return bal['amount'] >= amount