Beispiel #1
0
def handle_invoke_config(project_dir_path: str, config: str):
    try:
        if config != '':
            config_path = os.path.join(project_dir_path, config)
            if not os.path.exists(config_path):
                if os.path.dirname(config) != '':
                    raise PunicaException(PunicaError.other_error(config + ' not found'))
                else:
                    config_path = os.path.join(project_dir_path, 'contracts', config)
                    if not os.path.exists(config_path):
                        raise PunicaException(PunicaError.other_error(config_path + ' not exist'))
        else:
            config_path = os.path.join(project_dir_path, 'contracts', DEFAULT_CONFIG)
        if not os.path.exists(config_path):
            raise PunicaException(PunicaError.other_error(config_path + ' not found'))
        with open(config_path, 'r') as f:
            config = json.load(f)
    except FileNotFoundError:
        raise PunicaException(PunicaError.config_file_not_found)
    try:
        wallet_file = config['defaultWallet']
        invoke_config = config['invokeConfig']
        password_config = config['password']
    except KeyError:
        raise PunicaException(PunicaError.other_error('the config file lack invokeConfig or password'))
    if not isinstance(invoke_config, dict):
        raise PunicaException(PunicaError.config_file_error)
    return wallet_file, invoke_config, password_config
Beispiel #2
0
 def list_all_functions(project_dir: str, config_name: str):
     if config_name == '':
         config_name = DEFAULT_CONFIG
     try:
         wallet_file, invoke_config, password_config = handle_invoke_config(project_dir, config_name)
     except Exception as e:
         print(e.args)
         return
     try:
         abi_file_name = invoke_config['abi']
     except KeyError:
         raise PunicaException(PunicaError.config_file_error)
     abi_dir_path = os.path.join(project_dir, 'contracts', 'build')
     try:
         dict_abi = read_abi(abi_dir_path, abi_file_name)
     except PunicaException as e:
         print(e.args)
         return
     try:
         func_in_abi_list = dict_abi['functions']
     except KeyError:
         raise PunicaException(PunicaError.other_error('abi file is wrong'))
     func_name_in_abi_list = list()
     for func_in_abi_dict in func_in_abi_list:
         try:
             func_name = func_in_abi_dict['name']
         except KeyError:
             raise PunicaException(PunicaError.other_error('abi file is wrong'))
         func_name_in_abi_list.append(func_name)
     print("All Functions:")
     invoke_function_list = invoke_config['functions']
     for function_information in invoke_function_list:
         if function_information['operation'] in func_name_in_abi_list:
             print('\t', function_information['operation'])
Beispiel #3
0
def read_wallet(project_path: str, wallet_file_name: str = '') -> WalletManager:
    if not os.path.isdir(project_path):
        raise PunicaException(PunicaError.directory_error)
    wallet_manager = WalletManager()
    if wallet_file_name == '' or wallet_file_name == '"':
        wallet_dir_path = os.path.join(project_path, 'wallet')
        dir_list = os.listdir(wallet_dir_path)
        if len(dir_list) == 1:
            wallet_path = os.path.join(wallet_dir_path, dir_list[0])
        elif os.path.exists(os.path.join(wallet_dir_path, 'wallet.json')):
            print('Use the default wallet file: wallet.json')
            wallet_path = os.path.join(wallet_dir_path, 'wallet.json')
        else:
            raise PunicaException(PunicaError.wallet_file_unspecified)
    else:
        wallet_path = os.path.join(project_path, wallet_file_name)
        if not os.path.exists(wallet_path):
            if os.path.dirname(wallet_file_name) != '':
                raise PunicaException(PunicaError.other_error(wallet_file_name + ' not found'))
            wallet_path = os.path.join(project_path, 'wallet', wallet_file_name)
            if not os.path.exists(wallet_path):
                raise PunicaError.other_error(wallet_path, ' is error')
    try:
        wallet_manager.open_wallet(wallet_path)
    except SDKException as e:
        raise PunicaException(PunicaError.wallet_file_error)
    return wallet_manager
Beispiel #4
0
def handle_deploy_config(project_dir_path: str, config: str = ''):
    try:
        if config != '':
            config_path = os.path.join(project_dir_path, config)
            if os.path.exists(config_path):
                if not os.path.isfile(config_path):
                    raise PunicaError.other_error(config_path, ' is not file')
            else:
                config_path = os.path.join(project_dir_path, 'contracts', config)
                if not os.path.exists(config_path):
                    raise PunicaError.other_error(config_path, ' not exist')
        else:
            config_path = os.path.join(project_dir_path, 'contracts', DEFAULT_CONFIG)
        if not os.path.exists(config_path):
            print(config_path, ' not exist')
            os._exit(0)
        with open(config_path, 'r') as f:
            config = json.load(f)
    except FileNotFoundError:
        raise PunicaException(PunicaError.config_file_not_found)
    try:
        wallet_file = config['defaultWallet']
        deploy_information = config['deployConfig']
        password_information = config['password']
    except KeyError:
        raise PunicaException(PunicaError.config_file_error)
    if not isinstance(deploy_information, dict):
        raise PunicaException(PunicaError.config_file_error)
    return wallet_file, deploy_information, password_information
Beispiel #5
0
def read_abi(abi_dir_path: str, abi_file_name: str) -> dict:
    if not os.path.isdir(abi_dir_path):
        raise PunicaException(PunicaError.other_error('build folder not exist, please compile first'))
    abi_file_path = os.path.join(abi_dir_path, abi_file_name)
    if not os.path.exists(abi_file_path):
        raise PunicaException(PunicaError.other_error('abi config file not exist'))
    with open(abi_file_path, 'r') as f:
        dict_abi = json.load(f)
    return dict_abi
Beispiel #6
0
 def params_normalize2(list_param: list):
     list_params = list()
     for param in list_param:
         if isinstance(param, dict):
             item = param.get('value', '')
             if isinstance(item, bool):
                 list_params.append(item)
             elif isinstance(item, int):
                 list_params.append(item)
             elif isinstance(item, str):
                 list_params.append(Invoke.handle_param_str2(item))
             elif isinstance(item, list):
                 list_temp = list()
                 for i in item:
                     list_temp.append(Invoke.parse_param(i))
                 list_params.append(list_temp)
             elif isinstance(item, dict):
                 dict_temp = dict()
                 for k, v in item.items():
                     dict_temp[k] = Invoke.parse_param(v)
                 list_params.append(dict_temp)
             else:
                 raise PunicaException(
                     PunicaError.other_error('not support data type'))
     return list_params
Beispiel #7
0
def handle_network_config(config_dir_path: str, network: str = '', is_print: bool = True) -> str:
    try:
        print(config_dir_path)
        config_file_path = os.path.join(config_dir_path, 'punica-config.json')
        with open(config_file_path, 'r') as f:
            config = json.load(f)
    except FileNotFoundError:
        raise PunicaException(PunicaError.config_file_not_found)
    try:
        network_dict = config['networks']
        default_net = config['defaultNet']
    except KeyError:
        raise PunicaException(PunicaError.config_file_error)
    if network == '':
        if default_net == '':
            network = list(network_dict.keys())[0]
        else:
            default_network = network_dict.get(default_net, '')
            if default_network == '':
                raise PunicaException(PunicaError.other_error('there is not the network: ' + default_net))
            else:
                network = default_net
    try:
        rpc_address = ''.join([network_dict[network]['host'], ':', str(network_dict[network]['port'])])
    except KeyError:
        raise PunicaException(PunicaError.config_file_error)
    if is_print:
        print('Using network \'{}\'.\n'.format(network))
    return rpc_address
Beispiel #8
0
 def compile_contract(contract_path: str,
                      local: bool = False,
                      abi_save_path: str = '',
                      avm_save_path: str = ''):
     if abi_save_path == '':
         split_path = os.path.split(contract_path)
         save_path = os.path.join(os.path.dirname(split_path[0]), 'build',
                                  split_path[1])
         if save_path.endswith('.py'):
             abi_save_path = save_path.replace('.py', '_abi.json')
         else:
             abi_save_path = save_path.replace('.cs', '_abi.json')
     if avm_save_path == '':
         split_path = os.path.split(contract_path)
         save_path = os.path.join(os.path.dirname(split_path[0]), 'build',
                                  split_path[1])
         if avm_save_path.endswith('.py'):
             avm_save_path = save_path.replace('.py', '.avm')
         else:
             avm_save_path = save_path.replace('.cs', '.avm')
     if not local:
         PunicaCompiler.compile_contract_remote(contract_path)
         return
     try:
         PunicaCompiler.generate_avm_file(contract_path, avm_save_path)
         PunicaCompiler.generate_abi_file(contract_path, abi_save_path)
         print('Compiled, Thank you')
     except PermissionError as error:
         if error.args[0] == 13:
             raise PunicaException(PunicaError.permission_error)
         else:
             raise PunicaException(PunicaError.other_error(error.args[1]))
Beispiel #9
0
def save_avm_file(avm_code: str, to_path: str):
    try:
        with open(to_path, 'w') as f:
            f.write(avm_code.lstrip('b\'').rstrip('\''))
    except PermissionError as error:
        if error.args[0] == 13:
            raise PunicaException(PunicaError.permission_error)
        else:
            raise PunicaException(PunicaError.other_error(error.args[1]))
Beispiel #10
0
 def get_password():
     while True:
         acct_password = getpass.getpass('Please input password: '******'Please repeat password: '******'password not match'))
 def params_normalize(dict_params: dict) -> list:
     list_params = list()
     if len(dict_params) == 0:
         return list_params
     for param in dict_params.values():
         if isinstance(param, list):
             for i in range(len(param)):
                 list_params2 = list()
                 if isinstance(param[i], dict):
                     for p in param[i].values():
                         if isinstance(p, str):
                             list_p = p.split(':')
                             if len(list_p) != 2:
                                 raise PunicaError.other_error('parameters error')
                             if list_p[0] == 'ByteArray':
                                 if len(list_p[1]) == 34:
                                     list_params2.append(Address.b58decode(list_p[1]).to_array())
                                 else:
                                     list_params2.append(list_p[1].encode())
                             elif list_p[0] == 'String':
                                 list_params2.append(list_p[1])
                         elif isinstance(p, int):
                             list_params2.append(p)
                 list_params.append(list_params2)
         elif isinstance(param, str):
             list_p = param.split(':')
             if len(list_p) != 2:
                 raise PunicaError.other_error("parameters error")
             if list_p[0] == 'ByteArray':
                 if len(list_p[1]) == 34:
                     try:
                         bs =  Address.b58decode(list_p[1]).to_array()
                         list_params.append(bs)
                     except SDKException:
                         list_params.append(list_p[1].encode())
                 else:
                     list_params.append(list_p[1].encode())
             elif list_p[0] == 'String':
                 list_params.append(list_p[1])
         elif isinstance(param, int):
             list_params.append(param)
     return list_params
 def compile_contract_remote(contract_path: str):
     with open(contract_path, "r") as f:
         contract = f.read()
         dict_payload = dict()
         if contract_path.endswith('.py'):
             dict_payload['type'] = 'Python'
             dict_payload['code'] = contract
             url = PYTHON_COMPILE_URL
         else:
             dict_payload['type'] = 'CSharp'
             dict_payload['code'] = contract
             url = CSHARP_COMPILE_URL
         header = {'Content-type': 'application/json'}
         timeout = 10
         path = os.path.dirname(contract_path)
         file_name = os.path.basename(contract_path).split(".")
         requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
         session = requests.session()
         response = session.post(url,
                                 json=dict_payload,
                                 headers=header,
                                 timeout=timeout,
                                 verify=False)
         if response.status_code != 200:
             raise PunicaException(
                 PunicaError.get_error(5000, 'Remote compile failed.'))
         result = json.loads(response.content.decode('utf-8'))
         if result["errcode"] == 0:
             avm_save_path = os.path.join(path, 'build',
                                          file_name[0] + ".avm")
             if not os.path.exists(os.path.join(path, 'build')):
                 os.makedirs(os.path.join(path, 'build'))
             with open(avm_save_path, "w", encoding='utf-8') as f:
                 avm = result["avm"].lstrip('b\'')
                 temp = avm.rstrip('\'')
                 f.write(temp)
             abi_save_path = os.path.join(path, 'build',
                                          file_name[0] + "_abi.json")
             with open(abi_save_path, "w", encoding='utf-8') as f2:
                 r = re.sub('\\\\n', '', str(result["abi"]))
                 abi = str(r.lstrip('b\''))
                 temp = abi.rstrip('\'')
                 f2.write(temp.replace(' ', ''))
             print("Compiled, Thank you")
             invoke_config_path = os.path.join(path, DEFAULT_CONFIG)
             if os.path.exists(invoke_config_path):
                 PunicaCompiler.update_invoke_config(
                     abi_save_path, invoke_config_path)
             else:
                 PunicaCompiler.generate_invoke_config(
                     abi_save_path, invoke_config_path)
         else:
             print("compile failed")
             print(result)
Beispiel #13
0
 def generate_signed_deploy_transaction(hex_avm_code: str,
                                        project_path: str = '',
                                        wallet_file_name: str = '',
                                        config: str = ''):
     wallet_file, deploy_information, password_information = handle_deploy_config(
         project_path, config)
     if wallet_file_name != '':
         wallet_manager = read_wallet(project_path, wallet_file_name)
     else:
         wallet_manager = read_wallet(project_path, wallet_file)
     need_storage = deploy_information.get('needStorage', True)
     name = deploy_information.get('name', os.path.split(project_path)[1])
     version = deploy_information.get('version', '0.0.1')
     author = deploy_information.get('author', '')
     email = deploy_information.get('email', '')
     desc = deploy_information.get('desc', '')
     b58_payer_address = deploy_information.get('payer', '')
     if b58_payer_address == '':
         b58_payer_address = wallet_manager.get_default_account(
         ).get_address()
     if b58_payer_address == '':
         raise PunicaException(
             PunicaError.other_error('payer address should not be None'))
     gas_limit = deploy_information.get('gasLimit', 21000000)
     gas_price = deploy_information.get('gasPrice', 500)
     ontology = OntologySdk()
     tx = ontology.neo_vm().make_deploy_transaction(hex_avm_code,
                                                    need_storage, name,
                                                    version, author, email,
                                                    desc, b58_payer_address,
                                                    gas_limit, gas_price)
     password = password_information.get(b58_payer_address, '')
     if password == '':
         password = getpass.getpass(
             '\tPlease input payer account password: '******' not found'))
     ontology.sign_transaction(tx, payer_acct)
     return tx
Beispiel #14
0
 def list_boxes(self):
     response = requests.get(self.__box_repos_url).content.decode()
     repos = json.loads(response)
     if isinstance(repos, dict):
         message = repos.get('message', '')
         if 'API rate limit exceeded' in message:
             raise PunicaException(PunicaError.other_error(message))
     echo('\nThe easiest way to get started:\n')
     for index, repo in enumerate(repos):
         name = repo.get('name', '')
         echo(f' {index}. {name}')
     echo('')
Beispiel #15
0
 def get_function(params: dict, function_name: str, abi_info: AbiInfo):
     if function_name == '':
         raise PunicaException(PunicaError.other_error('function_name should not be nil'))
     params = Invoke.params_normalize(params)
     abi_function = abi_info.get_function(function_name)
     if len(abi_function.parameters) == 0:
         pass
     elif len(abi_function.parameters) == 1:
         abi_function.set_params_value((params,))
     elif len(abi_function.parameters) == len(params):
         abi_function.set_params_value(tuple(params))
     return abi_function
Beispiel #16
0
 def list_boxes():
     repos_url = 'https://api.github.com/users/punica-box/repos'
     response = requests.get(repos_url).content.decode()
     repos = json.loads(response)
     if isinstance(repos, dict):
         message = repos.get('message', '')
         if 'API rate limit exceeded' in message:
             raise PunicaException(PunicaError.other_error(message))
     name_list = []
     for repo in repos:
         name = repo.get('name', '')
         name_list.append(name)
     return name_list
Beispiel #17
0
 def git_clone(repo_url: str, repo_to_path: str = ''):
     if repo_to_path == '':
         repo_to_path = os.getcwd()
     print('Downloading...')
     try:
         git.Repo.clone_from(url=repo_url, to_path=repo_to_path, depth=1)
     except git.GitCommandError as e:
         network_error = 'Could not read from remote repository'
         file_exist_error = 'already exists and is not an empty directory'
         if network_error in str(e.args[2]):
             raise PunicaException(PunicaError.network_error)
         elif file_exist_error in str(e.args[2]):
             raise PunicaException(PunicaError.file_exist_error)
         else:
             raise PunicaException(PunicaError.other_error(e.args[2]))
Beispiel #18
0
 def parse_param(param):
     if isinstance(param, bool):
         return param
     elif isinstance(param, int):
         return param
     elif isinstance(param, str):
         return Invoke.handle_param_str2(param)
     elif isinstance(param, list):
         list_temp = list()
         for i in param:
             list_temp.append(Invoke.parse_param(i))
         return list_temp
     elif isinstance(param, dict):
         dict_temp = dict()
         for k, v in param.items():
             dict_temp[k] = Invoke.parse_param(v)
         return dict_temp
     else:
         raise PunicaException(PunicaError.other_error('not support data type'))
Beispiel #19
0
def read_avm(avm_dir_path: str, avm_file_name: str = '') -> (str, str):
    if not os.path.isdir(avm_dir_path):
        raise PunicaException(PunicaError.directory_error)
    if avm_file_name != '':
        avm_file_path = os.path.join(avm_dir_path, avm_file_name)
        if not os.path.exists(avm_file_path):
            raise PunicaException(PunicaError.other_error(avm_file_path + ' not exist'))
        with open(avm_file_path, 'r') as f:
            hex_avm = f.read()
    else:
        dir_list = os.listdir(avm_dir_path)
        hex_avm = ''
        for file in dir_list:
            split_path = os.path.splitext(file)
            if (split_path[0] == avm_file_name or avm_file_name == '') and split_path[1] == '.avm':
                avm_file_name = ''.join(split_path)
                avm_path = os.path.join(avm_dir_path, file)
                with open(avm_path, 'r') as f:
                    hex_avm = f.read()
                    break
    return hex_avm, avm_file_name
Beispiel #20
0
    def download_repo(repo_url: str, repo_to_path: str = ''):
        if repo_to_path == '':
            repo_to_path = getcwd()
        spinner = Halo(spinner='dots')

        def calcu_progress_scale(cur_count: int, max_count: int):
            return round(cur_count / max_count * 100, 2)

        def show_spinner(stage_info: str,
                         cur_count: int,
                         max_count: int,
                         message: str = ''):
            if spinner.spinner_id is None:
                spinner.start()
            scale = calcu_progress_scale(cur_count, max_count)
            if len(message) == 0:
                spinner.text = f'{stage_info}: {scale}% ({cur_count}/{max_count})'
            else:
                spinner.text = f'{stage_info}: {scale}%, {message}'
            if scale == 100:
                spinner.succeed()
            return

        def update(self,
                   op_code: RemoteProgress,
                   cur_count: int,
                   max_count: int = None,
                   message: str = ''):
            if op_code == RemoteProgress.COUNTING:
                show_spinner('Counting objects', cur_count, max_count)
                return
            if op_code == RemoteProgress.COMPRESSING:
                show_spinner('Compressing objects', cur_count, max_count)
                return
            if op_code == RemoteProgress.RECEIVING:
                show_spinner('Receiving objects', cur_count, max_count,
                             message)
                return
            if op_code == RemoteProgress.RESOLVING:
                show_spinner('Resolving deltas', cur_count, max_count)
                return
            if op_code == RemoteProgress.WRITING:
                show_spinner('Writing objects', cur_count, max_count)
                return
            if op_code == RemoteProgress.FINDING_SOURCES:
                show_spinner('Finding sources', cur_count, max_count)
                return
            if op_code == RemoteProgress.CHECKING_OUT:
                show_spinner('Checking out files', cur_count, max_count)
                return

        RemoteProgress.update = update

        try:
            Repo.clone_from(url=repo_url,
                            to_path=repo_to_path,
                            depth=1,
                            progress=RemoteProgress())
            if spinner.spinner_id is not None and len(spinner.text) != 0:
                spinner.fail()
                return False
            return True
        except GitCommandError as e:
            if spinner.spinner_id is not None and len(spinner.text) != 0:
                spinner.fail()
            if e.status == 126:
                echo('Please check your network.')
            elif e.status == 128:
                echo('Please check your Git tool.')
            else:
                raise PunicaException(PunicaError.other_error(e.args[2]))
            return False
    def invoke_all_function_in_list(wallet_file_name: str = '', project_dir_path: str = '', network: str = '',
                                    exec_func_str: str = ''):
        if project_dir_path == '':
            project_dir_path = os.getcwd()
        if not os.path.isdir(project_dir_path):
            raise PunicaException(PunicaError.dir_path_error)
        ontology = OntologySdk()
        wallet_dir_path = os.path.join(project_dir_path, 'wallet')
        ontology.wallet_manager = read_wallet(wallet_dir_path, wallet_file_name)
        rpc_address = handle_network_config(project_dir_path, network)
        ontology.rpc.set_address(rpc_address)
        invoke_config, password_config = handle_invoke_config(project_dir_path)
        try:
            abi_file_name = invoke_config['abi']
        except KeyError:
            raise PunicaException(PunicaError.config_file_error)
        try:
            default_b58_payer_address = invoke_config['defaultPayer']
        except KeyError:
            raise PunicaException(PunicaError.config_file_error)
        print('Running invocation: {}'.format(abi_file_name))
        abi_dir_path = os.path.join(project_dir_path, 'contracts', 'build')
        dict_abi = read_abi(abi_dir_path, abi_file_name)
        try:
            hex_contract_address = dict_abi['hash']
        except KeyError:
            raise PunicaException(PunicaError.abi_file_error)

        if not isinstance(hex_contract_address, str) or len(hex_contract_address) != 40:
            raise PunicaException(PunicaError.abi_file_error)
        contract = ontology.rpc.get_smart_contract(hex_contract_address)
        if contract == 'unknow contracts':
            print('Contract 0x{} hasn\'t been deployed in current network: {}'.format(hex_contract_address, network))
            raise PunicaException(PunicaError.abi_file_error)
        contract_address = bytearray(binascii.a2b_hex(hex_contract_address))
        contract_address.reverse()
        abi_info = Invoke.generate_abi_info(dict_abi)
        gas_price = invoke_config.get('gasPrice', 500)
        gas_limit = invoke_config.get('gasLimit', 21000000)
        invoke_function_dict = invoke_config.get('Functions', dict())
        all_exec_func = list()
        if exec_func_str != '':
            all_exec_func = exec_func_str.split(',')
            for exec_func in all_exec_func:
                if exec_func not in invoke_function_dict.keys():
                    raise PunicaError.other_error('there is not the function :', exec_func + ' in the abi file')
        print('Unlock default payer account...')
        if password_config[default_b58_payer_address] != '':
            default_payer_acct = ontology.wallet_manager.get_account(default_b58_payer_address,
                                                                     password_config[default_b58_payer_address])
        else:
            default_payer_acct = Invoke.unlock_account(default_b58_payer_address, wallet_manager)
        for function_key in invoke_function_dict:
            if len(all_exec_func) != 0 and function_key not in all_exec_func:
                continue
            print('Invoking {}...'.format(function_key))
            abi_function = abi_info.get_function(function_key)
            function_information = invoke_function_dict[function_key]
            try:
                params = function_information['params']
                print("params: ", params)
                params = Invoke.params_normalize(params)
                if len(abi_function.parameters) == 0:
                    pass
                elif len(abi_function.parameters) == 1:
                    abi_function.set_params_value((params,))

                elif len(abi_function.parameters) == len(params):
                    abi_function.set_params_value(tuple(params))
                else:
                    abi_function = None
                    print('\tInvoke failed, params mismatching with the abi file')
                if abi_function is not None:
                    if function_information['preExec']:
                        tx = Invoke.generate_unsigned_invoke_transaction(contract_address, abi_function, bytearray(),
                                                                         gas_price, gas_limit)
                        result = ontology.rpc.send_raw_transaction_pre_exec(tx)
                        print('\tInvoke successful...')
                        print('\t\t... Invoke result: {}'.format(result))
                    else:
                        b58_payer_address = function_information.get('payer', default_b58_payer_address)
                        if b58_payer_address == default_b58_payer_address:
                            payer_acct = default_payer_acct
                        else:
                            if password_config[b58_payer_address] != '':
                                payer_acct = ontology.wallet_manager.get_account(b58_payer_address, password_config[b58_payer_address])
                            else:
                                payer_acct = Invoke.unlock_account(b58_payer_address, wallet_manager)
                        tx = Invoke.generate_unsigned_invoke_transaction(contract_address, abi_function,
                                                                         payer_acct.get_address().to_array(), gas_price,
                                                                         gas_limit)
                        ontology.add_sign_transaction(tx, payer_acct)
                        dict_signers = function_information.get('signers', dict())
                        signer_list = list()
                        if len(dict_signers) != 0:
                            print('Unlock signers account...')
                            for b58_signer_address in dict_signers['signer']:
                                if b58_signer_address == b58_payer_address:
                                    pass
                                else:
                                    if password_config[b58_signer_address] != '':
                                        signer = ontology.wallet_manager.get_account(b58_signer_address, password_config[b58_signer_address])
                                    else:
                                        signer = Invoke.unlock_account(b58_signer_address, wallet_manager)
                                    signer_list.append(signer)
                            if dict_signers['m'] == 1:
                                for signer in signer_list:
                                    ontology.add_sign_transaction(tx, signer)
                            elif dict_signers['m'] > 1:
                                list_public_key = list()
                                for pubkey in dict_signers['publicKeys']:
                                    list_public_key.append(bytearray.fromhex(pubkey))
                                for signer in signer_list:
                                    ontology.add_multi_sign_transaction(tx, dict_signers['m'], list_public_key, signer)
                        ontology.rpc.set_address(rpc_address)
                        try:
                            tx_hash = ontology.rpc.send_raw_transaction(tx)
                            if tx_hash == '':
                                print('\tInvoke failed...')
                            else:
                                print('\tInvoke successful...')
                                print('\t\t... txHash: 0x{}'.format(tx_hash))
                        except SDKException as e:
                            print('\tInvoke failed, {}'.format(e.args[1].replace('Other Error, ', '')))

            except (KeyError, RuntimeError) as e:
                print('\tInvoke failed,', e.args)
Beispiel #22
0
    def invoke_all_function_in_list(wallet_file_name: str = '', project_dir_path: str = '', network: str = '',
                                    exec_func_str: str = '', config_name: str = '', pre_exec: str = ''):
        if project_dir_path == '':
            project_dir_path = os.getcwd()
        if not os.path.isdir(project_dir_path):
            raise PunicaException(PunicaError.dir_path_error)
        try:
            wallet_file, invoke_config, password_config = handle_invoke_config(project_dir_path, config_name)
            sleep_time = invoke_config.get('sleepTime', 6)
        except PunicaException as e:
            print(e.args)
            return
        ontology = OntologySdk()
        rpc_address = handle_network_config(project_dir_path, network)
        ontology.rpc.set_address(rpc_address)
        if wallet_file_name != '':
            ontology.wallet_manager = read_wallet(project_dir_path, wallet_file_name)
        else:
            ontology.wallet_manager = read_wallet(project_dir_path, wallet_file)
        try:
            abi_file_name = invoke_config['abi']
        except KeyError:
            raise PunicaException(PunicaError.config_file_error)
        try:
            default_b58_payer_address = invoke_config['defaultPayer']
        except KeyError:
            raise PunicaException(PunicaError.other_error("defaultPayer is null"))
        print('Running invocation: {}'.format(abi_file_name))
        abi_dir_path = os.path.join(project_dir_path, 'contracts', 'build')
        dict_abi = read_abi(abi_dir_path, abi_file_name)
        try:
            hex_contract_address = dict_abi['hash']
        except KeyError:
            raise PunicaException(PunicaError.abi_file_error)

        if not isinstance(hex_contract_address, str) or len(hex_contract_address) != 40:
            raise PunicaException(PunicaError.abi_file_error)
        contract = ontology.rpc.get_smart_contract(hex_contract_address)
        if contract == 'unknow contracts':
            print('Contract 0x{} hasn\'t been deployed in current network: {}'.format(hex_contract_address, network))
            raise PunicaException(PunicaError.abi_file_error)
        contract_address = bytearray(binascii.a2b_hex(hex_contract_address))
        contract_address.reverse()
        abi_info = Invoke.generate_abi_info(dict_abi)
        gas_price = invoke_config.get('gasPrice', 500)
        gas_limit = invoke_config.get('gasLimit', 21000000)
        invoke_function_list = invoke_config.get('functions', list())
        invoke_function_name_list = list()
        for invoke_function in invoke_function_list:
            invoke_function_name_list.append(invoke_function['operation'])
        all_exec_func_list = list()
        if exec_func_str != '':
            all_exec_func_list = exec_func_str.split(',')
        if default_b58_payer_address != '':
            print('Unlock default payer account...')
            default_payer_acct = Invoke.get_account(ontology, password_config, default_b58_payer_address)
        if len(all_exec_func_list) == 0:
            all_exec_func_list = invoke_function_name_list
        for function_name in all_exec_func_list:
            if function_name not in invoke_function_name_list:
                print('there is not the function:', '\"' + function_name + '\"' + ' in the default-config file')
                continue
            print('Invoking ', function_name)
            abi_function = abi_info.get_function(function_name)
            if abi_function is None:
                raise PunicaException(PunicaError.other_error('\"' + function_name + '\"' + 'not found in the abi file'))
            function_information = None
            for invoke_function in invoke_function_list:
                if invoke_function['operation'] == function_name:
                    function_information = invoke_function
                    break
            if function_information is None:
                print('there is not the function: ', function_name)
                return
            try:
                paramList = function_information['args']
                try:
                    # params = Invoke.params_normalize(paramsList)
                    params = Invoke.params_normalize2(paramList)
                    params_list = Invoke.params_build(function_name, params)
                except PunicaException as e:
                    print(e.args)
                    return
                # if len(abi_function.parameters) == 0:
                #     pass
                # elif len(abi_function.parameters) == 1:
                #     abi_function.set_params_value(tuple(params))
                # elif len(abi_function.parameters) == len(params):
                #     abi_function.set_params_value(tuple(params))
                # else:
                #     abi_function = None
                #     print('\tInvoke failed, params mismatching with the abi file')
                if abi_function is not None:
                    if (function_information['preExec'] and pre_exec == '') or (pre_exec == 'true'):
                        tx = Invoke.generate_unsigned_invoke_transaction(contract_address, params_list, bytearray(),
                                                                         gas_price, gas_limit)
                        result = ontology.rpc.send_raw_transaction_pre_exec(tx)
                        print('Invoke successful')
                        if isinstance(result, list):
                            print('Invoke result: {}'.format(result))
                            # print('Invoke result: {}'.format(list(map(lambda r: "0x" + r, result))))
                        else:
                            if result is None:
                                print('Invoke result: {}'.format(''))
                            else:
                                print('Invoke result: {}'.format(result))
                    else:
                        b58_payer_address = function_information.get('payer', default_b58_payer_address)
                        if default_b58_payer_address != '' and b58_payer_address == default_b58_payer_address:
                            payer_acct = default_payer_acct
                        else:
                            payer_acct = Invoke.get_account(ontology, password_config, b58_payer_address)
                        if payer_acct is None or payer_acct == '':
                            print('defaultPayer is None in invokeConfig')
                            return
                        tx = Invoke.generate_unsigned_invoke_transaction(contract_address, params_list,
                                                                         payer_acct.get_address().to_bytes(), gas_price,
                                                                         gas_limit)
                        ontology.add_sign_transaction(tx, payer_acct)
                        dict_signers = function_information.get('signature', dict())
                        signer_list = list()
                        if len(dict_signers) != 0:
                            print('Unlock signers account...')
                            for b58_signer_address in dict_signers['signers']:
                                if b58_signer_address == b58_payer_address:
                                    signer_list.append(payer_acct)
                                    continue
                                else:
                                    signer = Invoke.get_account(ontology, password_config, b58_signer_address)
                                    signer_list.append(signer)
                            if dict_signers['m'] == 1:
                                for signer in signer_list:
                                    ontology.add_sign_transaction(tx, signer)
                            elif dict_signers['m'] > 1:
                                list_public_key = list()
                                for pubkey in dict_signers['publicKeys']:
                                    list_public_key.append(bytearray.fromhex(pubkey))
                                for signer in signer_list:
                                    ontology.add_multi_sign_transaction(tx, dict_signers['m'], list_public_key, signer)
                        ontology.rpc.set_address(rpc_address)
                        try:
                            tx_hash = ontology.rpc.send_raw_transaction(tx)
                            time.sleep(sleep_time)
                            if tx_hash == '':
                                print('Invoke failed...')
                                print('txHash: 0x{}'.format(tx.hash256_explorer()))
                            else:
                                print('Invoke successful')
                                print('txHash: 0x{}'.format(tx_hash))
                        except SDKException as e:
                            print('txHash: 0x{}'.format(tx.hash256_explorer()))
                            print('\tInvoke failed, {}'.format(e.args[1].replace('Other Error, ', '')))

            except (KeyError, RuntimeError) as e:
                print('\tInvoke failed,', e.args)