diff --git a/nucypher/blockchain/eth/clients.py b/nucypher/blockchain/eth/clients.py index b864ea24c5b..5695e2f68ab 100644 --- a/nucypher/blockchain/eth/clients.py +++ b/nucypher/blockchain/eth/clients.py @@ -85,6 +85,10 @@ def __init__(self, self.backend = backend self.log = Logger(self.__class__.__name__) + @classmethod + def _get_variant(cls, w3): + return cls + @classmethod def from_w3(cls, w3: Web3) -> 'Web3Client': """ @@ -129,7 +133,7 @@ def from_w3(cls, w3: Web3) -> 'Web3Client': 'platform': client_data[2] if len(client_data) == 4 else None # Plaftorm is optional } - instance = ClientSubclass(w3, **client_kwargs) + instance = ClientSubclass._get_variant(w3)(w3, **client_kwargs) return instance class ConnectionNotEstablished(RuntimeError): @@ -224,6 +228,12 @@ def sign_message(self, account: str, message: bytes) -> str: class GethClient(Web3Client): + @classmethod + def _get_variant(cls, w3): + if 'infura' in w3.provider.endpoint_uri: + return InfuraClient + return cls + @property def is_local(self): return int(self.w3.net.version) not in PUBLIC_CHAINS @@ -233,7 +243,8 @@ def peers(self): return self.w3.geth.admin.peers() def unlock_account(self, address, password): - return self.w3.geth.personal.unlockAccount(address, password) + if not self.is_local: + return self.w3.geth.personal.unlockAccount(address, password) class ParityClient(Web3Client): @@ -260,6 +271,16 @@ def sync(self, *args, **kwargs): return True +class InfuraClient(Web3Client): + + is_local = False + + def unlock_account(self, address, password): + return True + + def sync(self, *args, **kwargs): + return True + class EthereumTesterClient(Web3Client): is_local = True diff --git a/nucypher/blockchain/eth/interfaces.py b/nucypher/blockchain/eth/interfaces.py index 96a4c9746a1..80f09c033f5 100644 --- a/nucypher/blockchain/eth/interfaces.py +++ b/nucypher/blockchain/eth/interfaces.py @@ -269,8 +269,7 @@ def _setup_solidity(self, compiler: SolidityCompiler = None): def _attach_provider(self, provider: Web3Providers = None, - provider_uri: str = None, - remote: bool = False) -> None: + provider_uri: str = None) -> None: """ https://web3py.readthedocs.io/en/latest/providers.html#providers """ @@ -307,9 +306,6 @@ def _attach_provider(self, self.__provider = providers[scheme]() except KeyError: raise ValueError("{} is an invalid or unsupported blockchain provider URI".format(provider_uri)) - else: - # Mark the provider as remote if needed - self.is_remote = remote or scheme == 'infura' def _get_IPC_provider(self): uri_breakdown = urlparse(self.provider_uri) diff --git a/tests/blockchain/eth/clients/test_mocked_clients.py b/tests/blockchain/eth/clients/test_mocked_clients.py index 9556f00c6c0..a66ca67aa94 100644 --- a/tests/blockchain/eth/clients/test_mocked_clients.py +++ b/tests/blockchain/eth/clients/test_mocked_clients.py @@ -2,25 +2,32 @@ GethClient, ParityClient, GanacheClient, + InfuraClient, PUBLIC_CHAINS ) from nucypher.blockchain.eth.interfaces import BlockchainInterface class MockGethProvider: - + endpoint_uri = 'file:///ipc.geth' clientVersion = 'Geth/v1.4.11-stable-fed692f6/darwin/go1.7' class MockParityProvider: - + endpoint_uri = 'file:///ipc.parity' clientVersion = 'Parity-Ethereum/v2.5.1-beta-e0141f8-20190510/x86_64-linux-gnu/rustc1.34.1' class MockGanacheProvider: + endpoint_uri = 'http://ganache:8445' clientVersion = 'EthereumJS TestRPC/v2.1.5/ethereum-js' +class MockInfuraProvider: + endpoint_uri = 'wss://:@goerli.infura.io/ws/v3/1234567890987654321abcdef' + clientVersion = 'Geth/v1.8.23-omnibus-2ad89aaa/linux-amd64/go1.11.1' + + class ChainIdReporter: # Support older and newer versions of web3 py in-test @@ -56,6 +63,9 @@ class GethClientTestInterface(BlockChainInterfaceTestBase): def _get_IPC_provider(self): return MockGethProvider() + def _get_infura_provider(self): + return MockInfuraProvider() + @property def is_local(self): return int(self.w3.net.version) not in PUBLIC_CHAINS @@ -87,6 +97,22 @@ def test_geth_web3_client(): assert interface.chain_id == 5 +def test_infura_web3_client(): + interface = GethClientTestInterface( + provider_uri='infura://1234567890987654321abcdef' + ) + assert isinstance(interface.client, InfuraClient) + assert interface.node_technology == 'Geth' + assert interface.node_version == 'v1.8.23-omnibus-2ad89aaa' + assert interface.platform == 'linux-amd64' + assert interface.backend == 'go1.11.1' + + assert interface.is_local is False + assert interface.chain_id == 5 + + assert interface.unlock_account('address', 'password') # should return True + + def test_parity_web3_client(): interface = ParityClientTestInterface( provider_uri='file:///ipc.parity'