def __init__(self, project_dir: str = '', network: str = '', wallet_path: str = '', contract_config_path: str = ''): super().__init__(project_dir) contract_config_file_path = path.join(self.project_dir, 'contracts', 'config.json') old_contract_config_file_path = path.join(self.project_dir, 'contracts', 'default-config.json') if len(contract_config_path) != 0: self._contract_config_file_path = contract_config_path elif path.exists(contract_config_file_path): self._contract_config_file_path = contract_config_file_path elif path.exists(old_contract_config_file_path): self._contract_config_file_path = old_contract_config_file_path else: raise PunicaException(PunicaError.config_file_not_found) try: with open(self._contract_config_file_path, 'r') as f: self._contract_config = json.load(f) except FileNotFoundError: raise PunicaException(PunicaError.config_file_not_found) self._avm_dir = path.join(project_dir, 'build', 'contracts') self._wallet_dir = path.join(project_dir, 'wallet') if len(network) == 0: network = self.default_network self._network = network self._ontology = Ontology() self._ontology.rpc.set_address(self.get_rpc_address(network)) if len(wallet_path) == 0: wallet_path = path.join(self.wallet_dir, self._contract_config.get('defaultWallet', 'wallet.json')) self._wallet_path = wallet_path self._ontology.wallet_manager.open_wallet(self._wallet_path)
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'])
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
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]))
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
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
def read_abi(abi_dir_path: str, abi_file_name: str) -> dict: if not os.path.isdir(abi_dir_path): raise PunicaException(PunicaError.directory_error) abi_file_path = os.path.join(abi_dir_path, abi_file_name) if not os.path.exists(abi_file_path): raise PunicaException(PunicaError.config_file_not_found) with open(abi_file_path, 'r') as f: dict_abi = json.load(f) return dict_abi
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]))
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
def get_invoke_dict(abi_file_name: str, project_path: str = ''): if project_path == '': project_path = os.getcwd() if not os.path.isdir(project_path): raise PunicaException(PunicaError.dir_path_error) abi_dir_path = os.path.join(project_path, 'build') dict_abi = read_abi(abi_dir_path, abi_file_name) if len(dict_abi) == 0: raise PunicaException(PunicaError.abi_file_empty) return dict_abi
def read_avm_code(avm_dir: str, contract_name: str): if not contract_name.endswith('.avm'): contract_name = ''.join([contract_name, '.avm']) avm_file_path = path.join(avm_dir, contract_name) if not path.exists(avm_file_path): raise PunicaException(PunicaError.avm_file_not_found) with open(avm_file_path, 'r') as f: avm_code = f.read() if len(avm_code) == 0: raise PunicaException(PunicaError.avm_file_empty) return avm_code
def handle_param_str2(p: str): list_p = p.split(':') if len(list_p) != 2: raise PunicaException(PunicaError.parameter_type_error) if list_p[0] == 'ByteArray': return bytearray.fromhex(list_p[1]) elif list_p[0] == 'String': return list_p[1] elif list_p[0] == 'Address': return Address.b58decode(list_p[1]).to_bytes() else: raise PunicaException(PunicaError.parameter_type_error)
def handle_deploy_config(config_dir_path: str) -> dict: try: 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: deploy_information = config['invokeConfig'] except KeyError: raise PunicaException(PunicaError.config_file_error) if not isinstance(deploy_information, dict): raise PunicaException(PunicaError.config_file_error) return deploy_information
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]))
def __init__(self, project_dir: str = ''): super().__init__(project_dir) pj_config_file_path = path.join(self.project_dir, 'punica.json') old_pj_config_file_path = path.join(self.project_dir, 'punica.json') if path.exists(pj_config_file_path): self._pj_config_file_path = pj_config_file_path elif path.exists(old_pj_config_file_path): self._pj_config_file_path = old_pj_config_file_path else: raise PunicaException(PunicaError.config_file_not_found) try: with open(self._pj_config_file_path, 'r') as f: self._pj_config = json.load(f) except FileNotFoundError: raise PunicaException(PunicaError.config_file_not_found)
def handle_invoke_config(config_dir_path: str): try: config_file_path = os.path.join(config_dir_path, 'contracts', 'invoke-config.json') with open(config_file_path, 'r') as f: config = json.load(f) except FileNotFoundError: raise PunicaException(PunicaError.config_file_not_found) try: invoke_config = config['invokeConfig'] password_config = config['password'] except KeyError: raise PunicaException(PunicaError.config_file_error) if not isinstance(invoke_config, dict): raise PunicaException(PunicaError.config_file_error) return invoke_config, password_config
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
def withdraw_ong(project_dir_path: str, claimer: str, to: str, amount, gas_limit, gas_price, network): if project_dir_path == '': project_dir_path = os.getcwd() if not os.path.isdir(project_dir_path): raise PunicaException(PunicaError.dir_path_error) rpc_address = handle_network_config(project_dir_path, network) sdk = OntologySdk() sdk.rpc.set_address(rpc_address) sdk.wallet_manager = Account.get_wallet_manager(project_dir_path) if len(sdk.wallet_manager.wallet_in_mem.accounts) == 0: print('there is not account in the wallet.json') return has_sender = False for acc in sdk.wallet_manager.wallet_in_mem.accounts: if claimer == acc.address: has_sender = True break if not has_sender: print('there is not sender in the wallet.json') return claimer_pwd = getpass.getpass('Please input claimer password: '******'tx_hash: ', tx_hash)
def get_avm_file_path(self, file_name: str): if not file_name.endswith('.avm'): file_name = ''.join([file_name, '.avm']) avm_file_path = path.join(self.avm_dir, file_name) if not path.exists(avm_file_path): raise PunicaException(PunicaError.avm_file_not_found) return avm_file_path
def transfer(project_dir_path, asset: str, sender, to, amount, gas_price, gas_limit, network): if asset == '' or asset.lower() != 'ont' and asset.lower() != 'ong': print('asset should be ont or ong') return if project_dir_path == '': project_dir_path = os.getcwd() if not os.path.isdir(project_dir_path): raise PunicaException(PunicaError.dir_path_error) rpc_address = handle_network_config(project_dir_path, network) sdk = OntologySdk() sdk.set_rpc(rpc_address) wallet_manager = Account.get_wallet_manager(project_dir_path) if len(wallet_manager.wallet_in_mem.accounts) == 0: print('there is not account in the wallet.json') return has_sender = False for acc in wallet_manager.wallet_in_mem.accounts: if sender == acc.address: has_sender = True break if not has_sender: print('there is not sender in the wallet.json') return sender_account = Invoke.unlock_account(sender, wallet_manager) if sender_account is None: return tx_hash = sdk.native_vm().asset().send_transfer(asset, sender_account, to, amount, sender_account, gas_limit, gas_price) print('tx_hash: ', tx_hash)
def generate_test_template(project_dir_path, config, abi): if project_dir_path == '': project_dir_path = os.getcwd() if not os.path.isdir(project_dir_path): raise PunicaException(PunicaError.dir_path_error) if abi != '': abi_path = os.path.join(project_dir_path, abi) if not os.path.exists(abi_path): abi_path = os.path.join(project_dir_path, 'contracts', 'build', abi) if not os.path.exists(abi_path): print(abi_path, 'not exist') os._exit(0) Test.generate_test_file(project_dir_path, '', abi_path) else: if config != '': config_path = os.path.join(project_dir_path, config) if not os.path.exists(config): config_path = os.path.join(project_dir_path, 'contracts', config) 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) invoke_dict, password = handle_invoke_config( project_dir_path, os.path.basename(config_path)) abi_path = os.path.join(project_dir_path, 'contracts', 'build', invoke_dict['abi']) if not os.path.exists(abi_path): print(abi_path, 'not exist') os._exit(0) Test.generate_test_file(project_dir_path, abi_path)
def get_wasm_file_path(self, file_name: str): if not file_name.endswith('.wasm'): file_name = ''.join([file_name, '.wasm']) wasm_file_path = path.join(self.contract_build_dir, file_name) if not path.exists(wasm_file_path): raise PunicaException(PunicaError.wasm_file_not_found) return wasm_file_path
def deploy_smart_contract(project_dir: str = '', network: str = '', avm_file_name: str = '', wallet_file_name: str = ''): if project_dir == '': project_dir = os.getcwd() avm_dir_path = os.path.join(project_dir, 'contracts', 'build') rpc_address = handle_network_config(project_dir, network) hex_avm_code, avm_file_name = read_avm(avm_dir_path, avm_file_name) if hex_avm_code == '': raise PunicaException(PunicaError.avm_file_empty) hex_contract_address = Deploy.generate_contract_address( avm_dir_path, avm_file_name) ontology = OntologySdk() ontology.rpc.set_address(rpc_address) contract = ontology.rpc.get_smart_contract(hex_contract_address) print('Running deployment: {}'.format(avm_file_name)) if contract == 'unknow contracts': print('\tDeploying...') print('\t... 0x{}'.format(hex_avm_code[:64])) tx = Deploy.generate_signed_deploy_transaction( hex_avm_code, project_dir, wallet_file_name) ontology.rpc.set_address(rpc_address) tx_hash = ontology.rpc.send_raw_transaction(tx) return tx_hash else: print('\tDeploy failed...') print('\tContract has been deployed...') print('\tContract address is 0x{}...'.format(hex_contract_address))
def handle_param_str(list_params2: list, p: str): list_p = p.split(':') if len(list_p) != 2: raise PunicaException(PunicaError.parameter_type_error) if list_p[0] == 'ByteArray': if len(list_p[1]) == 34: list_params2.append(Address.b58decode(list_p[1]).to_bytes()) else: list_params2.append(list_p[1].encode()) elif list_p[0] == 'String': list_params2.append(list_p[1]) elif list_p[0] == 'Address': list_params2.append(Address.b58decode(list_p[1]).to_bytes()) elif list_p[0] == 'Hex': list_params2.append(bytearray.fromhex(list_p[1])) else: raise PunicaException(PunicaError.parameter_type_error)
def get_password(): while True: acct_password = getpass.getpass('Please input password: '******'Please repeat password: '******'password not match'))
def query_unbound_ong(project_dir_path, address, network): if project_dir_path == '': project_dir_path = os.getcwd() if not os.path.isdir(project_dir_path): raise PunicaException(PunicaError.dir_path_error) rpc_address = handle_network_config(project_dir_path, network) sdk = OntologySdk() sdk.rpc.set_address(rpc_address) balance = sdk.native_vm().asset().query_unbound_ong(address) print(address + ' UnboundOng: ', balance)
def read_wallet(wallet_dir_path: str, wallet_file_name: str = '') -> WalletManager: if not os.path.isdir(wallet_dir_path): raise PunicaException(PunicaError.directory_error) wallet_manager = WalletManager() if wallet_file_name == '': dir_list = os.listdir(wallet_dir_path) if len(dir_list) == 1: wallet_file_name = dir_list[0] else: raise PunicaException(PunicaError.wallet_file_unspecified) wallet_path = os.path.join(wallet_dir_path, wallet_file_name) if not os.path.isfile(wallet_path): raise PunicaException(PunicaError.wallet_file_not_found) try: wallet_manager.open_wallet(wallet_path) except SDKException: raise PunicaException(PunicaError.wallet_file_error) return wallet_manager
def generate_contract_address(avm_dir_path: str = '', avm_file_name: str = '') -> str: if avm_dir_path == '': avm_dir_path = os.path.join(os.getcwd(), 'build', 'contracts') if not os.path.isdir(avm_dir_path): raise PunicaException(PunicaError.dir_path_error) hex_avm_code = read_avm(avm_dir_path, avm_file_name)[0] hex_contract_address = Address.address_from_vm_code( hex_avm_code).to_reverse_hex_str() return hex_contract_address
def generate_repo_url(box_name: str) -> str: if re.match(r'^([a-zA-Z0-9-])+$', box_name): repo_url = [ 'https://github.com/punica-box/', box_name, '-box', '.git' ] elif re.match(r'^([a-zA-Z0-9-])+/([a-zA-Z0-9-])+$', box_name) is None: repo_url = ['https://github.com/', box_name, '.git'] else: raise PunicaException(PunicaError.invalid_box_name) return ''.join(repo_url)
def generate_abi_info(dict_abi: dict) -> AbiInfo: try: contract_address = dict_abi['hash'] functions = dict_abi['functions'] except KeyError: raise PunicaException(PunicaError.abi_file_error) entry_point = dict_abi.get('entrypoint', '') events = dict_abi.get('events', list()) abi_info = AbiInfo(contract_address, entry_point, functions, events) return abi_info