Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/providers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ Eth
- :meth:`web3.eth.send_raw_transaction() <web3.eth.Eth.send_raw_transaction>`
- :meth:`web3.eth.wait_for_transaction_receipt() <web3.eth.Eth.wait_for_transaction_receipt>`
- :meth:`web3.eth.sign() <web3.eth.Eth.sign>`
- :meth:`web3.eth.sign_transaction() <web3.eth.Eth.sign_transaction>`
- :meth:`web3.eth.replace_transaction() <web3.eth.Eth.replace_transaction>`

Net
Expand Down
1 change: 1 addition & 0 deletions newsfragments/2827.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add the ``sign_transaction`` method to the ``AsyncEth`` class
101 changes: 101 additions & 0 deletions web3/_utils/module_testing/eth_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,107 @@ async def test_eth_send_transaction_legacy(
assert txn["gas"] == 21000
assert txn["gasPrice"] == txn_params["gasPrice"]

@pytest.mark.asyncio
async def test_async_eth_sign_transaction(
self, async_w3: "AsyncWeb3", unlocked_account: ChecksumAddress
) -> None:
txn_params: TxParams = {
"from": unlocked_account,
"to": unlocked_account,
"value": Wei(1),
"gas": 21000,
"maxFeePerGas": async_w3.to_wei(2, "gwei"),
"maxPriorityFeePerGas": async_w3.to_wei(1, "gwei"),
"nonce": Nonce(0),
}
result = await async_w3.eth.sign_transaction(txn_params)
signatory_account = async_w3.eth.account.recover_transaction(result["raw"])
assert unlocked_account == signatory_account
assert result["tx"]["to"] == txn_params["to"]
assert result["tx"]["value"] == txn_params["value"]
assert result["tx"]["gas"] == txn_params["gas"]
assert result["tx"]["maxFeePerGas"] == txn_params["maxFeePerGas"]
assert (
result["tx"]["maxPriorityFeePerGas"] == txn_params["maxPriorityFeePerGas"]
)
assert result["tx"]["nonce"] == txn_params["nonce"]

@pytest.mark.asyncio
async def test_async_eth_sign_transaction_legacy(
self, async_w3: "AsyncWeb3", unlocked_account: ChecksumAddress
) -> None:
txn_params: TxParams = {
"from": unlocked_account,
"to": unlocked_account,
"value": Wei(1),
"gas": 21000,
"gasPrice": await async_w3.eth.gas_price,
"nonce": Nonce(0),
}
result = await async_w3.eth.sign_transaction(txn_params)
signatory_account = async_w3.eth.account.recover_transaction(result["raw"])
assert unlocked_account == signatory_account
assert result["tx"]["to"] == txn_params["to"]
assert result["tx"]["value"] == txn_params["value"]
assert result["tx"]["gas"] == txn_params["gas"]
assert result["tx"]["gasPrice"] == txn_params["gasPrice"]
assert result["tx"]["nonce"] == txn_params["nonce"]

@pytest.mark.asyncio
async def test_async_eth_sign_transaction_hex_fees(
self, async_w3: "AsyncWeb3", unlocked_account: ChecksumAddress
) -> None:
txn_params: TxParams = {
"from": unlocked_account,
"to": unlocked_account,
"value": Wei(1),
"gas": 21000,
"maxFeePerGas": hex(async_w3.to_wei(2, "gwei")),
"maxPriorityFeePerGas": hex(async_w3.to_wei(1, "gwei")),
"nonce": Nonce(0),
}
result = await async_w3.eth.sign_transaction(txn_params)
signatory_account = async_w3.eth.account.recover_transaction(result["raw"])
assert unlocked_account == signatory_account
assert result["tx"]["to"] == txn_params["to"]
assert result["tx"]["value"] == txn_params["value"]
assert result["tx"]["gas"] == txn_params["gas"]
assert result["tx"]["maxFeePerGas"] == int(str(txn_params["maxFeePerGas"]), 16)
assert result["tx"]["maxPriorityFeePerGas"] == int(
str(txn_params["maxPriorityFeePerGas"]), 16
)
assert result["tx"]["nonce"] == txn_params["nonce"]

@pytest.mark.asyncio
@pytest.mark.xfail(
reason="async name_to_address_middleware has not been implemented yet"
)
async def test_async_eth_sign_transaction_ens_names(
self, async_w3: "AsyncWeb3", unlocked_account: ChecksumAddress
) -> None:
with ens_addresses(async_w3, {"unlocked-account.eth": unlocked_account}):
txn_params: TxParams = {
"from": "unlocked-account.eth",
"to": "unlocked-account.eth",
"value": Wei(1),
"gas": 21000,
"maxFeePerGas": async_w3.to_wei(2, "gwei"),
"maxPriorityFeePerGas": async_w3.to_wei(1, "gwei"),
"nonce": Nonce(0),
}
result = await async_w3.eth.sign_transaction(txn_params)
signatory_account = async_w3.eth.account.recover_transaction(result["raw"])
assert unlocked_account == signatory_account
assert result["tx"]["to"] == unlocked_account
assert result["tx"]["value"] == txn_params["value"]
assert result["tx"]["gas"] == txn_params["gas"]
assert result["tx"]["maxFeePerGas"] == txn_params["maxFeePerGas"]
assert (
result["tx"]["maxPriorityFeePerGas"]
== txn_params["maxPriorityFeePerGas"]
)
assert result["tx"]["nonce"] == txn_params["nonce"]

@pytest.mark.asyncio
async def test_eth_send_transaction(
self, async_w3: "AsyncWeb3", unlocked_account_dual_type: ChecksumAddress
Expand Down
11 changes: 11 additions & 0 deletions web3/eth/async_eth.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
FilterParams,
LogReceipt,
Nonce,
SignedTx,
SyncStatus,
TxData,
TxParams,
Expand Down Expand Up @@ -547,6 +548,16 @@ async def sign(
) -> HexStr:
return await self._sign(account, data, hexstr, text)

# eth_signTransaction

_sign_transaction: Method[Callable[[TxParams], Awaitable[SignedTx]]] = Method(
RPC.eth_signTransaction,
mungers=[default_root_munger],
)

async def sign_transaction(self, transaction: TxParams) -> SignedTx:
return await self._sign_transaction(transaction)

# eth_newFilter, eth_newBlockFilter, eth_newPendingTransactionFilter

filter: Method[
Expand Down