Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event process receipt #1366

Merged
merged 1 commit into from
Jul 11, 2019
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
61 changes: 59 additions & 2 deletions docs/contracts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -718,11 +718,11 @@ For example:

:py:class:`ContractEvent` provides methods to interact with contract events. Positional and keyword arguments supplied to the contract event subclass will be used to find the contract event by signature.

.. py:method:: ContractEvents.myEvent(*args, **kwargs).processReceipt(transaction_receipt)
.. py:method:: ContractEvents.myEvent(*args, **kwargs).processReceipt(transaction_receipt, errors=WARN)

Extracts the pertinent logs from a transaction receipt.

Returns a tuple of :ref:`Event Log Objects <event-log-object>`, emitted from the event (e.g. ``myEvent``),
If there are no errors, ``processReceipt`` returns a tuple of :ref:`Event Log Objects <event-log-object>`, emitted from the event (e.g. ``myEvent``),
with decoded ouput.

.. code-block:: python
Expand All @@ -733,6 +733,63 @@ For example:
>>> rich_logs[0]['args']
{'myArg': 12345}

The default ``WARN`` flag logs a warning to the console if the log has errors, and the log that raised the warning will be discarded. Any logs that didn't encounter errors during processing will be returned.
There are also a few other flags available:

- ``STRICT`` - stops all processing and raises the error encountered.
- ``IGNORE`` - returns any raw logs that raised an error with an added "errors" field, along with any other logs were able to be processed.
- ``DISCARD`` - silently discards any logs that have errors, and returns processed logs that don't have errors.
- ``WARN`` - logs a warning to the console for the log that has an error, and discards the log. Returns any logs that are able to be processed.

An event log error flag needs to be imported from web3/log.py.

.. code-block:: python

>>> from web3.logs import STRICT, IGNORE, DISCARD, WARN

>>> tx_hash = contract.functions.myFunction(12345).transact({'to':contract_address})
>>> tx_receipt = w3.eth.getTransactionReceipt(tx_hash)
>>> returned_logs = contract.events.myEvent().processReceipt(tx_receipt, errors=IGNORE)
>>> assert returned_logs[0] == tx_receipt['logs'][0]
True
>>> returned_logs = contract.events.myEvent().processReceipt(tx_receipt, errors=DISCARD)
>>> assert returned_logs == ()
True


.. _event-log-object:

Event Log Object
~~~~~~~~~~~~~~~~

The Event Log Object is a python dictionary with the following keys:

* ``args``: Dictionary - The arguments coming from the event.
* ``event``: String - The event name.
* ``logIndex``: Number - integer of the log index position in the block.
* ``transactionIndex``: Number - integer of the transactions index position
log was created from.
* ``transactionHash``: String, 32 Bytes - hash of the transactions this log
was created from.
* ``address``: String, 32 Bytes - address from which this log originated.
* ``blockHash``: String, 32 Bytes - hash of the block where this log was
in. null when it's pending.
* ``blockNumber``: Number - the block number where this log was in. null
when it's pending.


.. code-block:: python

>>> transfer_filter = my_token_contract.eventFilter('Transfer', {'filter': {'_from': '0xdc3a9db694bcdd55ebae4a89b22ac6d12b3f0c24'}})
>>> transfer_filter.get_new_entries()
[...] # array of Event Log Objects that match the filter.
# wait a while...
>>> transfer_filter.get_new_entries()
[...] # new events since the last call
>>> transfer_filter.get_all_entries()
[...] # all events that match the filter.


Utils
-----

Expand Down
2 changes: 0 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
get_open_port,
)

pytest_plugins = ["pytest_ethereum.plugins"]


@pytest.fixture(scope="module", params=[lambda x: to_bytes(hexstr=x), identity])
def address_conversion_func(request):
Expand Down
127 changes: 127 additions & 0 deletions tests/core/contracts/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@
event_signature_to_log_topic,
)

from web3._utils.module_testing.event_contract import (
EVNT_CONTRACT_ABI,
EVNT_CONTRACT_CODE,
EVNT_CONTRACT_RUNTIME,
)
from web3._utils.module_testing.indexed_event_contract import (
IND_EVENT_CONTRACT_ABI,
IND_EVENT_CONTRACT_CODE,
IND_EVENT_CONTRACT_RUNTIME,
)

CONTRACT_NESTED_TUPLE_SOURCE = """
pragma solidity >=0.4.19 <0.6.0;
pragma experimental ABIEncoderV2;
Expand Down Expand Up @@ -402,6 +413,121 @@ def emitter(web3_empty, Emitter, wait_for_transaction, wait_for_block, address_c
return emitter_contract


@pytest.fixture()
def EVENT_CONTRACT_CODE():
return EVNT_CONTRACT_CODE


@pytest.fixture()
def EVENT_CONTRACT_RUNTIME():
return EVNT_CONTRACT_RUNTIME


@pytest.fixture()
def EVENT_CONTRACT_ABI():
return EVNT_CONTRACT_ABI


@pytest.fixture()
def EVENT_CONTRACT(
EVENT_CONTRACT_CODE,
EVENT_CONTRACT_RUNTIME,
EVENT_CONTRACT_ABI):
return {
'bytecode': EVENT_CONTRACT_CODE,
'bytecode_runtime': EVENT_CONTRACT_RUNTIME,
'abi': EVENT_CONTRACT_ABI,
}


@pytest.fixture()
def EventContract(web3_empty, EVENT_CONTRACT):
web3 = web3_empty
return web3.eth.contract(**EVENT_CONTRACT)


@pytest.fixture()
def event_contract(
web3_empty,
EventContract,
wait_for_transaction,
wait_for_block,
address_conversion_func):

web3 = web3_empty

wait_for_block(web3)
deploy_txn_hash = EventContract.constructor().transact({
'from': web3.eth.coinbase, 'gas': 1000000
})
deploy_receipt = wait_for_transaction(web3, deploy_txn_hash)
contract_address = address_conversion_func(deploy_receipt['contractAddress'])

bytecode = web3.eth.getCode(contract_address)
assert bytecode == EventContract.bytecode_runtime
event_contract = EventContract(address=contract_address)
assert event_contract.address == contract_address
return event_contract


@pytest.fixture()
def INDEXED_EVENT_CONTRACT_CODE():
return IND_EVENT_CONTRACT_CODE


@pytest.fixture()
def INDEXED_EVENT_CONTRACT_RUNTIME():
return IND_EVENT_CONTRACT_RUNTIME


@pytest.fixture()
def INDEXED_EVENT_CONTRACT_ABI():
return IND_EVENT_CONTRACT_ABI


@pytest.fixture()
def INDEXED_EVENT_CONTRACT(
INDEXED_EVENT_CONTRACT_CODE,
INDEXED_EVENT_CONTRACT_RUNTIME,
INDEXED_EVENT_CONTRACT_ABI):
return {
'bytecode': INDEXED_EVENT_CONTRACT_CODE,
'bytecode_runtime': INDEXED_EVENT_CONTRACT_RUNTIME,
'abi': INDEXED_EVENT_CONTRACT_ABI,
}


@pytest.fixture()
def IndexedEventContract(web3_empty, INDEXED_EVENT_CONTRACT):
web3 = web3_empty
return web3.eth.contract(**INDEXED_EVENT_CONTRACT)


@pytest.fixture()
def indexed_event(
web3_empty,
IndexedEventContract,
wait_for_transaction,
wait_for_block,
address_conversion_func):

web3 = web3_empty

wait_for_block(web3)
deploy_txn_hash = IndexedEventContract.constructor().transact({
'from': web3.eth.coinbase,
'gas': 1000000
})
deploy_receipt = wait_for_transaction(web3, deploy_txn_hash)
contract_address = address_conversion_func(deploy_receipt['contractAddress'])

bytecode = web3.eth.getCode(contract_address)
assert bytecode == IndexedEventContract.bytecode_runtime
indexed_event_contract = IndexedEventContract(address=contract_address)
assert indexed_event_contract.address == contract_address
return indexed_event_contract


CONTRACT_ARRAYS_SOURCE = """
contract ArraysContract {

Expand Down Expand Up @@ -698,6 +824,7 @@ class LogFunctions:
LogDoubleWithIndex = 9
LogTripleWithIndex = 10
LogQuadrupleWithIndex = 11
LogBytes = 12


@pytest.fixture()
Expand Down
12 changes: 12 additions & 0 deletions tests/core/contracts/contract_sources/Emitter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,28 @@ contract Emitter {
else if (which == WhichEvent.LogQuadrupleWithIndex) emit LogQuadrupleWithIndex(arg0, arg1, arg2, arg3);
else revert("Didn't match any allowable event index");
}

function logDynamicArgs(string arg0, string arg1) public {
emit LogDynamicArgs(arg0, arg1);
}

function logListArgs(bytes2[] arg0, bytes2[] arg1) public {
emit LogListArgs(arg0, arg1);
}

function logAddressIndexedArgs(address arg0, address arg1) public {
emit LogAddressIndexed(arg0, arg1);
}

function logAddressNotIndexedArgs(address arg0, address arg1) public {
emit LogAddressNotIndexed(arg0, arg1);
}

function logBytes(bytes v) public {
emit LogBytes(v);
}

function logString(string v) public {
emit LogString(v);
}
}
Loading