document contracts

This commit is contained in:
Piper Merriam 2016-09-08 13:07:34 -06:00
parent c58ba15eca
commit 2bc54c693c
3 changed files with 346 additions and 21 deletions

View File

@ -21,12 +21,13 @@ Contract Factories
Properties
----------
Each Contract Factory exposes the following properties.
Each Contract Factory exposes the following properties.
.. py:attribute:: Contract.address
The hexidecimal encoded 20 byte address of the contract.
The hexidecimal encoded 20 byte address of the contract. May be ``None``
if not provided during factory creation.
.. py:attribute:: Contract.abi
@ -36,9 +37,192 @@ Properties
.. py:attribute:: Contract.code
The contract bytecode string.
The contract bytecode string. May be ``None`` if not provided during
factory creation.
.. py:attribute:: Contract.code_runtime
The runtime part of the contract bytecode string.
The runtime part of the contract bytecode string. May be ``None`` if not
provided during factory creation.
.. py:attribute:: Contract.code_runtime
The runtime part of the contract bytecode string. May be ``None`` if not
provided during factory creation.
Methods
-------
Each Contract Factory exposes the following methods.
.. py:classmethod:: Contract.deploy(transaction=None, arguments=None)
Construct and send a transaction to deploy the contract.
If provided ``transaction`` should be a dictionary conforming to the
``web3.eth.sendTransaction(transaction)`` method. This value may not
contain the keys ``data`` or ``to``.
If the contract takes constructor arguments they should be provided as a
list via the ``arguments`` parameter.
If a ``gas`` value is not provided, then the ``gas`` value for the
deployment transaction will be created using the ``web3.eth.estimateGas()``
method.
Returns the transaction hash for the deploy transaction.
.. py:method:: Contract.transact(transaction).myMethod(*args, **kwargs)
Execute the specified function by sending a new public transaction.
This is executed in two steps.
The first portion of this function call ``transact(transaction)`` takes a
single parameter which should be a python dictionary conforming to
the same format as the ``web3.eth.sendTransaction(transaction)`` method.
This dictionary may not contain the keys ``data`` or ``to``.
The second portion of the function call ``myMethod(*args, **kwargs)``
selects the appropriate contract function based on the name and provided
argument. Arguments can be provided as positional arguments, keyword
arguments, or a mix of the two.
Returns the transaction hash.
.. code-block:: python
>>> token_contract.transact().transfer(web3.eth.accounts[1], 12345)
"0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd"
.. py:method:: Contract.call(transaction).myMethod(*args)
Call a contract function, executing the transaction locally using the
``eth_call`` API. This will not create a new public transaction.
This method behaves the same as the :py:method::`Contract.transact` method,
with transaction details being passed into the first portion of the
function call, and function arguments being passed into the second portion.
Returns the return value of the executed function.
.. code-block:: python
>>> my_contract.call().multiply7(3)
21
>>> token_contract.call({'from': web3.eth.coinbase}).myBalance()
12345 # the token balance for `web3.eth.coinbase`
>>> token_contract.call({'from': web3.eth.accounts[1]}).myBalance()
54321 # the token balance for the account `web3.eth.accounts[1]`
.. py:method:: Contract.estimateGas(transaction).myMethod(*args)
Call a contract function, executing the transaction locally using the
``eth_call`` API. This will not create a new public transaction.
This method behaves the same as the :py:method::`Contract.transact` method,
with transaction details being passed into the first portion of the
function call, and function arguments being passed into the second portion.
Returns the amount of gas consumed which can be used as a gas estimate for
executing this transaction publicly.
.. code-block:: python
>>> my_contract.estimateGas().multiply7(3)
42650
Events
------
.. py:method::
.. py:classmethod:: Contract.on(event_name, filter_params=None, *callbacks)
Creates a new :py:class:`web3.utils.filters.LogFilter` instance.
The ``event_name`` parameter should be the name of the contract event you
want to filter on.
If provided, ``filter_params`` should be a dictionary specifying
additional filters for log entries. The following keys are supported.
* ``filters``: ``dictionary`` - (optional) Dictionary keys should be
argument names for the Event arguments. Dictionary values should be the
value you want to filter on, or a list of values to be filtered on.
Lists of values will match log entries who's argument matches any value
in the list.
* ``fromBlock``: ``integer/tag`` - (optional, default: "latest") Integer
block number, or "latest" for the last mined block or "pending",
"earliest" for not yet mined transactions.
* ``toBlock``: ``integer/tag`` - (optional, default: "latest") Integer
block number, or "latest" for the last mined block or "pending",
"earliest" for not yet mined transactions.
* ``address``: ``string`` or list of ``strings``, each 20 Bytes -
(optional) Contract address or a list of addresses from which logs should
originate.
* ``topics``: list of 32 byte ``strings`` or ``null`` - (optional) Array of
topics that should be used for filtering. Topics are order-dependent.
This parameter can also be a list of topic lists in which case filtering
will match any of the provided topic arrays.
The event topic for the event specified by ``event_name`` will be added to
the ``filter_params['topics']`` list.
If the :py:attribute::`Contract.address` attribute for this contract is
non-null, the contract address will be added to the ``filter_params``.
If provided, the ``*callbacks`` parameter should be callables which accept
a single Event Log object. When callbacks are provided, the filter will be
*started*. Otherwise the filter will be returned without starting it.
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 its pending.
* ``blockNumber``: Number - the block number where this log was in. null
when its pending.
.. code-block:: python
>>> transfer_filter = my_token_contract.on('Transfer', {'filters': {'_from': '0xdc3a9db694bcdd55ebae4a89b22ac6d12b3f0c24'}})
>>> transfer_filter.get()
[...] # array of Event Log Objects that match the filter.
>>> transfer_filter.watch(my_callback)
# now `my_callback` will be called each time a new matching event log
# is encountered.
.. py:method::
.. py:classmethod:: Contract.pastEvents(event_name, filter_params=None, *callbacks)
Creates a new :py:class:`web3.utils.filters.PastLogFilter` instance which
will match historical event logs.
All parameters behave the same as the :py:method::`Contract.on` method with
the exception that:
* ``filter_params`` parameter may not contain the keys ``toBlock`` or
``fromBlock``.
.. code-block:: python
>>> transfer_filter = my_token_contract.pastEvents('Transfer', {'filters': {'_from': '0xdc3a9db694bcdd55ebae4a89b22ac6d12b3f0c24'}})
>>> transfer_filter.get()
[...] # array of Event Log Objects that match the filter for all historical events.

View File

@ -1,4 +1,145 @@
Filtering
=========
TODO
.. py:module:: web3.utils.filters
.. py:currentmodule:: web3.utils.filters
The ``web3.eth.filter`` method can be used to setup filter for:
* Pending Transactions
* New Blocks
* Event Logs
Filter API
----------
.. py:class:: Filter(web3, filter_id)
The :py:class::`Filter` object is a subclass of the
:py:class::`gevent.Greenlet` object. It exposes these additional properties
and methods.
.. py:attribute:: Filter.filter_id
The ``filter_id`` for this filter as returned by the ``eth_newFilter`` RPC
method when this filter was created.
.. py:attribute:: Filter.callbacks
A list of callbacks that this filter will call with new entries.
.. py:attribute:: Filter.running
Boolean as to whether this filter is currently polling.
.. py:attribute:: Filter.stopped
Boolean as to whether this filter has been stopped. Will be set to
``None`` if the filter has not yet been started.
.. py:method:: Filter.format_entry(entry)
Hook for subclasses to modify the format of the log entries this filter
returns, or passes to it's callback functions.
By default this returns the ``entry`` parameter umodified.
.. py:method:: Filter.is_valid_entry(entry)
Hook for subclasses to add additional programatic filtering. The default
implementation always returns ``True``.
.. py:method:: Filter.watch(*callbacks)
Registers the provided ``callbacks`` to be called with each new entry this
filter encounters and starts the filter polling for changes.
Can only be called once on each filter. Cannot be called on a filter that
has already been started.
.. py:method:: Filter.stop_watching(self, timeout=0)
Stops the filter from polling and uninstalls the filter. Blocks until all
events that are currently being processed have been processed.
Block and Transaction Filters
-----------------------------
.. py:class:: BlockFilter(...)
You can setup a filter for new blocks using ``web3.eth.filter('latest')`` which
will return a new :py:class::`BlockFilter` object.
.. code-block:: python
>>> def new_block_callback(block_hash):
... sys.stdout.write("New Block: {0}".format(block_hash))
...
>>> new_block_filter = web3.eth.filter('latest')
>>> new_block_filter.watch(new_block_filter)
# each time the client receieves a new block the `new_block_callback`
# function will be called with the block hash.
.. py:class:: TransactionFilter(...)
You can setup a filter for new blocks using ``web3.eth.filter('pending')`` which
will return a new :py:class::`BlockFilter` object.
.. code-block:: python
>>> def new_transaction_callback(transaction_hash):
... sys.stdout.write("New Block: {0}".format(transaction_hash))
...
>>> new_transaction_filter = web3.eth.filter('pending')
>>> new_transaction_filter.watch(new_transaction_filter)
# each time the client receieves a unmined transaction the
# `new_transaction_filter` function will be called with the transaction
# hash.
Event Log Filters
-----------------
.. py:class:: LogFilter(web3, filter_id, log_entry_formatter=None, data_filter_set=None)
The :py:class::`LogFilter` class is used for all filters pertaining to even
logs. It exposes the following additional methods.
.. py:method:: LogFilter.get(only_changes=True)
Synchronously retrieve the event logs for this filter.
If ``only_changes`` is ``True`` then logs will be retrieved using the
``web3.eth.getFilterChanges`` which returns only new entries since the last
poll.
If ``only_changes`` is ``False`` then the logs will be retrieved using the
``web3.eth.getFilterLogs`` which returns all logs that match the given
filter.
This method will raise a ``ValueError`` if called on a filter that is
currently polling.
The :py:class::`LogFilter` class is returned from the
:py:method::`web3.contract.Contract.on` and will be configured to extract the
event data from the event logs.
.. py:class:: PastLogFilter(...)
The :py:class::`PastLogFilter` is a subclass of :py:class::`LogFilter` that is
configured specially to return historical event logs. It conforms to the same
API as the ``LogFilter`` class.

View File

@ -365,31 +365,31 @@ class Contract(object):
return deploy_data
@combomethod
def on(self, event_name, default_filter_params=None, *callbacks):
def on(self, event_name, filter_params=None, *callbacks):
"""
register a callback to be triggered on the appropriate events.
"""
if default_filter_params is None:
default_filter_params = {}
if filter_params is None:
filter_params = {}
argument_filters = default_filter_params.pop('filter', {})
argument_filters = filter_params.pop('filter', {})
argument_filter_names = list(argument_filters.keys())
event_abi = self.find_matching_event_abi(event_name, argument_filter_names)
data_filter_set, filter_params = construct_event_filter_params(
data_filter_set, event_filter_params = construct_event_filter_params(
event_abi,
contract_address=self.address,
argument_filters=argument_filters,
**default_filter_params
**filter_params
)
log_data_extract_fn = functools.partial(get_event_data, event_abi)
log_filter = self.web3.eth.filter(filter_params)
log_filter = self.web3.eth.filter(event_filter_params)
log_filter.set_data_filters(data_filter_set)
log_filter.log_entry_formatter = log_data_extract_fn
log_filter.filter_params = filter_params
log_filter.filter_params = event_filter_params
if callbacks:
log_filter.watch(*callbacks)
@ -397,26 +397,26 @@ class Contract(object):
return log_filter
@combomethod
def pastEvents(self, event_name, default_filter_params=None, *callbacks):
def pastEvents(self, event_name, filter_params=None, *callbacks):
"""
register a callback to be triggered on all past events.
"""
if default_filter_params is None:
default_filter_params = {}
if filter_params is None:
filter_params = {}
if 'fromBlock' in default_filter_params or 'toBlock' in default_filter_params:
if 'fromBlock' in filter_params or 'toBlock' in filter_params:
raise ValueError("Cannot provide `fromBlock` or `toBlock` in `pastEvents` calls")
filter_params = {}
filter_params.update(default_filter_params)
filter_params.update({
event_filter_params = {}
event_filter_params.update(filter_params)
event_filter_params.update({
'fromBlock': "earliest",
'toBlock': self.web3.eth.blockNumber,
})
log_filter = self.on(
event_name,
default_filter_params=filter_params,
filter_params=event_filter_params,
)
past_log_filter = PastLogFilter(