def test_get_state(ethereum_testnet_config, ganache): """Test that get_state() with 'getBlock' function returns something containing the block number.""" ethereum_api = EthereumApi(**ethereum_testnet_config) callable_name = "getBlock" args = ("latest",) block = ethereum_api.get_state(callable_name, *args) assert block is not None, "response to getBlock is empty." assert "number" in block, "response to getBlock() does not contain 'number'"
def test_get_balance(): """Test the balance is zero for a new account.""" ethereum_api = EthereumApi(**ETHEREUM_TESTNET_CONFIG) ec = EthereumCrypto() balance = ethereum_api.get_balance(ec.address) assert balance == 0, "New account has a positive balance." ec = EthereumCrypto(private_key_path=ETHEREUM_PRIVATE_KEY_PATH) balance = ethereum_api.get_balance(ec.address) assert balance > 0, "Existing account has no balance."
def test_ethereum_api_get_deploy_transaction(*args): """Test EthereumApi.get_deploy_transaction.""" ethereum_api = EthereumApi() with patch.object(ethereum_api.api.eth, "getTransactionCount", return_value=None): assert ( ethereum_api.get_deploy_transaction( {"acc": "acc"}, "0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7" ) is None )
def test_get_contract_instance(erc1155_contract, ethereum_testnet_config): """Test the get contract instance method.""" contract, contract_address = erc1155_contract ethereum_api = EthereumApi(**ethereum_testnet_config) interface = {"abi": [], "bytecode": b""} instance = ethereum_api.get_contract_instance( contract_interface=interface, contract_address=contract_address, ) assert str(type(instance)) == "<class 'web3._utils.datatypes.Contract'>" instance = ethereum_api.get_contract_instance(contract_interface=interface,) assert ( str(type(instance)) == "<class 'web3._utils.datatypes.PropertyCheckingFactory'>" )
def test_get_contract_instance(): """Test the get contract instance method.""" contract_address = "0x250A2aeb3eB84782e83365b4c42dbE3CDA9920e4" ethereum_api = EthereumApi(**ETHEREUM_TESTNET_CONFIG) interface = {"abi": [], "bytecode": b""} instance = ethereum_api.get_contract_instance( contract_interface=interface, contract_address=contract_address, ) assert str(type(instance)) == "<class 'web3._utils.datatypes.Contract'>" instance = ethereum_api.get_contract_instance(contract_interface=interface,) assert ( str(type(instance)) == "<class 'web3._utils.datatypes.PropertyCheckingFactory'>" )
def test_sign_and_recover_message_public_key(): """Test the signing and the recovery function for the eth_crypto.""" account = EthereumCrypto(ETHEREUM_PRIVATE_KEY_PATH) sign_bytes = account.sign_message(message=b"hello") assert len(sign_bytes) > 0, "The len(signature) must not be 0" recovered_public_keys = EthereumApi.recover_public_keys_from_message( message=b"hello", signature=sign_bytes ) assert len(recovered_public_keys) == 1, "Wrong number of public keys recovered." assert ( EthereumApi.get_address_from_public_key(recovered_public_keys[0]) == account.address ), "Failed to recover the correct address."
def test_get_deploy_transaction(ethereum_testnet_config, ganache): """Test the get deploy transaction method.""" ethereum_api = EthereumApi(**ethereum_testnet_config) ec2 = EthereumCrypto() interface = {"abi": [], "bytecode": b""} deploy_tx = ethereum_api.get_deploy_transaction( contract_interface=interface, deployer_address=ec2.address, ) assert type(deploy_tx) == dict and len(deploy_tx) == 6 assert all( key in ["from", "value", "gas", "gasPrice", "nonce", "data"] for key in deploy_tx.keys() )
def test_construct_sign_and_submit_transfer_transaction(): """Test the construction, signing and submitting of a transfer transaction.""" account = EthereumCrypto(private_key_path=ETHEREUM_PRIVATE_KEY_PATH) ec2 = EthereumCrypto() ethereum_api = EthereumApi(**ETHEREUM_TESTNET_CONFIG) amount = 40000 tx_nonce = ethereum_api.generate_tx_nonce(ec2.address, account.address) transfer_transaction = ethereum_api.get_transfer_transaction( sender_address=account.address, destination_address=ec2.address, amount=amount, tx_fee=30000, tx_nonce=tx_nonce, chain_id=3, ) assert (isinstance(transfer_transaction, dict) and len(transfer_transaction) == 7), "Incorrect transfer_transaction constructed." signed_transaction = account.sign_transaction(transfer_transaction) assert (isinstance(signed_transaction, eth_account.datastructures.AttributeDict) and len(signed_transaction) == 5), "Incorrect signed_transaction constructed." transaction_digest = ethereum_api.send_signed_transaction( signed_transaction) assert transaction_digest is not None, "Failed to submit transfer transaction!" not_settled = True elapsed_time = 0 while not_settled and elapsed_time < 20: elapsed_time += 1 time.sleep(2) transaction_receipt = ethereum_api.get_transaction_receipt( transaction_digest) if transaction_receipt is None: continue is_settled = ethereum_api.is_transaction_settled(transaction_receipt) not_settled = not is_settled assert transaction_receipt is not None, "Failed to retrieve transaction receipt." assert is_settled, "Failed to verify tx!" tx = ethereum_api.get_transaction(transaction_digest) is_valid = ethereum_api.is_transaction_valid(tx, ec2.address, account.address, tx_nonce, amount) assert is_valid, "Failed to settle tx correctly!" assert tx != transaction_receipt, "Should not be same!"
def test_transfer(): """Test transfer of wealth.""" ethereum_api = EthereumApi(**ETHEREUM_TESTNET_CONFIG) ec1 = EthereumCrypto(private_key_path=ETHEREUM_PRIVATE_KEY_PATH) ec2 = EthereumCrypto() amount = 40000 fee = 30000 tx_nonce = ethereum_api.generate_tx_nonce(ec2.address, ec1.address) tx_digest = ethereum_api.transfer(ec1, ec2.address, amount, fee, tx_nonce, chain_id=3) assert tx_digest is not None, "Failed to submit transfer!" not_settled = True elapsed_time = 0 while not_settled and elapsed_time < 180: elapsed_time += 2 time.sleep(2) is_settled = ethereum_api.is_transaction_settled(tx_digest) not_settled = not is_settled assert is_settled, "Failed to complete tx!" is_valid = ethereum_api.is_transaction_valid(tx_digest, ec2.address, ec1.address, tx_nonce, amount) assert is_valid, "Failed to settle tx correctly!"
def test_sign_and_recover_message_deprecated(): """Test the signing and the recovery function for the eth_crypto.""" account = EthereumCrypto(ETHEREUM_PRIVATE_KEY_PATH) message = b"hello" message_hash = hashlib.sha256(message).digest() sign_bytes = account.sign_message(message=message_hash, is_deprecated_mode=True) assert len(sign_bytes) > 0, "The len(signature) must not be 0" recovered_addresses = EthereumApi.recover_message( message=message_hash, signature=sign_bytes, is_deprecated_mode=True ) assert len(recovered_addresses) == 1, "Wrong number of addresses recovered." assert ( recovered_addresses[0] == account.address ), "Failed to recover the correct address."
def _instantiate_api(identifier: str, config: Dict[str, Union[str, int]]) -> LedgerApi: """ Instantiate a ledger api. :param identifier: the ledger identifier :param config: the config of the api :return: the ledger api """ retry = 0 is_connected = False while retry < MAX_CONNECTION_RETRY: if identifier not in SUPPORTED_LEDGER_APIS: raise ValueError( "Unsupported identifier {} in ledger apis.".format(identifier) ) try: if identifier == FetchAIApi.identifier: api = FetchAIApi(**config) # type: LedgerApi elif identifier == EthereumApi.identifier: api = EthereumApi( cast(str, config["address"]), cast(str, config["gas_price"]) ) elif identifier == CosmosApi.identifier: api = CosmosApi(**config) is_connected = True break except Exception: # pragma: no cover retry += 1 logger.debug( "Connection attempt {} to {} ledger with provided config {} failed.".format( retry, identifier, config ) ) time.sleep(0.5) if not is_connected: # pragma: no cover logger.error( "Cannot connect to {} ledger with provided config {} after {} attemps. Giving up!".format( identifier, config, MAX_CONNECTION_RETRY ) ) sys.exit(1) return api
def __init__( self, ledger_api_configs: Dict[str, Dict[str, Union[str, int]]], default_ledger_id: str, ): """ Instantiate a wallet object. :param ledger_api_configs: the ledger api configs. :param default_ledger_id: the default ledger id. """ apis = {} # type: Dict[str, LedgerApi] configs = {} # type: Dict[str, Dict[str, Union[str, int]]] self._last_tx_statuses = {} # type: Dict[str, str] for identifier, config in ledger_api_configs.items(): self._last_tx_statuses[identifier] = UNKNOWN if identifier == FETCHAI: try: api = FetchAIApi(**config) # type: LedgerApi except Exception: logger.error( "Cannot connect to fetchai ledger with provided config." ) sys.exit(1) elif identifier == ETHEREUM: try: api = EthereumApi(cast(str, config["address"]), cast(str, config["gas_price"])) except Exception: logger.error( "Cannot connect to ethereum ledger with provided config." ) sys.exit(1) else: raise ValueError("Unsupported identifier in ledger apis.") apis[identifier] = api configs[identifier] = config self._apis = apis self._configs = configs self._default_ledger_id = default_ledger_id
def test_api_creation(): """Test api instantiation.""" assert EthereumApi( **ETHEREUM_TESTNET_CONFIG), "Failed to initialise the api"
def test_derive_address(): """Test the get_address_from_public_key method""" account = EthereumCrypto() address = EthereumApi.get_address_from_public_key(account.public_key) assert account.address == address, "Address derivation incorrect"
def test_get_hash(): """Test the get hash functionality.""" expected_hash = "0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8" hash_ = EthereumApi.get_hash(message=b"hello") assert expected_hash == hash_
def test_api_none(): """Test the "api" of the cryptoApi is none.""" eth_api = EthereumApi(**ETHEREUM_TESTNET_CONFIG) assert eth_api.api is not None, "The api property is None."
def test_api_creation(ethereum_testnet_config): """Test api instantiation.""" assert EthereumApi(**ethereum_testnet_config), "Failed to initialise the api"
def test_ethereum_api_get_transfer_transaction(*args): """Test EthereumApi.get_transfer_transaction.""" ethereum_api = EthereumApi() assert ethereum_api.get_transfer_transaction(*[MagicMock()] * 7) is None
def test_load_contract_interface(): """Test the load_contract_interface method.""" path = Path(ROOT_DIR, "tests", "data", "dummy_contract", "build", "some.json") result = EthereumApi.load_contract_interface(path) assert "abi" in result assert "bytecode" in result
def test_api_none(ethereum_testnet_config): """Test the "api" of the cryptoApi is none.""" eth_api = EthereumApi(**ethereum_testnet_config) assert eth_api.api is not None, "The api property is None."
def test_validate_address(): """Test the is_valid_address functionality.""" account = EthereumCrypto() assert EthereumApi.is_valid_address(account.address) assert not EthereumApi.is_valid_address(account.address + "wrong")