def GatherLoadedContractParams(args, script): if len(args) < 4: raise Exception( "please specify contract properties like {params} {return_type} {needs_storage} {needs_dynamic_invoke}" ) params = parse_param(args[0], ignore_int=True, prefer_hex=False) if type(params) is str: params = params.encode('utf-8') return_type = BigInteger(ContractParameterType.FromString(args[1]).value) needs_storage = bool(parse_param(args[2])) needs_dynamic_invoke = bool(parse_param(args[3])) contract_properties = 0 if needs_storage: contract_properties += ContractPropertyState.HasStorage if needs_dynamic_invoke: contract_properties += ContractPropertyState.HasDynamicInvoke out = generate_deploy_script(script, contract_properties=contract_properties, return_type=return_type, parameter_list=params) return out
def LoadContract(args): if len(args) < 5: print( "please specify contract to load like such: 'import contract {path} {params} {return_type} {needs_storage} {needs_dynamic_invoke}'" ) return path = args[0] params = parse_param(args[1], ignore_int=True, prefer_hex=False) if type(params) is str: params = params.encode('utf-8') return_type = BigInteger(ContractParameterType.FromString(args[2]).value) needs_storage = bool(parse_param(args[3])) needs_dynamic_invoke = bool(parse_param(args[4])) contract_properties = 0 if needs_storage: contract_properties += ContractPropertyState.HasStorage if needs_dynamic_invoke: contract_properties += ContractPropertyState.HasDynamicInvoke script = None if '.py' in path: print("Please load a compiled .avm file") return False with open(path, 'rb') as f: content = f.read() try: content = binascii.unhexlify(content) except Exception as e: pass script = content if script is not None: plist = params try: plist = bytearray(binascii.unhexlify(params)) except Exception as e: plist = bytearray(b'\x10') function_code = FunctionCode(script=script, param_list=bytearray(plist), return_type=return_type, contract_properties=contract_properties) return function_code print("error loading contract for path %s" % path) return None
def DoRun(contract_script, arguments, wallet, path, verbose=True, from_addr=None, min_fee=DEFAULT_MIN_FEE): test = get_arg(arguments, 1) if test is not None and test == 'test': if wallet is not None: f_args = arguments[2:] i_args = arguments[6:] script = GatherLoadedContractParams(f_args, contract_script) tx, result, total_ops, engine = test_deploy_and_invoke( script, i_args, wallet, from_addr, min_fee) i_args.reverse() return_type_results = [] try: rtype = ContractParameterType.FromString(f_args[1]) for r in result: cp = ContractParameter.AsParameterType(rtype, r) return_type_results.append(cp.ToJson()) except Exception as e: logger.error( 'Could not convert result to ContractParameter: %s ' % e) if tx is not None and result is not None: if verbose: print( "\n-----------------------------------------------------------" ) print("Calling %s with arguments %s " % (path, i_args)) print("Test deploy invoke successful") print("Used total of %s operations " % total_ops) print("Result %s " % return_type_results) print("Invoke TX gas cost: %s " % (tx.Gas.value / Fixed8.D)) print( "-------------------------------------------------------------\n" ) return tx, result, total_ops, engine else: if verbose: print("Test invoke failed") print("tx is, results are %s %s " % (tx, result)) else: print("please open a wallet to test built contract") return None, None, None, None
def GatherLoadedContractParams(args, script): if len(args) < 5: raise Exception("please specify contract properties like {needs_storage} {needs_dynamic_invoke} {is_payable} {params} {return_type}") params = parse_param(args[3], ignore_int=True, prefer_hex=False) if type(params) is str: params = params.encode('utf-8') try: for p in binascii.unhexlify(params): if p == ContractParameterType.Void.value: raise ValueError("Void is not a valid input parameter type") except binascii.Error: pass return_type = BigInteger(ContractParameterType.FromString(args[4]).value) needs_storage = bool(parse_param(args[0])) needs_dynamic_invoke = bool(parse_param(args[1])) is_payable = bool(parse_param(args[2])) contract_properties = 0 if needs_storage: contract_properties += ContractPropertyState.HasStorage if needs_dynamic_invoke: contract_properties += ContractPropertyState.HasDynamicInvoke if is_payable: contract_properties += ContractPropertyState.Payable out = generate_deploy_script(script, contract_properties=contract_properties, return_type=return_type, parameter_list=params) return out
def __init__(self, script=None, param_list=None, return_type=255, contract_properties=0): self.Script = script if param_list is None: self.ParameterList = [] else: self.ParameterList = param_list self.ReturnType = ContractParameterType.FromString(return_type).value self.ContractProperties = contract_properties
def LoadContract(path, needs_storage, needs_dynamic_invoke, is_payable, params_str, return_type): params = parse_param(params_str, ignore_int=True, prefer_hex=False) if type(params) is str: params = params.encode('utf-8') try: for p in binascii.unhexlify(params): if p == ContractParameterType.Void.value: raise ValueError("Void is not a valid input parameter type") except binascii.Error: pass rtype = BigInteger(ContractParameterType.FromString(return_type).value) contract_properties = 0 if needs_storage: contract_properties += ContractPropertyState.HasStorage if needs_dynamic_invoke: contract_properties += ContractPropertyState.HasDynamicInvoke if is_payable: contract_properties += ContractPropertyState.Payable if '.avm' not in path: raise ValueError("Please load a compiled .avm file") script = None with open(path, 'rb') as f: content = f.read() try: content = binascii.unhexlify(content) except Exception as e: pass script = content if script: try: plist = bytearray(binascii.unhexlify(params)) except Exception as e: plist = bytearray(b'\x10') function_code = FunctionCode(script=script, param_list=bytearray(plist), return_type=rtype, contract_properties=contract_properties) return function_code else: raise Exception(f"Error loading contract for path {path}")
def ToJson(self): """ Convert object members to a dictionary that can be parsed as JSON. Returns: dict: """ parameters = self.ParameterList.hex() paramlist = [ToName(ContractParameterType.FromString(parameters[i:i + 2]).value) for i in range(0, len(parameters), 2)] return { 'hash': self.ScriptHash().To0xString(), 'script': self.Script.hex(), 'parameters': paramlist, 'returntype': ToName(self.ReturnType) if type(self.ReturnType) is int else ToName(int(self.ReturnType)) }
def FromJson(json): """ Convert a json object to a ContractParameter object Args: item (dict): The item to convert to a ContractParameter object Returns: ContractParameter """ type = ContractParameterType.FromString(json['type']) value = json['value'] param = ContractParameter(type=type, value=None) if type == ContractParameterType.Signature or type == ContractParameterType.ByteArray: param.Value = bytearray.fromhex(value) elif type == ContractParameterType.Boolean: param.Value = bool(value) elif type == ContractParameterType.Integer: param.Value = int(value) elif type == ContractParameterType.Hash160: param.Value = UInt160.ParseString(value) elif type == ContractParameterType.Hash256: param.Value = UInt256.ParseString(value) # @TODO Not sure if this is working... elif type == ContractParameterType.PublicKey: param.Value = ECDSA.decode_secp256r1(value).G elif type == ContractParameterType.String: param.Value = str(value) elif type == ContractParameterType.Array: val = [ContractParameter.FromJson(item) for item in value] param.Value = val return param
def DoRun(contract_script, arguments, wallet, path, verbose=True, from_addr=None, min_fee=DEFAULT_MIN_FEE, invocation_test_mode=True, debug_map=None, invoke_attrs=None, owners=None): if not wallet: print("Please open a wallet to test build contract") return None, None, None, None f_args = arguments[1:] i_args = arguments[6:] try: script = GatherLoadedContractParams(f_args, contract_script) except Exception: raise TypeError tx, result, total_ops, engine = test_deploy_and_invoke( script, i_args, wallet, from_addr, min_fee, invocation_test_mode, debug_map=debug_map, invoke_attrs=invoke_attrs, owners=owners) i_args.reverse() return_type_results = [] try: rtype = ContractParameterType.FromString(f_args[4]) for r in result: cp = ContractParameter.AsParameterType(rtype, r) return_type_results.append(cp.ToJson()) except Exception: raise TypeError if tx and result: if verbose: print( "\n-----------------------------------------------------------" ) print("Calling %s with arguments %s " % (path, [item for item in reversed(engine.invocation_args)])) print("Test deploy invoke successful") print("Used total of %s operations " % total_ops) print("Result %s " % return_type_results) print("Invoke TX gas cost: %s " % (tx.Gas.value / Fixed8.D)) print( "-------------------------------------------------------------\n" ) return tx, result, total_ops, engine else: if verbose: print("Test invoke failed") print(f"tx is {tx}, results are {result}") return tx, result, None, None
def execute(self, arguments): wallet = PromptData.Wallet if not wallet: print("Please open a wallet") return False arguments, from_addr = PromptUtils.get_from_addr(arguments) arguments, priority_fee = PromptUtils.get_fee(arguments) arguments, invoke_attrs = PromptUtils.get_tx_attr_from_args(arguments) arguments, owners = PromptUtils.get_owners_from_params(arguments) arguments, return_type = PromptUtils.get_return_type_from_args(arguments) if len(arguments) < 1: print("Please specify the required parameters") return False hash_string = arguments[0] try: script_hash = UInt160.ParseString(hash_string) except Exception: # because UInt160 throws a generic exception. Should be fixed in the future print("Invalid script hash") return False p_fee = Fixed8.Zero() if priority_fee is not None: p_fee = priority_fee if p_fee is False: logger.debug("invalid fee") return False tx, fee, results, num_ops, engine_success = TestInvokeContract(wallet, arguments, from_addr=from_addr, invoke_attrs=invoke_attrs, owners=owners) if tx and results: if return_type is not None: try: parameterized_results = [ContractParameter.AsParameterType(ContractParameterType.FromString(return_type), item).ToJson() for item in results] except ValueError: logger.debug("invalid return type") return False else: parameterized_results = [ContractParameter.ToParameter(item).ToJson() for item in results] print( "\n-------------------------------------------------------------------------------------------------------------------------------------") print("Test invoke successful") print(f"Total operations: {num_ops}") print(f"Results {str(parameterized_results)}") print(f"Invoke TX GAS cost: {tx.Gas.value / Fixed8.D}") print(f"Invoke TX fee: {fee.value / Fixed8.D}") print( "-------------------------------------------------------------------------------------------------------------------------------------\n") comb_fee = p_fee + fee if comb_fee != fee: print(f"Priority Fee ({p_fee.value / Fixed8.D}) + Invoke TX Fee ({fee.value / Fixed8.D}) = {comb_fee.value / Fixed8.D}\n") print("Enter your password to send this invocation to the network") tx.Attributes = invoke_attrs try: passwd = prompt("[password]> ", is_password=True) except KeyboardInterrupt: print("Invocation cancelled") return False if not wallet.ValidatePassword(passwd): return print("Incorrect password") return InvokeContract(wallet, tx, comb_fee, from_addr=from_addr, owners=owners) else: print("Error testing contract invoke") return False