Skip to content

Commit 9b56702

Browse files
authored
Merge pull request #95 from fjarri-eth/more-methods
More RPC methods
2 parents e898ec3 + e67d536 commit 9b56702

6 files changed

Lines changed: 343 additions & 37 deletions

File tree

pdm.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pons/_client.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,10 +277,11 @@ async def call(
277277
) -> Any:
278278
"""
279279
Sends a prepared contact method call to the provided address.
280-
Returns the decoded output.
281280
282281
If ``sender_address`` is provided, it will be included in the call
283282
and affect the return value if the method uses ``msg.sender`` internally.
283+
284+
The decoded output is returned according to :py:class:`Method.decode_output` rules.
284285
"""
285286
with convert_errors(call.contract_abi):
286287
return await self._rpc.eth_call(call, block=block, sender_address=sender_address)

pons/_client_rpc.py

Lines changed: 168 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -126,19 +126,19 @@ def __init__(self, provider_session: ProviderSession):
126126
self._provider_session = provider_session
127127

128128
async def net_version(self) -> str:
129-
"""Calls the ``net_version`` RPC method."""
129+
"""Returns the current network id."""
130130
return await rpc_call(self._provider_session, "net_version", str)
131131

132132
async def eth_chain_id(self) -> int:
133-
"""Calls the ``eth_chainId`` RPC method."""
133+
"""Returns the chain ID used for signing replay-protected transactions."""
134134
return await rpc_call(self._provider_session, "eth_chainId", int)
135135

136136
async def eth_get_balance(self, address: Address, block: Block = BlockLabel.LATEST) -> Amount:
137-
"""Calls the ``eth_getBalance`` RPC method."""
137+
"""Returns the balance of the account of given address."""
138138
return await rpc_call(self._provider_session, "eth_getBalance", Amount, address, block)
139139

140140
async def eth_get_transaction_by_hash(self, tx_hash: TxHash) -> None | TxInfo:
141-
"""Calls the ``eth_getTransactionByHash`` RPC method."""
141+
"""Returns the information about a transaction requested by transaction hash."""
142142
# Need an explicit cast, mypy doesn't work with union types correctly.
143143
# See https://github.com/python/mypy/issues/16935
144144
return cast(
@@ -152,7 +152,13 @@ async def eth_get_transaction_by_hash(self, tx_hash: TxHash) -> None | TxInfo:
152152
)
153153

154154
async def eth_get_transaction_receipt(self, tx_hash: TxHash) -> None | TxReceipt:
155-
"""Calls the ``eth_getTransactionReceipt`` RPC method."""
155+
"""
156+
Returns the receipt of a transaction by transaction hash.
157+
158+
.. note::
159+
160+
That the receipt is not available for pending transactions.
161+
"""
156162
# Need an explicit cast, mypy doesn't work with union types correctly.
157163
# See https://github.com/python/mypy/issues/16935
158164
return cast(
@@ -168,7 +174,7 @@ async def eth_get_transaction_receipt(self, tx_hash: TxHash) -> None | TxReceipt
168174
async def eth_get_transaction_count(
169175
self, address: Address, block: Block = BlockLabel.LATEST
170176
) -> int:
171-
"""Calls the ``eth_getTransactionCount`` RPC method."""
177+
"""Returns the number of transactions sent from an address."""
172178
return await rpc_call(
173179
self._provider_session,
174180
"eth_getTransactionCount",
@@ -178,13 +184,13 @@ async def eth_get_transaction_count(
178184
)
179185

180186
async def eth_get_code(self, address: Address, block: Block = BlockLabel.LATEST) -> bytes:
181-
"""Calls the ``eth_getCode`` RPC method."""
187+
"""Returns code at a given address."""
182188
return await rpc_call(self._provider_session, "eth_getCode", bytes, address, block)
183189

184190
async def eth_get_storage_at(
185191
self, address: Address, position: int, block: Block = BlockLabel.LATEST
186192
) -> bytes:
187-
"""Calls the ``eth_getCode`` RPC method."""
193+
"""Returns the value from a storage position at a given address."""
188194
return await rpc_call(
189195
self._provider_session,
190196
"eth_getStorageAt",
@@ -201,11 +207,14 @@ async def eth_call(
201207
sender_address: None | Address = None,
202208
) -> Any:
203209
"""
204-
Sends a prepared contact method call to the provided address.
205-
Returns the decoded output.
210+
Executes a new message call immediately without creating a transaction on the blockchain.
211+
Often used for executing read-only smart contract functions,
212+
for example the ``balanceOf`` for an ERC-20 contract.
206213
207214
If ``sender_address`` is provided, it will be included in the call
208215
and affect the return value if the method uses ``msg.sender`` internally.
216+
217+
The decoded output is returned according to :py:class:`Method.decode_output` rules.
209218
"""
210219
params = EthCallParams(to=call.contract_address, data=call.data_bytes, from_=sender_address)
211220

@@ -219,25 +228,35 @@ async def eth_call(
219228
return call.decode_output(encoded_output)
220229

221230
async def eth_send_raw_transaction(self, tx_bytes: bytes) -> TxHash:
222-
"""Sends a signed and serialized transaction."""
231+
"""Creates new message call transaction or a contract creation for signed transactions."""
223232
return await rpc_call(self._provider_session, "eth_sendRawTransaction", TxHash, tx_bytes)
224233

225234
async def eth_estimate_gas(self, params: EstimateGasParams, block: Block) -> int:
226-
"""Calls the ``eth_estimateGas`` RPC method."""
235+
"""
236+
Generates and returns an estimate of how much gas is necessary
237+
to allow the transaction to complete.
238+
The transaction will not be added to the blockchain.
239+
Note that the estimate may be significantly more than the amount of gas
240+
actually used by the transaction, for a variety of reasons
241+
including EVM mechanics and node performance.
242+
"""
227243
return await rpc_call(self._provider_session, "eth_estimateGas", int, params, block)
228244

229245
async def eth_gas_price(self) -> Amount:
230-
"""Calls the ``eth_gasPrice`` RPC method."""
246+
"""
247+
Returns an estimate of the current price per gas in wei,
248+
according to a provider-specific algorithm.
249+
"""
231250
return await rpc_call(self._provider_session, "eth_gasPrice", Amount)
232251

233252
async def eth_block_number(self) -> int:
234-
"""Calls the ``eth_blockNumber`` RPC method."""
253+
"""Returns the number of the most recent block."""
235254
return await rpc_call(self._provider_session, "eth_blockNumber", int)
236255

237256
async def eth_get_block_by_hash(
238257
self, block_hash: BlockHash, *, with_transactions: bool = False
239258
) -> None | BlockInfo:
240-
"""Calls the ``eth_getBlockByHash`` RPC method."""
259+
"""Returns information about a block by hash."""
241260
# Need an explicit cast, mypy doesn't work with union types correctly.
242261
# See https://github.com/python/mypy/issues/16935
243262
return cast(
@@ -254,7 +273,7 @@ async def eth_get_block_by_hash(
254273
async def eth_get_block_by_number(
255274
self, block: Block = BlockLabel.LATEST, *, with_transactions: bool = False
256275
) -> None | BlockInfo:
257-
"""Calls the ``eth_getBlockByNumber`` RPC method."""
276+
"""Returns information about a block by block number."""
258277
# Need an explicit cast, mypy doesn't work with union types correctly.
259278
# See https://github.com/python/mypy/issues/16935
260279
return cast(
@@ -275,7 +294,7 @@ async def eth_get_logs(
275294
from_block: Block = BlockLabel.LATEST,
276295
to_block: Block = BlockLabel.LATEST,
277296
) -> tuple[LogEntry, ...]:
278-
"""Calls the ``eth_getLogs`` RPC method."""
297+
"""Returns an array of all logs matching a given filter object."""
279298
if isinstance(source, Iterable):
280299
source = tuple(source)
281300
params = FilterParams(
@@ -287,14 +306,14 @@ async def eth_get_logs(
287306
return await rpc_call(self._provider_session, "eth_getLogs", tuple[LogEntry, ...], params)
288307

289308
async def eth_new_block_filter(self) -> BlockFilter:
290-
"""Calls the ``eth_newBlockFilter`` RPC method."""
309+
"""Creates a filter in the node, to notify when a new block arrives."""
291310
result, provider_path = await rpc_call_pin(
292311
self._provider_session, "eth_newBlockFilter", int
293312
)
294313
return BlockFilter(id=result, provider_path=provider_path)
295314

296315
async def eth_new_pending_transaction_filter(self) -> PendingTransactionFilter:
297-
"""Calls the ``eth_newPendingTransactionFilter`` RPC method."""
316+
"""Creates a filter in the node, to notify when new pending transactions arrive."""
298317
result, provider_path = await rpc_call_pin(
299318
self._provider_session, "eth_newPendingTransactionFilter", int
300319
)
@@ -307,7 +326,10 @@ async def eth_new_filter(
307326
from_block: Block = BlockLabel.LATEST,
308327
to_block: Block = BlockLabel.LATEST,
309328
) -> LogFilter:
310-
"""Calls the ``eth_newFilter`` RPC method."""
329+
"""
330+
Creates a filter object, based on filter options,
331+
to notify when the state changes (logs).
332+
"""
311333
if isinstance(source, Iterable):
312334
source = tuple(source)
313335
params = FilterParams(
@@ -351,14 +373,138 @@ async def _query_filter(
351373
async def eth_get_filter_logs(
352374
self, filter_: BlockFilter | PendingTransactionFilter | LogFilter
353375
) -> tuple[BlockHash, ...] | tuple[TxHash, ...] | tuple[LogEntry, ...]:
354-
"""Calls the ``eth_getFilterLogs`` RPC method."""
376+
"""Returns an array of all logs matching filter with given id."""
355377
return await self._query_filter("eth_getFilterLogs", filter_)
356378

357379
async def eth_get_filter_changes(
358380
self, filter_: BlockFilter | PendingTransactionFilter | LogFilter
359381
) -> tuple[BlockHash, ...] | tuple[TxHash, ...] | tuple[LogEntry, ...]:
360382
"""
361-
Calls the ``eth_getFilterChanges`` RPC method.
383+
Polling method for a filter, which returns an array of logs which occurred since last poll.
384+
362385
Depending on what ``filter_`` was, returns a tuple of corresponding results.
363386
"""
364387
return await self._query_filter("eth_getFilterChanges", filter_)
388+
389+
async def eth_uninstall_filter(
390+
self, filter_: BlockFilter | PendingTransactionFilter | LogFilter
391+
) -> bool:
392+
"""
393+
Uninstalls a filter with given id. Should always be called when watch is no longer needed.
394+
395+
Returns ``true`` if there was an active filter with a given filter ID.
396+
397+
.. note::
398+
399+
Many providers will automatically uninstall filters after some time
400+
if they are not queried.
401+
"""
402+
return await rpc_call_at_pin(
403+
self._provider_session, filter_.provider_path, "eth_uninstallFilter", bool, filter_.id
404+
)
405+
406+
async def web3_client_version(self) -> str:
407+
"""Returns the current client version."""
408+
return await rpc_call(self._provider_session, "web3_clientVersion", str)
409+
410+
async def web3_sha3(self, data: bytes) -> bytes:
411+
"""Returns Keccak-256 (*not* the standardized SHA3-256) of the given data."""
412+
return await rpc_call(self._provider_session, "web3_sha3", bytes, data)
413+
414+
async def net_listening(self) -> bool:
415+
"""Returns ``True`` if client is actively listening for network connections."""
416+
return await rpc_call(self._provider_session, "net_listening", bool)
417+
418+
async def net_peer_count(self) -> int:
419+
"""Returns number of peers currently connected to the client."""
420+
return await rpc_call(self._provider_session, "net_peerCount", int)
421+
422+
async def eth_coinbase(self) -> Address:
423+
"""Returns the client coinbase address."""
424+
return await rpc_call(self._provider_session, "eth_coinbase", Address)
425+
426+
async def eth_accounts(self) -> list[Address]:
427+
"""Returns a list of addresses owned by client."""
428+
return await rpc_call(self._provider_session, "eth_accounts", list[Address])
429+
430+
async def eth_get_block_transaction_count_by_hash(self, block_hash: BlockHash) -> int:
431+
"""
432+
Returns the number of transactions in a block from a block
433+
matching the given block hash.
434+
"""
435+
return await rpc_call(
436+
self._provider_session, "eth_getBlockTransactionCountByHash", int, block_hash
437+
)
438+
439+
async def eth_get_block_transaction_count_by_number(self, block: Block) -> int:
440+
"""Returns the number of transactions in a block matching the given block number."""
441+
return await rpc_call(
442+
self._provider_session, "eth_getBlockTransactionCountByNumber", int, block
443+
)
444+
445+
async def eth_get_uncle_count_by_block_hash(self, block_hash: BlockHash) -> int:
446+
"""Returns the number of uncles in a block from a block matching the given block hash."""
447+
return await rpc_call(
448+
self._provider_session, "eth_getUncleCountByBlockHash", int, block_hash
449+
)
450+
451+
async def eth_get_uncle_count_by_block_number(self, block: Block) -> int:
452+
"""Returns the number of uncles in a block from a block matching the given block number."""
453+
return await rpc_call(self._provider_session, "eth_getUncleCountByBlockNumber", int, block)
454+
455+
async def eth_get_transaction_by_block_hash_and_index(
456+
self, block_hash: BlockHash, index: int
457+
) -> TxInfo:
458+
"""Returns information about a transaction by block hash and transaction index position."""
459+
return await rpc_call(
460+
self._provider_session,
461+
"eth_getTransactionByBlockHashAndIndex",
462+
TxInfo,
463+
block_hash,
464+
index,
465+
)
466+
467+
async def eth_get_transaction_by_block_number_and_index(
468+
self, block: Block, index: int
469+
) -> TxInfo:
470+
"""
471+
Returns information about a transaction by block number
472+
and transaction index position.
473+
"""
474+
return await rpc_call(
475+
self._provider_session, "eth_getTransactionByBlockNumberAndIndex", TxInfo, block, index
476+
)
477+
478+
async def eth_get_uncle_by_block_hash_and_index(
479+
self, block_hash: BlockHash, index: int
480+
) -> None | BlockInfo:
481+
"""Returns information about a uncle of a block by hash and uncle index position."""
482+
# Need an explicit cast, mypy doesn't work with union types correctly.
483+
# See https://github.com/python/mypy/issues/16935
484+
return cast(
485+
"None | BlockInfo",
486+
await rpc_call(
487+
self._provider_session,
488+
"eth_getUncleByBlockHashAndIndex",
489+
None | BlockInfo, # type: ignore[arg-type]
490+
block_hash,
491+
index,
492+
),
493+
)
494+
495+
async def eth_get_uncle_by_block_number_and_index(
496+
self, block: Block, index: int
497+
) -> None | BlockInfo:
498+
"""Returns information about a uncle of a block by number and uncle index position."""
499+
# Need an explicit cast, mypy doesn't work with union types correctly.
500+
# See https://github.com/python/mypy/issues/16935
501+
return cast(
502+
"None | BlockInfo",
503+
await rpc_call(
504+
self._provider_session,
505+
"eth_getUncleByBlockNumberAndIndex",
506+
None | BlockInfo, # type: ignore[arg-type]
507+
block,
508+
index,
509+
),
510+
)

pons/_contract_abi.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -638,14 +638,7 @@ def __str__(self) -> str:
638638

639639

640640
class Event:
641-
"""
642-
A contract event.
643-
644-
.. note::
645-
646-
If the name of a field given to the constructor matches a Python keyword,
647-
``_`` will be appended to it.
648-
"""
641+
"""A contract event."""
649642

650643
name: str
651644
"""The name of this event."""

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ compiler = [
2626
"py-solc-x>=2",
2727
]
2828
local-provider = [
29-
"alysis>=0.6.1",
29+
"alysis>=0.6.3",
3030
]
3131
http-provider = [
3232
"httpx>=0.22",
@@ -45,7 +45,7 @@ tests = [
4545
# from `compiler` feature
4646
"py-solc-x>=2",
4747
# from `local-provider` feature
48-
"alysis>=0.3.0",
48+
"alysis>=0.6.3",
4949
# from `http-provider` feature
5050
"httpx>=0.22",
5151
# from `http-provider-server` feature

0 commit comments

Comments
 (0)