Skip to content

Commit

Permalink
Move async_eth to eth
Browse files Browse the repository at this point in the history
  • Loading branch information
kclowes committed Jun 4, 2021
1 parent b596263 commit d4b2815
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 67 deletions.
5 changes: 3 additions & 2 deletions newsfragments/1999.feature.rst
Original file line number Diff line number Diff line change
@@ -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
8 changes: 6 additions & 2 deletions tests/integration/go_ethereum/test_goethereum_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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

Expand Down
43 changes: 43 additions & 0 deletions web3/_utils/async_transactions.py
Original file line number Diff line number Diff line change
@@ -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))
42 changes: 21 additions & 21 deletions web3/_utils/module_testing/eth_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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']))
Expand All @@ -103,18 +103,18 @@ 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

@pytest.mark.asyncio
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),
Expand All @@ -126,69 +126,69 @@ 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
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
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']

@pytest.mark.asyncio
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:
Expand Down
30 changes: 1 addition & 29 deletions web3/_utils/transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
2 changes: 0 additions & 2 deletions web3/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
abi_ens_resolver,
)
from web3.eth import (
AsyncEth,
Eth,
)
from web3.geth import (
Expand Down Expand Up @@ -222,7 +221,6 @@ def toChecksumAddress(value: Union[AnyAddress, str, bytes]) -> ChecksumAddress:
parity: Parity
geth: Geth
net: Net
async_eth: AsyncEth

def __init__(
self,
Expand Down
6 changes: 4 additions & 2 deletions web3/middleware/buffered_gas_estimate.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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',
Expand Down
2 changes: 1 addition & 1 deletion web3/middleware/gas_price_strategy.py
Original file line number Diff line number Diff line change
Expand Up @@ -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])
Expand Down
17 changes: 9 additions & 8 deletions web3/tools/benchmark/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
)
from web3.eth import (
AsyncEth,
Eth,
)
from web3.middleware import (
async_buffered_gas_estimate_middleware,
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand All @@ -122,15 +123,15 @@ 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 = [
{
"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",
Expand All @@ -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)
Expand All @@ -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),
},
]

Expand Down

0 comments on commit d4b2815

Please sign in to comment.