Skip to content

Commit b4d3945

Browse files
committed
Add formatter for data field for transaction results
- Nethermind returns both ``data`` and ``input`` with the same value for each. Add a formatter for ``data`` that will format the field if it is present. - Add a test for transaction result formatters via ``eth.get_transaction()`` test.
1 parent 9c88416 commit b4d3945

File tree

4 files changed

+138
-12
lines changed

4 files changed

+138
-12
lines changed

newsfragments/3129.misc.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add transaction result formatter for ``data`` field. Nethermind, for example, returns both ``data`` and ``input`` for transaction results.

tests/core/contracts/test_contract_constructor.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
from eth_utils import (
44
decode_hex,
55
)
6+
from hexbytes import (
7+
HexBytes,
8+
)
69

710
from web3._utils.contract_sources.contract_data.constructor_contracts import (
811
CONSTRUCTOR_WITH_ADDRESS_ARGUMENT_CONTRACT_RUNTIME,
@@ -217,11 +220,11 @@ def test_contract_constructor_build_transaction_no_constructor(
217220
txn = w3.eth.get_transaction(txn_hash)
218221
nonce = w3.eth.get_transaction_count(w3.eth.coinbase)
219222
unsent_txn = math_contract_factory.constructor().build_transaction({"nonce": nonce})
220-
assert txn["data"] == unsent_txn["data"]
223+
assert txn["data"] == HexBytes(unsent_txn["data"])
221224

222225
new_txn_hash = w3.eth.send_transaction(unsent_txn)
223226
new_txn = w3.eth.get_transaction(new_txn_hash)
224-
assert new_txn["data"] == unsent_txn["data"]
227+
assert new_txn["data"] == HexBytes(unsent_txn["data"])
225228
assert new_txn["nonce"] == nonce
226229

227230

@@ -234,11 +237,11 @@ def test_contract_constructor_build_transaction_without_arguments(
234237
txn = w3.eth.get_transaction(txn_hash)
235238
nonce = w3.eth.get_transaction_count(w3.eth.coinbase)
236239
unsent_txn = math_contract_factory.constructor().build_transaction({"nonce": nonce})
237-
assert txn["data"] == unsent_txn["data"]
240+
assert txn["data"] == HexBytes(unsent_txn["data"])
238241

239242
new_txn_hash = w3.eth.send_transaction(unsent_txn)
240243
new_txn = w3.eth.get_transaction(new_txn_hash)
241-
assert new_txn["data"] == unsent_txn["data"]
244+
assert new_txn["data"] == HexBytes(unsent_txn["data"])
242245
assert new_txn["nonce"] == nonce
243246

244247

@@ -266,11 +269,11 @@ def test_contract_constructor_build_transaction_with_arguments(
266269
unsent_txn = non_strict_contract_with_constructor_args_factory.constructor(
267270
*constructor_args, **constructor_kwargs
268271
).build_transaction({"nonce": nonce})
269-
assert txn["data"] == unsent_txn["data"]
272+
assert txn["data"] == HexBytes(unsent_txn["data"])
270273

271274
new_txn_hash = w3_non_strict_abi.eth.send_transaction(unsent_txn)
272275
new_txn = w3_non_strict_abi.eth.get_transaction(new_txn_hash)
273-
assert new_txn["data"] == unsent_txn["data"]
276+
assert new_txn["data"] == HexBytes(unsent_txn["data"])
274277
assert new_txn["nonce"] == nonce
275278

276279

@@ -525,11 +528,11 @@ async def test_async_contract_constructor_build_transaction_no_constructor(
525528
unsent_txn = await async_math_contract_factory.constructor().build_transaction(
526529
{"nonce": nonce}
527530
)
528-
assert txn["data"] == unsent_txn["data"]
531+
assert txn["data"] == HexBytes(unsent_txn["data"])
529532

530533
new_txn_hash = await async_w3.eth.send_transaction(unsent_txn)
531534
new_txn = await async_w3.eth.get_transaction(new_txn_hash)
532-
assert new_txn["data"] == unsent_txn["data"]
535+
assert new_txn["data"] == HexBytes(unsent_txn["data"])
533536
assert new_txn["nonce"] == nonce
534537

535538

@@ -547,11 +550,11 @@ async def test_async_contract_constructor_build_transaction_without_arguments(
547550
unsent_txn = await async_math_contract_factory.constructor().build_transaction(
548551
{"nonce": nonce}
549552
)
550-
assert txn["data"] == unsent_txn["data"]
553+
assert txn["data"] == HexBytes(unsent_txn["data"])
551554

552555
new_txn_hash = await async_w3.eth.send_transaction(unsent_txn)
553556
new_txn = await async_w3.eth.get_transaction(new_txn_hash)
554-
assert new_txn["data"] == unsent_txn["data"]
557+
assert new_txn["data"] == HexBytes(unsent_txn["data"])
555558
assert new_txn["nonce"] == nonce
556559

557560

@@ -586,9 +589,9 @@ async def test_async_contract_constructor_build_transaction_with_arguments(
586589
*constructor_args, **constructor_kwargs
587590
).build_transaction({"nonce": nonce})
588591
)
589-
assert txn["data"] == unsent_txn["data"]
592+
assert txn["data"] == HexBytes(unsent_txn["data"])
590593

591594
new_txn_hash = await async_w3_non_strict_abi.eth.send_transaction(unsent_txn)
592595
new_txn = await async_w3_non_strict_abi.eth.get_transaction(new_txn_hash)
593-
assert new_txn["data"] == unsent_txn["data"]
596+
assert new_txn["data"] == HexBytes(unsent_txn["data"])
594597
assert new_txn["nonce"] == nonce

tests/core/eth-module/test_transactions.py

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,31 @@
11
import pytest
22

3+
from eth_utils import (
4+
to_checksum_address,
5+
to_int,
6+
)
7+
from hexbytes import (
8+
HexBytes,
9+
)
10+
311
from web3._utils.ens import (
412
ens_addresses,
513
)
14+
from web3._utils.rpc_abi import (
15+
RPC,
16+
)
17+
from web3.datastructures import (
18+
AttributeDict,
19+
)
620
from web3.exceptions import (
721
NameNotFound,
822
TimeExhausted,
923
TransactionNotFound,
1024
Web3ValidationError,
1125
)
26+
from web3.middleware import (
27+
construct_result_generator_middleware,
28+
)
1229
from web3.middleware.simulate_unmined_transaction import (
1330
unmined_receipt_simulator_middleware,
1431
)
@@ -174,3 +191,107 @@ def test_unmined_transaction_wait_for_receipt(w3):
174191
txn_receipt = w3.eth.wait_for_transaction_receipt(txn_hash)
175192
assert txn_receipt["transactionHash"] == txn_hash
176193
assert txn_receipt["blockHash"] is not None
194+
195+
196+
def test_get_transaction_formatters(w3):
197+
non_checksummed_addr = "0xB2930B35844A230F00E51431ACAE96FE543A0347" # all uppercase
198+
unformatted_transaction = {
199+
"blockHash": (
200+
"0x849044202a39ae36888481f90d62c3826bca8269c2716d7a38696b4f45e61d83"
201+
),
202+
"blockNumber": "0x1b4",
203+
"transactionIndex": "0x0",
204+
"nonce": "0x0",
205+
"gas": "0x4c4b40",
206+
"gasPrice": "0x1",
207+
"maxFeePerGas": "0x1",
208+
"maxPriorityFeePerGas": "0x1",
209+
"value": "0x1",
210+
"from": non_checksummed_addr,
211+
"publicKey": "0x",
212+
"r": "0xd148ae70c8cbef3a038e70e6d1639f0951e60a2965820f33bad19d0a6c2b8116",
213+
"raw": "0x142ab034696c09dcfb2a8b086b494f3f4c419e67b6c04d95882f87156a3b6f35",
214+
"s": "0x6f5216fc207221a11efe2e4c3e3a881a0b5ca286ede538fc9dbc403b2009ea76",
215+
"to": non_checksummed_addr,
216+
"hash": "0x142ab034696c09dcfb2a8b086b494f3f4c419e67b6c04d95882f87156a3b6f35",
217+
"v": "0x1",
218+
"yParity": "0x1",
219+
"standardV": "0x1",
220+
"type": "0x2",
221+
"chainId": "0x539",
222+
"accessList": [
223+
{
224+
"address": non_checksummed_addr,
225+
"storageKeys": [
226+
"0x0000000000000000000000000000000000000000000000000000000000000032", # noqa: E501
227+
"0x0000000000000000000000000000000000000000000000000000000000000036", # noqa: E501
228+
],
229+
},
230+
{
231+
"address": non_checksummed_addr,
232+
"storageKeys": [],
233+
},
234+
],
235+
"input": "0x5b34b966",
236+
"data": "0x5b34b966",
237+
}
238+
239+
result_middleware = construct_result_generator_middleware(
240+
{
241+
RPC.eth_getTransactionByHash: lambda *_: unformatted_transaction,
242+
}
243+
)
244+
w3.middleware_onion.inject(result_middleware, "result_middleware", layer=0)
245+
246+
# test against eth_getTransactionByHash
247+
received_tx = w3.eth.get_transaction("")
248+
249+
checksummed_addr = to_checksum_address(non_checksummed_addr)
250+
assert non_checksummed_addr != checksummed_addr
251+
252+
expected = AttributeDict(
253+
{
254+
"blockHash": HexBytes(unformatted_transaction["blockHash"]),
255+
"blockNumber": to_int(hexstr=unformatted_transaction["blockNumber"]),
256+
"transactionIndex": 0,
257+
"nonce": 0,
258+
"gas": to_int(hexstr=unformatted_transaction["gas"]),
259+
"gasPrice": 1,
260+
"maxFeePerGas": 1,
261+
"maxPriorityFeePerGas": 1,
262+
"value": 1,
263+
"from": checksummed_addr,
264+
"publicKey": HexBytes(unformatted_transaction["publicKey"]),
265+
"r": HexBytes(unformatted_transaction["r"]),
266+
"raw": HexBytes(unformatted_transaction["raw"]),
267+
"s": HexBytes(unformatted_transaction["s"]),
268+
"to": to_checksum_address(non_checksummed_addr),
269+
"hash": HexBytes(unformatted_transaction["hash"]),
270+
"v": 1,
271+
"yParity": 1,
272+
"standardV": 1,
273+
"type": 2,
274+
"chainId": 1337,
275+
"accessList": [
276+
AttributeDict(
277+
{
278+
"address": checksummed_addr,
279+
"storageKeys": [
280+
"0x0000000000000000000000000000000000000000000000000000000000000032", # noqa: E501
281+
"0x0000000000000000000000000000000000000000000000000000000000000036", # noqa: E501
282+
],
283+
}
284+
),
285+
AttributeDict(
286+
{
287+
"address": checksummed_addr,
288+
"storageKeys": [],
289+
}
290+
),
291+
],
292+
"input": HexBytes(unformatted_transaction["input"]),
293+
"data": HexBytes(unformatted_transaction["data"]),
294+
}
295+
)
296+
assert received_tx == expected
297+
w3.middleware_onion.remove("result_middleware")

web3/_utils/method_formatters.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ def type_aware_apply_formatters_to_dict_keys_and_values(
219219
),
220220
),
221221
"input": HexBytes,
222+
"data": HexBytes, # Nethermind, for example, returns both `input` and `data`
222223
}
223224

224225

0 commit comments

Comments
 (0)