def transfer(self, from_acct: Account, b58_to_address: str, value: int, payer_acct: Account, gas_limit: int, gas_price: int) -> str: """ This interface is used to call the Transfer method in ope4 that transfer an amount of tokens from one account to another account. :param from_acct: an Account class that send the oep4 token. :param b58_to_address: a base58 encode address that receive the oep4 token. :param value: an int value that indicate the amount oep4 token that will be transferred in this transaction. :param payer_acct: an Account class that used to pay for the transaction. :param gas_limit: an int value that indicate the gas limit. :param gas_price: an int value that indicate the gas price. :return: the hexadecimal transaction hash value. """ func = InvokeFunction('transfer') if not isinstance(value, int): raise SDKException( ErrorCode.param_err('the data type of value should be int.')) if value < 0: raise SDKException( ErrorCode.param_err( 'the value should be equal or great than 0.')) if not isinstance(from_acct, Account): raise SDKException( ErrorCode.param_err( 'the data type of from_acct should be Account.')) Oep4.__b58_address_check(b58_to_address) from_address = from_acct.get_address().to_bytes() to_address = Address.b58decode(b58_to_address).to_bytes() func.set_params_value(from_address, to_address, value) tx_hash = self.__sdk.get_network().send_neo_vm_transaction( self.__hex_contract_address, from_acct, payer_acct, gas_limit, gas_price, func, False) return tx_hash
def test_notify(self): hex_contract_address = '6690b6638251be951dded8c537678200a470c679' notify_args = InvokeFunction('testHello') bool_msg = True int_msg = 1 bytes_msg = b'Hello' str_msg = 'Hello' bytes_address_msg = acct1.get_address().to_bytes() notify_args.set_params_value(bool_msg, int_msg, bytes_msg, str_msg, bytes_address_msg) tx_hash = sdk.rpc.send_neo_vm_transaction(hex_contract_address, None, acct1, gas_limit, gas_price, notify_args, False) time.sleep(randint(6, 10)) event = sdk.rpc.get_smart_contract_event_by_tx_hash(tx_hash) states = ContractEventParser.get_states_by_contract_address( event, hex_contract_address) states[0] = ContractDataParser.to_utf8_str(states[0]) self.assertEqual('testHello', states[0]) states[1] = ContractDataParser.to_bool(states[1]) self.assertEqual(bool_msg, states[1]) states[2] = ContractDataParser.to_int(states[2]) self.assertEqual(int_msg, states[2]) states[3] = ContractDataParser.to_bytes(states[3]) self.assertEqual(bytes_msg, states[3]) states[4] = ContractDataParser.to_utf8_str(states[4]) self.assertEqual(str_msg, states[4]) states[5] = ContractDataParser.to_b58_address(states[5]) self.assertEqual(acct1.get_address_base58(), states[5])
def test_oep4_transfer(self): hex_contract_address = '1ddbb682743e9d9e2b71ff419e97a9358c5c4ee9' func = InvokeFunction('transfer') bytes_from_address = acct1.get_address().to_bytes() bytes_to_address = acct2.get_address().to_bytes() value = 1 func.set_params_value(bytes_from_address, bytes_to_address, value) try: tx_hash = sdk.rpc.send_neo_vm_transaction(hex_contract_address, acct1, acct2, gas_limit, gas_price, func, False) self.assertEqual(64, len(tx_hash)) except SDKException as e: self.assertIn('already in the tx pool', e.args[1]) return time.sleep(randint(6, 10)) event = sdk.rpc.get_smart_contract_event_by_tx_hash(tx_hash) states = ContractEventParser.get_states_by_contract_address( event, hex_contract_address) states[0] = ContractDataParser.to_utf8_str(states[0]) self.assertEqual('transfer', states[0]) states[1] = ContractDataParser.to_b58_address(states[1]) self.assertEqual(acct1.get_address().b58encode(), states[1]) states[2] = ContractDataParser.to_b58_address(states[2]) self.assertEqual(acct2.get_address().b58encode(), states[2]) states[3] = ContractDataParser.to_int(states[3]) self.assertEqual(value, states[3])
def test_dict_in_ctx(self, map_msg, payer_acct, gas_limit, gas_price): func = InvokeFunction('testMapInMap') func.set_params_value(map_msg) tx_hash = self.__sdk.neo_vm().send_transaction( self.__hex_contract_address, None, payer_acct, gas_limit, gas_price, func, False) return tx_hash
def test_invoke_transaction(self): avm_code = '58c56b6a00527ac46a51527ac46a00c30548656c6c6f9c6416006a51c300c36a52527ac46a52c3650b006c756' \ '661006c756655c56b6a00527ac46a00c3681553797374656d2e52756e74696d652e4e6f7469667961516c7566' hex_contract_address = sdk.neo_vm.avm_code_to_hex_contract_address( avm_code) self.assertEqual('39f3fb644842c808828817bd73da0946d99f237f', hex_contract_address) hello = InvokeFunction('Hello') hello.set_params_value('Ontology') response = sdk.rpc.send_neo_vm_transaction(hex_contract_address, None, None, 0, 0, hello, True) self.assertEqual(1, response['State']) result = response['Result'] result = ContractDataParser.to_bool(result) self.assertEqual(True, result) gas_limit = 20000 gas_price = 500 tx_hash = sdk.rpc.send_neo_vm_transaction(hex_contract_address, None, acct1, gas_limit, gas_price, hello, False) sleep(6) response = sdk.rpc.get_smart_contract_event_by_tx_hash(tx_hash) notify = response['Notify'][0] self.assertEqual(hex_contract_address, notify['ContractAddress']) notify['States'] = ContractDataParser.to_utf8_str(notify['States']) self.assertEqual('Ontology', notify['States'])
def test_transfer_multi_args(self): transfer_1 = [ acct1.get_address().to_bytes(), acct2.get_address().to_bytes(), 10 ] transfer_2 = [ acct2.get_address().to_bytes(), acct3.get_address().to_bytes(), 100 ] hex_contract_address = 'ca91a73433c016fbcbcf98051d385785a6a5d9be' func = InvokeFunction('transfer_multi_args') func.set_params_value(transfer_1, transfer_2) tx_hash = self.send_tx(hex_contract_address, acct1, acct2, func) if len(tx_hash) == 0: return time.sleep(randint(7, 12)) event = sdk.rpc.get_smart_contract_event_by_tx_hash(tx_hash) states = ContractEventParser.get_states_by_contract_address( event, hex_contract_address) states[0] = ContractDataParser.to_utf8_str(states[0]) self.assertEqual('transfer_multi_args', states[0]) states[1][0][0] = ContractDataParser.to_b58_address(states[1][0][0]) self.assertEqual(acct1.get_address_base58(), states[1][0][0]) states[1][0][1] = ContractDataParser.to_b58_address(states[1][0][1]) self.assertEqual(acct2.get_address_base58(), states[1][0][1]) states[1][0][2] = ContractDataParser.to_int(states[1][0][2]) self.assertEqual(10, states[1][0][2]) states[1][1][0] = ContractDataParser.to_b58_address(states[1][1][0]) self.assertEqual(acct2.get_address_base58(), states[1][1][0]) states[1][1][1] = ContractDataParser.to_b58_address(states[1][1][1]) self.assertEqual(acct3.get_address_base58(), states[1][1][1]) states[1][1][2] = ContractDataParser.to_int(states[1][1][2]) self.assertEqual(100, states[1][1][2])
def test_list(self, list_msg: list, payer_acct, gas_limit, gas_price): func = InvokeFunction('testList') func.set_params_value(list_msg) tx_hash = self.__sdk.neo_vm().send_transaction( self.__hex_contract_address, None, payer_acct, gas_limit, gas_price, func, False) return tx_hash
def approve(self, owner_acct: Account, b58_spender_address: str, amount: int, payer_acct: Account, gas_limit: int, gas_price: int): """ This interface is used to call the Approve method in ope4 that allows spender to withdraw a certain amount of oep4 token from owner account multiple times. If this function is called again, it will overwrite the current allowance with new value. :param owner_acct: an Account class that indicate the owner. :param b58_spender_address: a base58 encode address that be allowed to spend the oep4 token in owner's account. :param amount: an int value that indicate the amount oep4 token that will be transferred in this transaction. :param payer_acct: an Account class that used to pay for the transaction. :param gas_limit: an int value that indicate the gas limit. :param gas_price: an int value that indicate the gas price. :return: the hexadecimal transaction hash value. """ func = InvokeFunction('approve') if not isinstance(amount, int): raise SDKException( ErrorCode.param_err('the data type of amount should be int.')) if amount < 0: raise SDKException( ErrorCode.param_err( 'the amount should be equal or great than 0.')) owner_address = owner_acct.get_address().to_bytes() Oep4.__b58_address_check(b58_spender_address) spender_address = Address.b58decode(b58_spender_address).to_bytes() func.set_params_value(owner_address, spender_address, amount) tx_hash = self.__sdk.get_network().send_neo_vm_transaction( self.__hex_contract_address, owner_acct, payer_acct, gas_limit, gas_price, func, False) return tx_hash
def test_dict_in_ctx(self): hex_contract_address = '6690b6638251be951dded8c537678200a470c679' bool_value = True int_value = 100 str_value = 'value3' dict_value = {'key': 'value'} list_value = [1, 10, 1024, [1, 10, 1024, [1, 10, 1024]]] dict_msg = { 'key': dict_value, 'key1': int_value, 'key2': str_value, 'key3': bool_value, 'key4': list_value } func = InvokeFunction('testMapInMap') func.set_params_value(dict_msg) tx_hash = sdk.rpc.send_neo_vm_transaction(hex_contract_address, None, acct1, gas_limit, gas_price, func, False) time.sleep(randint(6, 10)) event = sdk.rpc.get_smart_contract_event_by_tx_hash(tx_hash) states = ContractEventParser.get_states_by_contract_address( event, hex_contract_address) states[0] = ContractDataParser.to_utf8_str(states[0]) self.assertEqual('mapInfo', states[0]) states[1] = ContractDataParser.to_dict(states[1]) self.assertTrue(isinstance(states[1], dict))
def test_transfer_multi(self, transfer_list, payer_acct, gas_limit, gas_price): func = InvokeFunction('transferMulti') func.set_params_value(transfer_list) tx_hash = self.__sdk.neo_vm().send_transaction( self.__hex_contract_address, payer_acct, payer_acct, gas_limit, gas_price, func, False) return tx_hash
def test_dict(self, dict_msg: dict, pay_acct: Account, gas_limit, gas_price): func = InvokeFunction('testMap') func.set_params_value(dict_msg) tx_hash = self.__sdk.neo_vm().send_transaction( self.__hex_contract_address, None, pay_acct, gas_limit, gas_price, func, False) return tx_hash
def test_struct_list_and_str(self, struct_list, str_msg, payer_acct: Account, gas_limit, gas_price): func = InvokeFunction('testStructListAndStr') func.set_params_value(struct_list, str_msg) tx_hash = self.__sdk.neo_vm().send_transaction( self.__hex_contract_address, None, payer_acct, gas_limit, gas_price, func, False) return tx_hash
def test_oep4_symbol(self): hex_contract_address = '1ddbb682743e9d9e2b71ff419e97a9358c5c4ee9' func = InvokeFunction('symbol') self.assertEqual(bytearray(b'\x00\xc1\x06symbol'), func.create_invoke_code()) result = sdk.rpc.send_neo_vm_transaction_pre_exec( hex_contract_address, None, func) symbol = result['Result'] symbol = ContractDataParser.to_utf8_str(symbol) self.assertEqual('DX', symbol)
def test_oep4_name(self): hex_contract_address = '1ddbb682743e9d9e2b71ff419e97a9358c5c4ee9' func = InvokeFunction('name') self.assertEqual(bytearray(b'\x00\xc1\x04name'), func.create_invoke_code()) result = sdk.rpc.send_neo_vm_transaction_pre_exec( hex_contract_address, None, func) name = result['Result'] name = ContractDataParser.to_utf8_str(name) self.assertEqual('DXToken', name)
def test_get_dict_in_ctx(self): hex_contract_address = '6690b6638251be951dded8c537678200a470c679' key = 'key' func = InvokeFunction('testGetMapInMap') func.set_params_value(key) result = sdk.rpc.send_neo_vm_transaction(hex_contract_address, None, None, 0, 0, func, True) value = result['Result'] value = ContractDataParser.to_utf8_str(value) self.assertEqual('value', value)
def test_hello(self, bool_msg, int_msg, bytes_msg, str_msg, bytes_address_msg: bytes, payer_acct: Account, gas_limit: int, gas_price: int) -> str: notify_args = InvokeFunction('testHello') notify_args.set_params_value(bool_msg, int_msg, bytes_msg, str_msg, bytes_address_msg) tx_hash = self.__sdk.neo_vm().send_transaction( self.__hex_contract_address, None, payer_acct, gas_limit, gas_price, notify_args, False) return tx_hash
def test_oep4_balance_of(self): hex_contract_address = '1ddbb682743e9d9e2b71ff419e97a9358c5c4ee9' func = InvokeFunction('balanceOf') bytes_address = acct1.get_address().to_bytes() func.set_params_value(bytes_address) result = sdk.rpc.send_neo_vm_transaction(hex_contract_address, None, None, 0, 0, func, True) balance = result['Result'] balance = ContractDataParser.to_int(balance) self.assertGreater(balance, 100)
def hello(self, msg: str) -> str: if not isinstance(msg, str): raise RuntimeError('the type of msg should be str') func = InvokeFunction('hello') func.set_params_value(msg) res = self.__sdk.neo_vm().send_transaction(self.__hex_contract_address, None, None, 0, 0, func, True) res = ContractDataParser.to_utf8_str(res) return res
def get_status(self, claim_id: str): func = InvokeFunction('GetStatus') func.set_params_value(claim_id) result = self.__sdk.get_network().send_neo_vm_transaction_pre_exec( self.__hex_contract_address, None, func) status = result['Result'] if status == '': status = False else: status = ContractDataParser.to_dict(status) status = bool(status[3]) return status
def revoke(self, claim_id: str, issuer_acct: Account, payer_acct: Account, gas_limit: int, gas_price: int): if gas_limit < 0: raise SDKException(ErrorCode.other_error('Gas limit less than 0.')) if gas_price < 0: raise SDKException(ErrorCode.other_error('Gas price less than 0.')) func = InvokeFunction('Revoke') func.set_params_value(claim_id, issuer_acct.get_address_bytes()) tx_hash = self.__sdk.get_network().send_neo_vm_transaction( self.__hex_contract_address, issuer_acct, payer_acct, gas_limit, gas_price, func, False) return tx_hash
def transfer_multi(self, transfer_list: list, payer_acct: Account, signers: list, gas_limit: int, gas_price: int): """ This interface is used to call the TransferMulti method in ope4 that allow transfer amount of token from multiple from-account to multiple to-account multiple times. :param transfer_list: a parameter list with each item contains three sub-items: base58 encode transaction sender address, base58 encode transaction receiver address, amount of token in transaction. :param payer_acct: an Account class that used to pay for the transaction. :param signers: a signer list used to sign this transaction which should contained all sender in args. :param gas_limit: an int value that indicate the gas limit. :param gas_price: an int value that indicate the gas price. :return: the hexadecimal transaction hash value. """ func = InvokeFunction('transferMulti') for index, item in enumerate(transfer_list): Oep4.__b58_address_check(item[0]) Oep4.__b58_address_check(item[1]) if not isinstance(item[2], int): raise SDKException( ErrorCode.param_err( 'the data type of value should be int.')) if item[2] < 0: raise SDKException( ErrorCode.param_err( 'the value should be equal or great than 0.')) from_address_array = Address.b58decode(item[0]).to_bytes() to_address_array = Address.b58decode(item[1]).to_bytes() transfer_list[index] = [ from_address_array, to_address_array, item[2] ] for item in transfer_list: func.add_params_value(item) params = func.create_invoke_code() unix_time_now = int(time.time()) params.append(0x67) bytearray_contract_address = bytearray.fromhex( self.__hex_contract_address) bytearray_contract_address.reverse() for i in bytearray_contract_address: params.append(i) if len(signers) == 0: raise SDKException(ErrorCode.param_err('payer account is None.')) payer_address = payer_acct.get_address().to_bytes() tx = Transaction(0, 0xd1, unix_time_now, gas_price, gas_limit, payer_address, params, bytearray(), []) for signer in signers: tx.add_sign_transaction(signer) tx_hash = self.__sdk.get_network().send_raw_transaction(tx) return tx_hash
def transfer_from(self, spender_acct: Account, b58_from_address: str, b58_to_address: str, value: int, payer_acct: Account, gas_limit: int, gas_price: int): """ This interface is used to call the Allowance method in ope4 that allow spender to withdraw amount of oep4 token from from-account to to-account. :param spender_acct: an Account class that actually spend oep4 token. :param b58_from_address: an base58 encode address that actually pay oep4 token for the spender's spending. :param b58_to_address: a base58 encode address that receive the oep4 token. :param value: the amount of ope4 token in this transaction. :param payer_acct: an Account class that used to pay for the transaction. :param gas_limit: an int value that indicate the gas limit. :param gas_price: an int value that indicate the gas price. :return: the hexadecimal transaction hash value. """ func = InvokeFunction('transferFrom') Oep4.__b58_address_check(b58_from_address) Oep4.__b58_address_check(b58_to_address) if not isinstance(spender_acct, Account): raise SDKException( ErrorCode.param_err( 'the data type of spender_acct should be Account.')) spender_address_array = spender_acct.get_address().to_bytes() from_address_array = Address.b58decode(b58_from_address).to_bytes() to_address_array = Address.b58decode(b58_to_address).to_bytes() if not isinstance(value, int): raise SDKException( ErrorCode.param_err('the data type of value should be int.')) func.set_params_value(spender_address_array, from_address_array, to_address_array, value) params = func.create_invoke_code() unix_time_now = int(time.time()) params.append(0x67) bytearray_contract_address = bytearray.fromhex( self.__hex_contract_address) bytearray_contract_address.reverse() for i in bytearray_contract_address: params.append(i) if payer_acct is None: raise SDKException(ErrorCode.param_err('payer account is None.')) payer_address_array = payer_acct.get_address().to_bytes() tx = Transaction(0, 0xd1, unix_time_now, gas_price, gas_limit, payer_address_array, params, bytearray(), []) tx.sign_transaction(spender_acct) if spender_acct.get_address_base58() != payer_acct.get_address_base58( ): tx.add_sign_transaction(payer_acct) tx_hash = self.__sdk.get_network().send_raw_transaction(tx) return tx_hash
def name(self): func = InvokeFunction('name') res = self.__sdk.neo_vm().send_transaction(self.__hex_contract_address, None, None, 0, 0, func, True) res = ContractDataParser.to_utf8_str(res) return res
def test_list(self): hex_contract_address = '6690b6638251be951dded8c537678200a470c679' list_msg = [1, 10, 1024, [1, 10, 1024, [1, 10, 1024]]] func = InvokeFunction('testList') func.set_params_value(list_msg) tx_hash = sdk.rpc.send_neo_vm_transaction(hex_contract_address, None, acct1, gas_limit, gas_price, func, False) time.sleep(randint(6, 10)) event = sdk.rpc.get_smart_contract_event_by_tx_hash(tx_hash) states = ContractEventParser.get_states_by_contract_address( event, hex_contract_address) states[0] = ContractDataParser.to_utf8_str(states[0]) self.assertEqual('testMsgList', states[0]) states[1] = ContractDataParser.to_int_list(states[1]) self.assertEqual(list_msg, states[1])
def test_oep4_total_supply(self): hex_contract_address = '1ddbb682743e9d9e2b71ff419e97a9358c5c4ee9' func = InvokeFunction('totalSupply') result = sdk.rpc.send_neo_vm_transaction(hex_contract_address, None, None, 0, 0, func, True) total_supply = result['Result'] total_supply = ContractDataParser.to_int(total_supply) self.assertEqual(10000000000000000000, total_supply)
def test_oep4_decimal(self): hex_contract_address = '1ddbb682743e9d9e2b71ff419e97a9358c5c4ee9' func = InvokeFunction('decimals') result = sdk.rpc.send_neo_vm_transaction(hex_contract_address, None, None, 0, 0, func, True) decimals = result['Result'] decimals = ContractDataParser.to_int(decimals) self.assertEqual(10, decimals)
def test_oep4_symbol(self): hex_contract_address = '1ddbb682743e9d9e2b71ff419e97a9358c5c4ee9' func = InvokeFunction('symbol') result = sdk.rpc.send_neo_vm_transaction(hex_contract_address, None, None, 0, 0, func, True) symbol = result['Result'] symbol = ContractDataParser.to_utf8_str(symbol) self.assertEqual('DX', symbol)
def test_oep4_transfer_multi(self): hex_contract_address = '1ddbb682743e9d9e2b71ff419e97a9358c5c4ee9' bytes_from_address1 = acct1.get_address().to_bytes() bytes_to_address1 = acct2.get_address().to_bytes() value1 = 2 transfer1 = [bytes_from_address1, bytes_to_address1, value1] bytes_from_address2 = acct2.get_address().to_bytes() bytes_to_address2 = acct3.get_address().to_bytes() value2 = 1 transfer2 = [bytes_from_address2, bytes_to_address2, value2] func = InvokeFunction('transferMulti') func.set_params_value(transfer1, transfer2) try: tx_hash = sdk.rpc.send_neo_vm_transaction(hex_contract_address, acct1, acct2, gas_limit, gas_price, func, False) except SDKException as e: self.assertIn('already in the tx pool', e.args[1]) return time.sleep(randint(6, 10)) event = sdk.rpc.get_smart_contract_event_by_tx_hash(tx_hash) states_list = ContractEventParser.get_states_by_contract_address( event, hex_contract_address) states_list[0][0] = ContractDataParser.to_utf8_str(states_list[0][0]) self.assertEqual('transfer', states_list[0][0]) states_list[0][1] = ContractDataParser.to_b58_address( states_list[0][1]) self.assertEqual(acct1.get_address().b58encode(), states_list[0][1]) states_list[0][2] = ContractDataParser.to_b58_address( states_list[0][2]) self.assertEqual(acct2.get_address().b58encode(), states_list[0][2]) states_list[0][3] = ContractDataParser.to_int(states_list[0][3]) self.assertEqual(value1, states_list[0][3]) states_list[1][0] = ContractDataParser.to_utf8_str(states_list[1][0]) self.assertEqual('transfer', states_list[1][0]) states_list[1][1] = ContractDataParser.to_b58_address( states_list[1][1]) self.assertEqual(acct2.get_address().b58encode(), states_list[1][1]) states_list[1][2] = ContractDataParser.to_b58_address( states_list[1][2]) self.assertEqual(acct3.get_address().b58encode(), states_list[1][2]) states_list[1][3] = ContractDataParser.to_int(states_list[1][3]) self.assertEqual(value2, states_list[1][3])
def balance_of(self, b58_address: str) -> int: """ This interface is used to call the BalanceOf method in ope4 that query the ope4 token balance of the given base58 encode address. :param b58_address: the base58 encode address. :return: the oep4 token balance of the base58 encode address. """ func = InvokeFunction('balanceOf') Oep4.__b58_address_check(b58_address) address = Address.b58decode(b58_address).to_bytes() func.set_params_value(address) result = self.__sdk.get_network().send_neo_vm_transaction( self.__hex_contract_address, None, None, 0, 0, func, True) try: balance = ContractDataParser.to_int(result['Result']) except SDKException: balance = 0 return balance
def test_oep4_name(self): contract_address = '1ddbb682743e9d9e2b71ff419e97a9358c5c4ee9' bytearray_contract_address = bytearray( binascii.a2b_hex(contract_address)) bytearray_contract_address.reverse() func = InvokeFunction('name') result = sdk.rpc.send_neo_vm_transaction(bytearray_contract_address, None, None, 0, 0, func, True) name = result['Result'] name = ContractDataParser.to_utf8_str(name) self.assertEqual('DXToken', name)