From d4b2815af3324201548a03b1405b1daa313439d4 Mon Sep 17 00:00:00 2001 From: kclowes Date: Thu, 3 Jun 2021 11:32:04 -0600 Subject: [PATCH] Move async_eth to eth --- newsfragments/1999.feature.rst | 5 ++- .../go_ethereum/test_goethereum_http.py | 8 +++- web3/_utils/async_transactions.py | 43 +++++++++++++++++++ web3/_utils/module_testing/eth_module.py | 42 +++++++++--------- web3/_utils/transactions.py | 30 +------------ web3/main.py | 2 - web3/middleware/buffered_gas_estimate.py | 6 ++- web3/middleware/gas_price_strategy.py | 2 +- web3/tools/benchmark/main.py | 17 ++++---- 9 files changed, 88 insertions(+), 67 deletions(-) create mode 100644 web3/_utils/async_transactions.py diff --git a/newsfragments/1999.feature.rst b/newsfragments/1999.feature.rst index 9ece13adb9..eb19c81d63 100644 --- a/newsfragments/1999.feature.rst +++ b/newsfragments/1999.feature.rst @@ -1,4 +1,5 @@ Add ability for AsyncHTTPProvider to accept middleware -Also adds async gas_price_strategy middleware, and the AsyncEthereumTesterProvider now inherits from -AsyncBase +Also adds async gas_price_strategy middleware, and moves gas estimate to middleware. + +AsyncEthereumTesterProvider now inherits from AsyncBase diff --git a/tests/integration/go_ethereum/test_goethereum_http.py b/tests/integration/go_ethereum/test_goethereum_http.py index 3effe66a56..6b7b941cc5 100644 --- a/tests/integration/go_ethereum/test_goethereum_http.py +++ b/tests/integration/go_ethereum/test_goethereum_http.py @@ -8,6 +8,7 @@ AsyncEth, ) from web3.middleware import ( + async_buffered_gas_estimate_middleware, async_gas_price_strategy_middleware, ) from web3.providers.async_rpc import ( @@ -79,9 +80,12 @@ async def async_w3(geth_process, endpoint_uri): await wait_for_aiohttp(endpoint_uri) _web3 = Web3( AsyncHTTPProvider(endpoint_uri), - middlewares=[async_gas_price_strategy_middleware], + middlewares=[ + async_gas_price_strategy_middleware, + async_buffered_gas_estimate_middleware + ], modules={ - 'async_eth': (AsyncEth,), + 'eth': (AsyncEth,), }) return _web3 diff --git a/web3/_utils/async_transactions.py b/web3/_utils/async_transactions.py new file mode 100644 index 0000000000..6d8f0270ec --- /dev/null +++ b/web3/_utils/async_transactions.py @@ -0,0 +1,43 @@ +from typing import ( + TYPE_CHECKING, + Optional, + cast, +) + +from web3.types import ( + BlockIdentifier, + TxParams, + Wei, +) + +if TYPE_CHECKING: + from web3 import Web3 # noqa: F401 + from web3.eth import AsyncEth, Eth # noqa: F401 + + +async def get_block_gas_limit( + web3_eth: "AsyncEth", block_identifier: Optional[BlockIdentifier] = None +) -> Wei: + if block_identifier is None: + block_identifier = await web3_eth.block_number + block = await web3_eth.get_block(block_identifier) + return block['gasLimit'] + + +async def get_buffered_gas_estimate( + web3_eth: "Eth", transaction: TxParams, gas_buffer: Wei = Wei(100000) +) -> Wei: + gas_estimate_transaction = cast(TxParams, dict(**transaction)) + + gas_estimate = await web3_eth.estimate_gas(gas_estimate_transaction) # type: ignore + + gas_limit = await get_block_gas_limit(web3_eth) # type: ignore + + if gas_estimate > gas_limit: + raise ValueError( + "Contract does not appear to be deployable within the " + "current network gas limits. Estimated: {0}. Current gas " + "limit: {1}".format(gas_estimate, gas_limit) + ) + + return Wei(min(gas_limit, gas_estimate + gas_buffer)) diff --git a/web3/_utils/module_testing/eth_module.py b/web3/_utils/module_testing/eth_module.py index 8be497f948..6add07aede 100644 --- a/web3/_utils/module_testing/eth_module.py +++ b/web3/_utils/module_testing/eth_module.py @@ -61,7 +61,7 @@ class AsyncEthModuleTest: @pytest.mark.asyncio async def test_eth_gas_price(self, async_w3: "Web3") -> None: - gas_price = await async_w3.async_eth.gas_price + gas_price = await async_w3.eth.gas_price # type: ignore assert gas_price > 0 @pytest.mark.asyncio @@ -78,10 +78,10 @@ async def test_eth_send_transaction( 'to': unlocked_account_dual_type, 'value': Wei(1), 'gas': Wei(21000), - 'gasPrice': await async_w3.async_eth.gas_price, + 'gasPrice': await async_w3.eth.gas_price, # type: ignore } - txn_hash = await async_w3.async_eth.send_transaction(txn_params) - txn = await async_w3.async_eth.get_transaction(txn_hash) + txn_hash = await async_w3.eth.send_transaction(txn_params) # type: ignore + txn = await async_w3.eth.get_transaction(txn_hash) # type: ignore assert is_same_address(txn['from'], cast(ChecksumAddress, txn_params['from'])) assert is_same_address(txn['to'], cast(ChecksumAddress, txn_params['to'])) @@ -103,10 +103,10 @@ async def test_gas_price_strategy_middleware( def higher_gas_price_strategy(web3: "Web3", txn: TxParams) -> Wei: return Wei(20) - async_w3.async_eth.set_gas_price_strategy(higher_gas_price_strategy) + async_w3.eth.set_gas_price_strategy(higher_gas_price_strategy) - txn_hash = await async_w3.async_eth.send_transaction(txn_params) - txn = await async_w3.async_eth.get_transaction(txn_hash) + txn_hash = await async_w3.eth.send_transaction(txn_params) # type: ignore + txn = await async_w3.eth.get_transaction(txn_hash) # type: ignore assert txn['gasPrice'] == 20 @@ -114,7 +114,7 @@ def higher_gas_price_strategy(web3: "Web3", txn: TxParams) -> Wei: async def test_eth_estimate_gas( self, async_w3: "Web3", unlocked_account_dual_type: ChecksumAddress ) -> None: - gas_estimate = await async_w3.async_eth.estimate_gas({ + gas_estimate = await async_w3.eth.estimate_gas({ # type: ignore 'from': unlocked_account_dual_type, 'to': unlocked_account_dual_type, 'value': Wei(1), @@ -126,7 +126,7 @@ async def test_eth_estimate_gas( async def test_eth_getBlockByHash( self, async_w3: "Web3", empty_block: BlockData ) -> None: - block = await async_w3.async_eth.get_block(empty_block['hash']) + block = await async_w3.eth.get_block(empty_block['hash']) # type: ignore assert block['hash'] == empty_block['hash'] @pytest.mark.asyncio @@ -134,28 +134,28 @@ async def test_eth_getBlockByHash_not_found( self, async_w3: "Web3", empty_block: BlockData ) -> None: with pytest.raises(BlockNotFound): - await async_w3.async_eth.get_block(UNKNOWN_HASH) + await async_w3.eth.get_block(UNKNOWN_HASH) # type: ignore @pytest.mark.asyncio async def test_eth_getBlockByHash_pending( self, async_w3: "Web3" ) -> None: - block = await async_w3.async_eth.get_block('pending') + block = await async_w3.eth.get_block('pending') # type: ignore assert block['hash'] is None @pytest.mark.asyncio async def test_eth_getBlockByNumber_with_integer( self, async_w3: "Web3", empty_block: BlockData ) -> None: - block = await async_w3.async_eth.get_block(empty_block['number']) + block = await async_w3.eth.get_block(empty_block['number']) # type: ignore assert block['number'] == empty_block['number'] @pytest.mark.asyncio async def test_eth_getBlockByNumber_latest( self, async_w3: "Web3", empty_block: BlockData ) -> None: - current_block_number = await async_w3.async_eth.block_number - block = await async_w3.async_eth.get_block('latest') + current_block_number = await async_w3.eth.block_number # type: ignore + block = await async_w3.eth.get_block('latest') # type: ignore assert block['number'] == current_block_number @pytest.mark.asyncio @@ -163,22 +163,22 @@ async def test_eth_getBlockByNumber_not_found( self, async_w3: "Web3", empty_block: BlockData ) -> None: with pytest.raises(BlockNotFound): - await async_w3.async_eth.get_block(BlockNumber(12345)) + await async_w3.eth.get_block(BlockNumber(12345)) # type: ignore @pytest.mark.asyncio async def test_eth_getBlockByNumber_pending( self, async_w3: "Web3", empty_block: BlockData ) -> None: - current_block_number = await async_w3.async_eth.block_number - block = await async_w3.async_eth.get_block('pending') + current_block_number = await async_w3.eth.block_number # type: ignore + block = await async_w3.eth.get_block('pending') # type: ignore assert block['number'] == current_block_number + 1 @pytest.mark.asyncio async def test_eth_getBlockByNumber_earliest( self, async_w3: "Web3", empty_block: BlockData ) -> None: - genesis_block = await async_w3.async_eth.get_block(BlockNumber(0)) - block = await async_w3.async_eth.get_block('earliest') + genesis_block = await async_w3.eth.get_block(BlockNumber(0)) # type: ignore + block = await async_w3.eth.get_block('earliest') # type: ignore assert block['number'] == 0 assert block['hash'] == genesis_block['hash'] @@ -186,9 +186,9 @@ async def test_eth_getBlockByNumber_earliest( async def test_eth_getBlockByNumber_full_transactions( self, async_w3: "Web3", block_with_txn: BlockData ) -> None: - block = await async_w3.async_eth.get_block(block_with_txn['number'], True) + block = await async_w3.eth.get_block(block_with_txn['number'], True) # type: ignore transaction = block['transactions'][0] - assert transaction['hash'] == block_with_txn['transactions'][0] # type: ignore + assert transaction['hash'] == block_with_txn['transactions'][0] class EthModuleTest: diff --git a/web3/_utils/transactions.py b/web3/_utils/transactions.py index ee8913fdb5..48ab4b9427 100644 --- a/web3/_utils/transactions.py +++ b/web3/_utils/transactions.py @@ -59,7 +59,7 @@ if TYPE_CHECKING: from web3 import Web3 # noqa: F401 - from web3.eth import AsyncEth, Eth # noqa: F401 + from web3.eth import Eth # noqa: F401 @curry @@ -139,34 +139,6 @@ def get_buffered_gas_estimate( return Wei(min(gas_limit, gas_estimate + gas_buffer)) -async def async_get_block_gas_limit( - web3_eth: "AsyncEth", block_identifier: Optional[BlockIdentifier] = None -) -> Wei: - if block_identifier is None: - block_identifier = await web3_eth.block_number - block = await web3_eth.get_block(block_identifier) - return block['gasLimit'] - - -async def async_get_buffered_gas_estimate( - web3_eth: "AsyncEth", transaction: TxParams, gas_buffer: Wei = Wei(100000) -) -> Wei: - gas_estimate_transaction = cast(TxParams, dict(**transaction)) - - gas_estimate = await web3_eth.estimate_gas(gas_estimate_transaction) - - gas_limit = await async_get_block_gas_limit(web3_eth) - - if gas_estimate > gas_limit: - raise ValueError( - "Contract does not appear to be deployable within the " - "current network gas limits. Estimated: {0}. Current gas " - "limit: {1}".format(gas_estimate, gas_limit) - ) - - return Wei(min(gas_limit, gas_estimate + gas_buffer)) - - def get_required_transaction(web3: "Web3", transaction_hash: _Hash32) -> TxData: current_transaction = web3.eth.get_transaction(transaction_hash) if not current_transaction: diff --git a/web3/main.py b/web3/main.py index ffc0b0caa8..fe0b2a7a48 100644 --- a/web3/main.py +++ b/web3/main.py @@ -71,7 +71,6 @@ abi_ens_resolver, ) from web3.eth import ( - AsyncEth, Eth, ) from web3.geth import ( @@ -222,7 +221,6 @@ def toChecksumAddress(value: Union[AnyAddress, str, bytes]) -> ChecksumAddress: parity: Parity geth: Geth net: Net - async_eth: AsyncEth def __init__( self, diff --git a/web3/middleware/buffered_gas_estimate.py b/web3/middleware/buffered_gas_estimate.py index 42a3210317..06dcd0f06e 100644 --- a/web3/middleware/buffered_gas_estimate.py +++ b/web3/middleware/buffered_gas_estimate.py @@ -9,8 +9,10 @@ assoc, ) +from web3._utils.async_transactions import ( + get_buffered_gas_estimate as async_get_buffered_gas_estimate, +) from web3._utils.transactions import ( - async_get_buffered_gas_estimate, get_buffered_gas_estimate, ) from web3.types import ( @@ -46,7 +48,7 @@ async def middleware(method: RPCEndpoint, params: Any) -> RPCResponse: if method == 'eth_sendTransaction': transaction = params[0] if 'gas' not in transaction: - gas_estimate = await async_get_buffered_gas_estimate(web3.async_eth, transaction) + gas_estimate = await async_get_buffered_gas_estimate(web3.eth, transaction) transaction = assoc( transaction, 'gas', diff --git a/web3/middleware/gas_price_strategy.py b/web3/middleware/gas_price_strategy.py index ccc50df89a..213ddf6b07 100644 --- a/web3/middleware/gas_price_strategy.py +++ b/web3/middleware/gas_price_strategy.py @@ -46,7 +46,7 @@ async def middleware(method: RPCEndpoint, params: Any) -> RPCResponse: if method == 'eth_sendTransaction': transaction = params[0] if 'gasPrice' not in transaction: - generated_gas_price = await web3.async_eth.generate_gas_price(transaction) + generated_gas_price = await web3.eth.generate_gas_price(transaction) # type: ignore if generated_gas_price is not None: transaction = assoc(transaction, 'gasPrice', hex(generated_gas_price)) return await make_request(method, [transaction]) diff --git a/web3/tools/benchmark/main.py b/web3/tools/benchmark/main.py index cfcbd6febc..69fd464d6f 100644 --- a/web3/tools/benchmark/main.py +++ b/web3/tools/benchmark/main.py @@ -24,6 +24,7 @@ ) from web3.eth import ( AsyncEth, + Eth, ) from web3.middleware import ( async_buffered_gas_estimate_middleware, @@ -74,7 +75,7 @@ async def build_async_w3_http(endpoint_uri: str) -> Web3: _web3 = Web3( AsyncHTTPProvider(endpoint_uri), # type: ignore middlewares=[async_gas_price_strategy_middleware, async_buffered_gas_estimate_middleware], - modules={"async_eth": (AsyncEth,)}, + modules={"eth": (AsyncEth,)}, ) return _web3 @@ -107,8 +108,8 @@ def unlocked_account(w3: "Web3") -> ChecksumAddress: return w3.eth.coinbase -async def async_unlocked_account(w3: Web3, w3_eth: AsyncEth) -> ChecksumAddress: - coinbase = await w3_eth.coinbase +async def async_unlocked_account(w3: Web3, w3_eth: Eth) -> ChecksumAddress: + coinbase = await w3_eth.coinbase # type: ignore w3.geth.personal.unlock_account(coinbase, KEYFILE_PW) return coinbase @@ -122,7 +123,7 @@ def main(logger: logging.Logger, num_calls: int) -> None: async_w3_http = loop.run_until_complete(build_async_w3_http(fixture.endpoint_uri)) # TODO: swap out w3_http for the async_w3_http once GethPersonal module is async async_unlocked_acct = loop.run_until_complete( - async_unlocked_account(w3_http, async_w3_http.async_eth) + async_unlocked_account(w3_http, async_w3_http.eth) ) methods = [ @@ -130,7 +131,7 @@ def main(logger: logging.Logger, num_calls: int) -> None: "name": "eth_gasPrice", "params": {}, "exec": lambda: w3_http.eth.gas_price, - "async_exec": lambda: async_w3_http.async_eth.gas_price, + "async_exec": lambda: async_w3_http.eth.gas_price, }, { "name": "eth_sendTransaction", @@ -140,7 +141,7 @@ def main(logger: logging.Logger, num_calls: int) -> None: 'from': unlocked_account(w3_http), 'value': Wei(12345), }), - "async_exec": lambda: async_w3_http.async_eth.send_transaction({ + "async_exec": lambda: async_w3_http.eth.send_transaction({ 'to': '0xd3CdA913deB6f67967B99D67aCDFa1712C293601', 'from': async_unlocked_acct, 'value': Wei(12345) @@ -150,13 +151,13 @@ def main(logger: logging.Logger, num_calls: int) -> None: "name": "eth_blockNumber", "params": {}, "exec": lambda: w3_http.eth.block_number, - "async_exec": lambda: async_w3_http.async_eth.block_number, + "async_exec": lambda: async_w3_http.eth.block_number, }, { "name": "eth_getBlock", "params": {}, "exec": lambda: w3_http.eth.get_block(1), - "async_exec": lambda: async_w3_http.async_eth.get_block(1), + "async_exec": lambda: async_w3_http.eth.get_block(1), }, ]